@crustjs/crust 0.5.6 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/crust.js +63 -30
- package/dist/index.d.ts +19 -12
- package/dist/index.js +424 -1617
- package/package.json +12 -12
- package/schema/package.json +5 -6
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ crust build --artifact binary # stage standalone binaries in .crust/
|
|
|
16
16
|
crust publish # publish what crust build staged
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Every build selects its artifact with `--artifact` or `"crust": { "artifact": "package" | "binary" }` in package.json.
|
|
19
|
+
Every build selects its artifact with `--artifact` or `"crust": { "artifact": "package" | "binary" }` in package.json.
|
|
20
20
|
|
|
21
21
|
The same build is available to release scripts:
|
|
22
22
|
|
package/bin/crust.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Auto-generated by crust build -- do not edit
|
|
3
|
-
import { spawn } from "node:child_process";
|
|
4
|
-
import { chmodSync, existsSync } from "node:fs";
|
|
5
|
-
import { dirname, resolve } from "node:path";
|
|
6
|
-
import process from "node:process";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
|
|
9
3
|
const NAME = "crust";
|
|
4
|
+
if (typeof process.getBuiltinModule !== "function" ||
|
|
5
|
+
(process.platform !== "win32" && typeof process.execve !== "function")) {
|
|
6
|
+
console.error("[" + NAME + "] Requires Node.js >=24 (found " + process.version + ").");
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Builtins come from process.getBuiltinModule (cheaper than imports) and never from
|
|
11
|
+
// node:process: importing it touches stdio, which leaves the shared terminal and pipes
|
|
12
|
+
// non-blocking for the binary after execve.
|
|
13
|
+
const { chmodSync, closeSync, existsSync, openSync, readSync } = process.getBuiltinModule("node:fs");
|
|
14
|
+
const { resolve } = process.getBuiltinModule("node:path");
|
|
15
|
+
|
|
10
16
|
const PLATFORMS = {
|
|
11
17
|
"linux-x64": {
|
|
12
18
|
"packagePathSegment": "crust-linux-x64",
|
|
@@ -57,10 +63,20 @@ const PLATFORMS = {
|
|
|
57
63
|
"binaryFilename": "crust-bun-windows-arm64.exe"
|
|
58
64
|
}
|
|
59
65
|
};
|
|
60
|
-
const dir =
|
|
66
|
+
const dir = import.meta.dirname;
|
|
61
67
|
|
|
62
|
-
// Same check as Bun's own npm installer: glibc reports its version, musl does not.
|
|
63
68
|
function isMusl() {
|
|
69
|
+
// The first 2 KB of Node's ELF image hold its interpreter path (detect-libc reads the same
|
|
70
|
+
// span), which names its libc without the milliseconds a diagnostic report costs on every start.
|
|
71
|
+
try {
|
|
72
|
+
const fd = openSync("/proc/self/exe", "r");
|
|
73
|
+
const head = Buffer.alloc(2048);
|
|
74
|
+
const interpreter = head.toString("latin1", 0, readSync(fd, head, 0, head.length, 0));
|
|
75
|
+
closeSync(fd);
|
|
76
|
+
if (interpreter.includes("/ld-musl-")) return true;
|
|
77
|
+
if (interpreter.includes("/ld-linux-")) return false;
|
|
78
|
+
} catch {}
|
|
79
|
+
// Same check as Bun's own npm installer: glibc reports its version, musl does not.
|
|
64
80
|
try {
|
|
65
81
|
const report = process.report?.getReport();
|
|
66
82
|
if (report?.header) return report.header.glibcVersionRuntime === undefined;
|
|
@@ -98,32 +114,49 @@ if (!binPath) {
|
|
|
98
114
|
process.exit(1);
|
|
99
115
|
}
|
|
100
116
|
|
|
101
|
-
if (process.platform
|
|
117
|
+
if (process.platform === "win32") {
|
|
118
|
+
launchWindows(binPath);
|
|
119
|
+
} else {
|
|
102
120
|
try {
|
|
103
121
|
chmodSync(binPath, 0o755);
|
|
104
122
|
} catch {
|
|
105
|
-
// Ignore permission adjustment failures and let
|
|
123
|
+
// Ignore permission adjustment failures and let execve surface real errors.
|
|
106
124
|
}
|
|
125
|
+
// Become the binary: one process, so signals and exit status reach it with no relay.
|
|
126
|
+
// Node ignores SIGPIPE and SIGXFSZ, and ignored signals survive execve; handled ones reset.
|
|
127
|
+
// Ignores Node inherited (nohup's SIGHUP) were reset at its startup, so none pass on.
|
|
128
|
+
process.on("SIGPIPE", () => {});
|
|
129
|
+
process.on("SIGXFSZ", () => {});
|
|
130
|
+
// Early execve versions (e.g. Node 24.0.0) default to an empty environment.
|
|
131
|
+
process.execve(binPath, [binPath, ...process.argv.slice(2)], process.env);
|
|
107
132
|
}
|
|
108
133
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
child
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
134
|
+
// Windows has no execve. Its console delivers Ctrl-C to the binary directly, and
|
|
135
|
+
// child.kill("SIGINT") would hard-terminate it, so SIGINT is never forwarded.
|
|
136
|
+
function launchWindows(binPath) {
|
|
137
|
+
const { spawn } = process.getBuiltinModule("node:child_process");
|
|
138
|
+
const child = spawn(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
139
|
+
const forward = (signal) => child.kill(signal);
|
|
140
|
+
const ignore = () => {};
|
|
141
|
+
process.on("SIGINT", ignore);
|
|
142
|
+
process.on("SIGTERM", forward);
|
|
143
|
+
process.on("SIGHUP", forward);
|
|
144
|
+
child.on("error", (error) => {
|
|
145
|
+
console.error("[" + NAME + "] Failed to launch binary: " + error.message);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
});
|
|
148
|
+
child.on("exit", (code, signal) => {
|
|
149
|
+
process.off("SIGINT", ignore);
|
|
150
|
+
process.off("SIGTERM", forward);
|
|
151
|
+
process.off("SIGHUP", forward);
|
|
152
|
+
if (signal) {
|
|
153
|
+
try {
|
|
154
|
+
process.kill(process.pid, signal);
|
|
155
|
+
} catch {
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
124
159
|
}
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
process.exit(code ?? 0);
|
|
129
|
-
});
|
|
160
|
+
process.exit(code ?? 0);
|
|
161
|
+
});
|
|
162
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { BuildReport, BuildReport as BuildReport$1 } from "@crustjs/core";
|
|
2
|
-
|
|
2
|
+
declare const BUN_TARGET_NAMES: readonly ["bun-linux-x64", "bun-linux-arm64", "bun-linux-x64-musl", "bun-linux-arm64-musl", "bun-darwin-x64", "bun-darwin-arm64", "bun-windows-x64", "bun-windows-arm64"];
|
|
3
|
+
type BunTarget = (typeof BUN_TARGET_NAMES)[number];
|
|
4
|
+
declare const NODE_TARGET_NAMES: readonly ["linux-x64", "linux-arm64", "darwin-x64", "darwin-arm64", "win-x64", "win-arm64"];
|
|
5
|
+
type NodeTarget = (typeof NODE_TARGET_NAMES)[number];
|
|
6
|
+
/** `--target` value that stands for this machine's canonical target. */
|
|
7
|
+
declare const HOST_TARGET = "host";
|
|
3
8
|
/**
|
|
4
9
|
* What one build distributes: a runtime `package` (a root-only JavaScript
|
|
5
10
|
* bundle that needs the runtime installed) or standalone `binary` executables
|
|
@@ -31,8 +36,6 @@ type BuildArtifact = {
|
|
|
31
36
|
path: string;
|
|
32
37
|
command: string;
|
|
33
38
|
};
|
|
34
|
-
//#endregion
|
|
35
|
-
//#region src/build.d.ts
|
|
36
39
|
/** Options of the programmatic {@link build}; `crust build` maps its flags onto them. */
|
|
37
40
|
type BuildOptions = {
|
|
38
41
|
/** Project root whose package.json `bin` and `crust` are read. Default: `process.cwd()`. */
|
|
@@ -47,13 +50,20 @@ type BuildOptions = {
|
|
|
47
50
|
/**
|
|
48
51
|
* Canonical compiler targets, or `"host"` for this machine. Overrides
|
|
49
52
|
* package.json `crust.targets`; omit both to stage every target of the
|
|
50
|
-
* binary compiler. Rejected for runtime packages.
|
|
53
|
+
* binary compiler. Rejected for runtime packages. Known names are completion
|
|
54
|
+
* hints only; any string is checked at build time.
|
|
51
55
|
*/
|
|
52
|
-
targets?: readonly string[];
|
|
53
|
-
/** Env files inlining `PUBLIC_*` build-time constants, resolved against `cwd`.
|
|
56
|
+
targets?: readonly (BunTarget | NodeTarget | typeof HOST_TARGET | (string & {}))[];
|
|
57
|
+
/** Env files inlining `PUBLIC_*` build-time constants, resolved against `cwd`. */
|
|
54
58
|
envFiles?: readonly string[];
|
|
55
|
-
/** Minify the output. Default: true
|
|
59
|
+
/** Minify the output. Default: true. */
|
|
56
60
|
minify?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Precompile Bun standalone executables to bytecode for faster startup. Default:
|
|
63
|
+
* true for bun binaries; an explicit `true` is rejected for other runtimes and for
|
|
64
|
+
* runtime packages, whose consumer runtime may not read Bun bytecode.
|
|
65
|
+
*/
|
|
66
|
+
bytecode?: boolean;
|
|
57
67
|
/** Materialize Command Snapshots and run Extension build hooks before compiling. Default: true. */
|
|
58
68
|
validate?: boolean;
|
|
59
69
|
/** Receives each progress line `crust build` would print; silent when omitted. Warnings arrive as `"stderr"`. */
|
|
@@ -76,10 +86,8 @@ type BuildResult = {
|
|
|
76
86
|
* come from `bin`; the runtime, artifact, Bun plugins, extra directories, and
|
|
77
87
|
* external dependencies from package.json `crust`. Bundling and Command
|
|
78
88
|
* Snapshots run in bun subprocesses (bun on PATH, or the running Bun
|
|
79
|
-
* executable), so this works under Node as well when Bun is installed;
|
|
80
|
-
* binaries
|
|
81
|
-
* deno on PATH, and Node binaries a node on PATH that Crust's tsdown can build
|
|
82
|
-
* executables with.
|
|
89
|
+
* executable), so this works under Node as well when Bun is installed; Node
|
|
90
|
+
* binaries need a node on PATH that Crust's tsdown can build executables with.
|
|
83
91
|
*
|
|
84
92
|
* Throws on any failure. Planning and compiler-selection failures (bad
|
|
85
93
|
* options or package.json, a missing or hung compiler, an engines mismatch) leave the
|
|
@@ -89,5 +97,4 @@ type BuildResult = {
|
|
|
89
97
|
* process may leave `.crust.lock`; remove it only when no build is running.
|
|
90
98
|
*/
|
|
91
99
|
export declare function build(options?: BuildOptions): Promise<BuildResult>;
|
|
92
|
-
//#endregion
|
|
93
100
|
export type { BuildArtifact, BuildOptions, BuildReport, BuildResult };
|