@crustjs/crust-linux-x64-musl 0.5.6 → 0.6.1
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/bin/crust-bun-linux-x64-musl +2 -2
- package/bin/dist/index.d.ts +19 -12
- package/bin/dist/index.js +424 -1617
- package/bin/schema/package.json +5 -6
- package/package.json +3 -3
package/bin/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { chmod, copyFile, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
1
|
+
import { copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, rmdirSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { chmod, copyFile, mkdtemp, readFile, readdir, realpath, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import {
|
|
5
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
|
|
6
5
|
import { randomBytes } from "node:crypto";
|
|
7
|
-
import {
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
+
import { spawn } from "node:child_process";
|
|
8
8
|
import { once } from "node:events";
|
|
9
9
|
import { text } from "node:stream/consumers";
|
|
10
|
-
|
|
10
|
+
// \0rolldown/runtime.js
|
|
11
11
|
var __create = Object.create;
|
|
12
12
|
var __defProp = Object.defineProperty;
|
|
13
13
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
14
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
15
|
var __getProtoOf = Object.getPrototypeOf;
|
|
16
16
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
-
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
17
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod, mod.exports), cb = null), mod.exports);
|
|
18
18
|
var __copyProps = (to, from, except, desc) => {
|
|
19
19
|
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
20
20
|
key = keys[i];
|
|
@@ -29,26 +29,40 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
value: mod,
|
|
30
30
|
enumerable: true
|
|
31
31
|
}) : target, mod));
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* Set by `crust build` while it prepares the Command Snapshot: the absolute
|
|
36
|
-
* entry-isolated directory Extension build hooks write into. Core reads it
|
|
37
|
-
* to run the hooks; `resolveArtifactDir` reads it so sections evaluated during
|
|
38
|
-
* that run see the artifacts being built instead of the wiped `.crust/root`.
|
|
39
|
-
*/
|
|
40
|
-
const BUILD_OUT_DIR_ENV = "CRUST_INTERNAL_BUILD_OUT_DIR";
|
|
32
|
+
// ../utils/dist/signals.js
|
|
33
|
+
/** SigIgn bits from the first read, taken before Crust installs any listener. */
|
|
34
|
+
let ignoredMask;
|
|
41
35
|
/**
|
|
42
|
-
* `
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
36
|
+
* Whether `signal` is inherited as ignored, such as SIGHUP under `nohup` or SIGINT for a
|
|
37
|
+
* background job in a script. Adding a listener replaces that disposition and removing the
|
|
38
|
+
* last one restores the default action, so code that listens temporarily skips ignored
|
|
39
|
+
* signals to keep the process immune to them. Only Bun keeps an inherited ignore; Node
|
|
40
|
+
* resets it at startup, so this is always false there and skips the read.
|
|
41
|
+
*
|
|
42
|
+
* shortcut: Linux-only (`/proc/self/status`); macOS Bun still loses the ignore. Remove once
|
|
43
|
+
* Bun restores the previous disposition on listener removal (oven-sh/bun#47574).
|
|
48
44
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
function isSignalIgnored(signal) {
|
|
46
|
+
if (process.platform !== "linux" || process.versions.bun === void 0) return false;
|
|
47
|
+
ignoredMask ??= readIgnoredMask();
|
|
48
|
+
const number = process.getBuiltinModule("node:os").constants.signals[signal];
|
|
49
|
+
return number !== void 0 && number <= 32 && (ignoredMask >>> number - 1 & 1) === 1;
|
|
50
|
+
}
|
|
51
|
+
function readIgnoredMask() {
|
|
52
|
+
try {
|
|
53
|
+
const status = process.getBuiltinModule("node:fs").readFileSync("/proc/self/status", "utf8");
|
|
54
|
+
const hex = /^SigIgn:\s*([0-9a-f]+)$/m.exec(status)?.[1];
|
|
55
|
+
return hex ? Number.parseInt(hex.slice(-8), 16) : 0;
|
|
56
|
+
} catch {
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ../utils/dist/error.js
|
|
61
|
+
/** Narrows a caught Node.js system error to its stable errno contract. */
|
|
62
|
+
function isErrnoException(error) {
|
|
63
|
+
return error instanceof Error && "code" in error && typeof error.code === "string";
|
|
64
|
+
}
|
|
65
|
+
// ../core/dist/invocation-DKSTuFCO.js
|
|
52
66
|
/**
|
|
53
67
|
* A typed error for runtime recipe, Extension, Context, documentation, argv, and validation failures.
|
|
54
68
|
*
|
|
@@ -81,6 +95,9 @@ var CrustError = class extends Error {
|
|
|
81
95
|
this.code = code;
|
|
82
96
|
this.details = details[0];
|
|
83
97
|
}
|
|
98
|
+
static [Symbol.hasInstance](value) {
|
|
99
|
+
return Function.prototype[Symbol.hasInstance].call(this, value);
|
|
100
|
+
}
|
|
84
101
|
is(code) {
|
|
85
102
|
return Object.is(this.code, code);
|
|
86
103
|
}
|
|
@@ -96,7 +113,6 @@ var CrustError = class extends Error {
|
|
|
96
113
|
};
|
|
97
114
|
}
|
|
98
115
|
};
|
|
99
|
-
Object.freeze({ [Symbol("crust.handled")]: true });
|
|
100
116
|
/**
|
|
101
117
|
* Snapshot subprocess protocol used by first-party build tooling.
|
|
102
118
|
*
|
|
@@ -106,13 +122,23 @@ Object.freeze({ [Symbol("crust.handled")]: true });
|
|
|
106
122
|
* without dispatching a Command Action. In-process callers use `Crust.snapshot()`.
|
|
107
123
|
*
|
|
108
124
|
* Only source entries run by `crust build` honor it: finished Bun/Node bundles carry
|
|
109
|
-
* `process.env.CRUST_INTERNAL_BUILD === "1"` as a literal and compile the protocol out
|
|
110
|
-
* packaged Deno bundles set the `isPackagedBuild()` marker and skip it without
|
|
111
|
-
* reading the environment.
|
|
125
|
+
* `process.env.CRUST_INTERNAL_BUILD === "1"` as a literal and compile the protocol out.
|
|
112
126
|
*/
|
|
113
127
|
const SNAPSHOT_PATH_ENV = "CRUST_INTERNAL_SNAPSHOT_PATH";
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
// ../utils/dist/artifacts.js
|
|
129
|
+
/**
|
|
130
|
+
* Set by `crust build` while it prepares the Command Snapshot: the absolute
|
|
131
|
+
* entry-isolated directory Extension build hooks write into. Core reads it
|
|
132
|
+
* to run the hooks; `resolveArtifactDir` reads it so sections evaluated during
|
|
133
|
+
* that run see the artifacts being built instead of the wiped `.crust/root`.
|
|
134
|
+
*/
|
|
135
|
+
const BUILD_OUT_DIR_ENV = "CRUST_INTERNAL_BUILD_OUT_DIR";
|
|
136
|
+
// ../utils/dist/json.js
|
|
137
|
+
/** Narrow a JSON document root to an object (not array/scalar/null). */
|
|
138
|
+
function isJsonObject(value) {
|
|
139
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
140
|
+
}
|
|
141
|
+
// ../core/dist/tooling.js
|
|
116
142
|
const INSTALLED_COMMAND_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
117
143
|
/** {@link isInstalledCommandName}'s rule as prose, for error messages: "Use <rule>." */
|
|
118
144
|
const INSTALLED_COMMAND_NAME_RULE = "letters, digits, \".\", \"_\", and \"-\", starting with a letter or digit";
|
|
@@ -124,83 +150,18 @@ const INSTALLED_COMMAND_NAME_RULE = "letters, digits, \".\", \"_\", and \"-\", s
|
|
|
124
150
|
function isInstalledCommandName(name) {
|
|
125
151
|
return INSTALLED_COMMAND_NAME_PATTERN.test(name);
|
|
126
152
|
}
|
|
127
|
-
|
|
128
|
-
new RegExp([
|
|
153
|
+
[
|
|
129
154
|
String.raw`(?:\x1b\[|\x9b)[^\x1b\x18\x1a\x9c\x40-\x7e]*[\x40-\x7e\x18\x1a\x9c]?`,
|
|
130
155
|
String.raw`(?:\x1b\]|\x9d)[^\x07\x1b\x18\x1a\x9c]*(?:\x07|\x1b\\|[\x18\x1a\x9c])?`,
|
|
131
156
|
String.raw`(?:\x1b[PX^_]|[\x90\x98\x9e\x9f])[^\x1b\x18\x1a\x9c]*(?:\x1b\\|[\x18\x1a\x9c])?`,
|
|
132
157
|
String.raw`\x1b[\x20-\x2f][^\x1b]?`,
|
|
133
158
|
String.raw`\x1b[\x18\x1a\x9c\x30-\x7e]?`
|
|
134
|
-
].join("|")
|
|
135
|
-
const modifierCodes = {
|
|
136
|
-
/** Bold / increased intensity. */
|
|
137
|
-
bold: [1, 22],
|
|
138
|
-
/** Dim / decreased intensity. */
|
|
139
|
-
dim: [2, 22],
|
|
140
|
-
italic: [3, 23],
|
|
141
|
-
underline: [4, 24],
|
|
142
|
-
/** Inverse / reverse video. */
|
|
143
|
-
inverse: [7, 27],
|
|
144
|
-
/** Hidden / conceal. */
|
|
145
|
-
hidden: [8, 28],
|
|
146
|
-
/** Strikethrough / crossed out. */
|
|
147
|
-
strikethrough: [9, 29]
|
|
148
|
-
};
|
|
149
|
-
const colorCodes = {
|
|
150
|
-
black: [30, 39],
|
|
151
|
-
red: [31, 39],
|
|
152
|
-
green: [32, 39],
|
|
153
|
-
yellow: [33, 39],
|
|
154
|
-
blue: [34, 39],
|
|
155
|
-
magenta: [35, 39],
|
|
156
|
-
cyan: [36, 39],
|
|
157
|
-
white: [37, 39],
|
|
158
|
-
/** Bright black (gray). */
|
|
159
|
-
gray: [90, 39],
|
|
160
|
-
brightRed: [91, 39],
|
|
161
|
-
brightGreen: [92, 39],
|
|
162
|
-
brightYellow: [93, 39],
|
|
163
|
-
brightBlue: [94, 39],
|
|
164
|
-
brightMagenta: [95, 39],
|
|
165
|
-
brightCyan: [96, 39],
|
|
166
|
-
brightWhite: [97, 39],
|
|
167
|
-
bgBlack: [40, 49],
|
|
168
|
-
bgRed: [41, 49],
|
|
169
|
-
bgGreen: [42, 49],
|
|
170
|
-
bgYellow: [43, 49],
|
|
171
|
-
bgBlue: [44, 49],
|
|
172
|
-
bgMagenta: [45, 49],
|
|
173
|
-
bgCyan: [46, 49],
|
|
174
|
-
bgWhite: [47, 49],
|
|
175
|
-
bgBrightBlack: [100, 49],
|
|
176
|
-
bgBrightRed: [101, 49],
|
|
177
|
-
bgBrightGreen: [102, 49],
|
|
178
|
-
bgBrightYellow: [103, 49],
|
|
179
|
-
bgBrightBlue: [104, 49],
|
|
180
|
-
bgBrightMagenta: [105, 49],
|
|
181
|
-
bgBrightCyan: [106, 49],
|
|
182
|
-
bgBrightWhite: [107, 49]
|
|
183
|
-
};
|
|
184
|
-
const styleMethodCodes = {
|
|
185
|
-
...modifierCodes,
|
|
186
|
-
...colorCodes
|
|
187
|
-
};
|
|
188
|
-
const styleMethodNames = Object.freeze(Object.keys(styleMethodCodes));
|
|
189
|
-
const styleMethodPairs = Object.freeze(Object.fromEntries(styleMethodNames.map((name) => {
|
|
190
|
-
const [open, close] = styleMethodCodes[name];
|
|
191
|
-
return [name, {
|
|
192
|
-
open: `\x1b[${open}m`,
|
|
193
|
-
close: `\x1b[${close}m`
|
|
194
|
-
}];
|
|
195
|
-
})));
|
|
196
|
-
function isModifierName(name) {
|
|
197
|
-
return Object.hasOwn(modifierCodes, name);
|
|
198
|
-
}
|
|
159
|
+
].join("|");
|
|
199
160
|
function read(overrides, key, environment) {
|
|
200
161
|
return overrides !== void 0 && key in overrides ? overrides[key] : environment;
|
|
201
162
|
}
|
|
202
163
|
function readTTY(overrides) {
|
|
203
|
-
return
|
|
164
|
+
return (overrides !== void 0 && "isTTY" in overrides ? overrides.isTTY : process.stdout?.isTTY) ?? false;
|
|
204
165
|
}
|
|
205
166
|
function readForceColor(overrides) {
|
|
206
167
|
return read(overrides, "forceColor", process.env.FORCE_COLOR);
|
|
@@ -209,6 +170,9 @@ function readForceColor(overrides) {
|
|
|
209
170
|
function forceColorDisables(forceColor) {
|
|
210
171
|
return forceColor === "0" || forceColor === "false";
|
|
211
172
|
}
|
|
173
|
+
function isDumbTerm(term) {
|
|
174
|
+
return term?.toLowerCase() === "dumb";
|
|
175
|
+
}
|
|
212
176
|
function isTrueColorTerm(term) {
|
|
213
177
|
const lower = term.toLowerCase();
|
|
214
178
|
return lower.includes("24bit") || lower.includes("truecolor") || lower.endsWith("-direct");
|
|
@@ -232,25 +196,26 @@ function detectDepth(colorTerm, term) {
|
|
|
232
196
|
* - `"never"` → `"none"`.
|
|
233
197
|
* - `"always"` → `"truecolor"`.
|
|
234
198
|
* - `"auto"`:
|
|
235
|
-
* 1. `FORCE_COLOR` set → decides unconditionally (overrides TTY
|
|
236
|
-
* `NO_COLOR`,
|
|
199
|
+
* 1. `FORCE_COLOR` set → decides unconditionally (overrides TTY,
|
|
200
|
+
* `NO_COLOR`, and `TERM=dumb`, as in Node's `tty` color detection):
|
|
201
|
+
* `0` / `false` → `"none"`; `1` →
|
|
237
202
|
* `"16"`; `2` → `"256"`; `3` → `"truecolor"`; any other value
|
|
238
203
|
* (including empty) → forced on at the `COLORTERM` / `TERM`
|
|
239
204
|
* detected depth.
|
|
240
|
-
* 2. Not a TTY OR `NO_COLOR` set non-empty
|
|
205
|
+
* 2. Not a TTY OR `NO_COLOR` set non-empty OR `TERM=dumb`
|
|
206
|
+
* (case-insensitive) → `"none"`.
|
|
241
207
|
* 3. `COLORTERM` is `"truecolor"` or `"24bit"` (case-insensitive) →
|
|
242
208
|
* `"truecolor"`.
|
|
243
209
|
* 4. `TERM` ends with `-direct` OR contains `truecolor` / `24bit` →
|
|
244
210
|
* `"truecolor"`.
|
|
245
|
-
* 5. `TERM
|
|
246
|
-
* 6.
|
|
247
|
-
* 7. Any other TTY value → `"16"`.
|
|
211
|
+
* 5. `TERM` contains `256color` → `"256"`.
|
|
212
|
+
* 6. Any other TTY value → `"16"`.
|
|
248
213
|
*
|
|
249
214
|
* Detection follows the ecosystem `FORCE_COLOR` / `NO_COLOR` / `COLORTERM`
|
|
250
215
|
* / `TERM` conventions; no bespoke environment variables are introduced.
|
|
251
216
|
*
|
|
252
217
|
* @param mode - The color emission mode.
|
|
253
|
-
* @param overrides - Optional
|
|
218
|
+
* @param overrides - Optional capability inputs, such as another stream's TTY state or fixed test values.
|
|
254
219
|
* @returns The resolved {@link ColorDepth} tier.
|
|
255
220
|
*
|
|
256
221
|
* @example
|
|
@@ -286,14 +251,15 @@ function resolveColorDepth(mode, overrides) {
|
|
|
286
251
|
if (!readTTY(overrides)) return "none";
|
|
287
252
|
const noColor = read(overrides, "noColor", process.env.NO_COLOR);
|
|
288
253
|
if (noColor !== void 0 && noColor !== "") return "none";
|
|
289
|
-
if (
|
|
254
|
+
if (isDumbTerm(term)) return "none";
|
|
290
255
|
return detectDepth(colorTerm, term);
|
|
291
256
|
}
|
|
292
257
|
/**
|
|
293
258
|
* Resolve whether non-color ANSI modifiers should be emitted.
|
|
294
259
|
*
|
|
295
|
-
* In `"auto"` mode, modifiers are enabled when stdout is a TTY
|
|
296
|
-
* **not** affected by `NO_COLOR` (which only
|
|
260
|
+
* In `"auto"` mode, modifiers are enabled when stdout is a TTY and `TERM`
|
|
261
|
+
* is not `dumb`, but are **not** affected by `NO_COLOR` (which only
|
|
262
|
+
* controls color output).
|
|
297
263
|
* `FORCE_COLOR`, when set, decides unconditionally — it is the all-ANSI
|
|
298
264
|
* switch, while `NO_COLOR` is the colors-only switch.
|
|
299
265
|
*
|
|
@@ -305,750 +271,8 @@ function resolveModifierCapability(mode, overrides) {
|
|
|
305
271
|
if (mode === "never") return false;
|
|
306
272
|
const forceColor = readForceColor(overrides);
|
|
307
273
|
if (forceColor !== void 0) return !forceColorDisables(forceColor);
|
|
308
|
-
return readTTY(overrides);
|
|
274
|
+
return readTTY(overrides) && !isDumbTerm(read(overrides, "term", process.env.TERM));
|
|
309
275
|
}
|
|
310
|
-
const namedColorValues = {
|
|
311
|
-
aliceblue: [
|
|
312
|
-
240,
|
|
313
|
-
248,
|
|
314
|
-
255
|
|
315
|
-
],
|
|
316
|
-
antiquewhite: [
|
|
317
|
-
250,
|
|
318
|
-
235,
|
|
319
|
-
215
|
|
320
|
-
],
|
|
321
|
-
aqua: [
|
|
322
|
-
0,
|
|
323
|
-
255,
|
|
324
|
-
255
|
|
325
|
-
],
|
|
326
|
-
aquamarine: [
|
|
327
|
-
127,
|
|
328
|
-
255,
|
|
329
|
-
212
|
|
330
|
-
],
|
|
331
|
-
azure: [
|
|
332
|
-
240,
|
|
333
|
-
255,
|
|
334
|
-
255
|
|
335
|
-
],
|
|
336
|
-
beige: [
|
|
337
|
-
245,
|
|
338
|
-
245,
|
|
339
|
-
220
|
|
340
|
-
],
|
|
341
|
-
bisque: [
|
|
342
|
-
255,
|
|
343
|
-
228,
|
|
344
|
-
196
|
|
345
|
-
],
|
|
346
|
-
black: [
|
|
347
|
-
0,
|
|
348
|
-
0,
|
|
349
|
-
0
|
|
350
|
-
],
|
|
351
|
-
blanchedalmond: [
|
|
352
|
-
255,
|
|
353
|
-
235,
|
|
354
|
-
205
|
|
355
|
-
],
|
|
356
|
-
blue: [
|
|
357
|
-
0,
|
|
358
|
-
0,
|
|
359
|
-
255
|
|
360
|
-
],
|
|
361
|
-
blueviolet: [
|
|
362
|
-
138,
|
|
363
|
-
43,
|
|
364
|
-
226
|
|
365
|
-
],
|
|
366
|
-
brown: [
|
|
367
|
-
165,
|
|
368
|
-
42,
|
|
369
|
-
42
|
|
370
|
-
],
|
|
371
|
-
burlywood: [
|
|
372
|
-
222,
|
|
373
|
-
184,
|
|
374
|
-
135
|
|
375
|
-
],
|
|
376
|
-
cadetblue: [
|
|
377
|
-
95,
|
|
378
|
-
158,
|
|
379
|
-
160
|
|
380
|
-
],
|
|
381
|
-
chartreuse: [
|
|
382
|
-
127,
|
|
383
|
-
255,
|
|
384
|
-
0
|
|
385
|
-
],
|
|
386
|
-
chocolate: [
|
|
387
|
-
210,
|
|
388
|
-
105,
|
|
389
|
-
30
|
|
390
|
-
],
|
|
391
|
-
coral: [
|
|
392
|
-
255,
|
|
393
|
-
127,
|
|
394
|
-
80
|
|
395
|
-
],
|
|
396
|
-
cornflowerblue: [
|
|
397
|
-
100,
|
|
398
|
-
149,
|
|
399
|
-
237
|
|
400
|
-
],
|
|
401
|
-
cornsilk: [
|
|
402
|
-
255,
|
|
403
|
-
248,
|
|
404
|
-
220
|
|
405
|
-
],
|
|
406
|
-
crimson: [
|
|
407
|
-
220,
|
|
408
|
-
20,
|
|
409
|
-
60
|
|
410
|
-
],
|
|
411
|
-
cyan: [
|
|
412
|
-
0,
|
|
413
|
-
255,
|
|
414
|
-
255
|
|
415
|
-
],
|
|
416
|
-
darkblue: [
|
|
417
|
-
0,
|
|
418
|
-
0,
|
|
419
|
-
139
|
|
420
|
-
],
|
|
421
|
-
darkcyan: [
|
|
422
|
-
0,
|
|
423
|
-
139,
|
|
424
|
-
139
|
|
425
|
-
],
|
|
426
|
-
darkgoldenrod: [
|
|
427
|
-
184,
|
|
428
|
-
134,
|
|
429
|
-
11
|
|
430
|
-
],
|
|
431
|
-
darkgray: [
|
|
432
|
-
169,
|
|
433
|
-
169,
|
|
434
|
-
169
|
|
435
|
-
],
|
|
436
|
-
darkgreen: [
|
|
437
|
-
0,
|
|
438
|
-
100,
|
|
439
|
-
0
|
|
440
|
-
],
|
|
441
|
-
darkgrey: [
|
|
442
|
-
169,
|
|
443
|
-
169,
|
|
444
|
-
169
|
|
445
|
-
],
|
|
446
|
-
darkkhaki: [
|
|
447
|
-
189,
|
|
448
|
-
183,
|
|
449
|
-
107
|
|
450
|
-
],
|
|
451
|
-
darkmagenta: [
|
|
452
|
-
139,
|
|
453
|
-
0,
|
|
454
|
-
139
|
|
455
|
-
],
|
|
456
|
-
darkolivegreen: [
|
|
457
|
-
85,
|
|
458
|
-
107,
|
|
459
|
-
47
|
|
460
|
-
],
|
|
461
|
-
darkorange: [
|
|
462
|
-
255,
|
|
463
|
-
140,
|
|
464
|
-
0
|
|
465
|
-
],
|
|
466
|
-
darkorchid: [
|
|
467
|
-
153,
|
|
468
|
-
50,
|
|
469
|
-
204
|
|
470
|
-
],
|
|
471
|
-
darkred: [
|
|
472
|
-
139,
|
|
473
|
-
0,
|
|
474
|
-
0
|
|
475
|
-
],
|
|
476
|
-
darksalmon: [
|
|
477
|
-
233,
|
|
478
|
-
150,
|
|
479
|
-
122
|
|
480
|
-
],
|
|
481
|
-
darkseagreen: [
|
|
482
|
-
143,
|
|
483
|
-
188,
|
|
484
|
-
143
|
|
485
|
-
],
|
|
486
|
-
darkslateblue: [
|
|
487
|
-
72,
|
|
488
|
-
61,
|
|
489
|
-
139
|
|
490
|
-
],
|
|
491
|
-
darkslategray: [
|
|
492
|
-
47,
|
|
493
|
-
79,
|
|
494
|
-
79
|
|
495
|
-
],
|
|
496
|
-
darkslategrey: [
|
|
497
|
-
47,
|
|
498
|
-
79,
|
|
499
|
-
79
|
|
500
|
-
],
|
|
501
|
-
darkturquoise: [
|
|
502
|
-
0,
|
|
503
|
-
206,
|
|
504
|
-
209
|
|
505
|
-
],
|
|
506
|
-
darkviolet: [
|
|
507
|
-
148,
|
|
508
|
-
0,
|
|
509
|
-
211
|
|
510
|
-
],
|
|
511
|
-
deeppink: [
|
|
512
|
-
255,
|
|
513
|
-
20,
|
|
514
|
-
147
|
|
515
|
-
],
|
|
516
|
-
deepskyblue: [
|
|
517
|
-
0,
|
|
518
|
-
191,
|
|
519
|
-
255
|
|
520
|
-
],
|
|
521
|
-
dimgray: [
|
|
522
|
-
105,
|
|
523
|
-
105,
|
|
524
|
-
105
|
|
525
|
-
],
|
|
526
|
-
dimgrey: [
|
|
527
|
-
105,
|
|
528
|
-
105,
|
|
529
|
-
105
|
|
530
|
-
],
|
|
531
|
-
dodgerblue: [
|
|
532
|
-
30,
|
|
533
|
-
144,
|
|
534
|
-
255
|
|
535
|
-
],
|
|
536
|
-
firebrick: [
|
|
537
|
-
178,
|
|
538
|
-
34,
|
|
539
|
-
34
|
|
540
|
-
],
|
|
541
|
-
floralwhite: [
|
|
542
|
-
255,
|
|
543
|
-
250,
|
|
544
|
-
240
|
|
545
|
-
],
|
|
546
|
-
forestgreen: [
|
|
547
|
-
34,
|
|
548
|
-
139,
|
|
549
|
-
34
|
|
550
|
-
],
|
|
551
|
-
fuchsia: [
|
|
552
|
-
255,
|
|
553
|
-
0,
|
|
554
|
-
255
|
|
555
|
-
],
|
|
556
|
-
gainsboro: [
|
|
557
|
-
220,
|
|
558
|
-
220,
|
|
559
|
-
220
|
|
560
|
-
],
|
|
561
|
-
ghostwhite: [
|
|
562
|
-
248,
|
|
563
|
-
248,
|
|
564
|
-
255
|
|
565
|
-
],
|
|
566
|
-
gold: [
|
|
567
|
-
255,
|
|
568
|
-
215,
|
|
569
|
-
0
|
|
570
|
-
],
|
|
571
|
-
goldenrod: [
|
|
572
|
-
218,
|
|
573
|
-
165,
|
|
574
|
-
32
|
|
575
|
-
],
|
|
576
|
-
gray: [
|
|
577
|
-
128,
|
|
578
|
-
128,
|
|
579
|
-
128
|
|
580
|
-
],
|
|
581
|
-
green: [
|
|
582
|
-
0,
|
|
583
|
-
128,
|
|
584
|
-
0
|
|
585
|
-
],
|
|
586
|
-
greenyellow: [
|
|
587
|
-
173,
|
|
588
|
-
255,
|
|
589
|
-
47
|
|
590
|
-
],
|
|
591
|
-
grey: [
|
|
592
|
-
128,
|
|
593
|
-
128,
|
|
594
|
-
128
|
|
595
|
-
],
|
|
596
|
-
honeydew: [
|
|
597
|
-
240,
|
|
598
|
-
255,
|
|
599
|
-
240
|
|
600
|
-
],
|
|
601
|
-
hotpink: [
|
|
602
|
-
255,
|
|
603
|
-
105,
|
|
604
|
-
180
|
|
605
|
-
],
|
|
606
|
-
indianred: [
|
|
607
|
-
205,
|
|
608
|
-
92,
|
|
609
|
-
92
|
|
610
|
-
],
|
|
611
|
-
indigo: [
|
|
612
|
-
75,
|
|
613
|
-
0,
|
|
614
|
-
130
|
|
615
|
-
],
|
|
616
|
-
ivory: [
|
|
617
|
-
255,
|
|
618
|
-
255,
|
|
619
|
-
240
|
|
620
|
-
],
|
|
621
|
-
khaki: [
|
|
622
|
-
240,
|
|
623
|
-
230,
|
|
624
|
-
140
|
|
625
|
-
],
|
|
626
|
-
lavender: [
|
|
627
|
-
230,
|
|
628
|
-
230,
|
|
629
|
-
250
|
|
630
|
-
],
|
|
631
|
-
lavenderblush: [
|
|
632
|
-
255,
|
|
633
|
-
240,
|
|
634
|
-
245
|
|
635
|
-
],
|
|
636
|
-
lawngreen: [
|
|
637
|
-
124,
|
|
638
|
-
252,
|
|
639
|
-
0
|
|
640
|
-
],
|
|
641
|
-
lemonchiffon: [
|
|
642
|
-
255,
|
|
643
|
-
250,
|
|
644
|
-
205
|
|
645
|
-
],
|
|
646
|
-
lightblue: [
|
|
647
|
-
173,
|
|
648
|
-
216,
|
|
649
|
-
230
|
|
650
|
-
],
|
|
651
|
-
lightcoral: [
|
|
652
|
-
240,
|
|
653
|
-
128,
|
|
654
|
-
128
|
|
655
|
-
],
|
|
656
|
-
lightcyan: [
|
|
657
|
-
224,
|
|
658
|
-
255,
|
|
659
|
-
255
|
|
660
|
-
],
|
|
661
|
-
lightgoldenrodyellow: [
|
|
662
|
-
250,
|
|
663
|
-
250,
|
|
664
|
-
210
|
|
665
|
-
],
|
|
666
|
-
lightgray: [
|
|
667
|
-
211,
|
|
668
|
-
211,
|
|
669
|
-
211
|
|
670
|
-
],
|
|
671
|
-
lightgreen: [
|
|
672
|
-
144,
|
|
673
|
-
238,
|
|
674
|
-
144
|
|
675
|
-
],
|
|
676
|
-
lightgrey: [
|
|
677
|
-
211,
|
|
678
|
-
211,
|
|
679
|
-
211
|
|
680
|
-
],
|
|
681
|
-
lightpink: [
|
|
682
|
-
255,
|
|
683
|
-
182,
|
|
684
|
-
193
|
|
685
|
-
],
|
|
686
|
-
lightsalmon: [
|
|
687
|
-
255,
|
|
688
|
-
160,
|
|
689
|
-
122
|
|
690
|
-
],
|
|
691
|
-
lightseagreen: [
|
|
692
|
-
32,
|
|
693
|
-
178,
|
|
694
|
-
170
|
|
695
|
-
],
|
|
696
|
-
lightskyblue: [
|
|
697
|
-
135,
|
|
698
|
-
206,
|
|
699
|
-
250
|
|
700
|
-
],
|
|
701
|
-
lightslategray: [
|
|
702
|
-
119,
|
|
703
|
-
136,
|
|
704
|
-
153
|
|
705
|
-
],
|
|
706
|
-
lightslategrey: [
|
|
707
|
-
119,
|
|
708
|
-
136,
|
|
709
|
-
153
|
|
710
|
-
],
|
|
711
|
-
lightsteelblue: [
|
|
712
|
-
176,
|
|
713
|
-
196,
|
|
714
|
-
222
|
|
715
|
-
],
|
|
716
|
-
lightyellow: [
|
|
717
|
-
255,
|
|
718
|
-
255,
|
|
719
|
-
224
|
|
720
|
-
],
|
|
721
|
-
lime: [
|
|
722
|
-
0,
|
|
723
|
-
255,
|
|
724
|
-
0
|
|
725
|
-
],
|
|
726
|
-
limegreen: [
|
|
727
|
-
50,
|
|
728
|
-
205,
|
|
729
|
-
50
|
|
730
|
-
],
|
|
731
|
-
linen: [
|
|
732
|
-
250,
|
|
733
|
-
240,
|
|
734
|
-
230
|
|
735
|
-
],
|
|
736
|
-
magenta: [
|
|
737
|
-
255,
|
|
738
|
-
0,
|
|
739
|
-
255
|
|
740
|
-
],
|
|
741
|
-
maroon: [
|
|
742
|
-
128,
|
|
743
|
-
0,
|
|
744
|
-
0
|
|
745
|
-
],
|
|
746
|
-
mediumaquamarine: [
|
|
747
|
-
102,
|
|
748
|
-
205,
|
|
749
|
-
170
|
|
750
|
-
],
|
|
751
|
-
mediumblue: [
|
|
752
|
-
0,
|
|
753
|
-
0,
|
|
754
|
-
205
|
|
755
|
-
],
|
|
756
|
-
mediumorchid: [
|
|
757
|
-
186,
|
|
758
|
-
85,
|
|
759
|
-
211
|
|
760
|
-
],
|
|
761
|
-
mediumpurple: [
|
|
762
|
-
147,
|
|
763
|
-
112,
|
|
764
|
-
219
|
|
765
|
-
],
|
|
766
|
-
mediumseagreen: [
|
|
767
|
-
60,
|
|
768
|
-
179,
|
|
769
|
-
113
|
|
770
|
-
],
|
|
771
|
-
mediumslateblue: [
|
|
772
|
-
123,
|
|
773
|
-
104,
|
|
774
|
-
238
|
|
775
|
-
],
|
|
776
|
-
mediumspringgreen: [
|
|
777
|
-
0,
|
|
778
|
-
250,
|
|
779
|
-
154
|
|
780
|
-
],
|
|
781
|
-
mediumturquoise: [
|
|
782
|
-
72,
|
|
783
|
-
209,
|
|
784
|
-
204
|
|
785
|
-
],
|
|
786
|
-
mediumvioletred: [
|
|
787
|
-
199,
|
|
788
|
-
21,
|
|
789
|
-
133
|
|
790
|
-
],
|
|
791
|
-
midnightblue: [
|
|
792
|
-
25,
|
|
793
|
-
25,
|
|
794
|
-
112
|
|
795
|
-
],
|
|
796
|
-
mintcream: [
|
|
797
|
-
245,
|
|
798
|
-
255,
|
|
799
|
-
250
|
|
800
|
-
],
|
|
801
|
-
mistyrose: [
|
|
802
|
-
255,
|
|
803
|
-
228,
|
|
804
|
-
225
|
|
805
|
-
],
|
|
806
|
-
moccasin: [
|
|
807
|
-
255,
|
|
808
|
-
228,
|
|
809
|
-
181
|
|
810
|
-
],
|
|
811
|
-
navajowhite: [
|
|
812
|
-
255,
|
|
813
|
-
222,
|
|
814
|
-
173
|
|
815
|
-
],
|
|
816
|
-
navy: [
|
|
817
|
-
0,
|
|
818
|
-
0,
|
|
819
|
-
128
|
|
820
|
-
],
|
|
821
|
-
oldlace: [
|
|
822
|
-
253,
|
|
823
|
-
245,
|
|
824
|
-
230
|
|
825
|
-
],
|
|
826
|
-
olive: [
|
|
827
|
-
128,
|
|
828
|
-
128,
|
|
829
|
-
0
|
|
830
|
-
],
|
|
831
|
-
olivedrab: [
|
|
832
|
-
107,
|
|
833
|
-
142,
|
|
834
|
-
35
|
|
835
|
-
],
|
|
836
|
-
orange: [
|
|
837
|
-
255,
|
|
838
|
-
165,
|
|
839
|
-
0
|
|
840
|
-
],
|
|
841
|
-
orangered: [
|
|
842
|
-
255,
|
|
843
|
-
69,
|
|
844
|
-
0
|
|
845
|
-
],
|
|
846
|
-
orchid: [
|
|
847
|
-
218,
|
|
848
|
-
112,
|
|
849
|
-
214
|
|
850
|
-
],
|
|
851
|
-
palegoldenrod: [
|
|
852
|
-
238,
|
|
853
|
-
232,
|
|
854
|
-
170
|
|
855
|
-
],
|
|
856
|
-
palegreen: [
|
|
857
|
-
152,
|
|
858
|
-
251,
|
|
859
|
-
152
|
|
860
|
-
],
|
|
861
|
-
paleturquoise: [
|
|
862
|
-
175,
|
|
863
|
-
238,
|
|
864
|
-
238
|
|
865
|
-
],
|
|
866
|
-
palevioletred: [
|
|
867
|
-
219,
|
|
868
|
-
112,
|
|
869
|
-
147
|
|
870
|
-
],
|
|
871
|
-
papayawhip: [
|
|
872
|
-
255,
|
|
873
|
-
239,
|
|
874
|
-
213
|
|
875
|
-
],
|
|
876
|
-
peachpuff: [
|
|
877
|
-
255,
|
|
878
|
-
218,
|
|
879
|
-
185
|
|
880
|
-
],
|
|
881
|
-
peru: [
|
|
882
|
-
205,
|
|
883
|
-
133,
|
|
884
|
-
63
|
|
885
|
-
],
|
|
886
|
-
pink: [
|
|
887
|
-
255,
|
|
888
|
-
192,
|
|
889
|
-
203
|
|
890
|
-
],
|
|
891
|
-
plum: [
|
|
892
|
-
221,
|
|
893
|
-
160,
|
|
894
|
-
221
|
|
895
|
-
],
|
|
896
|
-
powderblue: [
|
|
897
|
-
176,
|
|
898
|
-
224,
|
|
899
|
-
230
|
|
900
|
-
],
|
|
901
|
-
purple: [
|
|
902
|
-
128,
|
|
903
|
-
0,
|
|
904
|
-
128
|
|
905
|
-
],
|
|
906
|
-
rebeccapurple: [
|
|
907
|
-
102,
|
|
908
|
-
51,
|
|
909
|
-
153
|
|
910
|
-
],
|
|
911
|
-
red: [
|
|
912
|
-
255,
|
|
913
|
-
0,
|
|
914
|
-
0
|
|
915
|
-
],
|
|
916
|
-
rosybrown: [
|
|
917
|
-
188,
|
|
918
|
-
143,
|
|
919
|
-
143
|
|
920
|
-
],
|
|
921
|
-
royalblue: [
|
|
922
|
-
65,
|
|
923
|
-
105,
|
|
924
|
-
225
|
|
925
|
-
],
|
|
926
|
-
saddlebrown: [
|
|
927
|
-
139,
|
|
928
|
-
69,
|
|
929
|
-
19
|
|
930
|
-
],
|
|
931
|
-
salmon: [
|
|
932
|
-
250,
|
|
933
|
-
128,
|
|
934
|
-
114
|
|
935
|
-
],
|
|
936
|
-
sandybrown: [
|
|
937
|
-
244,
|
|
938
|
-
164,
|
|
939
|
-
96
|
|
940
|
-
],
|
|
941
|
-
seagreen: [
|
|
942
|
-
46,
|
|
943
|
-
139,
|
|
944
|
-
87
|
|
945
|
-
],
|
|
946
|
-
seashell: [
|
|
947
|
-
255,
|
|
948
|
-
245,
|
|
949
|
-
238
|
|
950
|
-
],
|
|
951
|
-
sienna: [
|
|
952
|
-
160,
|
|
953
|
-
82,
|
|
954
|
-
45
|
|
955
|
-
],
|
|
956
|
-
silver: [
|
|
957
|
-
192,
|
|
958
|
-
192,
|
|
959
|
-
192
|
|
960
|
-
],
|
|
961
|
-
skyblue: [
|
|
962
|
-
135,
|
|
963
|
-
206,
|
|
964
|
-
235
|
|
965
|
-
],
|
|
966
|
-
slateblue: [
|
|
967
|
-
106,
|
|
968
|
-
90,
|
|
969
|
-
205
|
|
970
|
-
],
|
|
971
|
-
slategray: [
|
|
972
|
-
112,
|
|
973
|
-
128,
|
|
974
|
-
144
|
|
975
|
-
],
|
|
976
|
-
slategrey: [
|
|
977
|
-
112,
|
|
978
|
-
128,
|
|
979
|
-
144
|
|
980
|
-
],
|
|
981
|
-
snow: [
|
|
982
|
-
255,
|
|
983
|
-
250,
|
|
984
|
-
250
|
|
985
|
-
],
|
|
986
|
-
springgreen: [
|
|
987
|
-
0,
|
|
988
|
-
255,
|
|
989
|
-
127
|
|
990
|
-
],
|
|
991
|
-
steelblue: [
|
|
992
|
-
70,
|
|
993
|
-
130,
|
|
994
|
-
180
|
|
995
|
-
],
|
|
996
|
-
tan: [
|
|
997
|
-
210,
|
|
998
|
-
180,
|
|
999
|
-
140
|
|
1000
|
-
],
|
|
1001
|
-
teal: [
|
|
1002
|
-
0,
|
|
1003
|
-
128,
|
|
1004
|
-
128
|
|
1005
|
-
],
|
|
1006
|
-
thistle: [
|
|
1007
|
-
216,
|
|
1008
|
-
191,
|
|
1009
|
-
216
|
|
1010
|
-
],
|
|
1011
|
-
tomato: [
|
|
1012
|
-
255,
|
|
1013
|
-
99,
|
|
1014
|
-
71
|
|
1015
|
-
],
|
|
1016
|
-
turquoise: [
|
|
1017
|
-
64,
|
|
1018
|
-
224,
|
|
1019
|
-
208
|
|
1020
|
-
],
|
|
1021
|
-
violet: [
|
|
1022
|
-
238,
|
|
1023
|
-
130,
|
|
1024
|
-
238
|
|
1025
|
-
],
|
|
1026
|
-
wheat: [
|
|
1027
|
-
245,
|
|
1028
|
-
222,
|
|
1029
|
-
179
|
|
1030
|
-
],
|
|
1031
|
-
white: [
|
|
1032
|
-
255,
|
|
1033
|
-
255,
|
|
1034
|
-
255
|
|
1035
|
-
],
|
|
1036
|
-
whitesmoke: [
|
|
1037
|
-
245,
|
|
1038
|
-
245,
|
|
1039
|
-
245
|
|
1040
|
-
],
|
|
1041
|
-
yellow: [
|
|
1042
|
-
255,
|
|
1043
|
-
255,
|
|
1044
|
-
0
|
|
1045
|
-
],
|
|
1046
|
-
yellowgreen: [
|
|
1047
|
-
154,
|
|
1048
|
-
205,
|
|
1049
|
-
50
|
|
1050
|
-
]
|
|
1051
|
-
};
|
|
1052
276
|
/**
|
|
1053
277
|
* Apply an ANSI style pair to a string with nesting-safe composition.
|
|
1054
278
|
*
|
|
@@ -1081,422 +305,57 @@ function applyStyle(text, style) {
|
|
|
1081
305
|
if (result.includes(close)) result = result.replaceAll(close, close + open);
|
|
1082
306
|
return open + result + close;
|
|
1083
307
|
}
|
|
1084
|
-
/** Foreground close: matches the close of every static fg color (`\x1b[39m`). */
|
|
1085
|
-
const FG_CLOSE = "\x1B[39m";
|
|
1086
|
-
/** Background close: matches the close of every static bg color (`\x1b[49m`). */
|
|
1087
|
-
const BG_CLOSE = "\x1B[49m";
|
|
1088
|
-
/** Foreground/background extended-color SGR introducers. */
|
|
1089
|
-
const FG_INTRODUCER = "\x1B[38;";
|
|
1090
|
-
const BG_INTRODUCER = "\x1B[48;";
|
|
1091
|
-
/** Quote supported inputs, falling back to `String()` for hostile runtime values. */
|
|
1092
|
-
function describeInput(input) {
|
|
1093
|
-
try {
|
|
1094
|
-
return JSON.stringify(input) ?? String(input);
|
|
1095
|
-
} catch {
|
|
1096
|
-
return String(input);
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
function isNamedColor(value) {
|
|
1100
|
-
return Object.hasOwn(namedColorValues, value);
|
|
1101
|
-
}
|
|
1102
|
-
/** Parse a supported color into an RGB triple. */
|
|
1103
|
-
function parseRgb(input) {
|
|
1104
|
-
if (Array.isArray(input)) {
|
|
1105
|
-
if (input.length === 3 && input.every((channel) => Number.isInteger(channel) && channel >= 0 && channel <= 255)) return [
|
|
1106
|
-
input[0],
|
|
1107
|
-
input[1],
|
|
1108
|
-
input[2]
|
|
1109
|
-
];
|
|
1110
|
-
} else if (typeof input === "string") {
|
|
1111
|
-
const value = input.toLowerCase();
|
|
1112
|
-
if (isNamedColor(value)) return namedColorValues[value];
|
|
1113
|
-
const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(value)?.[1];
|
|
1114
|
-
if (hex) {
|
|
1115
|
-
const expanded = hex.length === 3 ? hex.split("").map((digit) => digit + digit).join("") : hex;
|
|
1116
|
-
return [
|
|
1117
|
-
Number.parseInt(expanded.slice(0, 2), 16),
|
|
1118
|
-
Number.parseInt(expanded.slice(2, 4), 16),
|
|
1119
|
-
Number.parseInt(expanded.slice(4, 6), 16)
|
|
1120
|
-
];
|
|
1121
|
-
}
|
|
1122
|
-
const rgb = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/.exec(value) ?? /^rgb\(\s*(\d{1,3})\s+(\d{1,3})\s+(\d{1,3})\s*\)$/.exec(value);
|
|
1123
|
-
if (rgb) {
|
|
1124
|
-
const channels = [
|
|
1125
|
-
Number(rgb[1]),
|
|
1126
|
-
Number(rgb[2]),
|
|
1127
|
-
Number(rgb[3])
|
|
1128
|
-
];
|
|
1129
|
-
if (channels.every((channel) => channel <= 255)) return channels;
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
throw new TypeError(`Invalid color input: ${describeInput(input)}`);
|
|
1133
|
-
}
|
|
1134
|
-
function rgbToAnsi256(r, g, b) {
|
|
1135
|
-
const levels = [
|
|
1136
|
-
0,
|
|
1137
|
-
95,
|
|
1138
|
-
135,
|
|
1139
|
-
175,
|
|
1140
|
-
215,
|
|
1141
|
-
255
|
|
1142
|
-
];
|
|
1143
|
-
const nearest = (channel) => levels.reduce((best, value, index) => Math.abs(value - channel) < Math.abs(levels[best] - channel) ? index : best, 0);
|
|
1144
|
-
const [ir, ig, ib] = [
|
|
1145
|
-
nearest(r),
|
|
1146
|
-
nearest(g),
|
|
1147
|
-
nearest(b)
|
|
1148
|
-
];
|
|
1149
|
-
const grayIndex = Math.min(23, Math.max(0, Math.round(((r + g + b) / 3 - 8) / 10)));
|
|
1150
|
-
const gray = 8 + grayIndex * 10;
|
|
1151
|
-
const distance = (cr, cg, cb) => (r - cr) ** 2 + (g - cg) ** 2 + (b - cb) ** 2;
|
|
1152
|
-
return distance(gray, gray, gray) < distance(levels[ir], levels[ig], levels[ib]) ? 232 + grayIndex : 16 + 36 * ir + 6 * ig + ib;
|
|
1153
|
-
}
|
|
1154
|
-
/**
|
|
1155
|
-
* Quantize `[r, g, b]` to a foreground SGR parameter (`30`–`37`, `90`–`97`).
|
|
1156
|
-
* Same algorithm as `ansi-styles` / `chalk`: bucket each channel at 50%,
|
|
1157
|
-
* pack into a 3-bit base color, then add 60 for bright when the max
|
|
1158
|
-
* channel rounds up. Call sites add `+10` for backgrounds.
|
|
1159
|
-
*/
|
|
1160
|
-
function rgbToAnsi16Param(r, g, b) {
|
|
1161
|
-
const brightnessBucket = Math.round(Math.max(r, g, b) / 127.5);
|
|
1162
|
-
if (brightnessBucket === 0) return 30;
|
|
1163
|
-
let ansi = 30 + ((Math.round(b / 255) << 2 | Math.round(g / 255) << 1 | Math.round(r / 255)) & 7);
|
|
1164
|
-
if (brightnessBucket === 2) ansi += 60;
|
|
1165
|
-
return ansi;
|
|
1166
|
-
}
|
|
1167
|
-
/**
|
|
1168
|
-
* Foreground SGR open sequence at `depth`.
|
|
1169
|
-
*/
|
|
1170
|
-
function fgOpen(input, depth) {
|
|
1171
|
-
const [r, g, b] = parseRgb(input);
|
|
1172
|
-
if (depth === "16") return `\x1b[${rgbToAnsi16Param(r, g, b)}m`;
|
|
1173
|
-
if (depth === "256") return `\x1b[38;5;${rgbToAnsi256(r, g, b)}m`;
|
|
1174
|
-
return `\x1b[38;2;${r};${g};${b}m`;
|
|
1175
|
-
}
|
|
1176
|
-
/**
|
|
1177
|
-
* Background SGR open sequence at `depth`. For `truecolor` / `256`,
|
|
1178
|
-
* derived from {@link fgOpen} by swapping the `\x1b[38;` introducer for
|
|
1179
|
-
* `\x1b[48;` (both the truecolor and 256-color forms use it). For `16`,
|
|
1180
|
-
* quantized directly to a real background SGR.
|
|
1181
|
-
*/
|
|
1182
|
-
function bgOpen(input, depth) {
|
|
1183
|
-
if (depth === "16") {
|
|
1184
|
-
const [r, g, b] = parseRgb(input);
|
|
1185
|
-
return `\x1b[${rgbToAnsi16Param(r, g, b) + 10}m`;
|
|
1186
|
-
}
|
|
1187
|
-
return fgOpen(input, depth).replace(FG_INTRODUCER, BG_INTRODUCER);
|
|
1188
|
-
}
|
|
1189
|
-
function colorPair(kind, input, depth) {
|
|
1190
|
-
if (depth === "none") {
|
|
1191
|
-
parseRgb(input);
|
|
1192
|
-
return {
|
|
1193
|
-
open: "",
|
|
1194
|
-
close: ""
|
|
1195
|
-
};
|
|
1196
|
-
}
|
|
1197
|
-
return {
|
|
1198
|
-
open: kind === "fg" ? fgOpen(input, depth) : bgOpen(input, depth),
|
|
1199
|
-
close: kind === "fg" ? FG_CLOSE : BG_CLOSE
|
|
1200
|
-
};
|
|
1201
|
-
}
|
|
1202
|
-
function paint(kind, text, input, depth) {
|
|
1203
|
-
const pair = colorPair(kind, input, depth);
|
|
1204
|
-
return depth === "none" ? text : applyStyle(text, pair);
|
|
1205
|
-
}
|
|
1206
|
-
const OSC = "\x1B]";
|
|
1207
|
-
const ST = "\x1B\\";
|
|
1208
|
-
const HYPERLINK_CLOSE = `${OSC}8;;${ST}`;
|
|
1209
|
-
function assertMatches(value, label, pattern, suffix = "") {
|
|
1210
|
-
if (!pattern.test(value)) throw new TypeError(`Invalid ${label}: ${JSON.stringify(value)} must contain only printable ASCII characters${suffix}.`);
|
|
1211
|
-
}
|
|
1212
|
-
function serializeParams(options) {
|
|
1213
|
-
const id = options?.id;
|
|
1214
|
-
if (id === void 0 || id === "") return "";
|
|
1215
|
-
assertMatches(id, "hyperlink id", /^[\x20-\x7e]*$/);
|
|
1216
|
-
if (id.includes(":") || id.includes(";")) throw new TypeError("Invalid hyperlink id: \":\" and \";\" are reserved by the OSC 8 format.");
|
|
1217
|
-
return `id=${id}`;
|
|
1218
|
-
}
|
|
1219
|
-
/**
|
|
1220
|
-
* Create an OSC 8 hyperlink escape pair for `url`. Backs {@link link} and
|
|
1221
|
-
* the `link` method on style instances; also used to validate URLs when
|
|
1222
|
-
* hyperlink emission is disabled.
|
|
1223
|
-
*
|
|
1224
|
-
* @param url - Target URL. Must contain only printable ASCII characters
|
|
1225
|
-
* and no spaces (per the OSC 8 spec). URL-encode characters outside
|
|
1226
|
-
* that range before passing.
|
|
1227
|
-
* @param options - Optional {@link HyperlinkOptions} — currently just
|
|
1228
|
-
* `id` for grouping multi-segment links.
|
|
1229
|
-
* @returns An {@link AnsiPair} whose `open` carries the URL and `close`
|
|
1230
|
-
* terminates the hyperlink.
|
|
1231
|
-
* @throws {TypeError} If `url` contains spaces or non-printable ASCII,
|
|
1232
|
-
* or if `options.id` contains `":"` / `";"` (reserved by OSC 8) or
|
|
1233
|
-
* non-printable characters.
|
|
1234
|
-
*
|
|
1235
|
-
* @internal
|
|
1236
|
-
*/
|
|
1237
|
-
function linkCode(url, options) {
|
|
1238
|
-
assertMatches(url, "hyperlink URL", /^[\x21-\x7e]*$/, " without spaces");
|
|
1239
|
-
const params = serializeParams(options);
|
|
1240
|
-
return {
|
|
1241
|
-
open: `${OSC}8;${params};${url}${ST}`,
|
|
1242
|
-
close: HYPERLINK_CLOSE
|
|
1243
|
-
};
|
|
1244
|
-
}
|
|
1245
|
-
/**
|
|
1246
|
-
* Wrap `text` in OSC 8 hyperlink escape sequences.
|
|
1247
|
-
*
|
|
1248
|
-
* @param text - The visible label.
|
|
1249
|
-
* @param url - Target URL. Must contain only printable ASCII characters
|
|
1250
|
-
* and no spaces (per the OSC 8 spec); URL-encode anything outside that
|
|
1251
|
-
* range before passing.
|
|
1252
|
-
* @param options - Optional {@link HyperlinkOptions}.
|
|
1253
|
-
* @returns The styled string.
|
|
1254
|
-
* @throws {TypeError} If `url` contains spaces or non-printable ASCII,
|
|
1255
|
-
* or if `options.id` contains `":"` / `";"` (reserved by OSC 8) or
|
|
1256
|
-
* non-printable characters.
|
|
1257
|
-
*
|
|
1258
|
-
* @example
|
|
1259
|
-
* ```ts
|
|
1260
|
-
* import { link } from "@crustjs/style";
|
|
1261
|
-
*
|
|
1262
|
-
* console.log(link("docs", "https://crustjs.com"));
|
|
1263
|
-
* console.log(link("page 1", "https://example.com/p1", { id: "intro" }));
|
|
1264
|
-
* ```
|
|
1265
|
-
*/
|
|
1266
|
-
function link$1(text, url, options) {
|
|
1267
|
-
return applyStyle(text, linkCode(url, options));
|
|
1268
|
-
}
|
|
1269
|
-
const dynamicColorKinds = ["fg", "bg"];
|
|
1270
|
-
function stepIsModifier(step) {
|
|
1271
|
-
return step.kind === "named" && isModifierName(step.name);
|
|
1272
|
-
}
|
|
1273
|
-
function stepPair(step, colorDepth) {
|
|
1274
|
-
return step.kind === "named" ? styleMethodPairs[step.name] : colorPair(step.kind, step.input, colorDepth);
|
|
1275
|
-
}
|
|
1276
|
-
function colorStep(kind, input) {
|
|
1277
|
-
const step = {
|
|
1278
|
-
kind,
|
|
1279
|
-
input
|
|
1280
|
-
};
|
|
1281
|
-
stepPair(step, "truecolor");
|
|
1282
|
-
return Array.isArray(input) ? {
|
|
1283
|
-
kind,
|
|
1284
|
-
input: [
|
|
1285
|
-
input[0],
|
|
1286
|
-
input[1],
|
|
1287
|
-
input[2]
|
|
1288
|
-
]
|
|
1289
|
-
} : step;
|
|
1290
|
-
}
|
|
1291
|
-
function applyChain(text, steps, resolveCapabilities) {
|
|
1292
|
-
if (text == null) return "";
|
|
1293
|
-
let result = String(text);
|
|
1294
|
-
if (result === "") return result;
|
|
1295
|
-
const capabilities = resolveCapabilities();
|
|
1296
|
-
const { modifiersEnabled, colorsEnabled } = capabilities;
|
|
1297
|
-
for (let i = steps.length - 1; i >= 0; i--) {
|
|
1298
|
-
const step = steps[i];
|
|
1299
|
-
if (step === void 0) continue;
|
|
1300
|
-
if (stepIsModifier(step) ? !modifiersEnabled : !colorsEnabled) continue;
|
|
1301
|
-
result = applyStyle(result, stepPair(step, capabilities.colorDepth));
|
|
1302
|
-
}
|
|
1303
|
-
return result;
|
|
1304
|
-
}
|
|
1305
308
|
function isTemplateStringsArray(value) {
|
|
1306
309
|
return Array.isArray(value) && "raw" in value && Array.isArray(value.raw);
|
|
1307
310
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
text += first[i] ?? "";
|
|
1320
|
-
if (i < rest.length) text += String(rest[i]);
|
|
1321
|
-
}
|
|
1322
|
-
return applyChain(text, steps, resolveCapabilities);
|
|
1323
|
-
}
|
|
1324
|
-
return applyChain(first, steps, resolveCapabilities);
|
|
1325
|
-
});
|
|
1326
|
-
if (cache.size >= 1024) cache.delete(cache.keys().next().value);
|
|
1327
|
-
cache.set(key, styleFn);
|
|
1328
|
-
for (const name of styleMethodNames) Object.defineProperty(styleFn, name, {
|
|
1329
|
-
configurable: false,
|
|
1330
|
-
enumerable: true,
|
|
1331
|
-
get() {
|
|
1332
|
-
return createChainableStyle([...steps, {
|
|
1333
|
-
kind: "named",
|
|
1334
|
-
name
|
|
1335
|
-
}]);
|
|
1336
|
-
}
|
|
1337
|
-
});
|
|
1338
|
-
for (const kind of dynamicColorKinds) Object.defineProperty(styleFn, kind, {
|
|
1339
|
-
configurable: false,
|
|
1340
|
-
enumerable: true,
|
|
1341
|
-
value: (input) => createChainableStyle([...steps, colorStep(kind, input)]),
|
|
1342
|
-
writable: false
|
|
1343
|
-
});
|
|
1344
|
-
let open = "";
|
|
1345
|
-
let close = "";
|
|
1346
|
-
for (const step of steps) {
|
|
1347
|
-
const pair = stepPair(step, pairDepth);
|
|
1348
|
-
open += pair.open;
|
|
1349
|
-
close = pair.close + close;
|
|
1350
|
-
}
|
|
1351
|
-
Object.defineProperty(styleFn, "open", {
|
|
1352
|
-
value: open,
|
|
1353
|
-
writable: false,
|
|
1354
|
-
configurable: false,
|
|
1355
|
-
enumerable: true
|
|
1356
|
-
});
|
|
1357
|
-
Object.defineProperty(styleFn, "close", {
|
|
1358
|
-
value: close,
|
|
1359
|
-
writable: false,
|
|
1360
|
-
configurable: false,
|
|
1361
|
-
enumerable: true
|
|
1362
|
-
});
|
|
1363
|
-
return Object.freeze(styleFn);
|
|
311
|
+
/**
|
|
312
|
+
* Resolve the text of a style function call: a direct `fn(text)` call passes
|
|
313
|
+
* `text` through; a tagged template `` fn`a ${b}` `` joins its cooked strings
|
|
314
|
+
* with each value coerced via `String(...)`.
|
|
315
|
+
*/
|
|
316
|
+
function callText(first, values) {
|
|
317
|
+
if (!isTemplateStringsArray(first)) return first;
|
|
318
|
+
let text = "";
|
|
319
|
+
for (let i = 0; i < first.length; i++) {
|
|
320
|
+
text += first[i] ?? "";
|
|
321
|
+
if (i < values.length) text += String(values[i]);
|
|
1364
322
|
}
|
|
1365
|
-
return
|
|
1366
|
-
}
|
|
1367
|
-
function buildStyleMethods(createChainableStyle) {
|
|
1368
|
-
const methods = {};
|
|
1369
|
-
for (const methodName of styleMethodNames) methods[methodName] = createChainableStyle([{
|
|
1370
|
-
kind: "named",
|
|
1371
|
-
name: methodName
|
|
1372
|
-
}]);
|
|
1373
|
-
return methods;
|
|
1374
|
-
}
|
|
1375
|
-
function resolveStyleCapabilities(options) {
|
|
1376
|
-
const mode = options?.mode ?? "auto";
|
|
1377
|
-
const modifiersEnabled = resolveModifierCapability(mode, options?.overrides);
|
|
1378
|
-
const colorDepth = resolveColorDepth(mode, options?.overrides);
|
|
1379
|
-
return {
|
|
1380
|
-
modifiersEnabled,
|
|
1381
|
-
colorDepth,
|
|
1382
|
-
colorsEnabled: colorDepth !== "none",
|
|
1383
|
-
trueColorEnabled: colorDepth === "truecolor"
|
|
1384
|
-
};
|
|
323
|
+
return text;
|
|
1385
324
|
}
|
|
1386
|
-
function
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
const createChainableStyle = buildChainableStyleFactory(resolveCapabilities, runtime);
|
|
1392
|
-
const methods = buildStyleMethods(createChainableStyle);
|
|
1393
|
-
const instance = {
|
|
1394
|
-
get enabled() {
|
|
1395
|
-
const { modifiersEnabled, colorsEnabled } = resolveCapabilities();
|
|
1396
|
-
return modifiersEnabled || colorsEnabled;
|
|
1397
|
-
},
|
|
1398
|
-
get colorsEnabled() {
|
|
1399
|
-
return resolveCapabilities().colorsEnabled;
|
|
1400
|
-
},
|
|
1401
|
-
get trueColorEnabled() {
|
|
1402
|
-
return resolveCapabilities().trueColorEnabled;
|
|
1403
|
-
},
|
|
1404
|
-
get colorDepth() {
|
|
1405
|
-
return resolveCapabilities().colorDepth;
|
|
1406
|
-
},
|
|
1407
|
-
link(text, url, hyperlinkOptions) {
|
|
1408
|
-
if (resolveCapabilities().modifiersEnabled) return link$1(text, url, hyperlinkOptions);
|
|
1409
|
-
linkCode(url, hyperlinkOptions);
|
|
1410
|
-
return text;
|
|
1411
|
-
},
|
|
1412
|
-
...Object.fromEntries(dynamicColorKinds.map((kind) => [kind, (...args) => {
|
|
1413
|
-
if (args.length === 1) return createChainableStyle([colorStep(kind, args[0])]);
|
|
1414
|
-
return paint(kind, args[0], args[1], resolveCapabilities().colorDepth);
|
|
1415
|
-
}])),
|
|
1416
|
-
...methods
|
|
325
|
+
/** A plain (non-chaining) style function that applies `pair` while `enabled()` is true. */
|
|
326
|
+
function plainStyleFn(pair, enabled) {
|
|
327
|
+
return (first, ...values) => {
|
|
328
|
+
const text = callText(first, values);
|
|
329
|
+
return enabled() ? applyStyle(text, pair) : text == null ? "" : String(text);
|
|
1417
330
|
};
|
|
1418
|
-
return Object.freeze(instance);
|
|
1419
331
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
*
|
|
1428
|
-
* @example
|
|
1429
|
-
* ```ts
|
|
1430
|
-
* import { style } from "@crustjs/style";
|
|
1431
|
-
*
|
|
1432
|
-
* console.log(style.bold("hello"));
|
|
1433
|
-
* console.log(style.red("error"));
|
|
1434
|
-
* ```
|
|
1435
|
-
*/
|
|
1436
|
-
const style = createStyleInstance(void 0, true);
|
|
1437
|
-
style.black;
|
|
1438
|
-
style.red;
|
|
1439
|
-
const green = style.green;
|
|
1440
|
-
const yellow = style.yellow;
|
|
1441
|
-
style.blue;
|
|
1442
|
-
style.magenta;
|
|
1443
|
-
const cyan = style.cyan;
|
|
1444
|
-
style.white;
|
|
1445
|
-
style.gray;
|
|
1446
|
-
style.brightRed;
|
|
1447
|
-
style.brightGreen;
|
|
1448
|
-
style.brightYellow;
|
|
1449
|
-
style.brightBlue;
|
|
1450
|
-
style.brightMagenta;
|
|
1451
|
-
style.brightCyan;
|
|
1452
|
-
style.brightWhite;
|
|
1453
|
-
style.bgBlack;
|
|
1454
|
-
style.bgRed;
|
|
1455
|
-
style.bgGreen;
|
|
1456
|
-
style.bgYellow;
|
|
1457
|
-
style.bgBlue;
|
|
1458
|
-
style.bgMagenta;
|
|
1459
|
-
style.bgCyan;
|
|
1460
|
-
style.bgWhite;
|
|
1461
|
-
style.bgBrightBlack;
|
|
1462
|
-
style.bgBrightRed;
|
|
1463
|
-
style.bgBrightGreen;
|
|
1464
|
-
style.bgBrightYellow;
|
|
1465
|
-
style.bgBrightBlue;
|
|
1466
|
-
style.bgBrightMagenta;
|
|
1467
|
-
style.bgBrightCyan;
|
|
1468
|
-
style.bgBrightWhite;
|
|
1469
|
-
const bold = style.bold;
|
|
1470
|
-
const dim = style.dim;
|
|
1471
|
-
style.italic;
|
|
1472
|
-
style.underline;
|
|
1473
|
-
style.inverse;
|
|
1474
|
-
style.hidden;
|
|
1475
|
-
style.strikethrough;
|
|
1476
|
-
style.link;
|
|
1477
|
-
style.fg;
|
|
1478
|
-
style.bg;
|
|
1479
|
-
//#endregion
|
|
1480
|
-
//#region ../utils/dist/error.js
|
|
1481
|
-
/** Narrows a caught Node.js system error to its stable errno contract. */
|
|
1482
|
-
function isErrnoException(error) {
|
|
1483
|
-
return error instanceof Error && "code" in error && typeof error.code === "string";
|
|
1484
|
-
}
|
|
1485
|
-
//#endregion
|
|
1486
|
-
//#region ../utils/dist/json.js
|
|
1487
|
-
/** Narrow a JSON document root to an object (not array/scalar/null). */
|
|
1488
|
-
function isJsonObject(value) {
|
|
1489
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
332
|
+
const modifiersEnabled = () => resolveModifierCapability("auto");
|
|
333
|
+
const colorsEnabled = () => resolveColorDepth("auto") !== "none";
|
|
334
|
+
function modifier(open, close) {
|
|
335
|
+
return plainStyleFn({
|
|
336
|
+
open: `\x1b[${open}m`,
|
|
337
|
+
close: `\x1b[${close}m`
|
|
338
|
+
}, modifiersEnabled);
|
|
1490
339
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
340
|
+
function color(open, close) {
|
|
341
|
+
return plainStyleFn({
|
|
342
|
+
open: `\x1b[${open}m`,
|
|
343
|
+
close: `\x1b[${close}m`
|
|
344
|
+
}, colorsEnabled);
|
|
345
|
+
}
|
|
346
|
+
const green = /* @__PURE__ */ color(32, 39);
|
|
347
|
+
const yellow = /* @__PURE__ */ color(33, 39);
|
|
348
|
+
const cyan = /* @__PURE__ */ color(36, 39);
|
|
349
|
+
const bold = /* @__PURE__ */ modifier(1, 22);
|
|
350
|
+
const dim = /* @__PURE__ */ modifier(2, 22);
|
|
351
|
+
// ../utils/dist/path.js
|
|
1493
352
|
/** Returns whether child is parent itself or lies below it. */
|
|
1494
353
|
function isWithin(parent, child) {
|
|
354
|
+
const { isAbsolute, relative, sep } = process.getBuiltinModule("node:path");
|
|
1495
355
|
const path = relative(parent, child);
|
|
1496
356
|
return path === "" || !isAbsolute(path) && path !== ".." && !path.startsWith(`..${sep}`);
|
|
1497
357
|
}
|
|
1498
|
-
|
|
1499
|
-
//#region src/artifacts.ts
|
|
358
|
+
// src/artifacts.ts
|
|
1500
359
|
/**
|
|
1501
360
|
* `crust.include` directories normalized to cwd-relative POSIX names. They are
|
|
1502
361
|
* staged exactly like Extension artifacts.
|
|
@@ -1525,20 +384,35 @@ function collectIncludeDirs(cwd, stageDir, include, artifactNames) {
|
|
|
1525
384
|
return includeDirs;
|
|
1526
385
|
}
|
|
1527
386
|
/**
|
|
387
|
+
* Names a template ships on purpose that `npm pack`/`npm publish` drop from
|
|
388
|
+
* every directory of a package whatever its `files` says, in any letter case.
|
|
389
|
+
* A dropped `.gitignore` or `.npmignore` also acts as ignore rules for its own
|
|
390
|
+
* directory. The rest of npm's ignore list (`.DS_Store`, `*.orig`, …) is junk
|
|
391
|
+
* nobody means to publish, so it stays silently dropped.
|
|
392
|
+
*/
|
|
393
|
+
const NPM_DROPPED_NAME = /^\.(?:gitignore|npmignore|npmrc)$/i;
|
|
394
|
+
/**
|
|
1528
395
|
* Walks `dir` the way the dereferencing copy will (through symlinked
|
|
1529
|
-
* directories) and rejects any path whose real location leaves the project
|
|
396
|
+
* directories) and rejects any path whose real location leaves the project,
|
|
397
|
+
* and any {@link NPM_DROPPED_NAME} name.
|
|
1530
398
|
*/
|
|
1531
399
|
function assertResolvesInsideProject(cwd, entry, dir) {
|
|
1532
400
|
const realCwd = realpathSync(cwd);
|
|
1533
401
|
const seen = /* @__PURE__ */ new Set();
|
|
402
|
+
const npmDropped = [];
|
|
1534
403
|
const walk = (path) => {
|
|
1535
404
|
const real = realpathSync(path);
|
|
1536
405
|
if (!isWithin(realCwd, real)) throw new Error(`package.json crust.include entry ${JSON.stringify(entry)} resolves outside the project root: ${relative(cwd, path)} -> ${real}`);
|
|
406
|
+
if (NPM_DROPPED_NAME.test(basename(path))) npmDropped.push(relative(cwd, path));
|
|
1537
407
|
if (seen.has(real) || !statSync(path).isDirectory()) return;
|
|
1538
408
|
seen.add(real);
|
|
1539
409
|
for (const child of readdirSync(path)) walk(join(path, child));
|
|
1540
410
|
};
|
|
1541
411
|
walk(dir);
|
|
412
|
+
if (npmDropped.length > 0) {
|
|
413
|
+
const listed = npmDropped.sort().map((path) => `\n ${path}`).join("");
|
|
414
|
+
throw new Error(`package.json crust.include entry ${JSON.stringify(entry)} contains files npm leaves out of published packages:${listed}\n Rename each (e.g. .gitignore -> _gitignore) and restore the name when your CLI copies it; scaffold() from @crustjs/create turns a leading _ on a file name into a dot.`);
|
|
415
|
+
}
|
|
1542
416
|
}
|
|
1543
417
|
/**
|
|
1544
418
|
* Copies one entry's Extension build hook output into the shared artifact
|
|
@@ -1591,8 +465,46 @@ function collectArtifacts(artifactOutDir) {
|
|
|
1591
465
|
manPages: names.includes("man") ? readdirSync(join(artifactOutDir, "man"), { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort() : []
|
|
1592
466
|
};
|
|
1593
467
|
}
|
|
1594
|
-
|
|
1595
|
-
|
|
468
|
+
// ../utils/dist/process.js
|
|
469
|
+
const LIFETIME_SIGNALS = [
|
|
470
|
+
"SIGINT",
|
|
471
|
+
"SIGTERM",
|
|
472
|
+
"SIGHUP",
|
|
473
|
+
"SIGQUIT"
|
|
474
|
+
];
|
|
475
|
+
const bindings = /* @__PURE__ */ new Set();
|
|
476
|
+
function onLifetimeSignal(signal) {
|
|
477
|
+
const pending = [...bindings];
|
|
478
|
+
bindings.clear();
|
|
479
|
+
removeLifetimeListeners();
|
|
480
|
+
for (const binding of pending) binding.onSignal(signal);
|
|
481
|
+
if (process.listenerCount(signal) === 0) process.kill(process.pid, signal);
|
|
482
|
+
}
|
|
483
|
+
function onLifetimeExit() {
|
|
484
|
+
for (const binding of bindings) binding.onExit();
|
|
485
|
+
}
|
|
486
|
+
function removeLifetimeListeners() {
|
|
487
|
+
for (const signal of LIFETIME_SIGNALS) process.removeListener(signal, onLifetimeSignal);
|
|
488
|
+
process.removeListener("exit", onLifetimeExit);
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Ties a detached POSIX child group to this process, which the group no longer shares
|
|
492
|
+
* terminal signals with. Until the returned release runs, SIGINT, SIGTERM, SIGHUP or SIGQUIT
|
|
493
|
+
* calls `onSignal` once and is then re-raised when no other listener handles it, and a
|
|
494
|
+
* synchronous exit (`process.exit`, an uncaught error) calls `onExit`. SIGKILL and native
|
|
495
|
+
* crashes cannot be observed and still orphan the group. A signal this process inherited as
|
|
496
|
+
* ignored (Bun on Linux, such as SIGHUP under `nohup`) stays ignored and is never listened for.
|
|
497
|
+
*/
|
|
498
|
+
function bindToProcessLifetime(binding) {
|
|
499
|
+
if (bindings.size === 0) {
|
|
500
|
+
for (const signal of LIFETIME_SIGNALS) if (!isSignalIgnored(signal)) process.prependListener(signal, onLifetimeSignal);
|
|
501
|
+
process.on("exit", onLifetimeExit);
|
|
502
|
+
}
|
|
503
|
+
bindings.add(binding);
|
|
504
|
+
return () => {
|
|
505
|
+
if (bindings.delete(binding) && bindings.size === 0) removeLifetimeListeners();
|
|
506
|
+
};
|
|
507
|
+
}
|
|
1596
508
|
const WINDOWS_SHELL_UNSAFE = /[\0\r\n"%!^`<>&|]/;
|
|
1597
509
|
const WINDOWS_SHELL_META = /([()\][%!^"`<>&|;, *?])/g;
|
|
1598
510
|
function escapeWindowsShellArgument(value) {
|
|
@@ -1604,7 +516,7 @@ function escapeWindowsShellArgument(value) {
|
|
|
1604
516
|
/** @internal Build Node's escaped Windows command-shim workaround. */
|
|
1605
517
|
function getWindowsShimCommand(command, args, shell, platform = process.platform) {
|
|
1606
518
|
if (shell || platform !== "win32" || !/\.(cmd|bat)$/i.test(command)) return null;
|
|
1607
|
-
const shimCommand = win32.normalize(command);
|
|
519
|
+
const shimCommand = process.getBuiltinModule("node:path").win32.normalize(command);
|
|
1608
520
|
for (const [index, value] of [shimCommand, ...args].entries()) if (WINDOWS_SHELL_UNSAFE.test(value)) {
|
|
1609
521
|
const label = index === 0 ? "command" : `argument ${index}`;
|
|
1610
522
|
throw new Error(`Windows command shim ${label} ${JSON.stringify(value)} contains unsafe shell characters`);
|
|
@@ -1630,6 +542,7 @@ function killProcessTree(child) {
|
|
|
1630
542
|
if (child.pid === void 0) return;
|
|
1631
543
|
if (process.platform === "win32") {
|
|
1632
544
|
if (child.exitCode === null && child.signalCode === null) {
|
|
545
|
+
const { spawnSync } = process.getBuiltinModule("node:child_process");
|
|
1633
546
|
const result = spawnSync("taskkill", [
|
|
1634
547
|
"/pid",
|
|
1635
548
|
String(child.pid),
|
|
@@ -1660,9 +573,12 @@ function killProcessTree(child) {
|
|
|
1660
573
|
* calls are passed through unchanged and own their shell escaping.
|
|
1661
574
|
*/
|
|
1662
575
|
async function runProcess(command, args = [], options = {}) {
|
|
576
|
+
options.signal?.throwIfAborted();
|
|
1663
577
|
const windowsShimCommand = getWindowsShimCommand(command, args, options.shell);
|
|
1664
578
|
const collect = (options.stdio ?? "collect") === "collect";
|
|
1665
579
|
const collectStdout = collect && options.stdout !== "ignore";
|
|
580
|
+
const detached = options.timeout !== void 0 && process.platform !== "win32";
|
|
581
|
+
const { spawn } = process.getBuiltinModule("node:child_process");
|
|
1666
582
|
const proc = spawn(windowsShimCommand?.command ?? command, windowsShimCommand?.args ?? args, {
|
|
1667
583
|
cwd: options.cwd,
|
|
1668
584
|
env: options.env,
|
|
@@ -1672,31 +588,54 @@ async function runProcess(command, args = [], options = {}) {
|
|
|
1672
588
|
collectStdout ? "pipe" : "ignore",
|
|
1673
589
|
"pipe"
|
|
1674
590
|
] : "inherit",
|
|
1675
|
-
detached
|
|
591
|
+
detached,
|
|
1676
592
|
windowsVerbatimArguments: windowsShimCommand?.windowsVerbatimArguments
|
|
1677
593
|
});
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
let failure = /* @__PURE__ */ new Error(`${[command, ...args].join(" ")} did not exit within ${timeout} ms and was killed.`);
|
|
594
|
+
const commandLine = [command, ...args].join(" ");
|
|
595
|
+
let stop;
|
|
596
|
+
const stopped = new Promise((_, reject) => {
|
|
597
|
+
stop = (message, reason) => {
|
|
598
|
+
let failure = new Error(message);
|
|
1684
599
|
try {
|
|
1685
600
|
killProcessTree(proc);
|
|
1686
601
|
} catch (cause) {
|
|
1687
|
-
failure = new Error(
|
|
602
|
+
failure = new Error(`Process-tree cleanup failed after ${reason}.`, { cause });
|
|
1688
603
|
}
|
|
1689
604
|
proc.stdout?.destroy();
|
|
1690
605
|
proc.stderr?.destroy();
|
|
1691
606
|
reject(failure);
|
|
1692
|
-
}
|
|
607
|
+
};
|
|
1693
608
|
});
|
|
609
|
+
const timeout = options.timeout;
|
|
610
|
+
const timer = timeout === void 0 ? void 0 : setTimeout(() => stop(`${commandLine} did not exit within ${timeout} ms and was killed.`, "timeout"), timeout);
|
|
611
|
+
const release = detached ? bindToProcessLifetime({
|
|
612
|
+
onSignal: (signal) => stop(`${commandLine} was interrupted by ${signal}.`, signal),
|
|
613
|
+
onExit: () => {
|
|
614
|
+
try {
|
|
615
|
+
killProcessTree(proc);
|
|
616
|
+
} catch {}
|
|
617
|
+
}
|
|
618
|
+
}) : () => {};
|
|
619
|
+
let forceKillTimer;
|
|
620
|
+
const onAbort = () => {
|
|
621
|
+
try {
|
|
622
|
+
if (detached || process.platform === "win32") killProcessTree(proc);
|
|
623
|
+
else {
|
|
624
|
+
proc.kill("SIGTERM");
|
|
625
|
+
forceKillTimer = setTimeout(() => proc.kill("SIGKILL"), 5e3);
|
|
626
|
+
}
|
|
627
|
+
} catch {}
|
|
628
|
+
};
|
|
629
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
630
|
+
const { text } = process.getBuiltinModule("node:stream/consumers");
|
|
631
|
+
const { once } = process.getBuiltinModule("node:events");
|
|
1694
632
|
try {
|
|
1695
633
|
const [stdout, stderr, [exitCode]] = await Promise.race([Promise.all([
|
|
1696
634
|
collectStdout ? text(proc.stdout) : "",
|
|
1697
635
|
collect ? text(proc.stderr) : "",
|
|
1698
636
|
once(proc, "close")
|
|
1699
|
-
]),
|
|
637
|
+
]), stopped]);
|
|
638
|
+
options.signal?.throwIfAborted();
|
|
1700
639
|
return {
|
|
1701
640
|
exitCode,
|
|
1702
641
|
stdout,
|
|
@@ -1704,9 +643,13 @@ async function runProcess(command, args = [], options = {}) {
|
|
|
1704
643
|
};
|
|
1705
644
|
} finally {
|
|
1706
645
|
clearTimeout(timer);
|
|
646
|
+
clearTimeout(forceKillTimer);
|
|
647
|
+
release();
|
|
648
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
1707
649
|
}
|
|
1708
650
|
}
|
|
1709
651
|
function isExecutableFile(path) {
|
|
652
|
+
const { accessSync, constants, statSync } = process.getBuiltinModule("node:fs");
|
|
1710
653
|
try {
|
|
1711
654
|
accessSync(path, constants.X_OK);
|
|
1712
655
|
return statSync(path).isFile();
|
|
@@ -1716,6 +659,7 @@ function isExecutableFile(path) {
|
|
|
1716
659
|
}
|
|
1717
660
|
/** Resolve a bare executable name from PATH (and PATHEXT on Windows). */
|
|
1718
661
|
function which(command) {
|
|
662
|
+
const { delimiter, extname, join, resolve, sep } = process.getBuiltinModule("node:path");
|
|
1719
663
|
if (command.includes(sep) || command.includes("/")) return isExecutableFile(command) ? command : null;
|
|
1720
664
|
const extensions = process.platform === "win32" && !extname(command) ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";") : [""];
|
|
1721
665
|
for (const directory of process.env.PATH?.split(delimiter) ?? []) for (const extension of extensions) {
|
|
@@ -1724,8 +668,7 @@ function which(command) {
|
|
|
1724
668
|
}
|
|
1725
669
|
return null;
|
|
1726
670
|
}
|
|
1727
|
-
|
|
1728
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/lrucache.js
|
|
671
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/lrucache.js
|
|
1729
672
|
var require_lrucache = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1730
673
|
var LRUCache = class {
|
|
1731
674
|
constructor() {
|
|
@@ -1757,8 +700,7 @@ var require_lrucache = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1757
700
|
};
|
|
1758
701
|
module.exports = LRUCache;
|
|
1759
702
|
}));
|
|
1760
|
-
|
|
1761
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/parse-options.js
|
|
703
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/parse-options.js
|
|
1762
704
|
var require_parse_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1763
705
|
const looseOption = Object.freeze({ loose: true });
|
|
1764
706
|
const emptyOpts = Object.freeze({});
|
|
@@ -1769,8 +711,7 @@ var require_parse_options = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
1769
711
|
};
|
|
1770
712
|
module.exports = parseOptions;
|
|
1771
713
|
}));
|
|
1772
|
-
|
|
1773
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/constants.js
|
|
714
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/constants.js
|
|
1774
715
|
var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1775
716
|
module.exports = {
|
|
1776
717
|
MAX_LENGTH: 256,
|
|
@@ -1792,13 +733,11 @@ var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1792
733
|
FLAG_LOOSE: 2
|
|
1793
734
|
};
|
|
1794
735
|
}));
|
|
1795
|
-
|
|
1796
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/debug.js
|
|
736
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/debug.js
|
|
1797
737
|
var require_debug = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1798
738
|
module.exports = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => {};
|
|
1799
739
|
}));
|
|
1800
|
-
|
|
1801
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/re.js
|
|
740
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/re.js
|
|
1802
741
|
var require_re = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1803
742
|
const { MAX_SAFE_COMPONENT_LENGTH, MAX_SAFE_BUILD_LENGTH, MAX_LENGTH } = require_constants();
|
|
1804
743
|
const debug = require_debug();
|
|
@@ -1876,8 +815,7 @@ var require_re = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1876
815
|
createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$");
|
|
1877
816
|
createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$");
|
|
1878
817
|
}));
|
|
1879
|
-
|
|
1880
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/identifiers.js
|
|
818
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/identifiers.js
|
|
1881
819
|
var require_identifiers = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1882
820
|
const numeric = /^[0-9]+$/;
|
|
1883
821
|
const compareIdentifiers = (a, b) => {
|
|
@@ -1896,8 +834,7 @@ var require_identifiers = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1896
834
|
rcompareIdentifiers
|
|
1897
835
|
};
|
|
1898
836
|
}));
|
|
1899
|
-
|
|
1900
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/semver.js
|
|
837
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/semver.js
|
|
1901
838
|
var require_semver = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1902
839
|
const debug = require_debug();
|
|
1903
840
|
const { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants();
|
|
@@ -2082,57 +1019,49 @@ var require_semver = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2082
1019
|
}
|
|
2083
1020
|
};
|
|
2084
1021
|
}));
|
|
2085
|
-
|
|
2086
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/compare.js
|
|
1022
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/compare.js
|
|
2087
1023
|
var require_compare = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2088
1024
|
const SemVer = require_semver();
|
|
2089
1025
|
const compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose));
|
|
2090
1026
|
module.exports = compare;
|
|
2091
1027
|
}));
|
|
2092
|
-
|
|
2093
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/eq.js
|
|
1028
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/eq.js
|
|
2094
1029
|
var require_eq = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2095
1030
|
const compare = require_compare();
|
|
2096
1031
|
const eq = (a, b, loose) => compare(a, b, loose) === 0;
|
|
2097
1032
|
module.exports = eq;
|
|
2098
1033
|
}));
|
|
2099
|
-
|
|
2100
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/neq.js
|
|
1034
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/neq.js
|
|
2101
1035
|
var require_neq = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2102
1036
|
const compare = require_compare();
|
|
2103
1037
|
const neq = (a, b, loose) => compare(a, b, loose) !== 0;
|
|
2104
1038
|
module.exports = neq;
|
|
2105
1039
|
}));
|
|
2106
|
-
|
|
2107
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/gt.js
|
|
1040
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/gt.js
|
|
2108
1041
|
var require_gt = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2109
1042
|
const compare = require_compare();
|
|
2110
1043
|
const gt = (a, b, loose) => compare(a, b, loose) > 0;
|
|
2111
1044
|
module.exports = gt;
|
|
2112
1045
|
}));
|
|
2113
|
-
|
|
2114
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/gte.js
|
|
1046
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/gte.js
|
|
2115
1047
|
var require_gte = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2116
1048
|
const compare = require_compare();
|
|
2117
1049
|
const gte = (a, b, loose) => compare(a, b, loose) >= 0;
|
|
2118
1050
|
module.exports = gte;
|
|
2119
1051
|
}));
|
|
2120
|
-
|
|
2121
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/lt.js
|
|
1052
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/lt.js
|
|
2122
1053
|
var require_lt = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2123
1054
|
const compare = require_compare();
|
|
2124
1055
|
const lt = (a, b, loose) => compare(a, b, loose) < 0;
|
|
2125
1056
|
module.exports = lt;
|
|
2126
1057
|
}));
|
|
2127
|
-
|
|
2128
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/lte.js
|
|
1058
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/lte.js
|
|
2129
1059
|
var require_lte = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2130
1060
|
const compare = require_compare();
|
|
2131
1061
|
const lte = (a, b, loose) => compare(a, b, loose) <= 0;
|
|
2132
1062
|
module.exports = lte;
|
|
2133
1063
|
}));
|
|
2134
|
-
|
|
2135
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/cmp.js
|
|
1064
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/cmp.js
|
|
2136
1065
|
var require_cmp = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2137
1066
|
const eq = require_eq();
|
|
2138
1067
|
const neq = require_neq();
|
|
@@ -2163,8 +1092,7 @@ var require_cmp = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2163
1092
|
};
|
|
2164
1093
|
module.exports = cmp;
|
|
2165
1094
|
}));
|
|
2166
|
-
|
|
2167
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/comparator.js
|
|
1095
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/comparator.js
|
|
2168
1096
|
var require_comparator = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2169
1097
|
const ANY = Symbol("SemVer ANY");
|
|
2170
1098
|
module.exports = class Comparator {
|
|
@@ -2235,8 +1163,7 @@ var require_comparator = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2235
1163
|
const SemVer = require_semver();
|
|
2236
1164
|
const Range = require_range();
|
|
2237
1165
|
}));
|
|
2238
|
-
|
|
2239
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/range.js
|
|
1166
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/range.js
|
|
2240
1167
|
var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2241
1168
|
const SPACE_CHARACTERS = /\s+/g;
|
|
2242
1169
|
module.exports = class Range {
|
|
@@ -2518,8 +1445,7 @@ var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2518
1445
|
return true;
|
|
2519
1446
|
};
|
|
2520
1447
|
}));
|
|
2521
|
-
|
|
2522
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/satisfies.js
|
|
1448
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/satisfies.js
|
|
2523
1449
|
var require_satisfies = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2524
1450
|
const Range = require_range();
|
|
2525
1451
|
const satisfies = (version, range, options) => {
|
|
@@ -2532,8 +1458,7 @@ var require_satisfies = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2532
1458
|
};
|
|
2533
1459
|
module.exports = satisfies;
|
|
2534
1460
|
}));
|
|
2535
|
-
|
|
2536
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/parse.js
|
|
1461
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/parse.js
|
|
2537
1462
|
var require_parse = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2538
1463
|
const SemVer = require_semver();
|
|
2539
1464
|
const parse = (version, options, throwErrors = false) => {
|
|
@@ -2547,8 +1472,7 @@ var require_parse = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2547
1472
|
};
|
|
2548
1473
|
module.exports = parse;
|
|
2549
1474
|
}));
|
|
2550
|
-
|
|
2551
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/valid.js
|
|
1475
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/valid.js
|
|
2552
1476
|
var require_valid$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2553
1477
|
const parse = require_parse();
|
|
2554
1478
|
const valid = (version, options) => {
|
|
@@ -2557,8 +1481,7 @@ var require_valid$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2557
1481
|
};
|
|
2558
1482
|
module.exports = valid;
|
|
2559
1483
|
}));
|
|
2560
|
-
|
|
2561
|
-
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/valid.js
|
|
1484
|
+
// ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/valid.js
|
|
2562
1485
|
var require_valid = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2563
1486
|
const Range = require_range();
|
|
2564
1487
|
const validRange = (range, options) => {
|
|
@@ -2570,16 +1493,11 @@ var require_valid = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2570
1493
|
};
|
|
2571
1494
|
module.exports = validRange;
|
|
2572
1495
|
}));
|
|
2573
|
-
|
|
2574
|
-
//#region src/targets.ts
|
|
1496
|
+
// src/targets.ts
|
|
2575
1497
|
var import_satisfies = /* @__PURE__ */ __toESM(require_satisfies(), 1);
|
|
2576
1498
|
var import_valid = /* @__PURE__ */ __toESM(require_valid$1(), 1);
|
|
2577
1499
|
var import_valid$1 = /* @__PURE__ */ __toESM(require_valid(), 1);
|
|
2578
|
-
const BUILD_RUNTIMES = [
|
|
2579
|
-
"bun",
|
|
2580
|
-
"deno",
|
|
2581
|
-
"node"
|
|
2582
|
-
];
|
|
1500
|
+
const BUILD_RUNTIMES = ["bun", "node"];
|
|
2583
1501
|
const BUN_TARGETS = {
|
|
2584
1502
|
runtime: "Bun",
|
|
2585
1503
|
targets: [
|
|
@@ -2647,57 +1565,6 @@ const BUN_TARGETS = {
|
|
|
2647
1565
|
}
|
|
2648
1566
|
}
|
|
2649
1567
|
};
|
|
2650
|
-
const DENO_TARGETS = {
|
|
2651
|
-
runtime: "Deno",
|
|
2652
|
-
targets: [
|
|
2653
|
-
"x86_64-unknown-linux-gnu",
|
|
2654
|
-
"aarch64-unknown-linux-gnu",
|
|
2655
|
-
"x86_64-apple-darwin",
|
|
2656
|
-
"aarch64-apple-darwin",
|
|
2657
|
-
"x86_64-pc-windows-msvc",
|
|
2658
|
-
"aarch64-pc-windows-msvc"
|
|
2659
|
-
],
|
|
2660
|
-
info: {
|
|
2661
|
-
"x86_64-unknown-linux-gnu": {
|
|
2662
|
-
alias: "linux-x64",
|
|
2663
|
-
platformKey: "linux-x64",
|
|
2664
|
-
os: "linux",
|
|
2665
|
-
cpu: "x64",
|
|
2666
|
-
libc: "glibc"
|
|
2667
|
-
},
|
|
2668
|
-
"aarch64-unknown-linux-gnu": {
|
|
2669
|
-
alias: "linux-arm64",
|
|
2670
|
-
platformKey: "linux-arm64",
|
|
2671
|
-
os: "linux",
|
|
2672
|
-
cpu: "arm64",
|
|
2673
|
-
libc: "glibc"
|
|
2674
|
-
},
|
|
2675
|
-
"x86_64-apple-darwin": {
|
|
2676
|
-
alias: "darwin-x64",
|
|
2677
|
-
platformKey: "darwin-x64",
|
|
2678
|
-
os: "darwin",
|
|
2679
|
-
cpu: "x64"
|
|
2680
|
-
},
|
|
2681
|
-
"aarch64-apple-darwin": {
|
|
2682
|
-
alias: "darwin-arm64",
|
|
2683
|
-
platformKey: "darwin-arm64",
|
|
2684
|
-
os: "darwin",
|
|
2685
|
-
cpu: "arm64"
|
|
2686
|
-
},
|
|
2687
|
-
"x86_64-pc-windows-msvc": {
|
|
2688
|
-
alias: "windows-x64",
|
|
2689
|
-
platformKey: "win32-x64",
|
|
2690
|
-
os: "win32",
|
|
2691
|
-
cpu: "x64"
|
|
2692
|
-
},
|
|
2693
|
-
"aarch64-pc-windows-msvc": {
|
|
2694
|
-
alias: "windows-arm64",
|
|
2695
|
-
platformKey: "win32-arm64",
|
|
2696
|
-
os: "win32",
|
|
2697
|
-
cpu: "arm64"
|
|
2698
|
-
}
|
|
2699
|
-
}
|
|
2700
|
-
};
|
|
2701
1568
|
const NODE_TARGETS = {
|
|
2702
1569
|
runtime: "Node",
|
|
2703
1570
|
targets: [
|
|
@@ -2786,8 +1653,7 @@ function hostTarget(table) {
|
|
|
2786
1653
|
const platformKey = hostPlatformKey();
|
|
2787
1654
|
return table.targets.find((target) => table.info[target].platformKey === platformKey) ?? null;
|
|
2788
1655
|
}
|
|
2789
|
-
|
|
2790
|
-
//#region src/compilers.ts
|
|
1656
|
+
// src/compilers.ts
|
|
2791
1657
|
/** A finished compiler process's stderr, then stdout, for error messages. */
|
|
2792
1658
|
function processOutput({ stdout, stderr }) {
|
|
2793
1659
|
return [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
|
|
@@ -2851,15 +1717,6 @@ function assertTargetsBuildableWithoutBun(targets, runner, host = hostTarget(BUN
|
|
|
2851
1717
|
throw new Error(`Cannot build ${host} without a separate bun executable on PATH.\n Bun reuses the running crust executable as the base for its own platform, which yields a binary that crashes on start.
|
|
2852
1718
|
Install Bun (https://bun.sh), or ${alternative}.`);
|
|
2853
1719
|
}
|
|
2854
|
-
/** The external `deno` on PATH; Deno has no embedded fallback. */
|
|
2855
|
-
function resolveDenoBuildRunner() {
|
|
2856
|
-
const denoPath = which("deno");
|
|
2857
|
-
if (!denoPath) throw new Error("Deno is required for the deno runtime but was not found on PATH.\n Install Deno from https://deno.com/ and try again.");
|
|
2858
|
-
return {
|
|
2859
|
-
command: denoPath,
|
|
2860
|
-
env: { ...process.env }
|
|
2861
|
-
};
|
|
2862
|
-
}
|
|
2863
1720
|
/** The external `node` on PATH, which runs tsdown's executable builder; there is no embedded fallback. */
|
|
2864
1721
|
function resolveNodeBuildRunner() {
|
|
2865
1722
|
const nodePath = which("node");
|
|
@@ -2871,14 +1728,13 @@ function resolveNodeBuildRunner() {
|
|
|
2871
1728
|
}
|
|
2872
1729
|
const RUNTIME_LABELS = {
|
|
2873
1730
|
bun: "Bun",
|
|
2874
|
-
deno: "Deno",
|
|
2875
1731
|
node: "Node"
|
|
2876
1732
|
};
|
|
2877
1733
|
const COMPILER_VERSION_TIMEOUT_MS = 3e4;
|
|
2878
1734
|
/**
|
|
2879
1735
|
* Runtime version reported by the runner itself (`<command> --version`), never
|
|
2880
|
-
* the runtime hosting this process: `bun` prints `1.4.2`, `
|
|
2881
|
-
* `
|
|
1736
|
+
* the runtime hosting this process: `bun` prints `1.4.2`, `node` prints
|
|
1737
|
+
* `v24.21.0`. Under the `BUN_BE_BUN` fallback
|
|
2882
1738
|
* this is the embedded Bun, which is the compiler. `cwd` must be the directory
|
|
2883
1739
|
* compilation runs in: a version-manager shim picks its runtime from it. A
|
|
2884
1740
|
* probe still running after {@link COMPILER_VERSION_TIMEOUT_MS} is killed and
|
|
@@ -2892,8 +1748,7 @@ async function readCompilerVersion(runtime, runner, cwd) {
|
|
|
2892
1748
|
timeout: COMPILER_VERSION_TIMEOUT_MS
|
|
2893
1749
|
});
|
|
2894
1750
|
const stdout = result.stdout.trim();
|
|
2895
|
-
const
|
|
2896
|
-
const version = result.exitCode === 0 && reported !== void 0 ? (0, import_valid.default)(reported) : null;
|
|
1751
|
+
const version = result.exitCode === 0 ? (0, import_valid.default)(stdout) : null;
|
|
2897
1752
|
if (version === null) {
|
|
2898
1753
|
const output = processOutput(result);
|
|
2899
1754
|
throw new Error(`Could not read the ${RUNTIME_LABELS[runtime]} version from ${runner.command} --version (exit ${result.exitCode})${output ? `:\n${output}` : "."}`);
|
|
@@ -2922,47 +1777,22 @@ function assertCompilerSatisfiesEngines(compiler, userPackageJson) {
|
|
|
2922
1777
|
}
|
|
2923
1778
|
}
|
|
2924
1779
|
/**
|
|
2925
|
-
* Select the binary compiler once for a build:
|
|
2926
|
-
*
|
|
2927
|
-
*
|
|
2928
|
-
* `engines`. Pass `runner` and the same `cwd` on to the `exec*`/`buildEntrypoint`
|
|
1780
|
+
* Select the Bun binary compiler once for a build: external bun first, then
|
|
1781
|
+
* the embedded fallback. Returns its actual version, read in the project
|
|
1782
|
+
* directory `cwd`, after validating it against `engines`. Pass `runner` and the same `cwd` on to the `exec*`/`buildEntrypoint`
|
|
2929
1783
|
* helpers so every step uses this same compiler.
|
|
2930
1784
|
*/
|
|
2931
|
-
async function resolveBinaryCompiler(
|
|
2932
|
-
const runner =
|
|
1785
|
+
async function resolveBinaryCompiler(userPackageJson, cwd) {
|
|
1786
|
+
const runner = resolveBunBuildRunner();
|
|
2933
1787
|
const compiler = {
|
|
2934
|
-
runtime,
|
|
1788
|
+
runtime: "bun",
|
|
2935
1789
|
runner,
|
|
2936
|
-
version: await readCompilerVersion(
|
|
1790
|
+
version: await readCompilerVersion("bun", runner, cwd)
|
|
2937
1791
|
};
|
|
2938
1792
|
assertCompilerSatisfiesEngines(compiler, userPackageJson);
|
|
2939
1793
|
return compiler;
|
|
2940
1794
|
}
|
|
2941
|
-
|
|
2942
|
-
* Oldest `deno` accepted to bundle a Deno runtime package. Deno 2.4 resolves a
|
|
2943
|
-
* package.json project's npm dependencies from the registry instead of its
|
|
2944
|
-
* installed node_modules, so it can bundle a different Crust than the project
|
|
2945
|
-
* installed. Tested on Linux x64 with Deno 2.5.0 through 2.9.6.
|
|
2946
|
-
*/
|
|
2947
|
-
const DENO_PACKAGE_MIN_VERSION = "2.5.0";
|
|
2948
|
-
/**
|
|
2949
|
-
* Select the external deno that bundles a Deno runtime package, reading its
|
|
2950
|
-
* version in the project directory `cwd`. Call it before staging is replaced.
|
|
2951
|
-
* A runtime package embeds no Deno, so `engines.deno` stays a consumer
|
|
2952
|
-
* requirement and is not checked against this bundler.
|
|
2953
|
-
*/
|
|
2954
|
-
async function resolveDenoPackageBundler(cwd, runner = resolveDenoBuildRunner()) {
|
|
2955
|
-
const version = await readCompilerVersion("deno", runner, cwd);
|
|
2956
|
-
if (!(0, import_satisfies.default)(version, `>=2.5.0`, { includePrerelease: true })) throw new Error(`Deno ${version} (${runner.command}) cannot bundle a Deno runtime package; deno ${DENO_PACKAGE_MIN_VERSION} or newer is required.\n Older deno bundle resolves package.json dependencies from the npm registry instead of the installed node_modules.
|
|
2957
|
-
crust does not install or upgrade Deno; put a newer deno first on PATH (e.g. with your version manager).`);
|
|
2958
|
-
return {
|
|
2959
|
-
runtime: "deno",
|
|
2960
|
-
runner,
|
|
2961
|
-
version
|
|
2962
|
-
};
|
|
2963
|
-
}
|
|
2964
|
-
//#endregion
|
|
2965
|
-
//#region src/bundle.ts
|
|
1795
|
+
// src/bundle.ts
|
|
2966
1796
|
function toBunEnvFileArgs(envFiles) {
|
|
2967
1797
|
return envFiles.flatMap((envFile) => ["--env-file", envFile]);
|
|
2968
1798
|
}
|
|
@@ -2978,8 +1808,7 @@ function resolveBunPluginSource(specifier, cwd) {
|
|
|
2978
1808
|
/**
|
|
2979
1809
|
* Marks every Bun/Node bundle crust produces so `resolveArtifactDir` (core)
|
|
2980
1810
|
* can tell a staged bundle from source at runtime. Not a `PUBLIC_*` variable:
|
|
2981
|
-
* it is internal to crust, never user-set.
|
|
2982
|
-
* standalone Deno binaries are detected directly.
|
|
1811
|
+
* it is internal to crust, never user-set.
|
|
2983
1812
|
*/
|
|
2984
1813
|
const CRUST_BUILD_DEFINE = { "process.env.CRUST_INTERNAL_BUILD": "\"1\"" };
|
|
2985
1814
|
const CRUST_BUILD_DEFINE_ARG = "process.env.CRUST_INTERNAL_BUILD=\"1\"";
|
|
@@ -3010,6 +1839,12 @@ for (const { specifier, source } of options.plugins) {
|
|
|
3010
1839
|
}
|
|
3011
1840
|
plugins.push(plugin);
|
|
3012
1841
|
}
|
|
1842
|
+
if (options.stripShebang) {
|
|
1843
|
+
// Last, so a project plugin's onLoad for the entry still wins. The emptied line keeps line numbers.
|
|
1844
|
+
plugins.push({ name: "crust-strip-shebang", setup(build) {
|
|
1845
|
+
build.onLoad({ filter: new RegExp(\`^(?:\${options.stripShebang.map(RegExp.escape).join("|")})$\`) }, async ({ path, loader }) => ({ contents: (await Bun.file(path).text()).replace(/^#![^\\n]*/, ""), loader }));
|
|
1846
|
+
} });
|
|
1847
|
+
}
|
|
3013
1848
|
const result = await Bun.build({ ...options.build, define: ${JSON.stringify(CRUST_BUILD_DEFINE)}, plugins, throw: false });
|
|
3014
1849
|
if (!result.success) {
|
|
3015
1850
|
for (const log of result.logs) console.error(log);
|
|
@@ -3025,7 +1860,7 @@ if (!options.build.compile) {
|
|
|
3025
1860
|
}
|
|
3026
1861
|
`;
|
|
3027
1862
|
}
|
|
3028
|
-
async function runBunPluginDriver(build, outfilePath, { cwd, envFiles, bunPlugins }, runner) {
|
|
1863
|
+
async function runBunPluginDriver(build, outfilePath, { cwd, envFiles, bunPlugins }, runner, stripShebang) {
|
|
3029
1864
|
const driverPath = join(cwd, `.crust-build-${randomBytes(6).toString("hex")}.ts`);
|
|
3030
1865
|
await writeFile(driverPath, createBunPluginDriverScript({
|
|
3031
1866
|
plugins: bunPlugins.map((specifier) => ({
|
|
@@ -3033,7 +1868,8 @@ async function runBunPluginDriver(build, outfilePath, { cwd, envFiles, bunPlugin
|
|
|
3033
1868
|
source: resolveBunPluginSource(specifier, cwd)
|
|
3034
1869
|
})),
|
|
3035
1870
|
build,
|
|
3036
|
-
outfile: outfilePath
|
|
1871
|
+
outfile: outfilePath,
|
|
1872
|
+
stripShebang
|
|
3037
1873
|
}));
|
|
3038
1874
|
try {
|
|
3039
1875
|
await runBuildProcess(runner, [...toBunEnvFileArgs(envFiles), driverPath], outfilePath, cwd);
|
|
@@ -3067,13 +1903,17 @@ async function execBuild(entryPath, outfilePath, target, settings, runner = reso
|
|
|
3067
1903
|
target: compileTarget,
|
|
3068
1904
|
outfile: outfilePath,
|
|
3069
1905
|
autoloadBunfig: false
|
|
3070
|
-
}
|
|
1906
|
+
},
|
|
1907
|
+
...settings.bytecode ? {
|
|
1908
|
+
bytecode: true,
|
|
1909
|
+
format: "esm"
|
|
1910
|
+
} : {}
|
|
3071
1911
|
}, outfilePath, settings, runner);
|
|
3072
1912
|
return;
|
|
3073
1913
|
}
|
|
3074
|
-
await runBuildProcess(runner, createBunCompileArgs(entryPath, outfilePath, settings.minify, compileTarget, settings.envFiles), outfilePath, settings.cwd);
|
|
1914
|
+
await runBuildProcess(runner, createBunCompileArgs(entryPath, outfilePath, settings.minify, compileTarget, settings.envFiles, settings.bytecode), outfilePath, settings.cwd);
|
|
3075
1915
|
}
|
|
3076
|
-
function createBunCompileArgs(entryPath, outfilePath, minify, target, envFiles = []) {
|
|
1916
|
+
function createBunCompileArgs(entryPath, outfilePath, minify, target, envFiles = [], bytecode = false) {
|
|
3077
1917
|
return [
|
|
3078
1918
|
"build",
|
|
3079
1919
|
"--compile",
|
|
@@ -3085,17 +1925,7 @@ function createBunCompileArgs(entryPath, outfilePath, minify, target, envFiles =
|
|
|
3085
1925
|
"--outfile",
|
|
3086
1926
|
outfilePath,
|
|
3087
1927
|
...minify ? ["--minify"] : [],
|
|
3088
|
-
"--
|
|
3089
|
-
target,
|
|
3090
|
-
entryPath
|
|
3091
|
-
];
|
|
3092
|
-
}
|
|
3093
|
-
function createDenoCompileArgs(entryPath, outfilePath, target) {
|
|
3094
|
-
return [
|
|
3095
|
-
"compile",
|
|
3096
|
-
"-A",
|
|
3097
|
-
"--output",
|
|
3098
|
-
outfilePath,
|
|
1928
|
+
...bytecode ? ["--bytecode", "--format=esm"] : [],
|
|
3099
1929
|
"--target",
|
|
3100
1930
|
target,
|
|
3101
1931
|
entryPath
|
|
@@ -3118,14 +1948,15 @@ async function runBuildProcess(runner, args, outfilePath, cwd) {
|
|
|
3118
1948
|
*/
|
|
3119
1949
|
async function execScriptBuild(target, entryPath, outfilePath, settings, runner = resolveBunBuildRunner()) {
|
|
3120
1950
|
const { cwd, minify, envFiles, external } = settings;
|
|
3121
|
-
|
|
1951
|
+
const stripShebang = target === "node" && /^#![^\n]*\bbun\b/.test(await readFile(entryPath, "utf8")) ? [entryPath, await realpath(entryPath)] : void 0;
|
|
1952
|
+
if (settings.bunPlugins.length > 0 || stripShebang !== void 0) await runBunPluginDriver({
|
|
3122
1953
|
entrypoints: [entryPath],
|
|
3123
1954
|
minify,
|
|
3124
1955
|
env: "PUBLIC_*",
|
|
3125
1956
|
target,
|
|
3126
1957
|
format: "esm",
|
|
3127
1958
|
external
|
|
3128
|
-
}, outfilePath, settings, runner);
|
|
1959
|
+
}, outfilePath, settings, runner, stripShebang);
|
|
3129
1960
|
else await runBuildProcess(runner, [
|
|
3130
1961
|
"build",
|
|
3131
1962
|
...toBunEnvFileArgs(envFiles),
|
|
@@ -3142,40 +1973,14 @@ async function execScriptBuild(target, entryPath, outfilePath, settings, runner
|
|
|
3142
1973
|
...minify ? ["--minify"] : [],
|
|
3143
1974
|
entryPath
|
|
3144
1975
|
], outfilePath, cwd);
|
|
3145
|
-
const output = await readFile(outfilePath, "utf8");
|
|
3146
|
-
|
|
3147
|
-
await writeFile(outfilePath,
|
|
1976
|
+
const output = (await readFile(outfilePath, "utf8")).replace(/^#![^\n]*(?:\n|$)/, "");
|
|
1977
|
+
if (target === "node" && output.startsWith("// @bun")) throw new Error(`Build failed for ${outfilePath}: Bun emitted Bun-only code for a Node bundle because the entry reached it starting with "#!/usr/bin/env bun".\n Remove that line from ${entryPath}, or from what a crust.bunPlugins onLoad hook returns for it.`);
|
|
1978
|
+
await writeFile(outfilePath, `#!/usr/bin/env ${target}\n${output}`);
|
|
3148
1979
|
if (process.platform !== "win32") await chmod(outfilePath, 493);
|
|
3149
1980
|
}
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
/**
|
|
3154
|
-
* Bundle a Deno runtime package entry with native `deno bundle`, which resolves
|
|
3155
|
-
* dependencies through the project's own Deno setup (deno.json imports,
|
|
3156
|
-
* package.json with its installed node_modules) and inlines them into one file.
|
|
3157
|
-
*
|
|
3158
|
-
* Bundle the declared command directly so Deno preserves its `import.meta.main`
|
|
3159
|
-
* semantics without making dependencies main. Prepend the packaged-build marker
|
|
3160
|
-
* (`PACKAGED_BUILD_KEY`) to the bundled code so it runs before the inlined
|
|
3161
|
-
* application graph. The output has no shebang or permission flags: consumers
|
|
3162
|
-
* choose grants with `deno run` / `deno install`.
|
|
3163
|
-
* No env files or plugins: `deno bundle` has no PUBLIC_* filter or Bun plugins.
|
|
3164
|
-
*/
|
|
3165
|
-
async function execDenoPackageBuild(entryPath, outfilePath, cwd, runner = resolveDenoBuildRunner()) {
|
|
3166
|
-
await runBuildProcess(runner, [
|
|
3167
|
-
"bundle",
|
|
3168
|
-
"--platform=deno",
|
|
3169
|
-
"--packages=bundle",
|
|
3170
|
-
"--output",
|
|
3171
|
-
outfilePath,
|
|
3172
|
-
resolve(cwd, entryPath)
|
|
3173
|
-
], outfilePath, cwd);
|
|
3174
|
-
const output = await readFile(outfilePath, "utf8");
|
|
3175
|
-
await writeFile(outfilePath, `globalThis[Symbol.for(${JSON.stringify(PACKAGED_BUILD_KEY)})] = true;\n` + output.replace(/^#![^\n]*(?:\n|$)/, ""));
|
|
3176
|
-
}
|
|
3177
|
-
//#endregion
|
|
3178
|
-
//#region src/launcher.ts
|
|
1981
|
+
// src/launcher.ts
|
|
1982
|
+
/** Node.js the launcher needs for `process.execve`: the same floor as every Crust package. */
|
|
1983
|
+
const LAUNCHER_NODE_RANGE = ">=24";
|
|
3179
1984
|
/** Platform binary filename: `<command>-<target>`, `.exe` on Windows. */
|
|
3180
1985
|
function binaryFilename(command, target) {
|
|
3181
1986
|
return `${command}-${target.target}${target.os === "win32" ? ".exe" : ""}`;
|
|
@@ -3190,18 +1995,34 @@ function generateLauncher(command, targets) {
|
|
|
3190
1995
|
const supportedPlatforms = targets.map((target) => target.targetAlias).join(", ");
|
|
3191
1996
|
return `#!/usr/bin/env node
|
|
3192
1997
|
// Auto-generated by crust build -- do not edit
|
|
3193
|
-
import { spawn } from "node:child_process";
|
|
3194
|
-
import { chmodSync, existsSync } from "node:fs";
|
|
3195
|
-
import { dirname, resolve } from "node:path";
|
|
3196
|
-
import process from "node:process";
|
|
3197
|
-
import { fileURLToPath } from "node:url";
|
|
3198
|
-
|
|
3199
1998
|
const NAME = ${JSON.stringify(command)};
|
|
1999
|
+
if (typeof process.getBuiltinModule !== "function" ||
|
|
2000
|
+
(process.platform !== "win32" && typeof process.execve !== "function")) {
|
|
2001
|
+
console.error("[" + NAME + "] Requires Node.js ${LAUNCHER_NODE_RANGE} (found " + process.version + ").");
|
|
2002
|
+
process.exit(1);
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
// Builtins come from process.getBuiltinModule (cheaper than imports) and never from
|
|
2006
|
+
// node:process: importing it touches stdio, which leaves the shared terminal and pipes
|
|
2007
|
+
// non-blocking for the binary after execve.
|
|
2008
|
+
const { chmodSync, closeSync, existsSync, openSync, readSync } = process.getBuiltinModule("node:fs");
|
|
2009
|
+
const { resolve } = process.getBuiltinModule("node:path");
|
|
2010
|
+
|
|
3200
2011
|
const PLATFORMS = ${JSON.stringify(targetMap, null, " ")};
|
|
3201
|
-
const dir =
|
|
2012
|
+
const dir = import.meta.dirname;
|
|
3202
2013
|
|
|
3203
|
-
// Same check as Bun's own npm installer: glibc reports its version, musl does not.
|
|
3204
2014
|
function isMusl() {
|
|
2015
|
+
// The first 2 KB of Node's ELF image hold its interpreter path (detect-libc reads the same
|
|
2016
|
+
// span), which names its libc without the milliseconds a diagnostic report costs on every start.
|
|
2017
|
+
try {
|
|
2018
|
+
const fd = openSync("/proc/self/exe", "r");
|
|
2019
|
+
const head = Buffer.alloc(2048);
|
|
2020
|
+
const interpreter = head.toString("latin1", 0, readSync(fd, head, 0, head.length, 0));
|
|
2021
|
+
closeSync(fd);
|
|
2022
|
+
if (interpreter.includes("/ld-musl-")) return true;
|
|
2023
|
+
if (interpreter.includes("/ld-linux-")) return false;
|
|
2024
|
+
} catch {}
|
|
2025
|
+
// Same check as Bun's own npm installer: glibc reports its version, musl does not.
|
|
3205
2026
|
try {
|
|
3206
2027
|
const report = process.report?.getReport();
|
|
3207
2028
|
if (report?.header) return report.header.glibcVersionRuntime === undefined;
|
|
@@ -3239,39 +2060,55 @@ if (!binPath) {
|
|
|
3239
2060
|
\tprocess.exit(1);
|
|
3240
2061
|
}
|
|
3241
2062
|
|
|
3242
|
-
if (process.platform
|
|
2063
|
+
if (process.platform === "win32") {
|
|
2064
|
+
\tlaunchWindows(binPath);
|
|
2065
|
+
} else {
|
|
3243
2066
|
\ttry {
|
|
3244
2067
|
\t\tchmodSync(binPath, 0o755);
|
|
3245
2068
|
\t} catch {
|
|
3246
|
-
\t\t// Ignore permission adjustment failures and let
|
|
2069
|
+
\t\t// Ignore permission adjustment failures and let execve surface real errors.
|
|
3247
2070
|
\t}
|
|
2071
|
+
\t// Become the binary: one process, so signals and exit status reach it with no relay.
|
|
2072
|
+
\t// Node ignores SIGPIPE and SIGXFSZ, and ignored signals survive execve; handled ones reset.
|
|
2073
|
+
\t// Ignores Node inherited (nohup's SIGHUP) were reset at its startup, so none pass on.
|
|
2074
|
+
\tprocess.on("SIGPIPE", () => {});
|
|
2075
|
+
\tprocess.on("SIGXFSZ", () => {});
|
|
2076
|
+
\t// Early execve versions (e.g. Node 24.0.0) default to an empty environment.
|
|
2077
|
+
\tprocess.execve(binPath, [binPath, ...process.argv.slice(2)], process.env);
|
|
3248
2078
|
}
|
|
3249
2079
|
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
child
|
|
3255
|
-
\
|
|
3256
|
-
\
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
\
|
|
3261
|
-
\t\
|
|
3262
|
-
\t\
|
|
3263
|
-
\t
|
|
3264
|
-
\
|
|
2080
|
+
// Windows has no execve. Its console delivers Ctrl-C to the binary directly, and
|
|
2081
|
+
// child.kill("SIGINT") would hard-terminate it, so SIGINT is never forwarded.
|
|
2082
|
+
function launchWindows(binPath) {
|
|
2083
|
+
\tconst { spawn } = process.getBuiltinModule("node:child_process");
|
|
2084
|
+
\tconst child = spawn(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
2085
|
+
\tconst forward = (signal) => child.kill(signal);
|
|
2086
|
+
\tconst ignore = () => {};
|
|
2087
|
+
\tprocess.on("SIGINT", ignore);
|
|
2088
|
+
\tprocess.on("SIGTERM", forward);
|
|
2089
|
+
\tprocess.on("SIGHUP", forward);
|
|
2090
|
+
\tchild.on("error", (error) => {
|
|
2091
|
+
\t\tconsole.error("[" + NAME + "] Failed to launch binary: " + error.message);
|
|
2092
|
+
\t\tprocess.exit(1);
|
|
2093
|
+
\t});
|
|
2094
|
+
\tchild.on("exit", (code, signal) => {
|
|
2095
|
+
\t\tprocess.off("SIGINT", ignore);
|
|
2096
|
+
\t\tprocess.off("SIGTERM", forward);
|
|
2097
|
+
\t\tprocess.off("SIGHUP", forward);
|
|
2098
|
+
\t\tif (signal) {
|
|
2099
|
+
\t\t\ttry {
|
|
2100
|
+
\t\t\t\tprocess.kill(process.pid, signal);
|
|
2101
|
+
\t\t\t} catch {
|
|
2102
|
+
\t\t\t\tprocess.exit(1);
|
|
2103
|
+
\t\t\t}
|
|
2104
|
+
\t\t\treturn;
|
|
3265
2105
|
\t\t}
|
|
3266
|
-
\t\
|
|
3267
|
-
\t}
|
|
3268
|
-
|
|
3269
|
-
\tprocess.exit(code ?? 0);
|
|
3270
|
-
});
|
|
2106
|
+
\t\tprocess.exit(code ?? 0);
|
|
2107
|
+
\t});
|
|
2108
|
+
}
|
|
3271
2109
|
`;
|
|
3272
2110
|
}
|
|
3273
|
-
|
|
3274
|
-
//#region src/distribute.ts
|
|
2111
|
+
// src/distribute.ts
|
|
3275
2112
|
/** Project-relative directory that `crust build` owns: wiped per build, read by `crust publish`. */
|
|
3276
2113
|
const CRUST_DIR = ".crust";
|
|
3277
2114
|
/**
|
|
@@ -3314,8 +2151,14 @@ function platformBinMap(commands, target) {
|
|
|
3314
2151
|
return Object.fromEntries(commands.map((command) => [command, `bin/${binaryFilename(command, target)}`]));
|
|
3315
2152
|
}
|
|
3316
2153
|
function buildDistributionRootPackageJson(metadata, commands, targets, { artifactDirs, manPages }) {
|
|
2154
|
+
const { engines } = metadata.rootPackageJson;
|
|
2155
|
+
const launcherEngines = targets.length > 0 && metadata.exports === void 0 ? {
|
|
2156
|
+
...engines !== void 0 && isJsonObject(engines) ? engines : {},
|
|
2157
|
+
node: LAUNCHER_NODE_RANGE
|
|
2158
|
+
} : void 0;
|
|
3317
2159
|
return {
|
|
3318
2160
|
...metadata.rootPackageJson,
|
|
2161
|
+
...launcherEngines ? { engines: launcherEngines } : {},
|
|
3319
2162
|
name: metadata.rootPackageName,
|
|
3320
2163
|
version: metadata.version,
|
|
3321
2164
|
type: "module",
|
|
@@ -3456,7 +2299,7 @@ function resolveDistributionMetadata(pkgJson, external) {
|
|
|
3456
2299
|
version: pkgJson.version,
|
|
3457
2300
|
rootPackageJson: pickRootMetadata(pkgJson),
|
|
3458
2301
|
sourceType: pkgJson.type,
|
|
3459
|
-
...pkgJson.exports !== void 0 ? { exports: pkgJson.exports } : {},
|
|
2302
|
+
...pkgJson.exports !== void 0 && pkgJson.exports !== null ? { exports: pkgJson.exports } : {},
|
|
3460
2303
|
...pkgJson.peerDependencies !== void 0 ? validatePeerDependencies(pkgJson.peerDependencies, pkgJson.peerDependenciesMeta) : {},
|
|
3461
2304
|
...external.length > 0 ? { dependencies: externalDependencies(pkgJson, external) } : {}
|
|
3462
2305
|
};
|
|
@@ -3639,14 +2482,12 @@ async function runDistributeBuild(plan, distribution, io, build) {
|
|
|
3639
2482
|
io.stdout(`\n${dim("Manifest:")} ${manifestPath}`);
|
|
3640
2483
|
return produced;
|
|
3641
2484
|
}
|
|
3642
|
-
|
|
3643
|
-
//#region package.json
|
|
2485
|
+
// package.json
|
|
3644
2486
|
var optionalDependencies = {
|
|
3645
|
-
"@tsdown/exe": "0.23.
|
|
3646
|
-
"tsdown": "0.23.
|
|
2487
|
+
"@tsdown/exe": "0.23.4",
|
|
2488
|
+
"tsdown": "0.23.4"
|
|
3647
2489
|
};
|
|
3648
|
-
|
|
3649
|
-
//#region src/node-exe.ts
|
|
2490
|
+
// src/node-exe.ts
|
|
3650
2491
|
/**
|
|
3651
2492
|
* Crust's own optional dependencies that build Node standalone binaries.
|
|
3652
2493
|
* Crust's staged root and platform packages declare them
|
|
@@ -3802,7 +2643,7 @@ await build({
|
|
|
3802
2643
|
// Bun leaves only Node built-ins as imports; fail on anything else, which
|
|
3803
2644
|
// an executable shipping no node_modules could not resolve.
|
|
3804
2645
|
deps: { alwaysBundle: () => true, onlyBundle: false, onlyImport: [] },
|
|
3805
|
-
exe: { outDir: options.exeDir, fileName: "app", targets: [options.target] },
|
|
2646
|
+
exe: { outDir: options.exeDir, fileName: "app", targets: [options.target], seaConfig: { useCodeCache: options.useCodeCache } },
|
|
3806
2647
|
});
|
|
3807
2648
|
`;
|
|
3808
2649
|
}
|
|
@@ -3824,7 +2665,7 @@ await build({
|
|
|
3824
2665
|
* signature) after a successful build
|
|
3825
2666
|
* @throws {Error} If the build fails
|
|
3826
2667
|
*/
|
|
3827
|
-
async function execNodeBinaryBuild(entryPath, outfilePath, target, settings, compiler, bunRunner, onWarning = () => {}) {
|
|
2668
|
+
async function execNodeBinaryBuild(entryPath, outfilePath, target, settings, compiler, bunRunner, onWarning = () => {}, useCodeCache = false) {
|
|
3828
2669
|
const { cwd, minify } = settings;
|
|
3829
2670
|
const workDir = await mkdtemp(join(tmpdir(), "crust-node-exe-"));
|
|
3830
2671
|
try {
|
|
@@ -3843,7 +2684,8 @@ async function execNodeBinaryBuild(entryPath, outfilePath, target, settings, com
|
|
|
3843
2684
|
bundleDir: join(workDir, "bundle"),
|
|
3844
2685
|
exeDir,
|
|
3845
2686
|
minify,
|
|
3846
|
-
target: nodeExeTarget(target, compiler.version)
|
|
2687
|
+
target: nodeExeTarget(target, compiler.version),
|
|
2688
|
+
useCodeCache
|
|
3847
2689
|
}));
|
|
3848
2690
|
const output = await runBuildProcess(compiler.runner, [scriptPath], outfilePath, cwd);
|
|
3849
2691
|
const produced = await readdir(exeDir);
|
|
@@ -3861,12 +2703,13 @@ async function execNodeBinaryBuild(entryPath, outfilePath, target, settings, com
|
|
|
3861
2703
|
}
|
|
3862
2704
|
function createNodeExeProvisionScript(tsdownPackageJson, targets) {
|
|
3863
2705
|
return `// Generated by crust build to provision Node binaries for targets; deleted when it exits.
|
|
3864
|
-
import { realpathSync } from "node:fs";
|
|
2706
|
+
import { readFileSync, realpathSync, statSync } from "node:fs";
|
|
3865
2707
|
import { createRequire } from "node:module";
|
|
3866
2708
|
import { pathToFileURL } from "node:url";
|
|
3867
2709
|
|
|
3868
2710
|
const exe = createRequire(realpathSync(${JSON.stringify(tsdownPackageJson)})).resolve("@tsdown/exe");
|
|
3869
|
-
const { resolveNodeBinary } = await import(pathToFileURL(exe).href);
|
|
2711
|
+
const { resolveNodeBinary, getCachedBinaryPath } = await import(pathToFileURL(exe).href);
|
|
2712
|
+
const useCodeCache = {};
|
|
3870
2713
|
for (const { name, target } of ${JSON.stringify(targets)}) {
|
|
3871
2714
|
try {
|
|
3872
2715
|
await resolveNodeBinary(target, {});
|
|
@@ -3874,7 +2717,23 @@ for (const { name, target } of ${JSON.stringify(targets)}) {
|
|
|
3874
2717
|
console.error(name + ": " + error.message + (error.cause?.message ? "\\n" + error.cause.message : ""));
|
|
3875
2718
|
process.exit(1);
|
|
3876
2719
|
}
|
|
3877
|
-
|
|
2720
|
+
// tsdown runs --build-sea with this Node, which writes the code cache; V8
|
|
2721
|
+
// rejects it (with a warning on every start) unless the embedded Node is this
|
|
2722
|
+
// exact binary with the same V8 flags, so another platform's or a distro build
|
|
2723
|
+
// of the same version, or NODE_OPTIONS such as --jitless, gets none. Decided
|
|
2724
|
+
// once per build: comparing reads both ~150 MB binaries.
|
|
2725
|
+
const embedded = getCachedBinaryPath(target);
|
|
2726
|
+
const host = (process.platform === "win32" ? "win" : process.platform) + "-" + process.arch;
|
|
2727
|
+
useCodeCache[name] = process.env.NODE_OPTIONS
|
|
2728
|
+
? "NODE_OPTIONS is set"
|
|
2729
|
+
: target.platform + "-" + target.arch !== host
|
|
2730
|
+
? "cross-built"
|
|
2731
|
+
: statSync(embedded, { throwIfNoEntry: false })?.size === statSync(process.execPath).size &&
|
|
2732
|
+
readFileSync(embedded).equals(readFileSync(process.execPath))
|
|
2733
|
+
? true
|
|
2734
|
+
: "the build's node is not the official v" + target.nodeVersion + " binary";
|
|
2735
|
+
}
|
|
2736
|
+
console.log(JSON.stringify(useCodeCache));
|
|
3878
2737
|
`;
|
|
3879
2738
|
}
|
|
3880
2739
|
/**
|
|
@@ -3887,6 +2746,9 @@ for (const { name, target } of ${JSON.stringify(targets)}) {
|
|
|
3887
2746
|
* download, or a checksum mismatch therefore fails here, before `.crust/` is
|
|
3888
2747
|
* replaced; cached targets need nothing.
|
|
3889
2748
|
*
|
|
2749
|
+
* @returns Per target, `true` when {@link execNodeBinaryBuild} may embed a V8 code
|
|
2750
|
+
* cache (the selected Node is byte-identical to the binary the target embeds and
|
|
2751
|
+
* `NODE_OPTIONS` is unset), or the reason it may not
|
|
3890
2752
|
* @throws {Error} If a target cannot be provisioned
|
|
3891
2753
|
*/
|
|
3892
2754
|
async function provisionNodeExeTargets(targets, cwd, compiler) {
|
|
@@ -3899,6 +2761,16 @@ async function provisionNodeExeTargets(targets, cwd, compiler) {
|
|
|
3899
2761
|
throw new Error(`Could not provision the Node ${compiler.version} binary that node standalone binaries embed${output ? `:\n${output}` : "."}\n tsdown downloads each target's official Node archive once and unpacks it with tar (GNU tar also needs xz for linux targets), or unzip for win targets on non-Windows hosts.
|
|
3900
2762
|
Install the missing tool, or build only targets this machine can provision (--target).`);
|
|
3901
2763
|
}
|
|
2764
|
+
const decided = JSON.parse(provision.stdout.trim().split("\n").at(-1) || "{}");
|
|
2765
|
+
return isJsonObject(decided) ? decided : {};
|
|
2766
|
+
}
|
|
2767
|
+
/** The build log's `Code cache:` value: `on`, `off (reason)`, or per-target groups when they differ. */
|
|
2768
|
+
function formatCodeCache(decisions) {
|
|
2769
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2770
|
+
for (const [target, decision] of Object.entries(decisions)) groups.set(decision, [...groups.get(decision) ?? [], target]);
|
|
2771
|
+
const entries = [...groups];
|
|
2772
|
+
if (entries.length === 1) return entries[0][0] === true ? "on" : `off (${entries[0][0]})`;
|
|
2773
|
+
return entries.map(([decision, targets]) => decision === true ? `on for ${targets.join(", ")}` : `off for ${targets.join(", ")} (${decision})`).join("; ");
|
|
3902
2774
|
}
|
|
3903
2775
|
/** Runs a generated `<name>.mjs` with `runner` from a temporary directory that is removed afterwards. */
|
|
3904
2776
|
async function runGeneratedScript(runner, name, source, cwd) {
|
|
@@ -3918,9 +2790,7 @@ async function runGeneratedScript(runner, name, source, cwd) {
|
|
|
3918
2790
|
});
|
|
3919
2791
|
}
|
|
3920
2792
|
}
|
|
3921
|
-
|
|
3922
|
-
//#region ../core/dist/index.js
|
|
3923
|
-
/** Mint an Extension identity from any non-blank, trimmed string. */
|
|
2793
|
+
// ../core/dist/index.js
|
|
3924
2794
|
function defineExtensionId(id) {
|
|
3925
2795
|
if (!id || id !== id.trim()) throw new CrustError("DEFINITION", "Extension id must be a non-empty, trimmed string", {
|
|
3926
2796
|
subject: "extension",
|
|
@@ -3928,15 +2798,8 @@ function defineExtensionId(id) {
|
|
|
3928
2798
|
});
|
|
3929
2799
|
return id;
|
|
3930
2800
|
}
|
|
3931
|
-
|
|
3932
|
-
//#region src/snapshot.ts
|
|
2801
|
+
// src/snapshot.ts
|
|
3933
2802
|
const SNAPSHOT_TIMEOUT_MS = 3e4;
|
|
3934
|
-
const SNAPSHOT_FORWARDED_SIGNALS = [
|
|
3935
|
-
"SIGINT",
|
|
3936
|
-
"SIGTERM",
|
|
3937
|
-
"SIGHUP",
|
|
3938
|
-
"SIGQUIT"
|
|
3939
|
-
];
|
|
3940
2803
|
function isBuildReport(value) {
|
|
3941
2804
|
return isJsonObject(value) && Array.isArray(value.extensions) && value.extensions.every((extension) => isJsonObject(extension) && typeof extension.id === "string" && Array.isArray(extension.files) && extension.files.every((file) => typeof file === "string"));
|
|
3942
2805
|
}
|
|
@@ -3997,27 +2860,18 @@ async function buildEntrypoint(entryPath, outDir, envFiles, io, cwd, runner = re
|
|
|
3997
2860
|
};
|
|
3998
2861
|
});
|
|
3999
2862
|
const timer = setTimeout(() => stop(`Command Snapshot preparation timed out after ${timeoutMs / 1e3}s.\n An Extension build hook may be hanging. Use --no-validate to skip entry preparation and build hooks.`), timeoutMs);
|
|
4000
|
-
const onSignal = (signal) => {
|
|
4001
|
-
removeLifetimeListeners();
|
|
4002
|
-
stop(`Command Snapshot preparation was interrupted by ${signal}.`);
|
|
4003
|
-
if (process.listenerCount(signal) === 0) process.kill(process.pid, signal);
|
|
4004
|
-
};
|
|
4005
2863
|
const killRemainingGroup = () => {
|
|
4006
2864
|
try {
|
|
4007
2865
|
killProcessTree(proc);
|
|
4008
2866
|
} catch {}
|
|
4009
2867
|
};
|
|
4010
|
-
const
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
};
|
|
4014
|
-
if (detached) {
|
|
4015
|
-
for (const signal of SNAPSHOT_FORWARDED_SIGNALS) process.prependListener(signal, onSignal);
|
|
4016
|
-
process.on("exit", killRemainingGroup);
|
|
4017
|
-
}
|
|
2868
|
+
const release = detached ? bindToProcessLifetime({
|
|
2869
|
+
onSignal: (signal) => stop(`Command Snapshot preparation was interrupted by ${signal}.`),
|
|
2870
|
+
onExit: killRemainingGroup
|
|
2871
|
+
}) : () => {};
|
|
4018
2872
|
const [rawStderr, [exitCode]] = await Promise.race([Promise.all([text(proc.stderr), once(proc, "close")]), stopped]).finally(() => {
|
|
4019
2873
|
clearTimeout(timer);
|
|
4020
|
-
|
|
2874
|
+
release();
|
|
4021
2875
|
if (detached) killRemainingGroup();
|
|
4022
2876
|
});
|
|
4023
2877
|
const stderr = rawStderr.trim();
|
|
@@ -4075,8 +2929,7 @@ async function buildEntrypoint(entryPath, outDir, envFiles, io, cwd, runner = re
|
|
|
4075
2929
|
});
|
|
4076
2930
|
}
|
|
4077
2931
|
}
|
|
4078
|
-
|
|
4079
|
-
//#region src/build.ts
|
|
2932
|
+
// src/build.ts
|
|
4080
2933
|
function readUserPackageJson(cwd) {
|
|
4081
2934
|
const packageJsonPath = join(cwd, "package.json");
|
|
4082
2935
|
if (!existsSync(packageJsonPath)) throw new Error(`package.json not found in ${cwd}\n crust build requires a package.json with name and version fields.`);
|
|
@@ -4165,7 +3018,6 @@ const NON_DEPENDENCY_SECTIONS = [
|
|
|
4165
3018
|
function validateExternal(external, pkg, runtime, artifact) {
|
|
4166
3019
|
if (external.length === 0) return;
|
|
4167
3020
|
if (artifact === "binary") throw new Error("package.json crust.external is not supported for standalone binaries (artifact binary).\n A binary bundles every dependency; remove crust.external or use artifact package.");
|
|
4168
|
-
if (runtime === "deno") throw new Error("package.json crust.external is not supported with the deno runtime.\n crust.external applies to Node and Bun runtime packages; remove crust.external or set crust.runtime to node or bun.");
|
|
4169
3021
|
const dependencies = pkg.dependencies !== void 0 && isJsonObject(pkg.dependencies) ? pkg.dependencies : {};
|
|
4170
3022
|
const rejectCrustPackage = (quoted, detail) => {
|
|
4171
3023
|
throw new Error(`package.json crust.external cannot name ${quoted}${detail}.\n Crust packages must stay bundled: core detects a packaged build through a define the bundler injects, and an external Crust package would load a second copy of core.`);
|
|
@@ -4186,23 +3038,17 @@ function validateExternal(external, pkg, runtime, artifact) {
|
|
|
4186
3038
|
if (aliased !== void 0) rejectCrustPackage(quoted, ` (an alias of ${aliased})`);
|
|
4187
3039
|
}
|
|
4188
3040
|
}
|
|
4189
|
-
const DENO_CONFIG_FILES = ["deno.json", "deno.jsonc"];
|
|
4190
3041
|
/**
|
|
4191
3042
|
* package.json `crust.runtime` > inference > Bun. Inference uses only
|
|
4192
|
-
* unambiguous signals:
|
|
4193
|
-
*
|
|
4194
|
-
*
|
|
3043
|
+
* unambiguous signals: `@types/node` without `@types/bun`. Lockfiles say which
|
|
3044
|
+
* package manager installed dependencies, not which runtime runs the CLI, so
|
|
3045
|
+
* they are not consulted.
|
|
4195
3046
|
*/
|
|
4196
|
-
function resolveBuildRuntime(pkg, config
|
|
3047
|
+
function resolveBuildRuntime(pkg, config) {
|
|
4197
3048
|
if (config.runtime !== void 0) return {
|
|
4198
3049
|
runtime: config.runtime,
|
|
4199
3050
|
source: "from package.json"
|
|
4200
3051
|
};
|
|
4201
|
-
const denoConfig = DENO_CONFIG_FILES.find((file) => existsSync(join(cwd, file)));
|
|
4202
|
-
if (denoConfig) return {
|
|
4203
|
-
runtime: "deno",
|
|
4204
|
-
source: `inferred from ${denoConfig}`
|
|
4205
|
-
};
|
|
4206
3052
|
if (hasDependency(pkg, "@types/node") && !hasDependency(pkg, "@types/bun")) return {
|
|
4207
3053
|
runtime: "node",
|
|
4208
3054
|
source: "inferred from @types/node"
|
|
@@ -4285,30 +3131,18 @@ function resolveBinEntries(cwd, pkg) {
|
|
|
4285
3131
|
};
|
|
4286
3132
|
});
|
|
4287
3133
|
}
|
|
4288
|
-
/** What earlier releases built for each runtime without being asked; quoted in the migration error. */
|
|
4289
|
-
const IMPLICIT_ARTIFACTS = {
|
|
4290
|
-
bun: "binary",
|
|
4291
|
-
deno: "binary",
|
|
4292
|
-
node: "package"
|
|
4293
|
-
};
|
|
4294
3134
|
/** `option` (the `artifact` build option or `--artifact`) > package.json `crust.artifact`; no default. */
|
|
4295
|
-
function resolveArtifact(option, config
|
|
3135
|
+
function resolveArtifact(option, config) {
|
|
4296
3136
|
if (option !== void 0 && !isArtifactKind(option)) throw new Error(`Invalid artifact ${JSON.stringify(option)}. Valid artifacts: ${ARTIFACT_KINDS.join(", ")}`);
|
|
4297
3137
|
const artifact = option ?? config.artifact;
|
|
4298
|
-
if (artifact === void 0) {
|
|
4299
|
-
const previous = IMPLICIT_ARTIFACTS[runtime];
|
|
4300
|
-
throw new Error(`crust build needs an artifact kind: pass --artifact package|binary or set package.json "crust": { "artifact": "package" | "binary" }.
|
|
4301
|
-
package: one JavaScript bundle per command that runs on the consumer's installed runtime.
|
|
4302
|
-
binary: standalone executables in per-platform npm packages behind a Node launcher.
|
|
4303
|
-
Earlier versions built a ${previous} for the ${runtime} runtime implicitly; set "artifact": "${previous}" to keep that output.`);
|
|
4304
|
-
}
|
|
3138
|
+
if (artifact === void 0) throw new Error("crust build needs an artifact kind: pass --artifact package|binary or set package.json \"crust\": { \"artifact\": \"package\" | \"binary\" }.\n package: one JavaScript bundle per command that runs on the consumer's installed runtime.\n binary: standalone executables in per-platform npm packages behind a Node launcher.");
|
|
4305
3139
|
return artifact;
|
|
4306
3140
|
}
|
|
4307
3141
|
function planBuild(options, cwd) {
|
|
4308
3142
|
const userPackageJson = readUserPackageJson(cwd);
|
|
4309
3143
|
const config = readCrustConfig(userPackageJson);
|
|
4310
|
-
const { runtime, source: runtimeSource } = resolveBuildRuntime(userPackageJson, config
|
|
4311
|
-
const artifact = resolveArtifact(options.artifact, config
|
|
3144
|
+
const { runtime, source: runtimeSource } = resolveBuildRuntime(userPackageJson, config);
|
|
3145
|
+
const artifact = resolveArtifact(options.artifact, config);
|
|
4312
3146
|
const entries = resolveBinEntries(cwd, userPackageJson);
|
|
4313
3147
|
validatePackageIdentity(userPackageJson, "package.json");
|
|
4314
3148
|
const envFiles = resolveEnvFilePaths(cwd, options.envFiles);
|
|
@@ -4316,10 +3150,8 @@ function planBuild(options, cwd) {
|
|
|
4316
3150
|
const external = config.external ?? [];
|
|
4317
3151
|
if (artifact === "package" && options.targets?.length) throw new Error("--target cannot be used with runtime packages (artifact package).\n A runtime package is one portable JavaScript bundle; drop --target or use artifact binary.");
|
|
4318
3152
|
if (artifact === "package" && config.targets !== void 0) throw new Error("package.json crust.targets is not supported for runtime packages (artifact package).\n A runtime package is one portable JavaScript bundle; remove crust.targets or set \"artifact\": \"binary\".");
|
|
4319
|
-
const
|
|
4320
|
-
if (
|
|
4321
|
-
if (runtime === "deno" && envFiles.length > 0) throw new Error(artifact === "binary" ? "--env-file is not supported with the deno runtime.\n deno compile embeds every variable from the file into the binary — secrets included —\n with no PUBLIC_* filter. Load configuration at runtime instead (e.g. deno run --env-file)." : "--env-file is not supported with the deno runtime.\n deno bundle has no PUBLIC_* build-time constants. Load configuration at runtime instead (e.g. deno run --env-file).");
|
|
4322
|
-
if (runtime === "deno" && bunPlugins.length > 0) throw new Error(`package.json crust.bunPlugins is not supported with the deno runtime.\n ${denoTool} has no Bun bundler; remove crust.bunPlugins or set crust.runtime to bun.`);
|
|
3153
|
+
const bunBinary = runtime === "bun" && artifact === "binary";
|
|
3154
|
+
if (options.bytecode && !bunBinary) throw new Error(artifact === "package" ? "--bytecode is not supported for runtime packages (artifact package).\n Bun bytecode only runs on the exact Bun version that built it, so it is embedded in bun binaries only; drop the flag." : `--bytecode is not supported with the ${runtime} runtime.\n Bytecode is Bun's JavaScriptCore format; Node binaries cannot use it. Drop the flag.`);
|
|
4323
3155
|
if (runtime === "node" && artifact === "binary" && bunPlugins.length > 0) throw new Error("package.json crust.bunPlugins is not supported for node standalone binaries.\n Remove crust.bunPlugins, or use artifact package or the bun runtime.");
|
|
4324
3156
|
validateExternal(external, userPackageJson, runtime, artifact);
|
|
4325
3157
|
const stageDir = resolve(cwd, CRUST_DIR);
|
|
@@ -4335,7 +3167,8 @@ function planBuild(options, cwd) {
|
|
|
4335
3167
|
outDir: join(stageDir, "artifacts"),
|
|
4336
3168
|
stageDir,
|
|
4337
3169
|
validate: options.validate ?? true,
|
|
4338
|
-
minify:
|
|
3170
|
+
minify: options.minify ?? true,
|
|
3171
|
+
bytecode: bunBinary && (options.bytecode ?? true)
|
|
4339
3172
|
};
|
|
4340
3173
|
if (artifact === "package") return {
|
|
4341
3174
|
...common,
|
|
@@ -4349,17 +3182,11 @@ function planBuild(options, cwd) {
|
|
|
4349
3182
|
artifact,
|
|
4350
3183
|
targets: resolveTargets(BUN_TARGETS, targetInputs)
|
|
4351
3184
|
};
|
|
4352
|
-
if (runtime === "node") return {
|
|
4353
|
-
...common,
|
|
4354
|
-
runtime,
|
|
4355
|
-
artifact,
|
|
4356
|
-
targets: resolveTargets(NODE_TARGETS, targetInputs)
|
|
4357
|
-
};
|
|
4358
3185
|
return {
|
|
4359
3186
|
...common,
|
|
4360
3187
|
runtime,
|
|
4361
3188
|
artifact,
|
|
4362
|
-
targets: resolveTargets(
|
|
3189
|
+
targets: resolveTargets(NODE_TARGETS, targetInputs)
|
|
4363
3190
|
};
|
|
4364
3191
|
}
|
|
4365
3192
|
/**
|
|
@@ -4368,20 +3195,10 @@ function planBuild(options, cwd) {
|
|
|
4368
3195
|
* the selected compiler's own version (`resolveBinaryCompiler`, or
|
|
4369
3196
|
* `resolveNodeBinaryCompiler` with tsdown's requirements for node, whose
|
|
4370
3197
|
* targets' embedded Node binaries are also provisioned here); runtime
|
|
4371
|
-
* packages are bundled by Bun
|
|
4372
|
-
*
|
|
4373
|
-
* against the bundler.
|
|
3198
|
+
* packages are bundled by Bun and embed no runtime, so engines stay a consumer
|
|
3199
|
+
* requirement there and are not checked against the bundler.
|
|
4374
3200
|
*/
|
|
4375
3201
|
async function selectCompilers(plan, io) {
|
|
4376
|
-
if (plan.artifact === "package" && plan.runtime === "deno") {
|
|
4377
|
-
const bundler = await resolveDenoPackageBundler(plan.cwd);
|
|
4378
|
-
io.stdout(`${dim("Compiler:")} deno ${bundler.version} ${dim(`(${bundler.runner.command}, deno bundle)`)}`);
|
|
4379
|
-
io.stderr("Deno runtime packages are experimental: they are bundled with deno bundle, which Deno marks experimental.");
|
|
4380
|
-
return {
|
|
4381
|
-
snapshotRunner: plan.validate ? resolveBunBuildRunner() : void 0,
|
|
4382
|
-
stage: (reports) => runDistributeBuild(plan, { execute: (entry, outfile) => execDenoPackageBuild(entry, outfile, plan.cwd, bundler.runner) }, io, reports)
|
|
4383
|
-
};
|
|
4384
|
-
}
|
|
4385
3202
|
if (plan.artifact === "package") {
|
|
4386
3203
|
const runner = resolveBunBuildRunner();
|
|
4387
3204
|
const target = plan.runtime === "bun" ? "bun" : "node";
|
|
@@ -4394,42 +3211,31 @@ async function selectCompilers(plan, io) {
|
|
|
4394
3211
|
if (plan.runtime === "node") {
|
|
4395
3212
|
const compiler = await resolveNodeBinaryCompiler(plan.userPackageJson, plan.cwd);
|
|
4396
3213
|
printCompiler(compiler);
|
|
4397
|
-
await provisionNodeExeTargets(plan.targets, plan.cwd, compiler);
|
|
3214
|
+
const useCodeCache = await provisionNodeExeTargets(plan.targets, plan.cwd, compiler);
|
|
3215
|
+
io.stdout(`${dim("Code cache:")} ${formatCodeCache(useCodeCache)}`);
|
|
4398
3216
|
const bunRunner = resolveBunBuildRunner();
|
|
4399
3217
|
const distribution = {
|
|
4400
3218
|
table: NODE_TARGETS,
|
|
4401
3219
|
targets: plan.targets,
|
|
4402
3220
|
embeddedRuntimeVersion: compiler.version,
|
|
4403
|
-
execute: (entry, outfile, target) => execNodeBinaryBuild(entry, outfile, target, plan, compiler, bunRunner, io.stderr)
|
|
3221
|
+
execute: (entry, outfile, target) => execNodeBinaryBuild(entry, outfile, target, plan, compiler, bunRunner, io.stderr, useCodeCache[target] === true)
|
|
4404
3222
|
};
|
|
4405
3223
|
return {
|
|
4406
3224
|
snapshotRunner: bunRunner,
|
|
4407
3225
|
stage: (reports) => runDistributeBuild(plan, distribution, io, reports)
|
|
4408
3226
|
};
|
|
4409
3227
|
}
|
|
4410
|
-
const compiler = await resolveBinaryCompiler(plan.
|
|
3228
|
+
const compiler = await resolveBinaryCompiler(plan.userPackageJson, plan.cwd);
|
|
4411
3229
|
printCompiler(compiler);
|
|
4412
|
-
|
|
4413
|
-
assertTargetsBuildableWithoutBun(plan.targets, compiler.runner);
|
|
4414
|
-
const distribution = {
|
|
4415
|
-
table: BUN_TARGETS,
|
|
4416
|
-
targets: plan.targets,
|
|
4417
|
-
embeddedRuntimeVersion: compiler.version,
|
|
4418
|
-
execute: (entry, outfile, target) => execBuild(entry, outfile, target, plan, compiler.runner)
|
|
4419
|
-
};
|
|
4420
|
-
return {
|
|
4421
|
-
snapshotRunner: compiler.runner,
|
|
4422
|
-
stage: (reports) => runDistributeBuild(plan, distribution, io, reports)
|
|
4423
|
-
};
|
|
4424
|
-
}
|
|
3230
|
+
assertTargetsBuildableWithoutBun(plan.targets, compiler.runner);
|
|
4425
3231
|
const distribution = {
|
|
4426
|
-
table:
|
|
3232
|
+
table: BUN_TARGETS,
|
|
4427
3233
|
targets: plan.targets,
|
|
4428
3234
|
embeddedRuntimeVersion: compiler.version,
|
|
4429
|
-
execute: (entry, outfile, target) =>
|
|
3235
|
+
execute: (entry, outfile, target) => execBuild(entry, outfile, target, plan, compiler.runner)
|
|
4430
3236
|
};
|
|
4431
3237
|
return {
|
|
4432
|
-
snapshotRunner:
|
|
3238
|
+
snapshotRunner: compiler.runner,
|
|
4433
3239
|
stage: (reports) => runDistributeBuild(plan, distribution, io, reports)
|
|
4434
3240
|
};
|
|
4435
3241
|
}
|
|
@@ -4469,10 +3275,8 @@ async function prepareEntries(plan, io, runner) {
|
|
|
4469
3275
|
* come from `bin`; the runtime, artifact, Bun plugins, extra directories, and
|
|
4470
3276
|
* external dependencies from package.json `crust`. Bundling and Command
|
|
4471
3277
|
* Snapshots run in bun subprocesses (bun on PATH, or the running Bun
|
|
4472
|
-
* executable), so this works under Node as well when Bun is installed;
|
|
4473
|
-
* binaries
|
|
4474
|
-
* deno on PATH, and Node binaries a node on PATH that Crust's tsdown can build
|
|
4475
|
-
* executables with.
|
|
3278
|
+
* executable), so this works under Node as well when Bun is installed; Node
|
|
3279
|
+
* binaries need a node on PATH that Crust's tsdown can build executables with.
|
|
4476
3280
|
*
|
|
4477
3281
|
* Throws on any failure. Planning and compiler-selection failures (bad
|
|
4478
3282
|
* options or package.json, a missing or hung compiler, an engines mismatch) leave the
|
|
@@ -4500,6 +3304,10 @@ async function build(options = {}) {
|
|
|
4500
3304
|
const plan = planBuild(options, cwd);
|
|
4501
3305
|
io.stdout(`${dim("Runtime:")} ${plan.runtime} ${dim(`(${plan.runtimeSource})`)}`);
|
|
4502
3306
|
io.stdout(`${dim("Artifact:")} ${plan.artifact}`);
|
|
3307
|
+
for (const { entryPath } of plan.entries) {
|
|
3308
|
+
const named = /^#![^\n]*\b(bun|node)\b/.exec(readFileSync(entryPath, "utf8"))?.[1];
|
|
3309
|
+
if (named !== void 0 && named !== plan.runtime) io.stderr(`${yellow("Warning:")} ${entryPath} starts with a ${named} shebang but crust.runtime is "${plan.runtime}". The build targets ${plan.runtime}; a linked command (npm link) still starts ${named}.`);
|
|
3310
|
+
}
|
|
4503
3311
|
const compilers = await selectCompilers(plan, io);
|
|
4504
3312
|
rmSync(plan.stageDir, {
|
|
4505
3313
|
recursive: true,
|
|
@@ -4516,5 +3324,4 @@ async function build(options = {}) {
|
|
|
4516
3324
|
rmdirSync(lockDir);
|
|
4517
3325
|
}
|
|
4518
3326
|
}
|
|
4519
|
-
//#endregion
|
|
4520
3327
|
export { build };
|