-
Notifications
You must be signed in to change notification settings - Fork 2k
/
Copy pathbuild-npm.js
107 lines (85 loc) · 3.17 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
'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 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`',
);
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
const packageJSON = buildPackageJSON();
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;
}