@crustjs/crust-linux-x64 0.4.1 → 0.5.0
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 +2 -2
- package/bin/dist/index.d.ts +31 -13
- package/bin/dist/index.js +1849 -365
- package/bin/schema/package.json +11 -3
- package/package.json +48 -44
package/bin/dist/index.js
CHANGED
|
@@ -1,169 +1,34 @@
|
|
|
1
1
|
import { accessSync, constants, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { chmod, copyFile, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
import { spawn } from "node:child_process";
|
|
5
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
7
6
|
import { randomBytes } from "node:crypto";
|
|
8
7
|
import { once } from "node:events";
|
|
9
8
|
import { text } from "node:stream/consumers";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* import { CrustError } from "@crustjs/core";
|
|
29
|
-
*
|
|
30
|
-
* const outcome = await app.run(["deploy"], { args: { target: "prod" } });
|
|
31
|
-
* if (outcome.status === "failed") {
|
|
32
|
-
* const err = outcome.error;
|
|
33
|
-
* if (err instanceof CrustError) {
|
|
34
|
-
* console.error(`[${err.code}] ${err.message}`);
|
|
35
|
-
* }
|
|
36
|
-
* }
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
var CrustError = class extends Error {
|
|
40
|
-
/** Machine-readable error code for programmatic handling */
|
|
41
|
-
code;
|
|
42
|
-
/** Structured payload for programmatic handling */
|
|
43
|
-
details;
|
|
44
|
-
/** Optional wrapped original error/value */
|
|
45
|
-
cause;
|
|
46
|
-
constructor(code, message, ...details) {
|
|
47
|
-
super(message);
|
|
48
|
-
this.name = "CrustError";
|
|
49
|
-
this.code = code;
|
|
50
|
-
this.details = details[0];
|
|
51
|
-
}
|
|
52
|
-
is(code) {
|
|
53
|
-
return Object.is(this.code, code);
|
|
54
|
-
}
|
|
55
|
-
withCause(cause) {
|
|
56
|
-
this.cause = cause;
|
|
57
|
-
return this;
|
|
58
|
-
}
|
|
59
|
-
toJSON() {
|
|
60
|
-
return {
|
|
61
|
-
code: this.code,
|
|
62
|
-
message: this.message,
|
|
63
|
-
details: this.details
|
|
64
|
-
};
|
|
9
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
|
+
//#region \0rolldown/runtime.js
|
|
11
|
+
var __create = Object.create;
|
|
12
|
+
var __defProp$1 = Object.defineProperty;
|
|
13
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
16
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
20
|
+
key = keys[i];
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp$1(to, key, {
|
|
22
|
+
get: ((k) => from[k]).bind(null, key),
|
|
23
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
24
|
+
});
|
|
65
25
|
}
|
|
26
|
+
return to;
|
|
66
27
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
subject,
|
|
72
|
-
name,
|
|
73
|
-
reason: "invalid-sections"
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
function normalizeSection(section, owner) {
|
|
77
|
-
const { title, body, only, except } = section;
|
|
78
|
-
if (!title.trim() || /[\r\n]/.test(title) || !body.trim() || only?.length === 0 || except?.length === 0 || only !== void 0 && except !== void 0) throw invalidSections(owner);
|
|
79
|
-
const audience = (ids) => {
|
|
80
|
-
return Object.freeze(ids.map((consumer) => typeof consumer === "string" ? consumer : consumer.id));
|
|
81
|
-
};
|
|
82
|
-
return Object.freeze({
|
|
83
|
-
title,
|
|
84
|
-
body,
|
|
85
|
-
...only ? { only: audience(only) } : except ? { except: audience(except) } : {}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
function validateCommandSections(name, sections) {
|
|
89
|
-
return sections.map((section) => normalizeSection(section, {
|
|
90
|
-
subject: "command",
|
|
91
|
-
name
|
|
92
|
-
}));
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Snapshot subprocess protocol used by first-party build tooling.
|
|
96
|
-
*
|
|
97
|
-
* When set to a non-empty file path, `.execute()` prepares the command tree,
|
|
98
|
-
* validates its documentation sections, optionally runs Extension build hooks when the
|
|
99
|
-
* build output directory is set, writes its final JSON snapshot and Build Report, and exits
|
|
100
|
-
* without dispatching a Command Action. In-process callers use `Crust.snapshot()`.
|
|
101
|
-
*
|
|
102
|
-
* Only source entries run by `crust build` honor it: finished Bun/Node bundles carry
|
|
103
|
-
* `process.env.CRUST_INTERNAL_BUILD === "1"` as a literal and compile the protocol out.
|
|
104
|
-
*/
|
|
105
|
-
const SNAPSHOT_PATH_ENV = "CRUST_INTERNAL_SNAPSHOT_PATH";
|
|
106
|
-
//#endregion
|
|
107
|
-
//#region ../core/dist/index.js
|
|
108
|
-
/** Mint an Extension identity from any non-blank, trimmed string. */
|
|
109
|
-
function defineExtensionId(id) {
|
|
110
|
-
if (!id.trim() || id !== id.trim()) throw new CrustError("DEFINITION", "Extension id must be a non-empty, trimmed string", {
|
|
111
|
-
subject: "extension",
|
|
112
|
-
reason: "empty-id"
|
|
113
|
-
});
|
|
114
|
-
return id;
|
|
115
|
-
}
|
|
116
|
-
const commandDefinitionInternal = Symbol.for("crust.commandDefinition");
|
|
117
|
-
function resolveCommandName(name, aliases = []) {
|
|
118
|
-
if (name.trim() === "") throw new CrustError("DEFINITION", "Command name must be a non-empty string", {
|
|
119
|
-
subject: "command",
|
|
120
|
-
name,
|
|
121
|
-
reason: "empty-name"
|
|
122
|
-
});
|
|
123
|
-
if (name === "__proto__") throw new CrustError("DEFINITION", "Command name \"__proto__\" is reserved", {
|
|
124
|
-
subject: "command",
|
|
125
|
-
name,
|
|
126
|
-
reason: "reserved-name"
|
|
127
|
-
});
|
|
128
|
-
if (aliases.includes(name)) throw new CrustError("DEFINITION", `Command "${name}" must not list its own canonical name as an alias`, {
|
|
129
|
-
subject: "command",
|
|
130
|
-
name,
|
|
131
|
-
reason: "alias-collision"
|
|
132
|
-
});
|
|
133
|
-
return name;
|
|
134
|
-
}
|
|
135
|
-
function isCommandRecipe(value) {
|
|
136
|
-
return typeof value === "function";
|
|
137
|
-
}
|
|
138
|
-
function defineCommand(nameInput, configOrRecipe, maybeRecipe) {
|
|
139
|
-
const hasConfig = !isCommandRecipe(configOrRecipe);
|
|
140
|
-
const config = hasConfig ? configOrRecipe : {};
|
|
141
|
-
const recipe = hasConfig ? maybeRecipe : configOrRecipe;
|
|
142
|
-
const name = resolveCommandName(nameInput, config.aliases);
|
|
143
|
-
for (const alias of config.aliases ?? []) if (alias === "" || /[ \t\n\r\v\f]/.test(alias) || alias.startsWith("-")) throw new CrustError("DEFINITION", `Command "${name}" has an invalid alias "${alias}"`);
|
|
144
|
-
const { sections, version: _rootVersion, ...metaRest } = config;
|
|
145
|
-
const meta = {
|
|
146
|
-
...metaRest,
|
|
147
|
-
...config.aliases ? { aliases: [...config.aliases] } : {},
|
|
148
|
-
...sections ? { sections: validateCommandSections(name, sections) } : {}
|
|
149
|
-
};
|
|
150
|
-
const internal = {
|
|
151
|
-
name,
|
|
152
|
-
recipe,
|
|
153
|
-
meta
|
|
154
|
-
};
|
|
155
|
-
const named = (defName) => {
|
|
156
|
-
return Object.freeze({
|
|
157
|
-
name: defName,
|
|
158
|
-
as: (newName) => named(resolveCommandName(newName, meta.aliases)),
|
|
159
|
-
[commandDefinitionInternal]: Object.freeze({
|
|
160
|
-
...internal,
|
|
161
|
-
name: defName
|
|
162
|
-
})
|
|
163
|
-
});
|
|
164
|
-
};
|
|
165
|
-
return named(name);
|
|
166
|
-
}
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp$1(target, "default", {
|
|
29
|
+
value: mod,
|
|
30
|
+
enumerable: true
|
|
31
|
+
}) : target, mod));
|
|
167
32
|
//#endregion
|
|
168
33
|
//#region ../style/dist/index.js
|
|
169
34
|
var __defProp = Object.defineProperty;
|
|
@@ -1463,15 +1328,7 @@ function linkCode(url, options) {
|
|
|
1463
1328
|
function link$1(text, url, options) {
|
|
1464
1329
|
return applyStyle(text, linkCode(url, options));
|
|
1465
1330
|
}
|
|
1466
|
-
const dynamicColorKinds = [[
|
|
1467
|
-
"fg",
|
|
1468
|
-
fgPairAtDepth,
|
|
1469
|
-
fg$1
|
|
1470
|
-
], [
|
|
1471
|
-
"bg",
|
|
1472
|
-
bgPairAtDepth,
|
|
1473
|
-
bg$1
|
|
1474
|
-
]];
|
|
1331
|
+
const dynamicColorKinds = [["fg", fg$1], ["bg", bg$1]];
|
|
1475
1332
|
const styleMethodPairs = ansiCodes_exports;
|
|
1476
1333
|
function stepIsModifier(step) {
|
|
1477
1334
|
return step.kind === "named" && isModifierName(step.name);
|
|
@@ -1480,6 +1337,21 @@ function stepPair(step, colorDepth) {
|
|
|
1480
1337
|
if (step.kind === "named") return styleMethodPairs[step.name];
|
|
1481
1338
|
return step.kind === "fg" ? fgPairAtDepth(step.input, colorDepth) : bgPairAtDepth(step.input, colorDepth);
|
|
1482
1339
|
}
|
|
1340
|
+
function colorStep(kind, input) {
|
|
1341
|
+
const step = {
|
|
1342
|
+
kind,
|
|
1343
|
+
input
|
|
1344
|
+
};
|
|
1345
|
+
stepPair(step, "truecolor");
|
|
1346
|
+
return Array.isArray(input) ? {
|
|
1347
|
+
kind,
|
|
1348
|
+
input: [
|
|
1349
|
+
input[0],
|
|
1350
|
+
input[1],
|
|
1351
|
+
input[2]
|
|
1352
|
+
]
|
|
1353
|
+
} : step;
|
|
1354
|
+
}
|
|
1483
1355
|
function applyChain(text, steps, resolveCapabilities) {
|
|
1484
1356
|
if (text == null) return "";
|
|
1485
1357
|
let result = String(text);
|
|
@@ -1527,16 +1399,10 @@ function buildChainableStyleFactory(resolveCapabilities, runtime) {
|
|
|
1527
1399
|
}]);
|
|
1528
1400
|
}
|
|
1529
1401
|
});
|
|
1530
|
-
for (const [kind
|
|
1402
|
+
for (const [kind] of dynamicColorKinds) Object.defineProperty(styleFn, kind, {
|
|
1531
1403
|
configurable: false,
|
|
1532
1404
|
enumerable: true,
|
|
1533
|
-
value: (input) =>
|
|
1534
|
-
pairAtDepth(input, "truecolor");
|
|
1535
|
-
return createChainableStyle([...steps, {
|
|
1536
|
-
kind,
|
|
1537
|
-
input
|
|
1538
|
-
}]);
|
|
1539
|
-
},
|
|
1405
|
+
value: (input) => createChainableStyle([...steps, colorStep(kind, input)]),
|
|
1540
1406
|
writable: false
|
|
1541
1407
|
});
|
|
1542
1408
|
let open = "";
|
|
@@ -1642,15 +1508,9 @@ function createStyleInstance(options, runtime) {
|
|
|
1642
1508
|
linkCode(url, hyperlinkOptions);
|
|
1643
1509
|
return text;
|
|
1644
1510
|
},
|
|
1645
|
-
...Object.fromEntries(dynamicColorKinds.map(([kind,
|
|
1511
|
+
...Object.fromEntries(dynamicColorKinds.map(([kind, paint]) => [kind, (...args) => {
|
|
1646
1512
|
const resolved = resolveCapabilities();
|
|
1647
|
-
if (args.length === 1)
|
|
1648
|
-
pairAtDepth(args[0], "truecolor");
|
|
1649
|
-
return createChainableStyle([{
|
|
1650
|
-
kind,
|
|
1651
|
-
input: args[0]
|
|
1652
|
-
}]);
|
|
1653
|
-
}
|
|
1513
|
+
if (args.length === 1) return createChainableStyle([colorStep(kind, args[0])]);
|
|
1654
1514
|
return paint(args[0], args[1], resolved.colorDepth);
|
|
1655
1515
|
}])),
|
|
1656
1516
|
...methods
|
|
@@ -1730,6 +1590,99 @@ function isWithin(parent, child) {
|
|
|
1730
1590
|
return path === "" || !isAbsolute(path) && path !== ".." && !path.startsWith(`..${sep}`);
|
|
1731
1591
|
}
|
|
1732
1592
|
//#endregion
|
|
1593
|
+
//#region ../utils/dist/artifacts.js
|
|
1594
|
+
/**
|
|
1595
|
+
* Set by `crust build` while it prepares the Command Snapshot: the absolute
|
|
1596
|
+
* entry-isolated directory Extension build hooks write into. Core reads it
|
|
1597
|
+
* to run the hooks; `resolveArtifactDir` reads it so sections evaluated during
|
|
1598
|
+
* that run see the artifacts being built instead of the wiped `.crust/root`.
|
|
1599
|
+
*/
|
|
1600
|
+
const BUILD_OUT_DIR_ENV = "CRUST_INTERNAL_BUILD_OUT_DIR";
|
|
1601
|
+
/**
|
|
1602
|
+
* `Symbol.for` registry key of the packaged-build marker, for bundlers without a
|
|
1603
|
+
* `define` option (native `deno bundle`). `crust build` prepends
|
|
1604
|
+
* `globalThis[Symbol.for(PACKAGED_BUILD_KEY)] = true` to the command bundle,
|
|
1605
|
+
* before the inlined application graph, so every bundled copy sees it.
|
|
1606
|
+
* The registry key is shared across module copies; the value is never read from
|
|
1607
|
+
* the environment, so detection needs no Deno env permission.
|
|
1608
|
+
*/
|
|
1609
|
+
const PACKAGED_BUILD_KEY = "crustjs.packagedBuild";
|
|
1610
|
+
//#endregion
|
|
1611
|
+
//#region ../core/dist/invocation-ljkrw2dt.js
|
|
1612
|
+
/**
|
|
1613
|
+
* A typed error for runtime recipe, Extension, Context, documentation, argv, and validation failures.
|
|
1614
|
+
*
|
|
1615
|
+
* Every `CrustError` carries a {@link CrustErrorCode} that identifies the specific
|
|
1616
|
+
* failure, enabling programmatic error handling without fragile message parsing.
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* ```ts
|
|
1620
|
+
* import { CrustError } from "@crustjs/core";
|
|
1621
|
+
*
|
|
1622
|
+
* const outcome = await app.run(["deploy"], { args: { target: "prod" } });
|
|
1623
|
+
* if (outcome.status === "failed") {
|
|
1624
|
+
* const err = outcome.error;
|
|
1625
|
+
* if (err instanceof CrustError) {
|
|
1626
|
+
* console.error(`[${err.code}] ${err.message}`);
|
|
1627
|
+
* }
|
|
1628
|
+
* }
|
|
1629
|
+
* ```
|
|
1630
|
+
*/
|
|
1631
|
+
var CrustError = class extends Error {
|
|
1632
|
+
/** Machine-readable error code for programmatic handling */
|
|
1633
|
+
code;
|
|
1634
|
+
/** Structured payload for programmatic handling */
|
|
1635
|
+
details;
|
|
1636
|
+
/** Optional wrapped original error/value */
|
|
1637
|
+
cause;
|
|
1638
|
+
constructor(code, message, ...details) {
|
|
1639
|
+
super(message);
|
|
1640
|
+
this.name = "CrustError";
|
|
1641
|
+
this.code = code;
|
|
1642
|
+
this.details = details[0];
|
|
1643
|
+
}
|
|
1644
|
+
is(code) {
|
|
1645
|
+
return Object.is(this.code, code);
|
|
1646
|
+
}
|
|
1647
|
+
withCause(cause) {
|
|
1648
|
+
this.cause = cause;
|
|
1649
|
+
return this;
|
|
1650
|
+
}
|
|
1651
|
+
toJSON() {
|
|
1652
|
+
return {
|
|
1653
|
+
code: this.code,
|
|
1654
|
+
message: this.message,
|
|
1655
|
+
details: this.details
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
globalThis.AsyncDisposableStack;
|
|
1660
|
+
Object.freeze({ [Symbol("crust.finished")]: true });
|
|
1661
|
+
/**
|
|
1662
|
+
* Snapshot subprocess protocol used by first-party build tooling.
|
|
1663
|
+
*
|
|
1664
|
+
* When set to a non-empty file path, `.execute()` prepares the command tree,
|
|
1665
|
+
* validates its documentation sections, optionally runs Extension build hooks when the
|
|
1666
|
+
* build output directory is set, writes its final JSON snapshot and Build Report, and exits
|
|
1667
|
+
* without dispatching a Command Action. In-process callers use `Crust.snapshot()`.
|
|
1668
|
+
*
|
|
1669
|
+
* Only source entries run by `crust build` honor it: finished Bun/Node bundles carry
|
|
1670
|
+
* `process.env.CRUST_INTERNAL_BUILD === "1"` as a literal and compile the protocol out;
|
|
1671
|
+
* packaged Deno bundles set the `isPackagedBuild()` marker and skip it without
|
|
1672
|
+
* reading the environment.
|
|
1673
|
+
*/
|
|
1674
|
+
const SNAPSHOT_PATH_ENV = "CRUST_INTERNAL_SNAPSHOT_PATH";
|
|
1675
|
+
//#endregion
|
|
1676
|
+
//#region ../core/dist/index.js
|
|
1677
|
+
/** Mint an Extension identity from any non-blank, trimmed string. */
|
|
1678
|
+
function defineExtensionId(id) {
|
|
1679
|
+
if (!id.trim() || id !== id.trim()) throw new CrustError("DEFINITION", "Extension id must be a non-empty, trimmed string", {
|
|
1680
|
+
subject: "extension",
|
|
1681
|
+
reason: "empty-id"
|
|
1682
|
+
});
|
|
1683
|
+
return id;
|
|
1684
|
+
}
|
|
1685
|
+
//#endregion
|
|
1733
1686
|
//#region ../utils/dist/error.js
|
|
1734
1687
|
/** Narrows a caught Node.js system error to its stable errno contract. */
|
|
1735
1688
|
function isErrnoException(error) {
|
|
@@ -1766,11 +1719,42 @@ function getWindowsShimCommand(command, args, shell, platform = process.platform
|
|
|
1766
1719
|
};
|
|
1767
1720
|
}
|
|
1768
1721
|
/**
|
|
1722
|
+
* @internal Kill a POSIX process group (spawned with `detached: true`) or a
|
|
1723
|
+
* live Windows process tree. Descendants that leave the group are not reached.
|
|
1724
|
+
* If POSIX group signaling fails, try the direct child before rethrowing.
|
|
1725
|
+
*/
|
|
1726
|
+
function killProcessTree(child) {
|
|
1727
|
+
if (child.pid === void 0) return;
|
|
1728
|
+
if (process.platform === "win32") {
|
|
1729
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
1730
|
+
const result = spawnSync("taskkill", [
|
|
1731
|
+
"/pid",
|
|
1732
|
+
String(child.pid),
|
|
1733
|
+
"/T",
|
|
1734
|
+
"/F"
|
|
1735
|
+
], {
|
|
1736
|
+
stdio: "ignore",
|
|
1737
|
+
timeout: 1e4
|
|
1738
|
+
});
|
|
1739
|
+
if (result.error || result.status !== 0) child.kill("SIGKILL");
|
|
1740
|
+
}
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
try {
|
|
1744
|
+
process.kill(-child.pid, "SIGKILL");
|
|
1745
|
+
} catch (error) {
|
|
1746
|
+
if (error.code === "ESRCH") return;
|
|
1747
|
+
child.kill("SIGKILL");
|
|
1748
|
+
throw error;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1769
1752
|
* Spawn a process and wait for it to exit without imposing an error policy.
|
|
1770
1753
|
*
|
|
1771
|
-
* On Windows, the automatic `.cmd`/`.bat` workaround
|
|
1772
|
-
*
|
|
1773
|
-
*
|
|
1754
|
+
* On Windows, the automatic `.cmd`/`.bat` workaround supports command shims
|
|
1755
|
+
* forwarding arguments through `%*`, not arbitrary batch files consuming `%1`.
|
|
1756
|
+
* Unsafe shell-expansion characters throw before spawning. Explicit `shell: true`
|
|
1757
|
+
* calls are passed through unchanged and own their shell escaping.
|
|
1774
1758
|
*/
|
|
1775
1759
|
async function runProcess(command, args = [], options = {}) {
|
|
1776
1760
|
const windowsShimCommand = getWindowsShimCommand(command, args, options.shell);
|
|
@@ -1785,18 +1769,39 @@ async function runProcess(command, args = [], options = {}) {
|
|
|
1785
1769
|
collectStdout ? "pipe" : "ignore",
|
|
1786
1770
|
"pipe"
|
|
1787
1771
|
] : "inherit",
|
|
1772
|
+
detached: options.timeout !== void 0 && process.platform !== "win32",
|
|
1788
1773
|
windowsVerbatimArguments: windowsShimCommand?.windowsVerbatimArguments
|
|
1789
1774
|
});
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1775
|
+
let timer;
|
|
1776
|
+
const deadline = new Promise((_, reject) => {
|
|
1777
|
+
if (options.timeout === void 0) return;
|
|
1778
|
+
const timeout = options.timeout;
|
|
1779
|
+
timer = setTimeout(() => {
|
|
1780
|
+
let failure = /* @__PURE__ */ new Error(`${[command, ...args].join(" ")} did not exit within ${timeout} ms and was killed.`);
|
|
1781
|
+
try {
|
|
1782
|
+
killProcessTree(proc);
|
|
1783
|
+
} catch (cause) {
|
|
1784
|
+
failure = new Error("Process-tree cleanup failed after timeout.", { cause });
|
|
1785
|
+
}
|
|
1786
|
+
proc.stdout?.destroy();
|
|
1787
|
+
proc.stderr?.destroy();
|
|
1788
|
+
reject(failure);
|
|
1789
|
+
}, timeout);
|
|
1790
|
+
});
|
|
1791
|
+
try {
|
|
1792
|
+
const [stdout, stderr, [exitCode]] = await Promise.race([Promise.all([
|
|
1793
|
+
collectStdout ? text(proc.stdout) : "",
|
|
1794
|
+
collect ? text(proc.stderr) : "",
|
|
1795
|
+
once(proc, "close")
|
|
1796
|
+
]), deadline]);
|
|
1797
|
+
return {
|
|
1798
|
+
exitCode,
|
|
1799
|
+
stdout,
|
|
1800
|
+
stderr
|
|
1801
|
+
};
|
|
1802
|
+
} finally {
|
|
1803
|
+
clearTimeout(timer);
|
|
1804
|
+
}
|
|
1800
1805
|
}
|
|
1801
1806
|
/** Resolve a bare executable name from PATH (and PATHEXT on Windows). */
|
|
1802
1807
|
function which(command) {
|
|
@@ -1818,53 +1823,908 @@ function which(command) {
|
|
|
1818
1823
|
return null;
|
|
1819
1824
|
}
|
|
1820
1825
|
//#endregion
|
|
1821
|
-
//#region
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1826
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/lrucache.js
|
|
1827
|
+
var require_lrucache = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1828
|
+
var LRUCache = class {
|
|
1829
|
+
constructor() {
|
|
1830
|
+
this.max = 1e3;
|
|
1831
|
+
this.map = /* @__PURE__ */ new Map();
|
|
1832
|
+
}
|
|
1833
|
+
get(key) {
|
|
1834
|
+
const value = this.map.get(key);
|
|
1835
|
+
if (value === void 0) return;
|
|
1836
|
+
else {
|
|
1837
|
+
this.map.delete(key);
|
|
1838
|
+
this.map.set(key, value);
|
|
1839
|
+
return value;
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
delete(key) {
|
|
1843
|
+
return this.map.delete(key);
|
|
1844
|
+
}
|
|
1845
|
+
set(key, value) {
|
|
1846
|
+
if (!this.delete(key) && value !== void 0) {
|
|
1847
|
+
if (this.map.size >= this.max) {
|
|
1848
|
+
const firstKey = this.map.keys().next().value;
|
|
1849
|
+
this.delete(firstKey);
|
|
1850
|
+
}
|
|
1851
|
+
this.map.set(key, value);
|
|
1852
|
+
}
|
|
1853
|
+
return this;
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
module.exports = LRUCache;
|
|
1857
|
+
}));
|
|
1858
|
+
//#endregion
|
|
1859
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/parse-options.js
|
|
1860
|
+
var require_parse_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1861
|
+
const looseOption = Object.freeze({ loose: true });
|
|
1862
|
+
const emptyOpts = Object.freeze({});
|
|
1863
|
+
const parseOptions = (options) => {
|
|
1864
|
+
if (!options) return emptyOpts;
|
|
1865
|
+
if (typeof options !== "object") return looseOption;
|
|
1866
|
+
return options;
|
|
1867
|
+
};
|
|
1868
|
+
module.exports = parseOptions;
|
|
1869
|
+
}));
|
|
1870
|
+
//#endregion
|
|
1871
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/constants.js
|
|
1872
|
+
var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1873
|
+
module.exports = {
|
|
1874
|
+
MAX_LENGTH: 256,
|
|
1875
|
+
MAX_SAFE_COMPONENT_LENGTH: 16,
|
|
1876
|
+
MAX_SAFE_BUILD_LENGTH: 250,
|
|
1877
|
+
MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER ||
|
|
1878
|
+
/* istanbul ignore next */ 9007199254740991,
|
|
1879
|
+
RELEASE_TYPES: [
|
|
1880
|
+
"major",
|
|
1881
|
+
"premajor",
|
|
1882
|
+
"minor",
|
|
1883
|
+
"preminor",
|
|
1884
|
+
"patch",
|
|
1885
|
+
"prepatch",
|
|
1886
|
+
"prerelease"
|
|
1887
|
+
],
|
|
1888
|
+
SEMVER_SPEC_VERSION: "2.0.0",
|
|
1889
|
+
FLAG_INCLUDE_PRERELEASE: 1,
|
|
1890
|
+
FLAG_LOOSE: 2
|
|
1891
|
+
};
|
|
1892
|
+
}));
|
|
1893
|
+
//#endregion
|
|
1894
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/debug.js
|
|
1895
|
+
var require_debug = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1896
|
+
module.exports = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => {};
|
|
1897
|
+
}));
|
|
1898
|
+
//#endregion
|
|
1899
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/re.js
|
|
1900
|
+
var require_re = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1901
|
+
const { MAX_SAFE_COMPONENT_LENGTH, MAX_SAFE_BUILD_LENGTH, MAX_LENGTH } = require_constants();
|
|
1902
|
+
const debug = require_debug();
|
|
1903
|
+
exports = module.exports = {};
|
|
1904
|
+
const re = exports.re = [];
|
|
1905
|
+
const safeRe = exports.safeRe = [];
|
|
1906
|
+
const src = exports.src = [];
|
|
1907
|
+
const safeSrc = exports.safeSrc = [];
|
|
1908
|
+
const t = exports.t = {};
|
|
1909
|
+
let R = 0;
|
|
1910
|
+
const LETTERDASHNUMBER = "[a-zA-Z0-9-]";
|
|
1911
|
+
const safeRegexReplacements = [
|
|
1912
|
+
["\\s", 1],
|
|
1913
|
+
["\\d", MAX_LENGTH],
|
|
1914
|
+
[LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH]
|
|
1915
|
+
];
|
|
1916
|
+
const makeSafeRegex = (value) => {
|
|
1917
|
+
for (const [token, max] of safeRegexReplacements) value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`);
|
|
1918
|
+
return value;
|
|
1919
|
+
};
|
|
1920
|
+
const createToken = (name, value, isGlobal) => {
|
|
1921
|
+
const safe = makeSafeRegex(value);
|
|
1922
|
+
const index = R++;
|
|
1923
|
+
debug(name, index, value);
|
|
1924
|
+
t[name] = index;
|
|
1925
|
+
src[index] = value;
|
|
1926
|
+
safeSrc[index] = safe;
|
|
1927
|
+
re[index] = new RegExp(value, isGlobal ? "g" : void 0);
|
|
1928
|
+
safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0);
|
|
1929
|
+
};
|
|
1930
|
+
createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*");
|
|
1931
|
+
createToken("NUMERICIDENTIFIERLOOSE", "\\d+");
|
|
1932
|
+
createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`);
|
|
1933
|
+
createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`);
|
|
1934
|
+
createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`);
|
|
1935
|
+
createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`);
|
|
1936
|
+
createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`);
|
|
1937
|
+
createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`);
|
|
1938
|
+
createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`);
|
|
1939
|
+
createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`);
|
|
1940
|
+
createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`);
|
|
1941
|
+
createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`);
|
|
1942
|
+
createToken("FULL", `^${src[t.FULLPLAIN]}$`);
|
|
1943
|
+
createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`);
|
|
1944
|
+
createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`);
|
|
1945
|
+
createToken("GTLT", "((?:<|>)?=?)");
|
|
1946
|
+
createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);
|
|
1947
|
+
createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`);
|
|
1948
|
+
createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`);
|
|
1949
|
+
createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`);
|
|
1950
|
+
createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`);
|
|
1951
|
+
createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`);
|
|
1952
|
+
createToken("COERCEPLAIN", `(^|[^\\d])(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`);
|
|
1953
|
+
createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`);
|
|
1954
|
+
createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`);
|
|
1955
|
+
createToken("COERCERTL", src[t.COERCE], true);
|
|
1956
|
+
createToken("COERCERTLFULL", src[t.COERCEFULL], true);
|
|
1957
|
+
createToken("LONETILDE", "(?:~>?)");
|
|
1958
|
+
createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true);
|
|
1959
|
+
exports.tildeTrimReplace = "$1~";
|
|
1960
|
+
createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`);
|
|
1961
|
+
createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`);
|
|
1962
|
+
createToken("LONECARET", "(?:\\^)");
|
|
1963
|
+
createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true);
|
|
1964
|
+
exports.caretTrimReplace = "$1^";
|
|
1965
|
+
createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`);
|
|
1966
|
+
createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`);
|
|
1967
|
+
createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`);
|
|
1968
|
+
createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`);
|
|
1969
|
+
createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true);
|
|
1970
|
+
exports.comparatorTrimReplace = "$1$2$3";
|
|
1971
|
+
createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`);
|
|
1972
|
+
createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`);
|
|
1973
|
+
createToken("STAR", "(<|>)?=?\\s*\\*");
|
|
1974
|
+
createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$");
|
|
1975
|
+
createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$");
|
|
1976
|
+
}));
|
|
1977
|
+
//#endregion
|
|
1978
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/identifiers.js
|
|
1979
|
+
var require_identifiers = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1980
|
+
const numeric = /^[0-9]+$/;
|
|
1981
|
+
const compareIdentifiers = (a, b) => {
|
|
1982
|
+
if (typeof a === "number" && typeof b === "number") return a === b ? 0 : a < b ? -1 : 1;
|
|
1983
|
+
const anum = numeric.test(a);
|
|
1984
|
+
const bnum = numeric.test(b);
|
|
1985
|
+
if (anum && bnum) {
|
|
1986
|
+
a = +a;
|
|
1987
|
+
b = +b;
|
|
1988
|
+
}
|
|
1989
|
+
return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1;
|
|
1990
|
+
};
|
|
1991
|
+
const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a);
|
|
1992
|
+
module.exports = {
|
|
1993
|
+
compareIdentifiers,
|
|
1994
|
+
rcompareIdentifiers
|
|
1995
|
+
};
|
|
1996
|
+
}));
|
|
1997
|
+
//#endregion
|
|
1998
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/semver.js
|
|
1999
|
+
var require_semver = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2000
|
+
const debug = require_debug();
|
|
2001
|
+
const { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants();
|
|
2002
|
+
const { safeRe: re, t } = require_re();
|
|
2003
|
+
const parseOptions = require_parse_options();
|
|
2004
|
+
const { compareIdentifiers } = require_identifiers();
|
|
2005
|
+
const isPrereleaseIdentifier = (prerelease, identifier) => {
|
|
2006
|
+
const identifiers = identifier.split(".");
|
|
2007
|
+
if (identifiers.length > prerelease.length) return false;
|
|
2008
|
+
for (let i = 0; i < identifiers.length; i++) if (compareIdentifiers(prerelease[i], identifiers[i]) !== 0) return false;
|
|
2009
|
+
return true;
|
|
2010
|
+
};
|
|
2011
|
+
module.exports = class SemVer {
|
|
2012
|
+
constructor(version, options) {
|
|
2013
|
+
options = parseOptions(options);
|
|
2014
|
+
if (version instanceof SemVer) {
|
|
2015
|
+
if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) return version;
|
|
2016
|
+
else version = version.version;
|
|
2017
|
+
} else if (typeof version !== "string") throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`);
|
|
2018
|
+
if (version.length > MAX_LENGTH) throw new TypeError(`version is longer than ${MAX_LENGTH} characters`);
|
|
2019
|
+
debug("SemVer", version, options);
|
|
2020
|
+
this.options = options;
|
|
2021
|
+
this.loose = !!options.loose;
|
|
2022
|
+
this.includePrerelease = !!options.includePrerelease;
|
|
2023
|
+
const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]);
|
|
2024
|
+
if (!m) throw new TypeError(`Invalid Version: ${version}`);
|
|
2025
|
+
this.raw = version;
|
|
2026
|
+
this.major = +m[1];
|
|
2027
|
+
this.minor = +m[2];
|
|
2028
|
+
this.patch = +m[3];
|
|
2029
|
+
if (this.major > MAX_SAFE_INTEGER || this.major < 0) throw new TypeError("Invalid major version");
|
|
2030
|
+
if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) throw new TypeError("Invalid minor version");
|
|
2031
|
+
if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) throw new TypeError("Invalid patch version");
|
|
2032
|
+
if (!m[4]) this.prerelease = [];
|
|
2033
|
+
else this.prerelease = m[4].split(".").map((id) => {
|
|
2034
|
+
if (/^[0-9]+$/.test(id)) {
|
|
2035
|
+
const num = +id;
|
|
2036
|
+
if (num >= 0 && num < MAX_SAFE_INTEGER) return num;
|
|
2037
|
+
}
|
|
2038
|
+
return id;
|
|
2039
|
+
});
|
|
2040
|
+
this.build = m[5] ? m[5].split(".") : [];
|
|
2041
|
+
this.format();
|
|
2042
|
+
}
|
|
2043
|
+
format() {
|
|
2044
|
+
this.version = `${this.major}.${this.minor}.${this.patch}`;
|
|
2045
|
+
if (this.prerelease.length) this.version += `-${this.prerelease.join(".")}`;
|
|
2046
|
+
return this.version;
|
|
2047
|
+
}
|
|
2048
|
+
toString() {
|
|
2049
|
+
return this.version;
|
|
2050
|
+
}
|
|
2051
|
+
compare(other) {
|
|
2052
|
+
debug("SemVer.compare", this.version, this.options, other);
|
|
2053
|
+
if (!(other instanceof SemVer)) {
|
|
2054
|
+
if (typeof other === "string" && other === this.version) return 0;
|
|
2055
|
+
other = new SemVer(other, this.options);
|
|
2056
|
+
}
|
|
2057
|
+
if (other.version === this.version) return 0;
|
|
2058
|
+
return this.compareMain(other) || this.comparePre(other);
|
|
2059
|
+
}
|
|
2060
|
+
compareMain(other) {
|
|
2061
|
+
if (!(other instanceof SemVer)) other = new SemVer(other, this.options);
|
|
2062
|
+
if (this.major < other.major) return -1;
|
|
2063
|
+
if (this.major > other.major) return 1;
|
|
2064
|
+
if (this.minor < other.minor) return -1;
|
|
2065
|
+
if (this.minor > other.minor) return 1;
|
|
2066
|
+
if (this.patch < other.patch) return -1;
|
|
2067
|
+
if (this.patch > other.patch) return 1;
|
|
2068
|
+
return 0;
|
|
2069
|
+
}
|
|
2070
|
+
comparePre(other) {
|
|
2071
|
+
if (!(other instanceof SemVer)) other = new SemVer(other, this.options);
|
|
2072
|
+
if (this.prerelease.length && !other.prerelease.length) return -1;
|
|
2073
|
+
else if (!this.prerelease.length && other.prerelease.length) return 1;
|
|
2074
|
+
else if (!this.prerelease.length && !other.prerelease.length) return 0;
|
|
2075
|
+
let i = 0;
|
|
2076
|
+
do {
|
|
2077
|
+
const a = this.prerelease[i];
|
|
2078
|
+
const b = other.prerelease[i];
|
|
2079
|
+
debug("prerelease compare", i, a, b);
|
|
2080
|
+
if (a === void 0 && b === void 0) return 0;
|
|
2081
|
+
else if (b === void 0) return 1;
|
|
2082
|
+
else if (a === void 0) return -1;
|
|
2083
|
+
else if (a === b) continue;
|
|
2084
|
+
else return compareIdentifiers(a, b);
|
|
2085
|
+
} while (++i);
|
|
2086
|
+
}
|
|
2087
|
+
compareBuild(other) {
|
|
2088
|
+
if (!(other instanceof SemVer)) other = new SemVer(other, this.options);
|
|
2089
|
+
let i = 0;
|
|
2090
|
+
do {
|
|
2091
|
+
const a = this.build[i];
|
|
2092
|
+
const b = other.build[i];
|
|
2093
|
+
debug("build compare", i, a, b);
|
|
2094
|
+
if (a === void 0 && b === void 0) return 0;
|
|
2095
|
+
else if (b === void 0) return 1;
|
|
2096
|
+
else if (a === void 0) return -1;
|
|
2097
|
+
else if (a === b) continue;
|
|
2098
|
+
else return compareIdentifiers(a, b);
|
|
2099
|
+
} while (++i);
|
|
2100
|
+
}
|
|
2101
|
+
inc(release, identifier, identifierBase) {
|
|
2102
|
+
if (release.startsWith("pre")) {
|
|
2103
|
+
if (!identifier && identifierBase === false) throw new Error("invalid increment argument: identifier is empty");
|
|
2104
|
+
if (identifier) {
|
|
2105
|
+
const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]);
|
|
2106
|
+
if (!match || match[1] !== identifier) throw new Error(`invalid identifier: ${identifier}`);
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
switch (release) {
|
|
2110
|
+
case "premajor":
|
|
2111
|
+
this.prerelease.length = 0;
|
|
2112
|
+
this.patch = 0;
|
|
2113
|
+
this.minor = 0;
|
|
2114
|
+
this.major++;
|
|
2115
|
+
this.inc("pre", identifier, identifierBase);
|
|
2116
|
+
break;
|
|
2117
|
+
case "preminor":
|
|
2118
|
+
this.prerelease.length = 0;
|
|
2119
|
+
this.patch = 0;
|
|
2120
|
+
this.minor++;
|
|
2121
|
+
this.inc("pre", identifier, identifierBase);
|
|
2122
|
+
break;
|
|
2123
|
+
case "prepatch":
|
|
2124
|
+
this.prerelease.length = 0;
|
|
2125
|
+
this.inc("patch", identifier, identifierBase);
|
|
2126
|
+
this.inc("pre", identifier, identifierBase);
|
|
2127
|
+
break;
|
|
2128
|
+
case "prerelease":
|
|
2129
|
+
if (this.prerelease.length === 0) this.inc("patch", identifier, identifierBase);
|
|
2130
|
+
this.inc("pre", identifier, identifierBase);
|
|
2131
|
+
break;
|
|
2132
|
+
case "release":
|
|
2133
|
+
if (this.prerelease.length === 0) throw new Error(`version ${this.raw} is not a prerelease`);
|
|
2134
|
+
this.prerelease.length = 0;
|
|
2135
|
+
break;
|
|
2136
|
+
case "major":
|
|
2137
|
+
if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) this.major++;
|
|
2138
|
+
this.minor = 0;
|
|
2139
|
+
this.patch = 0;
|
|
2140
|
+
this.prerelease = [];
|
|
2141
|
+
break;
|
|
2142
|
+
case "minor":
|
|
2143
|
+
if (this.patch !== 0 || this.prerelease.length === 0) this.minor++;
|
|
2144
|
+
this.patch = 0;
|
|
2145
|
+
this.prerelease = [];
|
|
2146
|
+
break;
|
|
2147
|
+
case "patch":
|
|
2148
|
+
if (this.prerelease.length === 0) this.patch++;
|
|
2149
|
+
this.prerelease = [];
|
|
2150
|
+
break;
|
|
2151
|
+
case "pre": {
|
|
2152
|
+
const base = Number(identifierBase) ? 1 : 0;
|
|
2153
|
+
if (this.prerelease.length === 0) this.prerelease = [base];
|
|
2154
|
+
else {
|
|
2155
|
+
let i = this.prerelease.length;
|
|
2156
|
+
while (--i >= 0) if (typeof this.prerelease[i] === "number") {
|
|
2157
|
+
this.prerelease[i]++;
|
|
2158
|
+
i = -2;
|
|
2159
|
+
}
|
|
2160
|
+
if (i === -1) {
|
|
2161
|
+
if (identifier === this.prerelease.join(".") && identifierBase === false) throw new Error("invalid increment argument: identifier already exists");
|
|
2162
|
+
this.prerelease.push(base);
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
if (identifier) {
|
|
2166
|
+
let prerelease = [identifier, base];
|
|
2167
|
+
if (identifierBase === false) prerelease = [identifier];
|
|
2168
|
+
if (isPrereleaseIdentifier(this.prerelease, identifier)) {
|
|
2169
|
+
const prereleaseBase = this.prerelease[identifier.split(".").length];
|
|
2170
|
+
if (isNaN(prereleaseBase)) this.prerelease = prerelease;
|
|
2171
|
+
} else this.prerelease = prerelease;
|
|
2172
|
+
}
|
|
2173
|
+
break;
|
|
2174
|
+
}
|
|
2175
|
+
default: throw new Error(`invalid increment argument: ${release}`);
|
|
2176
|
+
}
|
|
2177
|
+
this.raw = this.format();
|
|
2178
|
+
if (this.build.length) this.raw += `+${this.build.join(".")}`;
|
|
2179
|
+
return this;
|
|
2180
|
+
}
|
|
2181
|
+
};
|
|
2182
|
+
}));
|
|
2183
|
+
//#endregion
|
|
2184
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/compare.js
|
|
2185
|
+
var require_compare = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2186
|
+
const SemVer = require_semver();
|
|
2187
|
+
const compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose));
|
|
2188
|
+
module.exports = compare;
|
|
2189
|
+
}));
|
|
2190
|
+
//#endregion
|
|
2191
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/eq.js
|
|
2192
|
+
var require_eq = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2193
|
+
const compare = require_compare();
|
|
2194
|
+
const eq = (a, b, loose) => compare(a, b, loose) === 0;
|
|
2195
|
+
module.exports = eq;
|
|
2196
|
+
}));
|
|
2197
|
+
//#endregion
|
|
2198
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/neq.js
|
|
2199
|
+
var require_neq = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2200
|
+
const compare = require_compare();
|
|
2201
|
+
const neq = (a, b, loose) => compare(a, b, loose) !== 0;
|
|
2202
|
+
module.exports = neq;
|
|
2203
|
+
}));
|
|
2204
|
+
//#endregion
|
|
2205
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/gt.js
|
|
2206
|
+
var require_gt = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2207
|
+
const compare = require_compare();
|
|
2208
|
+
const gt = (a, b, loose) => compare(a, b, loose) > 0;
|
|
2209
|
+
module.exports = gt;
|
|
2210
|
+
}));
|
|
2211
|
+
//#endregion
|
|
2212
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/gte.js
|
|
2213
|
+
var require_gte = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2214
|
+
const compare = require_compare();
|
|
2215
|
+
const gte = (a, b, loose) => compare(a, b, loose) >= 0;
|
|
2216
|
+
module.exports = gte;
|
|
2217
|
+
}));
|
|
2218
|
+
//#endregion
|
|
2219
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/lt.js
|
|
2220
|
+
var require_lt = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2221
|
+
const compare = require_compare();
|
|
2222
|
+
const lt = (a, b, loose) => compare(a, b, loose) < 0;
|
|
2223
|
+
module.exports = lt;
|
|
2224
|
+
}));
|
|
2225
|
+
//#endregion
|
|
2226
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/lte.js
|
|
2227
|
+
var require_lte = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2228
|
+
const compare = require_compare();
|
|
2229
|
+
const lte = (a, b, loose) => compare(a, b, loose) <= 0;
|
|
2230
|
+
module.exports = lte;
|
|
2231
|
+
}));
|
|
2232
|
+
//#endregion
|
|
2233
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/cmp.js
|
|
2234
|
+
var require_cmp = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2235
|
+
const eq = require_eq();
|
|
2236
|
+
const neq = require_neq();
|
|
2237
|
+
const gt = require_gt();
|
|
2238
|
+
const gte = require_gte();
|
|
2239
|
+
const lt = require_lt();
|
|
2240
|
+
const lte = require_lte();
|
|
2241
|
+
const cmp = (a, op, b, loose) => {
|
|
2242
|
+
switch (op) {
|
|
2243
|
+
case "===":
|
|
2244
|
+
if (typeof a === "object") a = a.version;
|
|
2245
|
+
if (typeof b === "object") b = b.version;
|
|
2246
|
+
return a === b;
|
|
2247
|
+
case "!==":
|
|
2248
|
+
if (typeof a === "object") a = a.version;
|
|
2249
|
+
if (typeof b === "object") b = b.version;
|
|
2250
|
+
return a !== b;
|
|
2251
|
+
case "":
|
|
2252
|
+
case "=":
|
|
2253
|
+
case "==": return eq(a, b, loose);
|
|
2254
|
+
case "!=": return neq(a, b, loose);
|
|
2255
|
+
case ">": return gt(a, b, loose);
|
|
2256
|
+
case ">=": return gte(a, b, loose);
|
|
2257
|
+
case "<": return lt(a, b, loose);
|
|
2258
|
+
case "<=": return lte(a, b, loose);
|
|
2259
|
+
default: throw new TypeError(`Invalid operator: ${op}`);
|
|
2260
|
+
}
|
|
2261
|
+
};
|
|
2262
|
+
module.exports = cmp;
|
|
2263
|
+
}));
|
|
2264
|
+
//#endregion
|
|
2265
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/comparator.js
|
|
2266
|
+
var require_comparator = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2267
|
+
const ANY = Symbol("SemVer ANY");
|
|
2268
|
+
module.exports = class Comparator {
|
|
2269
|
+
static get ANY() {
|
|
2270
|
+
return ANY;
|
|
2271
|
+
}
|
|
2272
|
+
constructor(comp, options) {
|
|
2273
|
+
options = parseOptions(options);
|
|
2274
|
+
if (comp instanceof Comparator) {
|
|
2275
|
+
if (comp.loose === !!options.loose) return comp;
|
|
2276
|
+
else comp = comp.value;
|
|
2277
|
+
}
|
|
2278
|
+
comp = comp.trim().split(/\s+/).join(" ");
|
|
2279
|
+
debug("comparator", comp, options);
|
|
2280
|
+
this.options = options;
|
|
2281
|
+
this.loose = !!options.loose;
|
|
2282
|
+
this.parse(comp);
|
|
2283
|
+
if (this.semver === ANY) this.value = "";
|
|
2284
|
+
else this.value = this.operator + this.semver.version;
|
|
2285
|
+
debug("comp", this);
|
|
2286
|
+
}
|
|
2287
|
+
parse(comp) {
|
|
2288
|
+
const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR];
|
|
2289
|
+
const m = comp.match(r);
|
|
2290
|
+
if (!m) throw new TypeError(`Invalid comparator: ${comp}`);
|
|
2291
|
+
this.operator = m[1] !== void 0 ? m[1] : "";
|
|
2292
|
+
if (this.operator === "=") this.operator = "";
|
|
2293
|
+
if (!m[2]) this.semver = ANY;
|
|
2294
|
+
else this.semver = new SemVer(m[2], this.options.loose);
|
|
2295
|
+
}
|
|
2296
|
+
toString() {
|
|
2297
|
+
return this.value;
|
|
2298
|
+
}
|
|
2299
|
+
test(version) {
|
|
2300
|
+
debug("Comparator.test", version, this.options.loose);
|
|
2301
|
+
if (this.semver === ANY || version === ANY) return true;
|
|
2302
|
+
if (typeof version === "string") try {
|
|
2303
|
+
version = new SemVer(version, this.options);
|
|
2304
|
+
} catch (er) {
|
|
2305
|
+
return false;
|
|
2306
|
+
}
|
|
2307
|
+
return cmp(version, this.operator, this.semver, this.options);
|
|
2308
|
+
}
|
|
2309
|
+
intersects(comp, options) {
|
|
2310
|
+
if (!(comp instanceof Comparator)) throw new TypeError("a Comparator is required");
|
|
2311
|
+
if (this.operator === "") {
|
|
2312
|
+
if (this.value === "") return true;
|
|
2313
|
+
return new Range(comp.value, options).test(this.value);
|
|
2314
|
+
} else if (comp.operator === "") {
|
|
2315
|
+
if (comp.value === "") return true;
|
|
2316
|
+
return new Range(this.value, options).test(comp.semver);
|
|
2317
|
+
}
|
|
2318
|
+
options = parseOptions(options);
|
|
2319
|
+
if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) return false;
|
|
2320
|
+
if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) return false;
|
|
2321
|
+
if (this.operator.startsWith(">") && comp.operator.startsWith(">")) return true;
|
|
2322
|
+
if (this.operator.startsWith("<") && comp.operator.startsWith("<")) return true;
|
|
2323
|
+
if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) return true;
|
|
2324
|
+
if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) return true;
|
|
2325
|
+
if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) return true;
|
|
2326
|
+
return false;
|
|
2327
|
+
}
|
|
2328
|
+
};
|
|
2329
|
+
const parseOptions = require_parse_options();
|
|
2330
|
+
const { safeRe: re, t } = require_re();
|
|
2331
|
+
const cmp = require_cmp();
|
|
2332
|
+
const debug = require_debug();
|
|
2333
|
+
const SemVer = require_semver();
|
|
2334
|
+
const Range = require_range();
|
|
2335
|
+
}));
|
|
2336
|
+
//#endregion
|
|
2337
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/range.js
|
|
2338
|
+
var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2339
|
+
const SPACE_CHARACTERS = /\s+/g;
|
|
2340
|
+
module.exports = class Range {
|
|
2341
|
+
constructor(range, options) {
|
|
2342
|
+
options = parseOptions(options);
|
|
2343
|
+
if (range instanceof Range) {
|
|
2344
|
+
if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) return range;
|
|
2345
|
+
else return new Range(range.raw, options);
|
|
2346
|
+
}
|
|
2347
|
+
if (range instanceof Comparator) {
|
|
2348
|
+
this.raw = range.value;
|
|
2349
|
+
this.set = [[range]];
|
|
2350
|
+
this.formatted = void 0;
|
|
2351
|
+
return this;
|
|
2352
|
+
}
|
|
2353
|
+
this.options = options;
|
|
2354
|
+
this.loose = !!options.loose;
|
|
2355
|
+
this.includePrerelease = !!options.includePrerelease;
|
|
2356
|
+
this.raw = range.trim().replace(SPACE_CHARACTERS, " ");
|
|
2357
|
+
this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length);
|
|
2358
|
+
if (!this.set.length) throw new TypeError(`Invalid SemVer Range: ${this.raw}`);
|
|
2359
|
+
if (this.set.length > 1) {
|
|
2360
|
+
const first = this.set[0];
|
|
2361
|
+
this.set = this.set.filter((c) => !isNullSet(c[0]));
|
|
2362
|
+
if (this.set.length === 0) this.set = [first];
|
|
2363
|
+
else if (this.set.length > 1) {
|
|
2364
|
+
for (const c of this.set) if (c.length === 1 && isAny(c[0])) {
|
|
2365
|
+
this.set = [c];
|
|
2366
|
+
break;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
this.formatted = void 0;
|
|
2371
|
+
}
|
|
2372
|
+
get range() {
|
|
2373
|
+
if (this.formatted === void 0) {
|
|
2374
|
+
this.formatted = "";
|
|
2375
|
+
for (let i = 0; i < this.set.length; i++) {
|
|
2376
|
+
if (i > 0) this.formatted += "||";
|
|
2377
|
+
const comps = this.set[i];
|
|
2378
|
+
for (let k = 0; k < comps.length; k++) {
|
|
2379
|
+
if (k > 0) this.formatted += " ";
|
|
2380
|
+
this.formatted += comps[k].toString().trim();
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
return this.formatted;
|
|
2385
|
+
}
|
|
2386
|
+
format() {
|
|
2387
|
+
return this.range;
|
|
2388
|
+
}
|
|
2389
|
+
toString() {
|
|
2390
|
+
return this.range;
|
|
2391
|
+
}
|
|
2392
|
+
parseRange(range) {
|
|
2393
|
+
range = range.replace(BUILDSTRIPRE, "");
|
|
2394
|
+
const memoKey = ((this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE)) + ":" + range;
|
|
2395
|
+
const cached = cache.get(memoKey);
|
|
2396
|
+
if (cached) return cached;
|
|
2397
|
+
const loose = this.options.loose;
|
|
2398
|
+
const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE];
|
|
2399
|
+
range = range.replace(hr, hyphenReplace(this.options.includePrerelease));
|
|
2400
|
+
debug("hyphen replace", range);
|
|
2401
|
+
range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace);
|
|
2402
|
+
debug("comparator trim", range);
|
|
2403
|
+
range = range.replace(re[t.TILDETRIM], tildeTrimReplace);
|
|
2404
|
+
debug("tilde trim", range);
|
|
2405
|
+
range = range.replace(re[t.CARETTRIM], caretTrimReplace);
|
|
2406
|
+
debug("caret trim", range);
|
|
2407
|
+
let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options));
|
|
2408
|
+
if (loose) rangeList = rangeList.filter((comp) => {
|
|
2409
|
+
debug("loose invalid filter", comp, this.options);
|
|
2410
|
+
return !!comp.match(re[t.COMPARATORLOOSE]);
|
|
2411
|
+
});
|
|
2412
|
+
debug("range list", rangeList);
|
|
2413
|
+
const rangeMap = /* @__PURE__ */ new Map();
|
|
2414
|
+
const comparators = rangeList.map((comp) => new Comparator(comp, this.options));
|
|
2415
|
+
for (const comp of comparators) {
|
|
2416
|
+
if (isNullSet(comp)) return [comp];
|
|
2417
|
+
rangeMap.set(comp.value, comp);
|
|
2418
|
+
}
|
|
2419
|
+
if (rangeMap.size > 1 && rangeMap.has("")) rangeMap.delete("");
|
|
2420
|
+
const result = [...rangeMap.values()];
|
|
2421
|
+
cache.set(memoKey, result);
|
|
2422
|
+
return result;
|
|
2423
|
+
}
|
|
2424
|
+
intersects(range, options) {
|
|
2425
|
+
if (!(range instanceof Range)) throw new TypeError("a Range is required");
|
|
2426
|
+
return this.set.some((thisComparators) => {
|
|
2427
|
+
return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => {
|
|
2428
|
+
return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => {
|
|
2429
|
+
return rangeComparators.every((rangeComparator) => {
|
|
2430
|
+
return thisComparator.intersects(rangeComparator, options);
|
|
2431
|
+
});
|
|
2432
|
+
});
|
|
2433
|
+
});
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
test(version) {
|
|
2437
|
+
if (!version) return false;
|
|
2438
|
+
if (typeof version === "string") try {
|
|
2439
|
+
version = new SemVer(version, this.options);
|
|
2440
|
+
} catch (er) {
|
|
2441
|
+
return false;
|
|
2442
|
+
}
|
|
2443
|
+
for (let i = 0; i < this.set.length; i++) if (testSet(this.set[i], version, this.options)) return true;
|
|
2444
|
+
return false;
|
|
2445
|
+
}
|
|
2446
|
+
};
|
|
2447
|
+
const cache = new (require_lrucache())();
|
|
2448
|
+
const parseOptions = require_parse_options();
|
|
2449
|
+
const Comparator = require_comparator();
|
|
2450
|
+
const debug = require_debug();
|
|
2451
|
+
const SemVer = require_semver();
|
|
2452
|
+
const { safeRe: re, src, t, comparatorTrimReplace, tildeTrimReplace, caretTrimReplace } = require_re();
|
|
2453
|
+
const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants();
|
|
2454
|
+
const BUILDSTRIPRE = new RegExp(src[t.BUILD], "g");
|
|
2455
|
+
const isNullSet = (c) => c.value === "<0.0.0-0";
|
|
2456
|
+
const isAny = (c) => c.value === "";
|
|
2457
|
+
const isSatisfiable = (comparators, options) => {
|
|
2458
|
+
let result = true;
|
|
2459
|
+
const remainingComparators = comparators.slice();
|
|
2460
|
+
let testComparator = remainingComparators.pop();
|
|
2461
|
+
while (result && remainingComparators.length) {
|
|
2462
|
+
result = remainingComparators.every((otherComparator) => {
|
|
2463
|
+
return testComparator.intersects(otherComparator, options);
|
|
2464
|
+
});
|
|
2465
|
+
testComparator = remainingComparators.pop();
|
|
2466
|
+
}
|
|
2467
|
+
return result;
|
|
2468
|
+
};
|
|
2469
|
+
const parseComparator = (comp, options) => {
|
|
2470
|
+
comp = comp.replace(re[t.BUILD], "");
|
|
2471
|
+
debug("comp", comp, options);
|
|
2472
|
+
comp = replaceCarets(comp, options);
|
|
2473
|
+
debug("caret", comp);
|
|
2474
|
+
comp = replaceTildes(comp, options);
|
|
2475
|
+
debug("tildes", comp);
|
|
2476
|
+
comp = replaceXRanges(comp, options);
|
|
2477
|
+
debug("xrange", comp);
|
|
2478
|
+
comp = replaceStars(comp, options);
|
|
2479
|
+
debug("stars", comp);
|
|
2480
|
+
return comp;
|
|
2481
|
+
};
|
|
2482
|
+
const isX = (id) => !id || id.toLowerCase() === "x" || id === "*";
|
|
2483
|
+
const invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p);
|
|
2484
|
+
const replaceTildes = (comp, options) => {
|
|
2485
|
+
return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" ");
|
|
2486
|
+
};
|
|
2487
|
+
const replaceTilde = (comp, options) => {
|
|
2488
|
+
const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE];
|
|
2489
|
+
const z = options.includePrerelease ? "-0" : "";
|
|
2490
|
+
return comp.replace(r, (_, M, m, p, pr) => {
|
|
2491
|
+
debug("tilde", comp, _, M, m, p, pr);
|
|
2492
|
+
let ret;
|
|
2493
|
+
if (isX(M)) ret = "";
|
|
2494
|
+
else if (isX(m)) ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`;
|
|
2495
|
+
else if (isX(p)) ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`;
|
|
2496
|
+
else if (pr) {
|
|
2497
|
+
debug("replaceTilde pr", pr);
|
|
2498
|
+
ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`;
|
|
2499
|
+
} else ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`;
|
|
2500
|
+
debug("tilde return", ret);
|
|
2501
|
+
return ret;
|
|
2502
|
+
});
|
|
2503
|
+
};
|
|
2504
|
+
const replaceCarets = (comp, options) => {
|
|
2505
|
+
return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" ");
|
|
2506
|
+
};
|
|
2507
|
+
const replaceCaret = (comp, options) => {
|
|
2508
|
+
debug("caret", comp, options);
|
|
2509
|
+
const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET];
|
|
2510
|
+
const z = options.includePrerelease ? "-0" : "";
|
|
2511
|
+
return comp.replace(r, (_, M, m, p, pr) => {
|
|
2512
|
+
debug("caret", comp, _, M, m, p, pr);
|
|
2513
|
+
let ret;
|
|
2514
|
+
if (isX(M)) ret = "";
|
|
2515
|
+
else if (isX(m)) ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`;
|
|
2516
|
+
else if (isX(p)) {
|
|
2517
|
+
if (M === "0") ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`;
|
|
2518
|
+
else ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`;
|
|
2519
|
+
} else if (pr) {
|
|
2520
|
+
debug("replaceCaret pr", pr);
|
|
2521
|
+
if (M === "0") {
|
|
2522
|
+
if (m === "0") ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`;
|
|
2523
|
+
else ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`;
|
|
2524
|
+
} else ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`;
|
|
2525
|
+
} else {
|
|
2526
|
+
debug("no pr");
|
|
2527
|
+
if (M === "0") {
|
|
2528
|
+
if (m === "0") ret = `>=${M}.${m}.${p} <${M}.${m}.${+p + 1}-0`;
|
|
2529
|
+
else ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`;
|
|
2530
|
+
} else ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`;
|
|
2531
|
+
}
|
|
2532
|
+
debug("caret return", ret);
|
|
2533
|
+
return ret;
|
|
2534
|
+
});
|
|
2535
|
+
};
|
|
2536
|
+
const replaceXRanges = (comp, options) => {
|
|
2537
|
+
debug("replaceXRanges", comp, options);
|
|
2538
|
+
return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" ");
|
|
2539
|
+
};
|
|
2540
|
+
const replaceXRange = (comp, options) => {
|
|
2541
|
+
comp = comp.trim();
|
|
2542
|
+
const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE];
|
|
2543
|
+
return comp.replace(r, (ret, gtlt, M, m, p, pr) => {
|
|
2544
|
+
debug("xRange", comp, ret, gtlt, M, m, p, pr);
|
|
2545
|
+
if (invalidXRangeOrder(M, m, p)) return comp;
|
|
2546
|
+
const xM = isX(M);
|
|
2547
|
+
const xm = xM || isX(m);
|
|
2548
|
+
const xp = xm || isX(p);
|
|
2549
|
+
const anyX = xp;
|
|
2550
|
+
if (gtlt === "=" && anyX) gtlt = "";
|
|
2551
|
+
pr = options.includePrerelease ? "-0" : "";
|
|
2552
|
+
if (xM) {
|
|
2553
|
+
if (gtlt === ">" || gtlt === "<") ret = "<0.0.0-0";
|
|
2554
|
+
else ret = "*";
|
|
2555
|
+
} else if (gtlt && anyX) {
|
|
2556
|
+
if (xm) m = 0;
|
|
2557
|
+
p = 0;
|
|
2558
|
+
if (gtlt === ">") {
|
|
2559
|
+
gtlt = ">=";
|
|
2560
|
+
if (xm) {
|
|
2561
|
+
M = +M + 1;
|
|
2562
|
+
m = 0;
|
|
2563
|
+
p = 0;
|
|
2564
|
+
} else {
|
|
2565
|
+
m = +m + 1;
|
|
2566
|
+
p = 0;
|
|
2567
|
+
}
|
|
2568
|
+
} else if (gtlt === "<=") {
|
|
2569
|
+
gtlt = "<";
|
|
2570
|
+
if (xm) M = +M + 1;
|
|
2571
|
+
else m = +m + 1;
|
|
2572
|
+
}
|
|
2573
|
+
if (gtlt === "<") pr = "-0";
|
|
2574
|
+
ret = `${gtlt + M}.${m}.${p}${pr}`;
|
|
2575
|
+
} else if (xm) ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`;
|
|
2576
|
+
else if (xp) ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`;
|
|
2577
|
+
debug("xRange return", ret);
|
|
2578
|
+
return ret;
|
|
2579
|
+
});
|
|
2580
|
+
};
|
|
2581
|
+
const replaceStars = (comp, options) => {
|
|
2582
|
+
debug("replaceStars", comp, options);
|
|
2583
|
+
return comp.trim().replace(re[t.STAR], "");
|
|
2584
|
+
};
|
|
2585
|
+
const replaceGTE0 = (comp, options) => {
|
|
2586
|
+
debug("replaceGTE0", comp, options);
|
|
2587
|
+
return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], "");
|
|
2588
|
+
};
|
|
2589
|
+
const hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => {
|
|
2590
|
+
if (isX(fM)) from = "";
|
|
2591
|
+
else if (isX(fm)) from = `>=${fM}.0.0${incPr ? "-0" : ""}`;
|
|
2592
|
+
else if (isX(fp)) from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`;
|
|
2593
|
+
else if (fpr) from = `>=${from}`;
|
|
2594
|
+
else from = `>=${from}${incPr ? "-0" : ""}`;
|
|
2595
|
+
if (isX(tM)) to = "";
|
|
2596
|
+
else if (isX(tm)) to = `<${+tM + 1}.0.0-0`;
|
|
2597
|
+
else if (isX(tp)) to = `<${tM}.${+tm + 1}.0-0`;
|
|
2598
|
+
else if (tpr) to = `<=${tM}.${tm}.${tp}-${tpr}`;
|
|
2599
|
+
else if (incPr) to = `<${tM}.${tm}.${+tp + 1}-0`;
|
|
2600
|
+
else to = `<=${to}`;
|
|
2601
|
+
return `${from} ${to}`.trim();
|
|
2602
|
+
};
|
|
2603
|
+
const testSet = (set, version, options) => {
|
|
2604
|
+
for (let i = 0; i < set.length; i++) if (!set[i].test(version)) return false;
|
|
2605
|
+
if (version.prerelease.length && !options.includePrerelease) {
|
|
2606
|
+
for (let i = 0; i < set.length; i++) {
|
|
2607
|
+
debug(set[i].semver);
|
|
2608
|
+
if (set[i].semver === Comparator.ANY) continue;
|
|
2609
|
+
if (set[i].semver.prerelease.length > 0) {
|
|
2610
|
+
const allowed = set[i].semver;
|
|
2611
|
+
if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) return true;
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
return false;
|
|
2615
|
+
}
|
|
2616
|
+
return true;
|
|
2617
|
+
};
|
|
2618
|
+
}));
|
|
2619
|
+
//#endregion
|
|
2620
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/satisfies.js
|
|
2621
|
+
var require_satisfies = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2622
|
+
const Range = require_range();
|
|
2623
|
+
const satisfies = (version, range, options) => {
|
|
2624
|
+
try {
|
|
2625
|
+
range = new Range(range, options);
|
|
2626
|
+
} catch (er) {
|
|
2627
|
+
return false;
|
|
2628
|
+
}
|
|
2629
|
+
return range.test(version);
|
|
2630
|
+
};
|
|
2631
|
+
module.exports = satisfies;
|
|
2632
|
+
}));
|
|
2633
|
+
//#endregion
|
|
2634
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/parse.js
|
|
2635
|
+
var require_parse = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2636
|
+
const SemVer = require_semver();
|
|
2637
|
+
const parse = (version, options, throwErrors = false) => {
|
|
2638
|
+
if (version instanceof SemVer) return version;
|
|
2639
|
+
try {
|
|
2640
|
+
return new SemVer(version, options);
|
|
2641
|
+
} catch (er) {
|
|
2642
|
+
if (!throwErrors) return null;
|
|
2643
|
+
throw er;
|
|
2644
|
+
}
|
|
2645
|
+
};
|
|
2646
|
+
module.exports = parse;
|
|
2647
|
+
}));
|
|
2648
|
+
//#endregion
|
|
2649
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/valid.js
|
|
2650
|
+
var require_valid$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2651
|
+
const parse = require_parse();
|
|
2652
|
+
const valid = (version, options) => {
|
|
2653
|
+
const v = parse(version, options);
|
|
2654
|
+
return v ? v.version : null;
|
|
2655
|
+
};
|
|
2656
|
+
module.exports = valid;
|
|
2657
|
+
}));
|
|
2658
|
+
//#endregion
|
|
2659
|
+
//#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/valid.js
|
|
2660
|
+
var require_valid = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2661
|
+
const Range = require_range();
|
|
2662
|
+
const validRange = (range, options) => {
|
|
2663
|
+
try {
|
|
2664
|
+
return new Range(range, options).range || "*";
|
|
2665
|
+
} catch (er) {
|
|
2666
|
+
return null;
|
|
2667
|
+
}
|
|
2668
|
+
};
|
|
2669
|
+
module.exports = validRange;
|
|
2670
|
+
}));
|
|
2671
|
+
//#endregion
|
|
2672
|
+
//#region package.json
|
|
2673
|
+
var import_satisfies = /* @__PURE__ */ __toESM(require_satisfies(), 1);
|
|
2674
|
+
var import_valid = /* @__PURE__ */ __toESM(require_valid$1(), 1);
|
|
2675
|
+
var import_valid$1 = /* @__PURE__ */ __toESM(require_valid(), 1);
|
|
2676
|
+
var optionalDependencies = {
|
|
2677
|
+
"@tsdown/exe": "0.23.0",
|
|
2678
|
+
"tsdown": "0.23.0"
|
|
2679
|
+
};
|
|
2680
|
+
//#endregion
|
|
2681
|
+
//#region src/utils/build-helpers.ts
|
|
2682
|
+
const BUILD_RUNTIMES = [
|
|
2683
|
+
"bun",
|
|
2684
|
+
"deno",
|
|
2685
|
+
"node"
|
|
2686
|
+
];
|
|
2687
|
+
const BUN_TARGETS = {
|
|
2688
|
+
runtime: "Bun",
|
|
2689
|
+
targets: [
|
|
2690
|
+
"bun-linux-x64",
|
|
2691
|
+
"bun-linux-arm64",
|
|
2692
|
+
"bun-linux-x64-musl",
|
|
2693
|
+
"bun-linux-arm64-musl",
|
|
2694
|
+
"bun-darwin-x64",
|
|
2695
|
+
"bun-darwin-arm64",
|
|
2696
|
+
"bun-windows-x64",
|
|
2697
|
+
"bun-windows-arm64"
|
|
2698
|
+
],
|
|
2699
|
+
info: {
|
|
2700
|
+
"bun-linux-x64": {
|
|
2701
|
+
alias: "linux-x64",
|
|
2702
|
+
platformKey: "linux-x64",
|
|
2703
|
+
os: "linux",
|
|
2704
|
+
cpu: "x64",
|
|
2705
|
+
libc: "glibc"
|
|
2706
|
+
},
|
|
2707
|
+
"bun-linux-arm64": {
|
|
2708
|
+
alias: "linux-arm64",
|
|
2709
|
+
platformKey: "linux-arm64",
|
|
2710
|
+
os: "linux",
|
|
2711
|
+
cpu: "arm64",
|
|
2712
|
+
libc: "glibc"
|
|
2713
|
+
},
|
|
2714
|
+
"bun-linux-x64-musl": {
|
|
2715
|
+
alias: "linux-x64-musl",
|
|
2716
|
+
platformKey: "linux-x64-musl",
|
|
2717
|
+
os: "linux",
|
|
2718
|
+
cpu: "x64",
|
|
2719
|
+
libc: "musl"
|
|
2720
|
+
},
|
|
2721
|
+
"bun-linux-arm64-musl": {
|
|
2722
|
+
alias: "linux-arm64-musl",
|
|
2723
|
+
platformKey: "linux-arm64-musl",
|
|
2724
|
+
os: "linux",
|
|
2725
|
+
cpu: "arm64",
|
|
2726
|
+
libc: "musl"
|
|
2727
|
+
},
|
|
1868
2728
|
"bun-darwin-x64": {
|
|
1869
2729
|
alias: "darwin-x64",
|
|
1870
2730
|
platformKey: "darwin-x64",
|
|
@@ -1942,8 +2802,57 @@ const DENO_TARGETS = {
|
|
|
1942
2802
|
}
|
|
1943
2803
|
}
|
|
1944
2804
|
};
|
|
1945
|
-
|
|
1946
|
-
|
|
2805
|
+
const NODE_TARGETS = {
|
|
2806
|
+
runtime: "Node",
|
|
2807
|
+
targets: [
|
|
2808
|
+
"linux-x64",
|
|
2809
|
+
"linux-arm64",
|
|
2810
|
+
"darwin-x64",
|
|
2811
|
+
"darwin-arm64",
|
|
2812
|
+
"win-x64",
|
|
2813
|
+
"win-arm64"
|
|
2814
|
+
],
|
|
2815
|
+
info: {
|
|
2816
|
+
"linux-x64": {
|
|
2817
|
+
alias: "linux-x64",
|
|
2818
|
+
platformKey: "linux-x64",
|
|
2819
|
+
os: "linux",
|
|
2820
|
+
cpu: "x64",
|
|
2821
|
+
libc: "glibc"
|
|
2822
|
+
},
|
|
2823
|
+
"linux-arm64": {
|
|
2824
|
+
alias: "linux-arm64",
|
|
2825
|
+
platformKey: "linux-arm64",
|
|
2826
|
+
os: "linux",
|
|
2827
|
+
cpu: "arm64",
|
|
2828
|
+
libc: "glibc"
|
|
2829
|
+
},
|
|
2830
|
+
"darwin-x64": {
|
|
2831
|
+
alias: "darwin-x64",
|
|
2832
|
+
platformKey: "darwin-x64",
|
|
2833
|
+
os: "darwin",
|
|
2834
|
+
cpu: "x64"
|
|
2835
|
+
},
|
|
2836
|
+
"darwin-arm64": {
|
|
2837
|
+
alias: "darwin-arm64",
|
|
2838
|
+
platformKey: "darwin-arm64",
|
|
2839
|
+
os: "darwin",
|
|
2840
|
+
cpu: "arm64"
|
|
2841
|
+
},
|
|
2842
|
+
"win-x64": {
|
|
2843
|
+
alias: "windows-x64",
|
|
2844
|
+
platformKey: "win32-x64",
|
|
2845
|
+
os: "win32",
|
|
2846
|
+
cpu: "x64"
|
|
2847
|
+
},
|
|
2848
|
+
"win-arm64": {
|
|
2849
|
+
alias: "windows-arm64",
|
|
2850
|
+
platformKey: "win32-arm64",
|
|
2851
|
+
os: "win32",
|
|
2852
|
+
cpu: "arm64"
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
};
|
|
1947
2856
|
/**
|
|
1948
2857
|
* Canonical targets for `--target` inputs, deduplicated in input order. No
|
|
1949
2858
|
* inputs means every target of the table; `host` means this machine's target.
|
|
@@ -2043,14 +2952,234 @@ function bunCompileTarget(target, runner, host = hostTarget(BUN_TARGETS)) {
|
|
|
2043
2952
|
/**
|
|
2044
2953
|
* Refuse the host target when only the `BUN_BE_BUN` fallback runner is
|
|
2045
2954
|
* available and no `-baseline` alias can stand in for it (arm64 hosts).
|
|
2955
|
+
* Pass the selected `runner` to judge that compiler instead of looking up
|
|
2956
|
+
* `bun` on PATH again.
|
|
2046
2957
|
*/
|
|
2047
|
-
function assertTargetsBuildableWithoutBun(targets, host = hostTarget(BUN_TARGETS)) {
|
|
2048
|
-
|
|
2958
|
+
function assertTargetsBuildableWithoutBun(targets, host = hostTarget(BUN_TARGETS), runner) {
|
|
2959
|
+
const externalBun = runner ? runner.env.BUN_BE_BUN !== "1" : which("bun") !== null;
|
|
2960
|
+
if (host === null || !targets.includes(host) || bunBaselineAlias(host) !== null || externalBun) return;
|
|
2049
2961
|
const others = targets.filter((target) => target !== host);
|
|
2050
2962
|
const alternative = others.length > 0 ? `pass --target with the other targets (e.g. ${others.map((target) => `--target ${target}`).join(" ")})` : "build a different target";
|
|
2051
2963
|
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.
|
|
2052
2964
|
Install Bun (https://bun.sh), or ${alternative}.`);
|
|
2053
2965
|
}
|
|
2966
|
+
/** The external `deno` on PATH; Deno has no embedded fallback. */
|
|
2967
|
+
function resolveDenoBuildRunner() {
|
|
2968
|
+
const denoPath = which("deno");
|
|
2969
|
+
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.");
|
|
2970
|
+
return {
|
|
2971
|
+
command: denoPath,
|
|
2972
|
+
env: { ...process.env }
|
|
2973
|
+
};
|
|
2974
|
+
}
|
|
2975
|
+
/** The external `node` on PATH, which runs tsdown's executable builder; there is no embedded fallback. */
|
|
2976
|
+
function resolveNodeBuildRunner() {
|
|
2977
|
+
const nodePath = which("node");
|
|
2978
|
+
if (!nodePath) throw new Error("Node is required for node standalone binaries but was not found on PATH.\n Binaries embed the selected node's version; install Node (https://nodejs.org) or put it first on PATH with your version manager.");
|
|
2979
|
+
return {
|
|
2980
|
+
command: nodePath,
|
|
2981
|
+
env: { ...process.env }
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
const RUNTIME_LABELS = {
|
|
2985
|
+
bun: "Bun",
|
|
2986
|
+
deno: "Deno",
|
|
2987
|
+
node: "Node"
|
|
2988
|
+
};
|
|
2989
|
+
const COMPILER_VERSION_TIMEOUT_MS = 3e4;
|
|
2990
|
+
/**
|
|
2991
|
+
* Runtime version reported by the runner itself (`<command> --version`), never
|
|
2992
|
+
* the runtime hosting this process: `bun` prints `1.4.2`, `deno` prints
|
|
2993
|
+
* `deno 2.9.6 (…)`, `node` prints `v24.21.0`. Under the `BUN_BE_BUN` fallback
|
|
2994
|
+
* this is the embedded Bun, which is the compiler. `cwd` must be the directory
|
|
2995
|
+
* compilation runs in: a version-manager shim picks its runtime from it. A
|
|
2996
|
+
* probe still running after {@link COMPILER_VERSION_TIMEOUT_MS} is killed and
|
|
2997
|
+
* fails the build, before `.crust/` is replaced.
|
|
2998
|
+
*/
|
|
2999
|
+
async function readCompilerVersion(runtime, runner, cwd) {
|
|
3000
|
+
const { exitCode, stdout, stderr } = await runProcess(runner.command, ["--version"], {
|
|
3001
|
+
env: runner.env,
|
|
3002
|
+
cwd,
|
|
3003
|
+
stdio: "collect",
|
|
3004
|
+
timeout: COMPILER_VERSION_TIMEOUT_MS
|
|
3005
|
+
});
|
|
3006
|
+
const reported = runtime === "deno" ? /^deno (\S+)/.exec(stdout.trim())?.[1] : stdout.trim();
|
|
3007
|
+
const version = exitCode === 0 && reported !== void 0 ? (0, import_valid.default)(reported) : null;
|
|
3008
|
+
if (version === null) {
|
|
3009
|
+
const output = [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
|
|
3010
|
+
throw new Error(`Could not read the ${RUNTIME_LABELS[runtime]} version from ${runner.command} --version (exit ${exitCode})${output ? `:\n${output}` : "."}`);
|
|
3011
|
+
}
|
|
3012
|
+
return version;
|
|
3013
|
+
}
|
|
3014
|
+
function isVersionRange(value) {
|
|
3015
|
+
return typeof value === "string" && (0, import_valid$1.default)(value) !== null;
|
|
3016
|
+
}
|
|
3017
|
+
/**
|
|
3018
|
+
* Check the selected compiler against the project's `engines.<runtime>` with
|
|
3019
|
+
* npm semver semantics. An absent constraint allows any version; an exact
|
|
3020
|
+
* value is a requirement, not a request to install that version.
|
|
3021
|
+
*/
|
|
3022
|
+
function assertCompilerSatisfiesEngines(compiler, userPackageJson) {
|
|
3023
|
+
if (userPackageJson === void 0 || !isJsonObject(userPackageJson)) return;
|
|
3024
|
+
const { engines } = userPackageJson;
|
|
3025
|
+
if (engines === void 0) return;
|
|
3026
|
+
if (!isJsonObject(engines)) throw new Error("package.json engines must be an object of runtime version ranges.");
|
|
3027
|
+
const constraint = engines[compiler.runtime];
|
|
3028
|
+
if (constraint === void 0) return;
|
|
3029
|
+
const field = `package.json engines.${compiler.runtime}`;
|
|
3030
|
+
if (!isVersionRange(constraint)) throw new Error(`${field} is not a valid semver range: ${JSON.stringify(constraint)}.\n Use an exact version or range such as "1.4.2" or ">=1.4.0".`);
|
|
3031
|
+
if (!(0, import_satisfies.default)(compiler.version, constraint)) {
|
|
3032
|
+
const label = RUNTIME_LABELS[compiler.runtime];
|
|
3033
|
+
throw new Error(`${label} ${compiler.version} (${compiler.runner.command}) does not satisfy ${field} "${constraint}".\n Binaries embed the selected compiler's ${label} version; crust does not install or upgrade it.\n Put a matching ${compiler.runtime} first on PATH (e.g. with your version manager), or update ${field}.`);
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
/**
|
|
3037
|
+
* Select the binary compiler once for a build: the Bun runner (external bun
|
|
3038
|
+
* first, then the embedded fallback) or the external deno. Returns its actual
|
|
3039
|
+
* version, read in the project directory `cwd`, after validating it against
|
|
3040
|
+
* `engines`. Pass `runner` and the same `cwd` on to the `exec*`/`buildEntrypoint`
|
|
3041
|
+
* helpers so every step uses this same compiler.
|
|
3042
|
+
*/
|
|
3043
|
+
async function resolveBinaryCompiler(runtime, userPackageJson, cwd) {
|
|
3044
|
+
const runner = runtime === "bun" ? resolveBunBuildRunner() : resolveDenoBuildRunner();
|
|
3045
|
+
const compiler = {
|
|
3046
|
+
runtime,
|
|
3047
|
+
runner,
|
|
3048
|
+
version: await readCompilerVersion(runtime, runner, cwd)
|
|
3049
|
+
};
|
|
3050
|
+
assertCompilerSatisfiesEngines(compiler, userPackageJson);
|
|
3051
|
+
return compiler;
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* Crust's own optional dependencies that build Node standalone binaries.
|
|
3055
|
+
* Crust's staged root and platform packages declare them
|
|
3056
|
+
* (scripts/stage-node-exe-dependencies.ts) so an installed crust resolves them
|
|
3057
|
+
* next to itself; an install that skipped them only affects Node binaries.
|
|
3058
|
+
*/
|
|
3059
|
+
const NODE_EXE_BACKEND_PACKAGES = ["tsdown", "@tsdown/exe"];
|
|
3060
|
+
/**
|
|
3061
|
+
* A file of Crust's own installation that the backend is resolved from, never
|
|
3062
|
+
* the project or PATH. A compiled crust serves its modules from Bun's virtual
|
|
3063
|
+
* filesystem (`/$bunfs/`, `B:/~BUN/` on Windows), so there it is the
|
|
3064
|
+
* executable, inside its platform package.
|
|
3065
|
+
*/
|
|
3066
|
+
function crustInstallPath(moduleUrl = import.meta.url, execPath = process.execPath) {
|
|
3067
|
+
return /^file:\/\/\/(?:\$bunfs|[A-Za-z]:\/~BUN)\//.test(moduleUrl) ? execPath : fileURLToPath(moduleUrl);
|
|
3068
|
+
}
|
|
3069
|
+
/**
|
|
3070
|
+
* `<dir>/node_modules/<name>/package.json` for the nearest `dir` at or above
|
|
3071
|
+
* `from`: Node's node_modules lookup without its NODE_PATH and global-folder
|
|
3072
|
+
* fallbacks, so only an installation next to `from` can supply the package.
|
|
3073
|
+
* Package managers hoist crust's backend into the project's node_modules, so
|
|
3074
|
+
* the found package may be the project's own: callers check its version.
|
|
3075
|
+
*/
|
|
3076
|
+
function findInstalledPackageJson(from, name) {
|
|
3077
|
+
for (let dir = from;; dir = dirname(dir)) {
|
|
3078
|
+
const candidate = join(dir, "node_modules", name, "package.json");
|
|
3079
|
+
if (existsSync(candidate)) return candidate;
|
|
3080
|
+
if (dirname(dir) === dir) return null;
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
function isVersionedPackageJson(value) {
|
|
3084
|
+
return isJsonObject(value) && typeof value.version === "string";
|
|
3085
|
+
}
|
|
3086
|
+
function isTsdownPackageJson(value) {
|
|
3087
|
+
return isVersionedPackageJson(value) && value.engines !== void 0 && isJsonObject(value.engines) && value.engines.node !== void 0 && isVersionRange(value.engines.node);
|
|
3088
|
+
}
|
|
3089
|
+
function createNodeExeProbeScript(tsdownPackageJson) {
|
|
3090
|
+
return `// Generated by crust build to read tsdown's executable minimum; deleted when it exits.
|
|
3091
|
+
import { createRequire } from "node:module";
|
|
3092
|
+
import { pathToFileURL } from "node:url";
|
|
3093
|
+
|
|
3094
|
+
const internal = createRequire(${JSON.stringify(tsdownPackageJson)}).resolve("tsdown/internal");
|
|
3095
|
+
console.log((await import(pathToFileURL(internal).href)).NODE_SEA_MIN_VERSION);
|
|
3096
|
+
`;
|
|
3097
|
+
}
|
|
3098
|
+
const NODE_TOOLCHAIN_GUIDANCE = " Binaries embed the selected node's version; crust does not install or upgrade it.\n Put a supported node first on PATH (e.g. with your version manager).";
|
|
3099
|
+
/**
|
|
3100
|
+
* Checks the selected Node against the installed backend's two separate
|
|
3101
|
+
* requirements: tsdown's package `engines.node` and its executable builder's
|
|
3102
|
+
* minimum (skipped while unknown). Both come from the installed tsdown, not
|
|
3103
|
+
* from this file.
|
|
3104
|
+
*/
|
|
3105
|
+
function assertNodeExeBackendSupports(compiler, backend) {
|
|
3106
|
+
const selected = `Node ${compiler.version} (${compiler.runner.command})`;
|
|
3107
|
+
if (!(0, import_satisfies.default)(compiler.version, backend.engines)) throw new Error(`${selected} is not supported by tsdown ${backend.version}, which builds node standalone binaries: its package requires Node "${backend.engines}".\n${NODE_TOOLCHAIN_GUIDANCE}`);
|
|
3108
|
+
if (backend.seaMinVersion !== void 0 && !(0, import_satisfies.default)(compiler.version, `>=${backend.seaMinVersion}`)) throw new Error(`${selected} cannot build standalone executables: tsdown ${backend.version}'s executable builder requires Node ${backend.seaMinVersion} or later.\n${NODE_TOOLCHAIN_GUIDANCE}`);
|
|
3109
|
+
}
|
|
3110
|
+
/**
|
|
3111
|
+
* Finds Crust's installed tsdown and @tsdown/exe from `installPath`, at the
|
|
3112
|
+
* versions its package.json `optionalDependencies` pin, and validates the
|
|
3113
|
+
* selected Node against tsdown's requirements, loading the executable
|
|
3114
|
+
* builder's minimum under that Node. `cwd` is the project
|
|
3115
|
+
* directory, as for every other compiler step.
|
|
3116
|
+
*/
|
|
3117
|
+
async function resolveNodeExeBackend(compiler, cwd, installPath = crustInstallPath()) {
|
|
3118
|
+
const reinstall = ` @crustjs/crust ships ${NODE_EXE_BACKEND_PACKAGES.join(" and ")} as optional dependencies, which package managers skip when optional dependencies are disabled or the installing node does not satisfy tsdown's engines.\n Reinstall @crustjs/crust with optional dependencies enabled under a node that can build Node binaries (e.g. the one on PATH here).`;
|
|
3119
|
+
const packageJsonPath = findInstalledPackageJson(dirname(installPath), "tsdown");
|
|
3120
|
+
if (packageJsonPath === null) throw new Error(`tsdown, which builds node standalone binaries, is not installed with crust (${installPath}).\n${reinstall}`);
|
|
3121
|
+
const exePackageJsonPath = findInstalledPackageJson(dirname(realpathSync(packageJsonPath)), "@tsdown/exe");
|
|
3122
|
+
if (exePackageJsonPath === null) throw new Error(`@tsdown/exe is not installed beside crust's tsdown (${packageJsonPath}).\n${reinstall}`);
|
|
3123
|
+
for (const [name, path] of [["tsdown", packageJsonPath], ["@tsdown/exe", exePackageJsonPath]]) {
|
|
3124
|
+
const installed = JSON.parse(readFileSync(path, "utf8"));
|
|
3125
|
+
const version = isVersionedPackageJson(installed) ? installed.version : "without a version";
|
|
3126
|
+
const pinned = optionalDependencies[name];
|
|
3127
|
+
if (!(0, import_satisfies.default)(version, pinned)) throw new Error(`${name} ${version} (${path}) is not the ${name} ${pinned} that crust builds node standalone binaries with.\n${reinstall}`);
|
|
3128
|
+
}
|
|
3129
|
+
const tsdownPackage = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
3130
|
+
if (!isTsdownPackageJson(tsdownPackage)) throw new Error(`Unexpected tsdown package metadata in ${packageJsonPath}.\n${reinstall}`);
|
|
3131
|
+
const backend = {
|
|
3132
|
+
packageJsonPath,
|
|
3133
|
+
version: tsdownPackage.version,
|
|
3134
|
+
engines: tsdownPackage.engines.node
|
|
3135
|
+
};
|
|
3136
|
+
assertNodeExeBackendSupports(compiler, backend);
|
|
3137
|
+
const workDir = await mkdtemp(join(tmpdir(), "crust-node-exe-probe-"));
|
|
3138
|
+
try {
|
|
3139
|
+
const scriptPath = join(workDir, "probe.mjs");
|
|
3140
|
+
await writeFile(scriptPath, createNodeExeProbeScript(packageJsonPath));
|
|
3141
|
+
const { exitCode, stdout, stderr } = await runProcess(compiler.runner.command, [scriptPath], {
|
|
3142
|
+
env: compiler.runner.env,
|
|
3143
|
+
cwd,
|
|
3144
|
+
stdio: "collect"
|
|
3145
|
+
});
|
|
3146
|
+
const seaMinVersion = exitCode === 0 ? (0, import_valid.default)(stdout.trim()) : null;
|
|
3147
|
+
if (seaMinVersion === null) {
|
|
3148
|
+
const output = [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
|
|
3149
|
+
throw new Error(`tsdown ${backend.version}'s executable builder could not be loaded with ${compiler.runner.command} (exit ${exitCode}).\n${reinstall}${output ? `\n${output}` : ""}`);
|
|
3150
|
+
}
|
|
3151
|
+
const resolved = {
|
|
3152
|
+
...backend,
|
|
3153
|
+
seaMinVersion
|
|
3154
|
+
};
|
|
3155
|
+
assertNodeExeBackendSupports(compiler, resolved);
|
|
3156
|
+
return resolved;
|
|
3157
|
+
} finally {
|
|
3158
|
+
await rm(workDir, {
|
|
3159
|
+
recursive: true,
|
|
3160
|
+
force: true
|
|
3161
|
+
});
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
/**
|
|
3165
|
+
* Select the Node binary compiler once for a build: the external `node`, its
|
|
3166
|
+
* version read in the project directory `cwd`, validated against the
|
|
3167
|
+
* project's `engines.node` and then the installed tsdown's requirements.
|
|
3168
|
+
* Pass it to {@link execNodeBinaryBuild} for every command and target.
|
|
3169
|
+
*/
|
|
3170
|
+
async function resolveNodeBinaryCompiler(userPackageJson, cwd) {
|
|
3171
|
+
const runner = resolveNodeBuildRunner();
|
|
3172
|
+
const compiler = {
|
|
3173
|
+
runtime: "node",
|
|
3174
|
+
runner,
|
|
3175
|
+
version: await readCompilerVersion("node", runner, cwd)
|
|
3176
|
+
};
|
|
3177
|
+
assertCompilerSatisfiesEngines(compiler, userPackageJson);
|
|
3178
|
+
return {
|
|
3179
|
+
...compiler,
|
|
3180
|
+
backend: await resolveNodeExeBackend(compiler, cwd)
|
|
3181
|
+
};
|
|
3182
|
+
}
|
|
2054
3183
|
/**
|
|
2055
3184
|
* Module source the generated driver imports for a `crust.bunPlugins` specifier.
|
|
2056
3185
|
*
|
|
@@ -2100,7 +3229,7 @@ if (!result.success) {
|
|
|
2100
3229
|
for (const log of result.logs) console.error(log);
|
|
2101
3230
|
process.exit(1);
|
|
2102
3231
|
}
|
|
2103
|
-
if (options.build.
|
|
3232
|
+
if (!options.build.compile) {
|
|
2104
3233
|
if (result.outputs.length !== 1) {
|
|
2105
3234
|
// Same refusal as \`bun build --outfile\`: a file-type asset import yields entry + asset.
|
|
2106
3235
|
console.error("error: cannot write multiple output files without an output directory");
|
|
@@ -2110,7 +3239,7 @@ if (options.build.target === "node") {
|
|
|
2110
3239
|
}
|
|
2111
3240
|
`;
|
|
2112
3241
|
}
|
|
2113
|
-
async function runBunPluginDriver(build, outfilePath, bunPlugins, envFiles, cwd) {
|
|
3242
|
+
async function runBunPluginDriver(build, outfilePath, bunPlugins, envFiles, cwd, runner) {
|
|
2114
3243
|
const driverPath = join(cwd, `.crust-build-${randomBytes(6).toString("hex")}.ts`);
|
|
2115
3244
|
await writeFile(driverPath, createBunPluginDriverScript({
|
|
2116
3245
|
plugins: bunPlugins.map((specifier) => ({
|
|
@@ -2121,7 +3250,7 @@ async function runBunPluginDriver(build, outfilePath, bunPlugins, envFiles, cwd)
|
|
|
2121
3250
|
outfile: outfilePath
|
|
2122
3251
|
}));
|
|
2123
3252
|
try {
|
|
2124
|
-
await runBuildProcess(
|
|
3253
|
+
await runBuildProcess(runner, [...toBunEnvFileArgs(envFiles), driverPath], outfilePath, cwd);
|
|
2125
3254
|
} finally {
|
|
2126
3255
|
await rm(driverPath, { force: true });
|
|
2127
3256
|
}
|
|
@@ -2141,10 +3270,10 @@ async function runBunPluginDriver(build, outfilePath, bunPlugins, envFiles, cwd)
|
|
|
2141
3270
|
* @param envFiles - Optional env files to load during build
|
|
2142
3271
|
* @param bunPlugins - Bun bundler plugin specifiers; when present the build
|
|
2143
3272
|
* runs through the generated `Bun.build` driver instead of `bun build`
|
|
3273
|
+
* @param runner - The selected Bun compiler (`resolveBinaryCompiler`)
|
|
2144
3274
|
* @throws {Error} If the build fails
|
|
2145
3275
|
*/
|
|
2146
|
-
async function execBuild(entryPath, outfilePath, minify, target, envFiles, cwd, bunPlugins = []) {
|
|
2147
|
-
const runner = resolveBunBuildRunner();
|
|
3276
|
+
async function execBuild(entryPath, outfilePath, minify, target, envFiles, cwd, bunPlugins = [], runner = resolveBunBuildRunner()) {
|
|
2148
3277
|
const compileTarget = bunCompileTarget(target, runner);
|
|
2149
3278
|
if (bunPlugins.length > 0) {
|
|
2150
3279
|
await runBunPluginDriver({
|
|
@@ -2157,7 +3286,7 @@ async function execBuild(entryPath, outfilePath, minify, target, envFiles, cwd,
|
|
|
2157
3286
|
outfile: outfilePath,
|
|
2158
3287
|
autoloadBunfig: false
|
|
2159
3288
|
}
|
|
2160
|
-
}, outfilePath, bunPlugins, envFiles, cwd);
|
|
3289
|
+
}, outfilePath, bunPlugins, envFiles, cwd, runner);
|
|
2161
3290
|
return;
|
|
2162
3291
|
}
|
|
2163
3292
|
await runBuildProcess(runner, createBunCompileArgs(entryPath, outfilePath, minify, compileTarget, envFiles), outfilePath, cwd);
|
|
@@ -2201,22 +3330,33 @@ async function runBuildProcess(runner, args, outfilePath, cwd) {
|
|
|
2201
3330
|
throw new Error(`Build failed for ${outfilePath}${output ? `:\n${output}` : ""}`);
|
|
2202
3331
|
}
|
|
2203
3332
|
}
|
|
2204
|
-
|
|
3333
|
+
/** Bundle a Node runtime package entry: ESM for Node behind `#!/usr/bin/env node`. */
|
|
3334
|
+
async function execNodeBuild(entryPath, outfilePath, minify, envFiles, cwd, bunPlugins = [], runner = resolveBunBuildRunner()) {
|
|
3335
|
+
await execScriptBuild("node", entryPath, outfilePath, minify, envFiles, cwd, bunPlugins, runner);
|
|
3336
|
+
}
|
|
3337
|
+
/**
|
|
3338
|
+
* Bundle a Bun runtime package entry: Bun-targeted ESM behind
|
|
3339
|
+
* `#!/usr/bin/env bun`, so the installed bin launches with Bun rather than Node.
|
|
3340
|
+
*/
|
|
3341
|
+
async function execBunPackageBuild(entryPath, outfilePath, minify, envFiles, cwd, bunPlugins = [], runner = resolveBunBuildRunner()) {
|
|
3342
|
+
await execScriptBuild("bun", entryPath, outfilePath, minify, envFiles, cwd, bunPlugins, runner);
|
|
3343
|
+
}
|
|
3344
|
+
async function execScriptBuild(target, entryPath, outfilePath, minify, envFiles, cwd, bunPlugins, runner) {
|
|
2205
3345
|
if (bunPlugins.length > 0) await runBunPluginDriver({
|
|
2206
3346
|
entrypoints: [entryPath],
|
|
2207
3347
|
minify,
|
|
2208
3348
|
env: "PUBLIC_*",
|
|
2209
|
-
target
|
|
3349
|
+
target,
|
|
2210
3350
|
format: "esm"
|
|
2211
|
-
}, outfilePath, bunPlugins, envFiles, cwd);
|
|
2212
|
-
else await runBuildProcess(
|
|
3351
|
+
}, outfilePath, bunPlugins, envFiles, cwd, runner);
|
|
3352
|
+
else await runBuildProcess(runner, [
|
|
2213
3353
|
"build",
|
|
2214
3354
|
...toBunEnvFileArgs(envFiles),
|
|
2215
3355
|
"--env=PUBLIC_*",
|
|
2216
3356
|
"--define",
|
|
2217
3357
|
CRUST_BUILD_DEFINE_ARG,
|
|
2218
3358
|
"--target",
|
|
2219
|
-
|
|
3359
|
+
target,
|
|
2220
3360
|
"--format",
|
|
2221
3361
|
"esm",
|
|
2222
3362
|
"--outfile",
|
|
@@ -2225,40 +3365,246 @@ async function execNodeBuild(entryPath, outfilePath, minify, envFiles, cwd, bunP
|
|
|
2225
3365
|
entryPath
|
|
2226
3366
|
], outfilePath, cwd);
|
|
2227
3367
|
const output = await readFile(outfilePath, "utf8");
|
|
2228
|
-
|
|
3368
|
+
const shebang = `#!/usr/bin/env ${target}\n`;
|
|
3369
|
+
await writeFile(outfilePath, shebang + output.replace(/^#![^\n]*(?:\n|$)/, ""));
|
|
2229
3370
|
if (process.platform !== "win32") await chmod(outfilePath, 493);
|
|
2230
3371
|
}
|
|
2231
|
-
async function execDenoBuild(entryPath, outfilePath, target, cwd) {
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
3372
|
+
async function execDenoBuild(entryPath, outfilePath, target, cwd, runner = resolveDenoBuildRunner()) {
|
|
3373
|
+
await runBuildProcess(runner, createDenoCompileArgs(entryPath, outfilePath, target), outfilePath, cwd);
|
|
3374
|
+
}
|
|
3375
|
+
/** tsdown's executable target for a Node target, embedding exactly `nodeVersion`. */
|
|
3376
|
+
function nodeExeTarget(target, nodeVersion) {
|
|
3377
|
+
const { os, cpu } = NODE_TARGETS.info[target];
|
|
3378
|
+
return {
|
|
3379
|
+
platform: os === "win32" ? "win" : os,
|
|
3380
|
+
arch: cpu,
|
|
3381
|
+
nodeVersion
|
|
3382
|
+
};
|
|
2238
3383
|
}
|
|
2239
3384
|
/**
|
|
2240
|
-
*
|
|
3385
|
+
* Script the selected Node runs to turn one Bun bundle into one target's
|
|
3386
|
+
* executable with tsdown's programmatic `build`. Every value is embedded via
|
|
3387
|
+
* JSON.stringify.
|
|
3388
|
+
*/
|
|
3389
|
+
function createNodeExeBuildScript(options) {
|
|
3390
|
+
return `// Generated by crust build for a Node standalone binary; deleted when the build finishes.
|
|
3391
|
+
import { createRequire } from "node:module";
|
|
3392
|
+
import { pathToFileURL } from "node:url";
|
|
3393
|
+
|
|
3394
|
+
const options = ${JSON.stringify(options)};
|
|
3395
|
+
const { build } = await import(pathToFileURL(createRequire(options.tsdownPackageJson).resolve("tsdown")).href);
|
|
3396
|
+
await build({
|
|
3397
|
+
config: false,
|
|
3398
|
+
cwd: options.cwd,
|
|
3399
|
+
entry: { app: options.entry },
|
|
3400
|
+
outDir: options.bundleDir,
|
|
3401
|
+
format: "esm",
|
|
3402
|
+
platform: "node",
|
|
3403
|
+
dts: false,
|
|
3404
|
+
// Rolldown reprints the Bun bundle, so it minifies again.
|
|
3405
|
+
minify: options.minify,
|
|
3406
|
+
logLevel: "warn",
|
|
3407
|
+
report: false,
|
|
3408
|
+
// Bun already inlined the PUBLIC_* constants; inline nothing from this environment.
|
|
3409
|
+
envPrefix: [],
|
|
3410
|
+
// Bun leaves only Node built-ins as imports; fail on anything else, which
|
|
3411
|
+
// an executable shipping no node_modules could not resolve.
|
|
3412
|
+
deps: { alwaysBundle: () => true, onlyBundle: false, onlyImport: [] },
|
|
3413
|
+
exe: { outDir: options.exeDir, fileName: "app", targets: [options.target] },
|
|
3414
|
+
});
|
|
3415
|
+
`;
|
|
3416
|
+
}
|
|
3417
|
+
/**
|
|
3418
|
+
* Build a single entry file into a Node standalone executable: Bun first
|
|
3419
|
+
* bundles it for Node exactly as a Node runtime package ({@link execNodeBuild}:
|
|
3420
|
+
* `PUBLIC_*` constants from `envFiles` and the environment, each module's own
|
|
3421
|
+
* `import.meta.main` and `require.main === module`, CommonJS and ESM inputs),
|
|
3422
|
+
* then tsdown's executable builder (Node SEA), run by the selected external
|
|
3423
|
+
* Node, turns that bundle into an executable embedding exactly its version
|
|
3424
|
+
* for `target`. tsdown takes a single entry per executable, so callers build
|
|
3425
|
+
* every command separately. Matching official Node binaries for targets are
|
|
3426
|
+
* downloaded, checksum-verified, and cached by @tsdown/exe. Builds for darwin
|
|
3427
|
+
* are only code-signed on a macOS host.
|
|
2241
3428
|
*
|
|
2242
|
-
*
|
|
2243
|
-
*
|
|
2244
|
-
*
|
|
3429
|
+
* @param compiler - The selected Node compiler (`resolveNodeBinaryCompiler`)
|
|
3430
|
+
* @param bunRunner - The Bun that bundles (`resolveBunBuildRunner`)
|
|
3431
|
+
* @param onWarning - Receives the backend's warnings (such as a skipped code
|
|
3432
|
+
* signature) after a successful build
|
|
3433
|
+
* @throws {Error} If the build fails
|
|
3434
|
+
*/
|
|
3435
|
+
async function execNodeBinaryBuild(entryPath, outfilePath, minify, target, envFiles, cwd, compiler, bunRunner, onWarning = () => {}) {
|
|
3436
|
+
const workDir = await mkdtemp(join(tmpdir(), "crust-node-exe-"));
|
|
3437
|
+
try {
|
|
3438
|
+
const scriptPath = join(workDir, "build.mjs");
|
|
3439
|
+
const bunBundle = join(workDir, "app.mjs");
|
|
3440
|
+
const exeDir = join(workDir, "exe");
|
|
3441
|
+
await execNodeBuild(resolve(cwd, entryPath), bunBundle, minify, envFiles, cwd, [], bunRunner);
|
|
3442
|
+
await writeFile(scriptPath, createNodeExeBuildScript({
|
|
3443
|
+
tsdownPackageJson: compiler.backend.packageJsonPath,
|
|
3444
|
+
cwd,
|
|
3445
|
+
entry: bunBundle,
|
|
3446
|
+
bundleDir: join(workDir, "bundle"),
|
|
3447
|
+
exeDir,
|
|
3448
|
+
minify,
|
|
3449
|
+
target: nodeExeTarget(target, compiler.version)
|
|
3450
|
+
}));
|
|
3451
|
+
const { exitCode, stdout, stderr } = await runProcess(compiler.runner.command, [scriptPath], {
|
|
3452
|
+
env: compiler.runner.env,
|
|
3453
|
+
cwd,
|
|
3454
|
+
stdio: "collect"
|
|
3455
|
+
});
|
|
3456
|
+
const output = [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
|
|
3457
|
+
if (exitCode !== 0) throw new Error(`Build failed for ${outfilePath}${output ? `:\n${output}` : ""}`);
|
|
3458
|
+
const produced = await readdir(exeDir);
|
|
3459
|
+
if (produced.length !== 1) throw new Error(`Build failed for ${outfilePath}: expected one executable from tsdown, found ${JSON.stringify(produced)}.`);
|
|
3460
|
+
await copyFile(join(exeDir, produced[0]), outfilePath);
|
|
3461
|
+
if (output) onWarning(output);
|
|
3462
|
+
} finally {
|
|
3463
|
+
await rm(workDir, {
|
|
3464
|
+
recursive: true,
|
|
3465
|
+
force: true,
|
|
3466
|
+
maxRetries: 3,
|
|
3467
|
+
retryDelay: 100
|
|
3468
|
+
});
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
function createNodeExeProvisionScript(tsdownPackageJson, targets) {
|
|
3472
|
+
return `// Generated by crust build to provision Node binaries for targets; deleted when it exits.
|
|
3473
|
+
import { realpathSync } from "node:fs";
|
|
3474
|
+
import { createRequire } from "node:module";
|
|
3475
|
+
import { pathToFileURL } from "node:url";
|
|
3476
|
+
|
|
3477
|
+
const exe = createRequire(realpathSync(${JSON.stringify(tsdownPackageJson)})).resolve("@tsdown/exe");
|
|
3478
|
+
const { resolveNodeBinary } = await import(pathToFileURL(exe).href);
|
|
3479
|
+
for (const { name, target } of ${JSON.stringify(targets)}) {
|
|
3480
|
+
try {
|
|
3481
|
+
await resolveNodeBinary(target, {});
|
|
3482
|
+
} catch (error) {
|
|
3483
|
+
console.error(name + ": " + error.message + (error.cause?.message ? "\\n" + error.cause.message : ""));
|
|
3484
|
+
process.exit(1);
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3487
|
+
`;
|
|
3488
|
+
}
|
|
3489
|
+
/**
|
|
3490
|
+
* Provisions the Node binary every target embeds before anything is staged,
|
|
3491
|
+
* with the selected Node and the call tsdown's executable builder makes per
|
|
3492
|
+
* target (@tsdown/exe's `resolveNodeBinary`): an uncached official archive of
|
|
3493
|
+
* exactly `compiler.version` is downloaded, checksum-verified, unpacked with
|
|
3494
|
+
* the tool that target's archive needs on this host, and cached, where
|
|
3495
|
+
* {@link execNodeBinaryBuild} then finds it. A missing unpacking tool, a failed
|
|
3496
|
+
* download, or a checksum mismatch therefore fails here, before `.crust/` is
|
|
3497
|
+
* replaced; cached targets need nothing.
|
|
3498
|
+
*
|
|
3499
|
+
* @throws {Error} If a target cannot be provisioned
|
|
3500
|
+
*/
|
|
3501
|
+
async function provisionNodeExeTargets(targets, cwd, compiler) {
|
|
3502
|
+
const workDir = await mkdtemp(join(tmpdir(), "crust-node-exe-provision-"));
|
|
3503
|
+
try {
|
|
3504
|
+
const scriptPath = join(workDir, "provision.mjs");
|
|
3505
|
+
await writeFile(scriptPath, createNodeExeProvisionScript(compiler.backend.packageJsonPath, targets.map((name) => ({
|
|
3506
|
+
name,
|
|
3507
|
+
target: nodeExeTarget(name, compiler.version)
|
|
3508
|
+
}))));
|
|
3509
|
+
const { exitCode, stdout, stderr } = await runProcess(compiler.runner.command, [scriptPath], {
|
|
3510
|
+
env: compiler.runner.env,
|
|
3511
|
+
cwd,
|
|
3512
|
+
stdio: "collect"
|
|
3513
|
+
});
|
|
3514
|
+
if (exitCode !== 0) {
|
|
3515
|
+
const output = [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
|
|
3516
|
+
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.
|
|
3517
|
+
Install the missing tool, or build only targets this machine can provision (--target).`);
|
|
3518
|
+
}
|
|
3519
|
+
} finally {
|
|
3520
|
+
await rm(workDir, {
|
|
3521
|
+
recursive: true,
|
|
3522
|
+
force: true
|
|
3523
|
+
});
|
|
3524
|
+
}
|
|
3525
|
+
}
|
|
3526
|
+
/**
|
|
3527
|
+
* Oldest `deno` accepted to bundle a Deno runtime package. Deno 2.4 resolves a
|
|
3528
|
+
* package.json project's npm dependencies from the registry instead of its
|
|
3529
|
+
* installed node_modules, so it can bundle a different Crust than the project
|
|
3530
|
+
* installed. Tested on Linux x64 with Deno 2.5.0 through 2.9.6.
|
|
3531
|
+
*/
|
|
3532
|
+
const DENO_PACKAGE_MIN_VERSION = "2.5.0";
|
|
3533
|
+
/**
|
|
3534
|
+
* Select the external deno that bundles a Deno runtime package, reading its
|
|
3535
|
+
* version in the project directory `cwd`. Call it before staging is replaced.
|
|
3536
|
+
* A runtime package embeds no Deno, so `engines.deno` stays a consumer
|
|
3537
|
+
* requirement and is not checked against this bundler.
|
|
3538
|
+
*/
|
|
3539
|
+
async function resolveDenoPackageBundler(cwd, runner = resolveDenoBuildRunner()) {
|
|
3540
|
+
const version = await readCompilerVersion("deno", runner, cwd);
|
|
3541
|
+
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.
|
|
3542
|
+
crust does not install or upgrade Deno; put a newer deno first on PATH (e.g. with your version manager).`);
|
|
3543
|
+
return {
|
|
3544
|
+
runtime: "deno",
|
|
3545
|
+
runner,
|
|
3546
|
+
version
|
|
3547
|
+
};
|
|
3548
|
+
}
|
|
3549
|
+
/**
|
|
3550
|
+
* Bundle a Deno runtime package entry with native `deno bundle`, which resolves
|
|
3551
|
+
* dependencies through the project's own Deno setup (deno.json imports,
|
|
3552
|
+
* package.json with its installed node_modules) and inlines them into one file.
|
|
2245
3553
|
*
|
|
2246
|
-
*
|
|
2247
|
-
*
|
|
2248
|
-
*
|
|
3554
|
+
* Bundle the declared command directly so Deno preserves its `import.meta.main`
|
|
3555
|
+
* semantics without making dependencies main. Prepend the packaged-build marker
|
|
3556
|
+
* (`PACKAGED_BUILD_KEY`) to the bundled code so it runs before the inlined
|
|
3557
|
+
* application graph. The output has no shebang or permission flags: consumers
|
|
3558
|
+
* choose grants with `deno run` / `deno install`.
|
|
3559
|
+
* No env files or plugins: `deno bundle` has no PUBLIC_* filter or Bun plugins.
|
|
2249
3560
|
*/
|
|
3561
|
+
async function execDenoPackageBuild(entryPath, outfilePath, cwd, runner = resolveDenoBuildRunner()) {
|
|
3562
|
+
await runBuildProcess(runner, [
|
|
3563
|
+
"bundle",
|
|
3564
|
+
"--platform=deno",
|
|
3565
|
+
"--packages=bundle",
|
|
3566
|
+
"--output",
|
|
3567
|
+
outfilePath,
|
|
3568
|
+
resolve(cwd, entryPath)
|
|
3569
|
+
], outfilePath, cwd);
|
|
3570
|
+
const output = await readFile(outfilePath, "utf8");
|
|
3571
|
+
await writeFile(outfilePath, `globalThis[Symbol.for(${JSON.stringify(PACKAGED_BUILD_KEY)})] = true;\n` + output.replace(/^#![^\n]*(?:\n|$)/, ""));
|
|
3572
|
+
}
|
|
2250
3573
|
const SNAPSHOT_TIMEOUT_MS = 3e4;
|
|
3574
|
+
const SNAPSHOT_FORWARDED_SIGNALS = [
|
|
3575
|
+
"SIGINT",
|
|
3576
|
+
"SIGTERM",
|
|
3577
|
+
"SIGHUP",
|
|
3578
|
+
"SIGQUIT"
|
|
3579
|
+
];
|
|
2251
3580
|
function isBuildReport(value) {
|
|
2252
3581
|
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"));
|
|
2253
3582
|
}
|
|
2254
|
-
|
|
3583
|
+
/**
|
|
3584
|
+
* Prepare a CLI entry's Command Snapshot in the user's project context.
|
|
3585
|
+
*
|
|
3586
|
+
* The entry runs as a subprocess with `CRUST_INTERNAL_SNAPSHOT_PATH` pointing
|
|
3587
|
+
* to a temporary file. `.execute()` validates and writes the command graph and
|
|
3588
|
+
* adjacent Build Report, then exits before any following entrypoint code can run.
|
|
3589
|
+
*
|
|
3590
|
+
* Runs with the same bun as compilation (`resolveBunBuildRunner`, or the
|
|
3591
|
+
* pinned Bun `runner`): bun on PATH, or a compiled standalone crust executable
|
|
3592
|
+
* as `BUN_BE_BUN=1`, so arbitrary `.ts` entries run without a separate `bun`
|
|
3593
|
+
* install.
|
|
3594
|
+
*
|
|
3595
|
+
* After `timeoutMs`, the entry's POSIX process group or live Windows process
|
|
3596
|
+
* tree is killed and preparation fails, even if a descendant still holds stderr.
|
|
3597
|
+
* On POSIX, SIGINT, SIGTERM, SIGHUP, SIGQUIT or a synchronous exit of this
|
|
3598
|
+
* process also kills the entry's group, and whatever remains of the group is
|
|
3599
|
+
* killed once preparation settles.
|
|
3600
|
+
*/
|
|
3601
|
+
async function buildEntrypoint(entryPath, outDir, envFiles, io, cwd, runner = resolveBunBuildRunner(), timeoutMs = SNAPSHOT_TIMEOUT_MS) {
|
|
2255
3602
|
const absoluteEntry = resolve(entryPath);
|
|
2256
3603
|
const snapshotDir = await mkdtemp(join(tmpdir(), "crust-snapshot-"));
|
|
2257
3604
|
const snapshotPath = join(snapshotDir, "command.json");
|
|
2258
3605
|
const buildReportPath = join(snapshotDir, "build-report.json");
|
|
2259
3606
|
try {
|
|
2260
|
-
const
|
|
2261
|
-
const spawnedAt = Date.now();
|
|
3607
|
+
const detached = process.platform !== "win32";
|
|
2262
3608
|
const proc = spawn(runner.command, [...toBunEnvFileArgs(envFiles), absoluteEntry], {
|
|
2263
3609
|
env: {
|
|
2264
3610
|
...runner.env,
|
|
@@ -2271,15 +3617,47 @@ async function buildEntrypoint(entryPath, outDir, envFiles, io, cwd) {
|
|
|
2271
3617
|
"ignore",
|
|
2272
3618
|
"pipe"
|
|
2273
3619
|
],
|
|
2274
|
-
|
|
3620
|
+
detached
|
|
3621
|
+
});
|
|
3622
|
+
let stop;
|
|
3623
|
+
const stopped = new Promise((_, reject) => {
|
|
3624
|
+
stop = (message) => {
|
|
3625
|
+
let failure = new Error(message);
|
|
3626
|
+
try {
|
|
3627
|
+
killProcessTree(proc);
|
|
3628
|
+
} catch (cause) {
|
|
3629
|
+
failure = new Error(`${message}\n Process-tree cleanup failed.`, { cause });
|
|
3630
|
+
}
|
|
3631
|
+
proc.stderr.destroy();
|
|
3632
|
+
reject(failure);
|
|
3633
|
+
};
|
|
2275
3634
|
});
|
|
2276
|
-
const
|
|
2277
|
-
const
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
if (
|
|
2281
|
-
|
|
3635
|
+
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);
|
|
3636
|
+
const onSignal = (signal) => {
|
|
3637
|
+
removeLifetimeListeners();
|
|
3638
|
+
stop(`Command Snapshot preparation was interrupted by ${signal}.`);
|
|
3639
|
+
if (process.listenerCount(signal) === 0) process.kill(process.pid, signal);
|
|
3640
|
+
};
|
|
3641
|
+
const killRemainingGroup = () => {
|
|
3642
|
+
try {
|
|
3643
|
+
killProcessTree(proc);
|
|
3644
|
+
} catch {}
|
|
3645
|
+
};
|
|
3646
|
+
const removeLifetimeListeners = () => {
|
|
3647
|
+
for (const signal of SNAPSHOT_FORWARDED_SIGNALS) process.removeListener(signal, onSignal);
|
|
3648
|
+
process.removeListener("exit", killRemainingGroup);
|
|
3649
|
+
};
|
|
3650
|
+
if (detached) {
|
|
3651
|
+
for (const signal of SNAPSHOT_FORWARDED_SIGNALS) process.prependListener(signal, onSignal);
|
|
3652
|
+
process.on("exit", killRemainingGroup);
|
|
2282
3653
|
}
|
|
3654
|
+
const [rawStderr, [exitCode]] = await Promise.race([Promise.all([text(proc.stderr), once(proc, "close")]), stopped]).finally(() => {
|
|
3655
|
+
clearTimeout(timer);
|
|
3656
|
+
removeLifetimeListeners();
|
|
3657
|
+
if (detached) killRemainingGroup();
|
|
3658
|
+
});
|
|
3659
|
+
const stderr = rawStderr.trim();
|
|
3660
|
+
if (proc.signalCode !== null) throw new Error(`Command Snapshot preparation was killed by ${proc.signalCode}.${stderr ? `\n${stderr}` : ""}`);
|
|
2283
3661
|
if (exitCode !== 0) throw new Error(stderr || "Command Snapshot preparation failed");
|
|
2284
3662
|
if (stderr) {
|
|
2285
3663
|
const styled = stderr.split("\n").map((line) => line.startsWith("Warning:") ? `${yellow("Warning:")}${line.slice(8)}` : line).join("\n");
|
|
@@ -2335,6 +3713,12 @@ async function buildEntrypoint(entryPath, outDir, envFiles, io, cwd) {
|
|
|
2335
3713
|
//#region src/utils/distribute.ts
|
|
2336
3714
|
/** Project-relative directory that `crust build` owns: wiped per build, read by `crust publish`. */
|
|
2337
3715
|
const CRUST_DIR = ".crust";
|
|
3716
|
+
/**
|
|
3717
|
+
* What one build distributes: a runtime `package` (a root-only JavaScript
|
|
3718
|
+
* bundle that needs the runtime installed) or standalone `binary` executables
|
|
3719
|
+
* in platform packages behind a Node launcher.
|
|
3720
|
+
*/
|
|
3721
|
+
const ARTIFACT_KINDS = ["package", "binary"];
|
|
2338
3722
|
const MAX_PACKAGE_NAME_LENGTH = 214;
|
|
2339
3723
|
const METADATA_KEYS = [
|
|
2340
3724
|
"description",
|
|
@@ -2633,9 +4017,10 @@ function copyLicense(cwd, packageDirs) {
|
|
|
2633
4017
|
const licensePath = join(cwd, licenseName);
|
|
2634
4018
|
for (const packageDir of packageDirs) copyFileSync(licensePath, join(packageDir, licenseName));
|
|
2635
4019
|
}
|
|
2636
|
-
function writeDistributionManifest(stageDir, metadata, commands, targets, build) {
|
|
4020
|
+
function writeDistributionManifest(stageDir, metadata, identity, commands, targets, build) {
|
|
2637
4021
|
const manifest = {
|
|
2638
4022
|
version: metadata.version,
|
|
4023
|
+
...identity,
|
|
2639
4024
|
root: {
|
|
2640
4025
|
name: metadata.rootPackageName,
|
|
2641
4026
|
dir: "root",
|
|
@@ -2656,7 +4041,17 @@ function writeDistributionManifest(stageDir, metadata, commands, targets, build)
|
|
|
2656
4041
|
writeJson(join(stageDir, "manifest.json"), manifest);
|
|
2657
4042
|
return manifest;
|
|
2658
4043
|
}
|
|
2659
|
-
|
|
4044
|
+
/** `pkg` without `engines.node`, dropping `engines` once nothing else is left. */
|
|
4045
|
+
function omitNodeEngine(pkg) {
|
|
4046
|
+
const { engines, ...rest } = pkg;
|
|
4047
|
+
if (engines?.node === void 0) return pkg;
|
|
4048
|
+
const others = Object.entries(engines).filter(([runtime]) => runtime !== "node");
|
|
4049
|
+
return others.length > 0 ? {
|
|
4050
|
+
...rest,
|
|
4051
|
+
engines: Object.fromEntries(others)
|
|
4052
|
+
} : rest;
|
|
4053
|
+
}
|
|
4054
|
+
function stageDistributionPackages(cwd, stageDir, metadata, platformMetadata, commands, targets, options) {
|
|
2660
4055
|
const rootDir = join(stageDir, "root");
|
|
2661
4056
|
const rootBinDir = join(rootDir, "bin");
|
|
2662
4057
|
mkdirSync(rootBinDir, { recursive: true });
|
|
@@ -2664,7 +4059,7 @@ function stageDistributionPackages(cwd, stageDir, metadata, commands, targets, o
|
|
|
2664
4059
|
copyRootReadme(cwd, rootDir);
|
|
2665
4060
|
for (const target of targets) {
|
|
2666
4061
|
mkdirSync(join(target.packageDir, "bin"), { recursive: true });
|
|
2667
|
-
writeJson(join(target.packageDir, "package.json"), buildDistributionPlatformPackageJson(
|
|
4062
|
+
writeJson(join(target.packageDir, "package.json"), buildDistributionPlatformPackageJson(platformMetadata, commands, target));
|
|
2668
4063
|
}
|
|
2669
4064
|
copyLicense(cwd, [rootDir, ...targets.map((target) => target.packageDir)]);
|
|
2670
4065
|
}
|
|
@@ -2674,15 +4069,20 @@ function stageDistributionPackages(cwd, stageDir, metadata, commands, targets, o
|
|
|
2674
4069
|
* Returns every generated package.json, launcher, and compiled command in staging order.
|
|
2675
4070
|
*/
|
|
2676
4071
|
async function runDistributeBuild(plan, distribution, io, build) {
|
|
2677
|
-
const
|
|
4072
|
+
const sourceMetadata = resolveDistributionMetadata(plan.cwd, plan.userPackageJson);
|
|
2678
4073
|
const commands = plan.entries.map((entry) => entry.command);
|
|
2679
4074
|
const table = distribution.table;
|
|
4075
|
+
const platformMetadata = plan.runtime === "node" && table ? {
|
|
4076
|
+
...sourceMetadata,
|
|
4077
|
+
rootPackageJson: omitNodeEngine(sourceMetadata.rootPackageJson)
|
|
4078
|
+
} : sourceMetadata;
|
|
4079
|
+
const metadata = sourceMetadata.exports === void 0 ? platformMetadata : sourceMetadata;
|
|
2680
4080
|
const distributionTargets = table ? distribution.targets.map((target) => resolveDistributionTarget(table, plan.stageDir, metadata.rootPackageName, target)) : [];
|
|
2681
4081
|
io.stdout(table ? `Staging ${bold(`${distributionTargets.length}`)} distribution target(s) in ${dim(plan.stageDir)}...` : `Staging a root-only npm package in ${dim(plan.stageDir)}...`);
|
|
2682
4082
|
const artifactOutDir = plan.validate ? plan.outDir : void 0;
|
|
2683
4083
|
const artifacts = collectArtifacts(artifactOutDir);
|
|
2684
4084
|
const includeDirs = collectIncludeDirs(plan.cwd, plan.stageDir, plan.include, artifacts.names);
|
|
2685
|
-
stageDistributionPackages(plan.cwd, plan.stageDir, metadata, commands, distributionTargets, {
|
|
4085
|
+
stageDistributionPackages(plan.cwd, plan.stageDir, metadata, platformMetadata, commands, distributionTargets, {
|
|
2686
4086
|
artifactDirs: [...artifacts.names, ...includeDirs],
|
|
2687
4087
|
manPages: artifacts.manPages
|
|
2688
4088
|
});
|
|
@@ -2746,7 +4146,14 @@ async function runDistributeBuild(plan, distribution, io, build) {
|
|
|
2746
4146
|
command
|
|
2747
4147
|
});
|
|
2748
4148
|
}
|
|
2749
|
-
writeDistributionManifest(plan.stageDir, metadata,
|
|
4149
|
+
writeDistributionManifest(plan.stageDir, metadata, table ? {
|
|
4150
|
+
runtime: plan.runtime,
|
|
4151
|
+
artifact: "binary",
|
|
4152
|
+
embeddedRuntimeVersion: distribution.embeddedRuntimeVersion
|
|
4153
|
+
} : {
|
|
4154
|
+
runtime: plan.runtime,
|
|
4155
|
+
artifact: "package"
|
|
4156
|
+
}, commands, distributionTargets, build);
|
|
2750
4157
|
const manifestPath = join(plan.stageDir, "manifest.json");
|
|
2751
4158
|
io.stdout(`\n${green("✓")} Staged ${bold(`${distributionTargets.length + 1}`)} npm package(s) successfully:`);
|
|
2752
4159
|
io.stdout(` ${rootDir}`);
|
|
@@ -2768,9 +4175,13 @@ function collectIncludeDirs(cwd, stageDir, include, artifactNames) {
|
|
|
2768
4175
|
if (!existsSync(dir) || !statSync(dir).isDirectory()) throw new Error(`package.json crust.include entry ${JSON.stringify(entry)} is not a directory: ${dir}`);
|
|
2769
4176
|
assertResolvesInsideProject(cwd, entry, dir);
|
|
2770
4177
|
if (isWithin(stageDir, dir) || isWithin(dir, stageDir)) throw new Error(`package.json crust.include entry ${JSON.stringify(entry)} overlaps the build output directory ${stageDir}, which crust build replaces.`);
|
|
2771
|
-
if (name.split(sep)[0] === "bin") throw new Error(`package.json crust.include entry ${JSON.stringify(entry)} conflicts with the generated npm bin directory.\n Include a directory with a different top-level name.`);
|
|
4178
|
+
if (name.toLowerCase().split(sep)[0] === "bin") throw new Error(`package.json crust.include entry ${JSON.stringify(entry)} conflicts with the generated npm bin directory.\n Include a directory with a different top-level name.`);
|
|
2772
4179
|
const posixName = name.replaceAll(sep, "/");
|
|
2773
|
-
const
|
|
4180
|
+
const key = posixName.toLowerCase();
|
|
4181
|
+
const overlap = names.find((staged) => {
|
|
4182
|
+
const stagedKey = staged.toLowerCase();
|
|
4183
|
+
return stagedKey === key || stagedKey.startsWith(`${key}/`) || key.startsWith(`${stagedKey}/`);
|
|
4184
|
+
});
|
|
2774
4185
|
if (overlap !== void 0) throw new Error(`package.json crust.include entry ${JSON.stringify(entry)} overlaps "${overlap}", which is already staged (duplicate include or Extension artifact directory).`);
|
|
2775
4186
|
names.push(posixName);
|
|
2776
4187
|
includeDirs.push(posixName);
|
|
@@ -2837,7 +4248,8 @@ function collectArtifacts(artifactOutDir) {
|
|
|
2837
4248
|
manPages: []
|
|
2838
4249
|
};
|
|
2839
4250
|
const names = readdirSync(artifactOutDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
2840
|
-
|
|
4251
|
+
const binName = names.find((name) => name.toLowerCase() === "bin");
|
|
4252
|
+
if (binName !== void 0) throw new Error(`Artifact directory "${binName}" in ${artifactOutDir} conflicts with the generated npm bin directory.\n Emit build artifacts under a different top-level name.`);
|
|
2841
4253
|
return {
|
|
2842
4254
|
names,
|
|
2843
4255
|
manPages: names.includes("man") ? readdirSync(join(artifactOutDir, "man"), { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort() : []
|
|
@@ -2848,6 +4260,7 @@ function collectArtifacts(artifactOutDir) {
|
|
|
2848
4260
|
/** Also mirrored by `schema/package.json`; build.test.ts guards against drift. */
|
|
2849
4261
|
const CRUST_CONFIG_KEYS = [
|
|
2850
4262
|
"runtime",
|
|
4263
|
+
"artifact",
|
|
2851
4264
|
"targets",
|
|
2852
4265
|
"bunPlugins",
|
|
2853
4266
|
"include"
|
|
@@ -2855,6 +4268,9 @@ const CRUST_CONFIG_KEYS = [
|
|
|
2855
4268
|
function isBuildRuntime(value) {
|
|
2856
4269
|
return typeof value === "string" && BUILD_RUNTIMES.some((runtime) => runtime === value);
|
|
2857
4270
|
}
|
|
4271
|
+
function isArtifactKind(value) {
|
|
4272
|
+
return typeof value === "string" && ARTIFACT_KINDS.some((kind) => kind === value);
|
|
4273
|
+
}
|
|
2858
4274
|
function isString(value) {
|
|
2859
4275
|
return typeof value === "string";
|
|
2860
4276
|
}
|
|
@@ -2873,6 +4289,10 @@ function readCrustConfig(pkg) {
|
|
|
2873
4289
|
if (!isBuildRuntime(crust.runtime)) throw new Error(`Invalid package.json crust.runtime ${JSON.stringify(crust.runtime)}. Valid runtimes: ${BUILD_RUNTIMES.join(", ")}`);
|
|
2874
4290
|
config.runtime = crust.runtime;
|
|
2875
4291
|
}
|
|
4292
|
+
if (crust.artifact !== void 0) {
|
|
4293
|
+
if (!isArtifactKind(crust.artifact)) throw new Error(`Invalid package.json crust.artifact ${JSON.stringify(crust.artifact)}. Valid artifacts: ${ARTIFACT_KINDS.join(", ")}`);
|
|
4294
|
+
config.artifact = crust.artifact;
|
|
4295
|
+
}
|
|
2876
4296
|
if (crust.targets !== void 0) {
|
|
2877
4297
|
if (!isStringArray(crust.targets) || crust.targets.length === 0) throw new Error("package.json crust.targets must be a non-empty array of canonical compiler targets, e.g. [\"bun-linux-x64\", \"bun-darwin-arm64\"].");
|
|
2878
4298
|
config.targets = crust.targets;
|
|
@@ -2997,19 +4417,44 @@ function resolveBinEntries(cwd, pkg) {
|
|
|
2997
4417
|
};
|
|
2998
4418
|
});
|
|
2999
4419
|
}
|
|
4420
|
+
/** What earlier releases built for each runtime without being asked; quoted in the migration error. */
|
|
4421
|
+
const IMPLICIT_ARTIFACTS = {
|
|
4422
|
+
bun: "binary",
|
|
4423
|
+
deno: "binary",
|
|
4424
|
+
node: "package"
|
|
4425
|
+
};
|
|
4426
|
+
/** `option` (the `artifact` build option or `--artifact`) > package.json `crust.artifact`; no default. */
|
|
4427
|
+
function resolveArtifact(option, config, runtime) {
|
|
4428
|
+
if (option !== void 0 && !isArtifactKind(option)) throw new Error(`Invalid artifact ${JSON.stringify(option)}. Valid artifacts: ${ARTIFACT_KINDS.join(", ")}`);
|
|
4429
|
+
const artifact = option ?? config.artifact;
|
|
4430
|
+
if (artifact === void 0) {
|
|
4431
|
+
const previous = IMPLICIT_ARTIFACTS[runtime];
|
|
4432
|
+
throw new Error(`crust build needs an artifact kind: pass --artifact package|binary or set package.json "crust": { "artifact": "package" | "binary" }.
|
|
4433
|
+
package: one JavaScript bundle per command that runs on the consumer's installed runtime.
|
|
4434
|
+
binary: standalone executables in per-platform npm packages behind a Node launcher.
|
|
4435
|
+
Earlier versions built a ${previous} for the ${runtime} runtime implicitly; set "artifact": "${previous}" to keep that output.`);
|
|
4436
|
+
}
|
|
4437
|
+
return {
|
|
4438
|
+
runtime,
|
|
4439
|
+
artifact
|
|
4440
|
+
};
|
|
4441
|
+
}
|
|
3000
4442
|
function planBuild(options, cwd) {
|
|
3001
4443
|
const userPackageJson = readUserPackageJson(cwd);
|
|
3002
4444
|
const config = readCrustConfig(userPackageJson);
|
|
3003
4445
|
const { runtime, source: runtimeSource } = resolveBuildRuntime(userPackageJson, config, cwd);
|
|
4446
|
+
const selection = resolveArtifact(options.artifact, config, runtime);
|
|
3004
4447
|
const entries = resolveBinEntries(cwd, userPackageJson);
|
|
3005
4448
|
validatePackageIdentity(userPackageJson, "package.json");
|
|
3006
4449
|
const envFiles = resolveEnvFilePaths(cwd, options.envFiles);
|
|
3007
4450
|
const bunPlugins = config.bunPlugins ?? [];
|
|
3008
|
-
if (
|
|
3009
|
-
if (
|
|
3010
|
-
|
|
3011
|
-
if (runtime === "deno" &&
|
|
3012
|
-
if (runtime === "deno" &&
|
|
4451
|
+
if (selection.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.");
|
|
4452
|
+
if (selection.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\".");
|
|
4453
|
+
const denoTool = selection.artifact === "binary" ? "deno compile" : "deno bundle";
|
|
4454
|
+
if (runtime === "deno" && options.minify) throw new Error(selection.artifact === "binary" ? "--minify is not supported with the deno runtime.\n deno compile has no minification step; drop the flag." : "--minify is not supported with the deno runtime.\n crust does not minify Deno runtime packages; drop the flag.");
|
|
4455
|
+
if (runtime === "deno" && envFiles.length > 0) throw new Error(selection.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).");
|
|
4456
|
+
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.`);
|
|
4457
|
+
if (runtime === "node" && selection.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.");
|
|
3013
4458
|
const stageDir = resolve(cwd, CRUST_DIR);
|
|
3014
4459
|
const common = {
|
|
3015
4460
|
cwd,
|
|
@@ -3024,39 +4469,102 @@ function planBuild(options, cwd) {
|
|
|
3024
4469
|
validate: options.validate ?? true,
|
|
3025
4470
|
minify: runtime === "deno" ? false : options.minify ?? true
|
|
3026
4471
|
};
|
|
3027
|
-
if (
|
|
4472
|
+
if (selection.artifact === "package") return {
|
|
3028
4473
|
...common,
|
|
3029
|
-
runtime
|
|
4474
|
+
runtime: selection.runtime,
|
|
4475
|
+
artifact: selection.artifact
|
|
3030
4476
|
};
|
|
3031
4477
|
const targetInputs = options.targets?.length ? options.targets : config.targets;
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
4478
|
+
const { runtime: binaryRuntime, artifact } = selection;
|
|
4479
|
+
if (binaryRuntime === "bun") return {
|
|
4480
|
+
...common,
|
|
4481
|
+
runtime: binaryRuntime,
|
|
4482
|
+
artifact,
|
|
4483
|
+
targets: resolveTargets(BUN_TARGETS, targetInputs)
|
|
4484
|
+
};
|
|
4485
|
+
if (binaryRuntime === "node") return {
|
|
4486
|
+
...common,
|
|
4487
|
+
runtime: binaryRuntime,
|
|
4488
|
+
artifact,
|
|
4489
|
+
targets: resolveTargets(NODE_TARGETS, targetInputs)
|
|
4490
|
+
};
|
|
3041
4491
|
return {
|
|
3042
4492
|
...common,
|
|
3043
|
-
runtime,
|
|
4493
|
+
runtime: binaryRuntime,
|
|
4494
|
+
artifact,
|
|
3044
4495
|
targets: resolveTargets(DENO_TARGETS, targetInputs)
|
|
3045
4496
|
};
|
|
3046
4497
|
}
|
|
3047
|
-
/**
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
4498
|
+
/**
|
|
4499
|
+
* Selects every compiler the build uses, once, before `.crust/` is wiped, so a
|
|
4500
|
+
* missing tool or an engines mismatch keeps the previous stage. Binaries use
|
|
4501
|
+
* the selected compiler's own version (`resolveBinaryCompiler`, or
|
|
4502
|
+
* `resolveNodeBinaryCompiler` with tsdown's requirements for node, whose
|
|
4503
|
+
* targets' embedded Node binaries are also provisioned here); runtime
|
|
4504
|
+
* packages are bundled by Bun (or, for Deno, by `deno bundle`) and embed no
|
|
4505
|
+
* runtime, so engines stay a consumer requirement there and are not checked
|
|
4506
|
+
* against the bundler.
|
|
4507
|
+
*/
|
|
4508
|
+
async function selectCompilers(plan, io) {
|
|
4509
|
+
if (plan.artifact === "package" && plan.runtime === "deno") {
|
|
4510
|
+
const bundler = await resolveDenoPackageBundler(plan.cwd);
|
|
4511
|
+
io.stdout(`${dim("Compiler:")} deno ${bundler.version} ${dim(`(${bundler.runner.command}, deno bundle)`)}`);
|
|
4512
|
+
io.stderr("Deno runtime packages are experimental: they are bundled with deno bundle, which Deno marks experimental.");
|
|
4513
|
+
return {
|
|
4514
|
+
snapshotRunner: plan.validate ? resolveBunBuildRunner() : void 0,
|
|
4515
|
+
stage: (reports) => runDistributeBuild(plan, { execute: (entry, outfile) => execDenoPackageBuild(entry, outfile, plan.cwd, bundler.runner) }, io, reports)
|
|
4516
|
+
};
|
|
4517
|
+
}
|
|
4518
|
+
if (plan.artifact === "package") {
|
|
4519
|
+
const runner = resolveBunBuildRunner();
|
|
4520
|
+
const bundle = plan.runtime === "bun" ? execBunPackageBuild : execNodeBuild;
|
|
4521
|
+
return {
|
|
4522
|
+
snapshotRunner: runner,
|
|
4523
|
+
stage: (reports) => runDistributeBuild(plan, { execute: (entry, outfile) => bundle(entry, outfile, plan.minify, plan.envFiles, plan.cwd, plan.bunPlugins, runner) }, io, reports)
|
|
4524
|
+
};
|
|
4525
|
+
}
|
|
4526
|
+
const printCompiler = (compiler) => io.stdout(`${dim("Compiler:")} ${compiler.runtime} ${compiler.version} ${dim(`(${compiler.runner.command})`)}`);
|
|
4527
|
+
if (plan.runtime === "node") {
|
|
4528
|
+
const compiler = await resolveNodeBinaryCompiler(plan.userPackageJson, plan.cwd);
|
|
4529
|
+
printCompiler(compiler);
|
|
4530
|
+
await provisionNodeExeTargets(plan.targets, plan.cwd, compiler);
|
|
4531
|
+
const bunRunner = resolveBunBuildRunner();
|
|
4532
|
+
const distribution = {
|
|
4533
|
+
table: NODE_TARGETS,
|
|
4534
|
+
targets: plan.targets,
|
|
4535
|
+
embeddedRuntimeVersion: compiler.version,
|
|
4536
|
+
execute: (entry, outfile, target) => execNodeBinaryBuild(entry, outfile, plan.minify, target, plan.envFiles, plan.cwd, compiler, bunRunner, io.stderr)
|
|
4537
|
+
};
|
|
4538
|
+
return {
|
|
4539
|
+
snapshotRunner: bunRunner,
|
|
4540
|
+
stage: (reports) => runDistributeBuild(plan, distribution, io, reports)
|
|
4541
|
+
};
|
|
4542
|
+
}
|
|
4543
|
+
const compiler = await resolveBinaryCompiler(plan.runtime, plan.userPackageJson, plan.cwd);
|
|
4544
|
+
printCompiler(compiler);
|
|
4545
|
+
if (plan.runtime === "bun") {
|
|
4546
|
+
assertTargetsBuildableWithoutBun(plan.targets, void 0, compiler.runner);
|
|
4547
|
+
const distribution = {
|
|
4548
|
+
table: BUN_TARGETS,
|
|
4549
|
+
targets: plan.targets,
|
|
4550
|
+
embeddedRuntimeVersion: compiler.version,
|
|
4551
|
+
execute: (entry, outfile, target) => execBuild(entry, outfile, plan.minify, target, plan.envFiles, plan.cwd, plan.bunPlugins, compiler.runner)
|
|
4552
|
+
};
|
|
4553
|
+
return {
|
|
4554
|
+
snapshotRunner: compiler.runner,
|
|
4555
|
+
stage: (reports) => runDistributeBuild(plan, distribution, io, reports)
|
|
4556
|
+
};
|
|
4557
|
+
}
|
|
4558
|
+
const distribution = {
|
|
3055
4559
|
table: DENO_TARGETS,
|
|
3056
4560
|
targets: plan.targets,
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
4561
|
+
embeddedRuntimeVersion: compiler.version,
|
|
4562
|
+
execute: (entry, outfile, target) => execDenoBuild(entry, outfile, target, plan.cwd, compiler.runner)
|
|
4563
|
+
};
|
|
4564
|
+
return {
|
|
4565
|
+
snapshotRunner: plan.validate ? resolveBunBuildRunner() : void 0,
|
|
4566
|
+
stage: (reports) => runDistributeBuild(plan, distribution, io, reports)
|
|
4567
|
+
};
|
|
3060
4568
|
}
|
|
3061
4569
|
/**
|
|
3062
4570
|
* Prepares every entry's Command Snapshot and checks that its root command is
|
|
@@ -3065,13 +4573,13 @@ async function runStagedBuild(plan, io, reports) {
|
|
|
3065
4573
|
* the merge fails on any path two entries both write. Returns each command's
|
|
3066
4574
|
* Build Report.
|
|
3067
4575
|
*/
|
|
3068
|
-
async function prepareEntries(plan, io) {
|
|
4576
|
+
async function prepareEntries(plan, io, runner) {
|
|
3069
4577
|
const owners = /* @__PURE__ */ new Map();
|
|
3070
4578
|
const reports = {};
|
|
3071
4579
|
for (const { command, entryPath } of plan.entries) {
|
|
3072
4580
|
const entryOutDir = await mkdtemp(join(tmpdir(), "crust-artifacts-"));
|
|
3073
4581
|
try {
|
|
3074
|
-
const { snapshot, build: report } = await buildEntrypoint(entryPath, entryOutDir, plan.envFiles, io, plan.cwd);
|
|
4582
|
+
const { snapshot, build: report } = await buildEntrypoint(entryPath, entryOutDir, plan.envFiles, io, plan.cwd, runner);
|
|
3075
4583
|
if (snapshot.meta.name !== command) throw new Error(`package.json bin ${JSON.stringify(command)} builds ${entryPath}, whose root command is named ${JSON.stringify(snapshot.meta.name)}.\n The installed command, help, man pages, and skills use the root command name, so new Crust(name) must match the bin key; rename one of them.`);
|
|
3076
4584
|
printBuildReport(command, report, io.stdout);
|
|
3077
4585
|
mergeEntryArtifacts(entryOutDir, plan.outDir, command, owners);
|
|
@@ -3087,19 +4595,23 @@ async function prepareEntries(plan, io) {
|
|
|
3087
4595
|
}
|
|
3088
4596
|
const activeBuilds = /* @__PURE__ */ new Set();
|
|
3089
4597
|
/**
|
|
3090
|
-
* Stages the publishable npm tree in `<cwd>/.crust
|
|
3091
|
-
* `bin/<command>.js` per package.json
|
|
3092
|
-
*
|
|
3093
|
-
*
|
|
3094
|
-
*
|
|
3095
|
-
* from
|
|
4598
|
+
* Stages the publishable npm tree in `<cwd>/.crust` for one runtime/artifact
|
|
4599
|
+
* combination: a root package with one `bin/<command>.js` per package.json
|
|
4600
|
+
* `bin` entry, each the command's bundle (artifact `package`) or a Node
|
|
4601
|
+
* launcher (artifact `binary`), plus for binaries one platform package per
|
|
4602
|
+
* target holding one executable per command. Command names and source entries
|
|
4603
|
+
* come from `bin`; the runtime, artifact, Bun plugins, and extra directories
|
|
4604
|
+
* from package.json `crust`. Bundling and Command Snapshots run in bun
|
|
3096
4605
|
* subprocesses (bun on PATH, or the running Bun executable), so this works
|
|
3097
|
-
* under Node as well when Bun is installed
|
|
4606
|
+
* under Node as well when Bun is installed; Deno binaries and Deno runtime
|
|
4607
|
+
* packages (experimental, deno 2.5.0 or newer) need deno on PATH, and Node
|
|
4608
|
+
* binaries a node on PATH that Crust's tsdown can build executables with.
|
|
3098
4609
|
*
|
|
3099
|
-
* Throws on any failure. Planning failures (bad
|
|
3100
|
-
*
|
|
3101
|
-
*
|
|
3102
|
-
*
|
|
4610
|
+
* Throws on any failure. Planning and compiler-selection failures (bad
|
|
4611
|
+
* options or package.json, a missing or hung compiler, an engines mismatch) leave the
|
|
4612
|
+
* previous `.crust/` stage untouched; later failures leave a wiped stage
|
|
4613
|
+
* without a completion `manifest.json`. Overlapping calls for the same real
|
|
4614
|
+
* project directory in this process are rejected before staging.
|
|
3103
4615
|
*/
|
|
3104
4616
|
async function build(options = {}) {
|
|
3105
4617
|
const cwd = resolve(options.cwd ?? process.cwd());
|
|
@@ -3114,12 +4626,14 @@ async function build(options = {}) {
|
|
|
3114
4626
|
};
|
|
3115
4627
|
const plan = planBuild(options, cwd);
|
|
3116
4628
|
io.stdout(`${dim("Runtime:")} ${plan.runtime} ${dim(`(${plan.runtimeSource})`)}`);
|
|
4629
|
+
io.stdout(`${dim("Artifact:")} ${plan.artifact}`);
|
|
4630
|
+
const compilers = await selectCompilers(plan, io);
|
|
3117
4631
|
rmSync(plan.stageDir, {
|
|
3118
4632
|
recursive: true,
|
|
3119
4633
|
force: true
|
|
3120
4634
|
});
|
|
3121
|
-
const reports = plan.validate ? await prepareEntries(plan, io) : void 0;
|
|
3122
|
-
const artifacts = await
|
|
4635
|
+
const reports = plan.validate ? await prepareEntries(plan, io, compilers.snapshotRunner) : void 0;
|
|
4636
|
+
const artifacts = await compilers.stage(reports);
|
|
3123
4637
|
return {
|
|
3124
4638
|
stageDir: plan.stageDir,
|
|
3125
4639
|
artifacts,
|
|
@@ -3129,35 +4643,5 @@ async function build(options = {}) {
|
|
|
3129
4643
|
activeBuilds.delete(project);
|
|
3130
4644
|
}
|
|
3131
4645
|
}
|
|
3132
|
-
defineCommand("build", { description: "Build your CLI for Bun, Deno, or Node" }, (command) => command.flags({
|
|
3133
|
-
name: "target",
|
|
3134
|
-
type: "string",
|
|
3135
|
-
multiple: true,
|
|
3136
|
-
description: `Canonical compiler target(s), or "${HOST_TARGET}" for this machine; repeatable. Omit to stage package.json crust.targets, or every Bun/Deno target`,
|
|
3137
|
-
short: "t"
|
|
3138
|
-
}, {
|
|
3139
|
-
name: "env-file",
|
|
3140
|
-
type: "string",
|
|
3141
|
-
multiple: true,
|
|
3142
|
-
description: "Explicit env file(s) used for build-time constants; repeatable"
|
|
3143
|
-
}, {
|
|
3144
|
-
name: "validate",
|
|
3145
|
-
type: "boolean",
|
|
3146
|
-
description: "Materialize command definitions before compiling; --no-validate also skips Extension build hooks",
|
|
3147
|
-
default: true
|
|
3148
|
-
}, {
|
|
3149
|
-
name: "minify",
|
|
3150
|
-
type: "boolean",
|
|
3151
|
-
description: "Minify the output (default for bun and node; unsupported for deno)"
|
|
3152
|
-
}).action(async ({ flags, stdout, stderr }) => {
|
|
3153
|
-
await build({
|
|
3154
|
-
cwd: process.cwd(),
|
|
3155
|
-
targets: flags.target,
|
|
3156
|
-
envFiles: flags["env-file"],
|
|
3157
|
-
minify: flags.minify,
|
|
3158
|
-
validate: flags.validate,
|
|
3159
|
-
onLog: (line, stream) => (stream === "stderr" ? stderr : stdout)(line)
|
|
3160
|
-
});
|
|
3161
|
-
}));
|
|
3162
4646
|
//#endregion
|
|
3163
4647
|
export { build };
|