-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build-packages.mjs
executable file
·118 lines (100 loc) · 3.58 KB
/
build-packages.mjs
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
#!/usr/bin/env node
/* eslint-disable unicorn/prefer-top-level-await */
import childProcess from 'node:child_process';
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { promisify } from 'node:util';
import { build } from 'esbuild';
import glob from 'fast-glob';
// if this script is moved, this will need to be adjusted
const exec = promisify(childProcess.exec);
const rootDir = path.dirname(fileURLToPath(import.meta.url));
const packages = await fs.readdir(`${rootDir}/packages`);
const packageName = process.argv[2];
if (!packageName || !packages.includes(packageName)) {
console.error(`Please specify the name of the package to build: node build-packages.mjs <package-name> (one of ${packages.join(', ')})`);
process.exit(1);
}
console.info(`Compiling package ${packageName}`);
const packageDir = `${rootDir}/packages/${packageName}`;
const sourceDir = path.join(packageDir, 'src');
const libDir = path.join(packageDir, 'lib');
const typesDir = path.join(packageDir, 'types');
const [sourceFiles] = await Promise.all([
// Find all .js and .ts files from /src.
glob(`${convertSlashes(sourceDir)}/**/*.{mjs,cjs,js,mts,cts,ts}`, { onlyFiles: true, absolute: false }),
// Delete /lib for a full rebuild.
rmDir(libDir),
// Delete /types for a full rebuild.
rmDir(typesDir),
]);
const filesToCompile = [];
const filesToCopyToLib = [];
const declarationFiles = [];
for (const file of sourceFiles) {
// mjs files cannot be built as they would be compiled to commonjs
if (file.endsWith('.mjs')) {
filesToCopyToLib.push(file);
} else if (file.endsWith('.d.ts')) {
declarationFiles.push(file);
} else {
filesToCompile.push(file);
}
}
// copy .d.ts files prior to generating them from the .ts files
// so the .ts files in lib/ will take priority..
await Promise.all([
copyFiles(declarationFiles, sourceDir, typesDir),
copyFiles(filesToCopyToLib, sourceDir, libDir),
]);
await Promise.all([
build({
// Adds source mapping
sourcemap: true,
// The compiled code should be usable in node v16
target: 'node16',
// The source code's format is commonjs.
format: 'cjs',
outdir: libDir,
entryPoints: filesToCompile.map(file => path.resolve(file)),
}),
exec('tsc --emitDeclarationOnly', {
env: {
// binaries installed from modules have symlinks in
// <pkg root>/node_modules/.bin.
PATH: `${process.env.PATH || ''}:${path.join(
rootDir,
'node_modules/.bin',
)}`,
},
cwd: packageDir,
}),
]);
async function rmDir(dirName) {
try {
await fs.stat(dirName);
await fs.rm(dirName, { recursive: true });
} catch {
/* no-op */
}
}
async function copyFiles(files, fromFolder, toFolder) {
await Promise.all(files.map(async file => {
const to = path.join(toFolder, path.relative(fromFolder, file));
const dir = path.dirname(to);
await fs.mkdir(dir, { recursive: true });
await fs.copyFile(file, to);
}));
}
// On Windows, `fileURLToPath()` returns a path with "back slashes" ("\"),
// and that's a correct behavior because Windows paths are supposed to be written in that form.
// But `fast-glob` has an issue with Windows-style paths written with "back slashes" ("\"):
// https://github.com/mrmlnc/fast-glob/issues/237
// It doesn't throw any error or provide any indication of the issue.
// It simply doesn't find any files.
// To fix that, we manually convert all "back slashes" to "forward slashes"
// when passing paths to `fast-glob` functions.
function convertSlashes(fileSystemPath) {
return fileSystemPath.replaceAll('\\', '/');
}