forked from graphql/graphql-js
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathbuild-npm.js
121 lines (97 loc) · 3.69 KB
/
build-npm.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
'use strict';
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const ts = require('typescript');
const babel = require('@babel/core');
const prettier = require('prettier');
const { readdirRecursive, showDirStats } = require('./utils.js');
const prettierConfig = JSON.parse(
fs.readFileSync(require.resolve('../.prettierrc'), 'utf-8'),
);
if (require.main === module) {
fs.rmSync('./npmDist', { recursive: true, force: true });
fs.mkdirSync('./npmDist');
const packageJSON = buildPackageJSON();
const srcFiles = readdirRecursive('./src', { ignoreDir: /^__.*__$/ });
for (const filepath of srcFiles) {
const srcPath = path.join('./src', filepath);
const destPath = path.join('./npmDist', filepath);
fs.mkdirSync(path.dirname(destPath), { recursive: true });
if (filepath.endsWith('.ts')) {
const cjs = babelBuild(srcPath, { envName: 'cjs' });
writeGeneratedFile(destPath.replace(/\.ts$/, '.js'), cjs);
const mjs = babelBuild(srcPath, { envName: 'mjs' });
writeGeneratedFile(destPath.replace(/\.ts$/, '.mjs'), mjs);
}
}
const tsProgram = ts.createProgram(['src/index.ts'], {
...ts.getDefaultCompilerOptions(),
declaration: true,
declarationDir: './npmDist',
emitDeclarationOnly: true,
});
const tsResult = tsProgram.emit(undefined, (filepath, body) => {
writeGeneratedFile(filepath, body);
});
assert(
!tsResult.emitSkipped,
'Fail to generate `*.d.ts` files, please run `npm run check`',
);
assert(packageJSON.types, 'Missing "types".');
const supportedTSVersions = Object.keys(packageJSON.typesVersions);
assert(
supportedTSVersions.length === 1,
'Property "typesVersions" should have exactly one key.',
);
// TODO: revisit once TS implements https://github.com/microsoft/TypeScript/issues/44795
fs.writeFileSync(
path.join('./npmDist', packageJSON.types),
// Provoke syntax error to show this message
`"Package 'graphql' support only TS versions that are ${supportedTSVersions[0]}".`,
);
fs.copyFileSync('./LICENSE', './npmDist/LICENSE');
fs.copyFileSync('./README.md', './npmDist/README.md');
// Should be done as the last step so only valid packages can be published
writeGeneratedFile('./npmDist/package.json', JSON.stringify(packageJSON));
showDirStats('./npmDist');
}
function writeGeneratedFile(filepath, body) {
const formatted = prettier.format(body, { filepath, ...prettierConfig });
fs.writeFileSync(filepath, formatted);
}
function babelBuild(srcPath, options) {
const { code } = babel.transformFileSync(srcPath, {
babelrc: false,
configFile: './.babelrc-npm.json',
...options,
});
return code + '\n';
}
function buildPackageJSON() {
const packageJSON = JSON.parse(
fs.readFileSync(require.resolve('../package.json'), 'utf-8'),
);
delete packageJSON.private;
delete packageJSON.scripts;
delete packageJSON.devDependencies;
const { version } = packageJSON;
const versionMatch = /^\d+\.\d+\.\d+-?(?<preReleaseTag>.*)?$/.exec(version);
if (!versionMatch) {
throw new Error('Version does not match semver spec: ' + version);
}
const { preReleaseTag } = versionMatch.groups;
if (preReleaseTag != null) {
const splittedTag = preReleaseTag.split('.');
// Note: `experimental-*` take precedence over `alpha`, `beta` or `rc`.
const publishTag = splittedTag[2] ?? splittedTag[0];
assert(
['alpha', 'beta', 'rc'].includes(publishTag) ||
publishTag.startsWith('experimental-'),
`"${publishTag}" tag is not supported.`,
);
assert(!packageJSON.publishConfig, 'Can not override "publishConfig".');
packageJSON.publishConfig = { tag: publishTag };
}
return packageJSON;
}