mb-run 1.0.3-dev-20261002-10cd644 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/vendor/.gitignore.txt +6 -1
- package/vendor/.oxfmtrc.root.json +6 -2
- package/vendor/.oxlintrc.root.json +6 -2
- package/vendor/scripts/bun-bundle.mjs +412 -0
- package/vendor/scripts/clean.mjs +108 -44
- package/vendor/scripts/create-release.mjs +147 -38
- package/vendor/scripts/deep-clean.mjs +111 -48
- package/vendor/scripts/downloads.mjs +67 -15
- package/vendor/scripts/git-status.mjs +155 -43
- package/vendor/scripts/git-sync-dev.mjs +77 -20
- package/vendor/scripts/prepublish-clean.mjs +87 -16
- package/vendor/scripts/prune-releases.mjs +119 -50
- package/vendor/scripts/prune-tags.mjs +151 -43
- package/vendor/scripts/remove-workflows.mjs +78 -59
- package/vendor/scripts/version.mjs +85 -35
package/CHANGELOG.md
CHANGED
|
@@ -23,13 +23,19 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
23
23
|
|
|
24
24
|
<a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="120"></a>
|
|
25
25
|
|
|
26
|
-
## [1.0.3] -
|
|
26
|
+
## [1.0.3] - 2026-10-02
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- [scripts]: Sync the own and vendored `scripts/*.mjs` to v.2.0.0 from matterbridge-native (adds `--help`, `--version` and `--dry-run` to `git-sync-dev.mjs`) and add `bun-bundle.mjs`.
|
|
27
31
|
|
|
28
32
|
### Fixed
|
|
29
33
|
|
|
30
34
|
- [oxc]: Exclude `scripts` directories from the vendored root lint and format configs.
|
|
31
35
|
- [upgrade]: Drop the npm-only `--no-fund --no-audit` flags from `bun link matterbridge` in the plugin `softReset:bun` script.
|
|
32
36
|
- [scripts]: Bump the vendored `scripts/clean.mjs` and `scripts/deep-clean.mjs` to v.1.3.1, which warn on unreadable paths instead of silently skipping them.
|
|
37
|
+
- [scripts]: Sync the own and vendored `scripts/*.mjs` with the latest versions from matterbridge-native (`clean.mjs` and `deep-clean.mjs` v.1.4.0, `prepublish-clean.mjs` v.1.2.0, the others v.1.1.0).
|
|
38
|
+
- [vendor]: Add the matterbridge-native exclusions (`artifacts`, `chip`, `tmp`, `.hutch`, `.cottontail-tmp`, plus `xmls` for oxc) to the vendored `.gitignore` v.1.0.4, `.oxfmtrc.json` v.1.0.8 and `.oxlintrc.json` v.1.0.20.
|
|
33
39
|
|
|
34
40
|
<a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="80"></a>
|
|
35
41
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mb-run",
|
|
3
|
-
"version": "1.0.3
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "mb-run",
|
|
9
|
-
"version": "1.0.3
|
|
9
|
+
"version": "1.0.3",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"cross-spawn": "7.0.6",
|
package/package.json
CHANGED
package/vendor/.gitignore.txt
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
# .gitignore 1.0.
|
|
1
|
+
# .gitignore 1.0.4
|
|
2
2
|
|
|
3
3
|
# This file specifies intentionally untracked directories and files that Git should ignore.
|
|
4
4
|
|
|
5
5
|
# Specific directories that should be ignored
|
|
6
6
|
.cache/
|
|
7
|
+
.cottontail-tmp/
|
|
8
|
+
.hutch/
|
|
9
|
+
artifacts/
|
|
7
10
|
build/
|
|
11
|
+
chip/
|
|
8
12
|
coverage/
|
|
9
13
|
dist/
|
|
10
14
|
node_modules/
|
|
11
15
|
out/
|
|
12
16
|
temp/
|
|
17
|
+
tmp/
|
|
13
18
|
|
|
14
19
|
# Specific files that should be ignored
|
|
15
20
|
.DS_Store
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
// .oxfmtrc.json 1.0.
|
|
1
|
+
// .oxfmtrc.json 1.0.8
|
|
2
2
|
|
|
3
3
|
// This Oxfmt configuration (shared between all matterbridge packages) is designed for a TypeScript project using ESM modules.
|
|
4
4
|
{
|
|
5
5
|
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
|
6
6
|
"ignorePatterns": [
|
|
7
7
|
"**/.cache/**",
|
|
8
|
+
"**/.cottontail-tmp/**",
|
|
8
9
|
"**/.git/**",
|
|
10
|
+
"**/.hutch/**",
|
|
9
11
|
"apps/**",
|
|
12
|
+
"**/artifacts/**",
|
|
10
13
|
"**/build/**",
|
|
11
|
-
"chip/**",
|
|
14
|
+
"**/chip/**",
|
|
12
15
|
"**/coverage/**",
|
|
13
16
|
"docs/**",
|
|
14
17
|
"**/dist/**",
|
|
@@ -17,6 +20,7 @@
|
|
|
17
20
|
"**/node_modules/**",
|
|
18
21
|
"**/out/**",
|
|
19
22
|
"**/screenshots/**",
|
|
23
|
+
"**/xmls/**",
|
|
20
24
|
"**/scripts/**",
|
|
21
25
|
"vendor/**",
|
|
22
26
|
"**/package-lock.json",
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
// .oxlintrc.json 1.0.
|
|
1
|
+
// .oxlintrc.json 1.0.20
|
|
2
2
|
|
|
3
3
|
// This Oxlint configuration (shared between all matterbridge packages) is designed for a TypeScript project using ESM modules.
|
|
4
4
|
{
|
|
5
5
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
6
6
|
"ignorePatterns": [
|
|
7
7
|
"**/.cache/**",
|
|
8
|
+
"**/.cottontail-tmp/**",
|
|
8
9
|
"**/.git/**",
|
|
10
|
+
"**/.hutch/**",
|
|
9
11
|
"apps/**",
|
|
12
|
+
"**/artifacts/**",
|
|
10
13
|
"**/build/**",
|
|
11
|
-
"chip/**",
|
|
14
|
+
"**/chip/**",
|
|
12
15
|
"**/coverage/**",
|
|
13
16
|
"docs/**",
|
|
14
17
|
"**/dist/**",
|
|
@@ -17,6 +20,7 @@
|
|
|
17
20
|
"**/node_modules/**",
|
|
18
21
|
"**/out/**",
|
|
19
22
|
"**/screenshots/**",
|
|
23
|
+
"**/xmls/**",
|
|
20
24
|
"**/scripts/**",
|
|
21
25
|
"vendor/**",
|
|
22
26
|
"**/package-lock.json",
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bun-bundle.mjs
|
|
3
|
+
* Version: 2.0.0
|
|
4
|
+
*
|
|
5
|
+
* Bundles the package with `Bun.build` and the type declarations with rollup + rollup-plugin-dts.
|
|
6
|
+
*
|
|
7
|
+
* Every entry of the package.json `exports` map is bundled, not only the package entrypoint:
|
|
8
|
+
* the `bun` condition (the TypeScript source) is the bundler entry, the `types` condition (the
|
|
9
|
+
* tsc emitted declaration) is the rollup entry, and the `import` condition gives the output
|
|
10
|
+
* name, with its leading `dist` directory replaced by `build`. So `./src/module.ts` is bundled
|
|
11
|
+
* into `build/module.js` and `dist/module.d.ts` into `build/module.d.ts`.
|
|
12
|
+
* Wildcard exports are expanded into sorted source files, preserving their matched subpaths.
|
|
13
|
+
*
|
|
14
|
+
* The tsc declarations must exist before the declaration bundle runs, so this script emits them
|
|
15
|
+
* first with `cleanBuildDts`, unless `--no-declaration-build` is passed. `Bun.build` produces the
|
|
16
|
+
* JavaScript, so that build only emits the declarations. The clean variant is used because every
|
|
17
|
+
* build flavour shares the same dist directory, so a stale build of another flavour would
|
|
18
|
+
* otherwise be considered up to date and bundled as is.
|
|
19
|
+
*
|
|
20
|
+
* The packages listed in `bundledPackages` are bundled in, every other bare import (node builtins
|
|
21
|
+
* and external dependencies) stays external in both bundles. That list is the workspace packages
|
|
22
|
+
* plus any dependency named there explicitly.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* bun scripts/bun-bundle.mjs Development bundle (sourcemaps, not minified)
|
|
26
|
+
* bun scripts/bun-bundle.mjs --production Production bundle (minified, no sourcemaps)
|
|
27
|
+
* bun scripts/bun-bundle.mjs --watch Development bundle, rebuilt on change
|
|
28
|
+
* bun scripts/bun-bundle.mjs --workspaces Also bundle every workspace package
|
|
29
|
+
* bun scripts/bun-bundle.mjs --no-declaration-build Reuse the existing dist declarations
|
|
30
|
+
* bun scripts/bun-bundle.mjs --dry-run, -n List the bundles without building or writing anything
|
|
31
|
+
* bun scripts/bun-bundle.mjs --version, -v Show the script version
|
|
32
|
+
* bun scripts/bun-bundle.mjs --help, -h Show the help
|
|
33
|
+
*
|
|
34
|
+
* The script runs only when executed directly. Importing it exposes `main` without side effects.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/* oxlint-disable no-console */
|
|
38
|
+
|
|
39
|
+
import { spawnSync } from 'node:child_process';
|
|
40
|
+
import { existsSync, readFileSync, rmSync, watch as watchDir } from 'node:fs';
|
|
41
|
+
import { createRequire } from 'node:module';
|
|
42
|
+
import path from 'node:path';
|
|
43
|
+
import process from 'node:process';
|
|
44
|
+
|
|
45
|
+
import { rollup } from 'rollup';
|
|
46
|
+
import { dts } from 'rollup-plugin-dts';
|
|
47
|
+
|
|
48
|
+
const scriptVersion = '2.0.0';
|
|
49
|
+
|
|
50
|
+
const require = createRequire(import.meta.url);
|
|
51
|
+
|
|
52
|
+
// The settings of the current run, assigned by main() before any bundling starts.
|
|
53
|
+
let root = path.resolve(import.meta.dirname, '..');
|
|
54
|
+
let production = false;
|
|
55
|
+
/** @type {Set<string>} */
|
|
56
|
+
let bundledPackages = new Set();
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Builds the help text.
|
|
60
|
+
*
|
|
61
|
+
* @returns {string} The usage message.
|
|
62
|
+
*/
|
|
63
|
+
const usage = () =>
|
|
64
|
+
[
|
|
65
|
+
'Usage: bun scripts/bun-bundle.mjs [--production] [--watch] [--workspaces] [--no-declaration-build] [--dry-run|-n]',
|
|
66
|
+
'',
|
|
67
|
+
' --production Production bundle (minified, no sourcemaps)',
|
|
68
|
+
' --watch Rebuild the JavaScript on change',
|
|
69
|
+
' --workspaces Also bundle every workspace package',
|
|
70
|
+
' --no-declaration-build Reuse the existing dist declarations',
|
|
71
|
+
' --dry-run, -n List the bundles without building or writing anything',
|
|
72
|
+
' --version, -v Show the script version',
|
|
73
|
+
' --help, -h Show this help message',
|
|
74
|
+
].join('\n');
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Reports whether an import specifier is a bare package specifier.
|
|
78
|
+
*
|
|
79
|
+
* A bare specifier names a package (`node:fs`, `rollup`, `@matterbridge/utils`)
|
|
80
|
+
* rather than a file, so it is the only kind that can be externalized or bundled by name.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} specifier - The import specifier to test.
|
|
83
|
+
* @returns {boolean} True for a bare specifier, false for a relative or absolute path.
|
|
84
|
+
*/
|
|
85
|
+
const isBare = (specifier) => !specifier.startsWith('.') && !path.isAbsolute(specifier);
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Reads the package.json of a package directory.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} dir - The absolute path of the package directory.
|
|
91
|
+
* @returns {Record<string, any>} The parsed package manifest.
|
|
92
|
+
*/
|
|
93
|
+
const readManifest = (dir) => JSON.parse(readFileSync(path.resolve(dir, 'package.json'), 'utf8'));
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Splits a bare specifier into its package name and its export subpath.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} specifier - The bare specifier, for example `@matterbridge/test/setupTest`.
|
|
99
|
+
* @returns {{ name: string, subpath: string }} The package name and the `exports` key of the subpath.
|
|
100
|
+
*/
|
|
101
|
+
const parseSpecifier = (specifier) => {
|
|
102
|
+
const segments = specifier.split('/');
|
|
103
|
+
const scoped = specifier.startsWith('@');
|
|
104
|
+
const name = segments.slice(0, scoped ? 2 : 1).join('/');
|
|
105
|
+
const rest = segments.slice(scoped ? 2 : 1);
|
|
106
|
+
return { name, subpath: rest.length > 0 ? `./${rest.join('/')}` : '.' };
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Resolves the declaration file of a bundled package specifier.
|
|
111
|
+
*
|
|
112
|
+
* rollup has no node resolution of its own, so the `types` condition of the package `exports`
|
|
113
|
+
* map is read here to turn a bare specifier into the absolute path of its .d.ts file. Packages
|
|
114
|
+
* without an `exports` map fall back to the top level `types` or `typings` field.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} specifier - The bare specifier, for example `@matterbridge/test/setupTest`.
|
|
117
|
+
* @returns {string | null} The absolute path of the declaration file, or null when it cannot be resolved.
|
|
118
|
+
*/
|
|
119
|
+
const resolveBundledDeclaration = (specifier) => {
|
|
120
|
+
const { name, subpath } = parseSpecifier(specifier);
|
|
121
|
+
|
|
122
|
+
let manifestPath;
|
|
123
|
+
try {
|
|
124
|
+
manifestPath = require.resolve(`${name}/package.json`, { paths: [root] });
|
|
125
|
+
} catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
130
|
+
const target = manifest.exports?.[subpath];
|
|
131
|
+
const fallback = subpath === '.' ? (manifest.types ?? manifest.typings ?? null) : null;
|
|
132
|
+
const types = typeof target === 'string' ? fallback : (target?.types ?? fallback);
|
|
133
|
+
if (!types) return null;
|
|
134
|
+
|
|
135
|
+
const resolved = path.resolve(path.dirname(manifestPath), types);
|
|
136
|
+
return existsSync(resolved) ? resolved : null;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Collects the bundle entries of a package from its `exports` map.
|
|
141
|
+
*
|
|
142
|
+
* Every export condition set that carries a `bun` source and an `import` output is bundled.
|
|
143
|
+
* Export targets without those conditions (a bare string target, or a conditions object that
|
|
144
|
+
* only points at already built files) are skipped, since there is no source to bundle.
|
|
145
|
+
*
|
|
146
|
+
* @param {string} dir - The absolute path of the package directory.
|
|
147
|
+
* @returns {{ subpath: string, source: string, outfile: string, declaration: string | null, declarationOutfile: string }[]} The entries to bundle.
|
|
148
|
+
*/
|
|
149
|
+
const getEntries = (dir) => {
|
|
150
|
+
const { exports: map } = readManifest(dir);
|
|
151
|
+
const entries = [];
|
|
152
|
+
|
|
153
|
+
for (const [subpath, target] of Object.entries(map ?? {})) {
|
|
154
|
+
if (!target || typeof target === 'string') continue;
|
|
155
|
+
const { bun: source, import: output, types } = target;
|
|
156
|
+
if (!source || !output) continue;
|
|
157
|
+
|
|
158
|
+
/** @type {string} */
|
|
159
|
+
const sourcePattern = source;
|
|
160
|
+
const wildcard = sourcePattern.indexOf('*');
|
|
161
|
+
const sources = wildcard === -1 ? [sourcePattern] : [...new Bun.Glob(sourcePattern.replaceAll('*', '**/*')).scanSync({ cwd: dir, onlyFiles: true })].toSorted();
|
|
162
|
+
|
|
163
|
+
for (const sourceFile of sources) {
|
|
164
|
+
// A package export star can include nested paths; use the same match in every target.
|
|
165
|
+
const normalizedSource = sourceFile.startsWith('./') ? sourceFile : `./${sourceFile}`;
|
|
166
|
+
const match = wildcard === -1 ? '' : normalizedSource.slice(wildcard, normalizedSource.length - (sourcePattern.length - wildcard - 1));
|
|
167
|
+
const expandedOutput = output.replaceAll('*', match);
|
|
168
|
+
const relative = expandedOutput.replace(/^\.\//, '');
|
|
169
|
+
const outfile = path.resolve(dir, 'build', relative.startsWith('dist/') ? relative.slice('dist/'.length) : path.basename(relative));
|
|
170
|
+
|
|
171
|
+
entries.push({
|
|
172
|
+
subpath: subpath.replaceAll('*', match),
|
|
173
|
+
source: path.resolve(dir, sourceFile),
|
|
174
|
+
outfile,
|
|
175
|
+
declaration: types ? path.resolve(dir, types.replaceAll('*', match)) : null,
|
|
176
|
+
declarationOutfile: outfile.replace(/\.js$/, '.d.ts'),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return entries;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Collects workspace package directories in declaration order, expanding glob patterns and removing duplicates.
|
|
186
|
+
*
|
|
187
|
+
* @returns {string[]} The absolute paths of the workspace package directories.
|
|
188
|
+
*/
|
|
189
|
+
const getWorkspaceDirs = () => {
|
|
190
|
+
const { workspaces: patterns = [] } = readManifest(root);
|
|
191
|
+
/** @type {Set<string>} */
|
|
192
|
+
const dirs = new Set();
|
|
193
|
+
for (const pattern of Array.isArray(patterns) ? patterns : (patterns.packages ?? [])) {
|
|
194
|
+
for (const match of new Bun.Glob(pattern).scanSync({ cwd: root, onlyFiles: false })) {
|
|
195
|
+
const dir = path.resolve(root, match);
|
|
196
|
+
if (existsSync(path.resolve(dir, 'package.json'))) dirs.add(dir);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return [...dirs];
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Reports whether a bare specifier belongs to a package that is bundled into the output.
|
|
204
|
+
*
|
|
205
|
+
* @param {string} specifier - The bare specifier to test.
|
|
206
|
+
* @returns {boolean} True when the package is bundled, false when it stays external.
|
|
207
|
+
*/
|
|
208
|
+
const isBundled = (specifier) => bundledPackages.has(parseSpecifier(specifier).name);
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Cleans and builds the tsc declarations the declaration bundles are assembled from.
|
|
212
|
+
*
|
|
213
|
+
* The root build references the workspace projects, so a single run emits the declarations of
|
|
214
|
+
* every package.
|
|
215
|
+
*
|
|
216
|
+
* @returns {void}
|
|
217
|
+
*/
|
|
218
|
+
const buildDeclarations = () => {
|
|
219
|
+
const script = 'cleanBuildDts';
|
|
220
|
+
console.log(`Cleaning and building the declarations with "bun run ${script}"...`);
|
|
221
|
+
const result = spawnSync('bun', ['run', script], { cwd: root, stdio: 'inherit', shell: process.platform === 'win32' });
|
|
222
|
+
if (result.status !== 0) {
|
|
223
|
+
throw new Error(`"bun run ${script}" failed with exit code ${result.status ?? 'unknown'}.`);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Bundles the source of a single export entry with `Bun.build`.
|
|
229
|
+
*
|
|
230
|
+
* `Bun.build` writes into a directory, so `naming` pins the file name of the single entrypoint
|
|
231
|
+
* to the name the `exports` map declares.
|
|
232
|
+
*
|
|
233
|
+
* @param {{ source: string, outfile: string }} entry - The entry to bundle.
|
|
234
|
+
* @returns {Promise<void>} Resolves when the bundle has been written.
|
|
235
|
+
*/
|
|
236
|
+
const bundleJavaScript = async (entry) => {
|
|
237
|
+
const result = await Bun.build({
|
|
238
|
+
entrypoints: [entry.source],
|
|
239
|
+
outdir: path.dirname(entry.outfile),
|
|
240
|
+
naming: path.basename(entry.outfile),
|
|
241
|
+
// The bun target resolves the `bun` export condition, so the workspace packages are bundled
|
|
242
|
+
// straight from their TypeScript sources, and the output carries the `// @bun` pragma.
|
|
243
|
+
target: 'bun',
|
|
244
|
+
format: 'esm',
|
|
245
|
+
sourcemap: production ? 'none' : 'linked',
|
|
246
|
+
minify: production,
|
|
247
|
+
// Report the failure below with the entry name instead of the generic "Bundle failed" error.
|
|
248
|
+
throw: false,
|
|
249
|
+
plugins: [
|
|
250
|
+
{
|
|
251
|
+
name: 'externalize-unbundled-packages',
|
|
252
|
+
setup(build) {
|
|
253
|
+
build.onResolve({ filter: /.*/ }, (args) => {
|
|
254
|
+
// Returning null defers to the default resolution, which bundles the module.
|
|
255
|
+
if (!isBare(args.path) || isBundled(args.path)) return null;
|
|
256
|
+
return { path: args.path, external: true };
|
|
257
|
+
});
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
if (!result.success) {
|
|
264
|
+
throw new AggregateError(result.logs, `Failed to bundle ${path.relative(root, entry.source)}.`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const bytes = result.outputs.reduce((total, output) => total + output.size, 0);
|
|
268
|
+
console.log(` ${path.relative(root, entry.outfile)} (${(bytes / 1024).toFixed(1)} kb)`);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Bundles the tsc declarations of a single export entry with rollup and rollup-plugin-dts.
|
|
273
|
+
*
|
|
274
|
+
* @param {{ subpath: string, declaration: string | null, declarationOutfile: string }} entry - The entry to bundle.
|
|
275
|
+
* @returns {Promise<void>} Resolves when the declaration bundle has been written.
|
|
276
|
+
*/
|
|
277
|
+
const bundleDeclarations = async (entry) => {
|
|
278
|
+
if (!entry.declaration) return;
|
|
279
|
+
if (!existsSync(entry.declaration)) {
|
|
280
|
+
throw new Error(`Declaration entry not found: ${entry.declaration}. Run the build without --no-declaration-build.`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const bundle = await rollup({
|
|
284
|
+
input: entry.declaration,
|
|
285
|
+
external: (specifier) => isBare(specifier) && !isBundled(specifier),
|
|
286
|
+
plugins: [
|
|
287
|
+
{
|
|
288
|
+
name: 'resolve-bundled-declarations',
|
|
289
|
+
resolveId(specifier) {
|
|
290
|
+
if (!isBare(specifier) || !isBundled(specifier)) return null;
|
|
291
|
+
return resolveBundledDeclaration(specifier);
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
dts({ respectExternal: true }),
|
|
295
|
+
],
|
|
296
|
+
onwarn(warning, warn) {
|
|
297
|
+
// The declarations are emitted by tsc, circular type references between them are expected.
|
|
298
|
+
if (warning.code === 'CIRCULAR_DEPENDENCY') return;
|
|
299
|
+
warn(warning);
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
await bundle.write({ file: entry.declarationOutfile, format: 'es' });
|
|
304
|
+
await bundle.close();
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Bundles every export entry of a package into its build directory.
|
|
309
|
+
*
|
|
310
|
+
* @param {string} dir - The absolute path of the package directory.
|
|
311
|
+
* @param {boolean} [declarations] - Whether to bundle the declarations as well. Defaults to true.
|
|
312
|
+
* @returns {Promise<void>} Resolves when every entry of the package has been bundled.
|
|
313
|
+
*/
|
|
314
|
+
const bundlePackage = async (dir, declarations = true) => {
|
|
315
|
+
const entries = getEntries(dir);
|
|
316
|
+
if (entries.length === 0) {
|
|
317
|
+
const name = path.relative(root, dir);
|
|
318
|
+
console.warn(`No bundleable exports found in ${name === '' ? '.' : name}, skipping.`);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
rmSync(path.resolve(dir, 'build'), { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
323
|
+
|
|
324
|
+
for (const entry of entries) {
|
|
325
|
+
await bundleJavaScript(entry);
|
|
326
|
+
if (declarations) await bundleDeclarations(entry);
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Rebuilds a package whenever one of its sources changes.
|
|
332
|
+
*
|
|
333
|
+
* `Bun.build` has no watch mode of its own, so the src directory is watched here. The rebuild is
|
|
334
|
+
* debounced because an editor save raises several events for a single write, and it skips the
|
|
335
|
+
* declarations, which would need a full tsc build on every keystroke.
|
|
336
|
+
*
|
|
337
|
+
* @param {string} dir - The absolute path of the package directory.
|
|
338
|
+
* @returns {void}
|
|
339
|
+
*/
|
|
340
|
+
const watchPackage = (dir) => {
|
|
341
|
+
const srcDir = path.resolve(dir, 'src');
|
|
342
|
+
if (!existsSync(srcDir)) return;
|
|
343
|
+
|
|
344
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
345
|
+
let timer;
|
|
346
|
+
watchDir(srcDir, { recursive: true }, () => {
|
|
347
|
+
clearTimeout(timer);
|
|
348
|
+
// oxlint-disable-next-line typescript/no-misused-promises -- The async rebuild handles its errors internally.
|
|
349
|
+
timer = setTimeout(async () => {
|
|
350
|
+
try {
|
|
351
|
+
await bundlePackage(dir, false);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
console.error(error);
|
|
354
|
+
}
|
|
355
|
+
}, 100);
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Bundles the package, and with `--workspaces` every workspace package.
|
|
361
|
+
*
|
|
362
|
+
* @param {string[]} [args] - Command line arguments, without the runtime and script paths.
|
|
363
|
+
* @param {string} [rootDir] - The absolute path of the root package directory.
|
|
364
|
+
* @returns {Promise<number>} The exit code.
|
|
365
|
+
*/
|
|
366
|
+
export const main = async (args = process.argv.slice(2), rootDir = path.resolve(import.meta.dirname, '..')) => {
|
|
367
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
368
|
+
console.log(scriptVersion);
|
|
369
|
+
return 0;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
373
|
+
console.log(usage());
|
|
374
|
+
return 0;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
root = rootDir;
|
|
378
|
+
production = args.includes('--production');
|
|
379
|
+
// The packages inlined into the output instead of resolved at runtime by the consumer. The
|
|
380
|
+
// workspace packages are always bundled; every other name listed here is bundled as well, so its
|
|
381
|
+
// consumers do not have to install it. Everything not listed stays an external import.
|
|
382
|
+
bundledPackages = new Set([...getWorkspaceDirs().map((dir) => readManifest(dir).name), 'node-ansi-logger']);
|
|
383
|
+
|
|
384
|
+
const dirs = [root, ...(args.includes('--workspaces') ? getWorkspaceDirs() : [])];
|
|
385
|
+
|
|
386
|
+
if (args.includes('--dry-run') || args.includes('-n')) {
|
|
387
|
+
for (const dir of dirs) {
|
|
388
|
+
for (const entry of getEntries(dir)) {
|
|
389
|
+
console.log(`[dry-run] Would bundle ${path.relative(root, entry.source)} -> ${path.relative(root, entry.outfile)}`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return 0;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (!args.includes('--no-declaration-build')) buildDeclarations();
|
|
396
|
+
|
|
397
|
+
for (const dir of dirs) {
|
|
398
|
+
await bundlePackage(dir);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
console.log(`Bundled the ${production ? 'production' : 'development'} exports.`);
|
|
402
|
+
|
|
403
|
+
if (args.includes('--watch')) {
|
|
404
|
+
for (const dir of dirs) {
|
|
405
|
+
watchPackage(dir);
|
|
406
|
+
}
|
|
407
|
+
console.log('Watching for changes...');
|
|
408
|
+
}
|
|
409
|
+
return 0;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
if (import.meta.main) process.exitCode = await main();
|