@zenbujs/core 0.0.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/LICENSE +11 -0
- package/dist/advice-config-CjgkEf2E.mjs +135 -0
- package/dist/advice-config-Cy133IQP.mjs +2 -0
- package/dist/advice-runtime.d.mts +35 -0
- package/dist/advice-runtime.mjs +131 -0
- package/dist/advice.d.mts +36 -0
- package/dist/advice.mjs +2 -0
- package/dist/base-window-BUt8pwbw.mjs +94 -0
- package/dist/base-window-DEIAk618.mjs +2 -0
- package/dist/build-config-pbv0w4oN.mjs +17 -0
- package/dist/build-electron-B4Gd0Gi4.mjs +516 -0
- package/dist/build-source-_q1n1zTV.mjs +162 -0
- package/dist/chunk-Dm34NbLt.mjs +6 -0
- package/dist/cli/bin.d.mts +1 -0
- package/dist/cli/bin.mjs +88 -0
- package/dist/cli/build.d.mts +53 -0
- package/dist/cli/build.mjs +48 -0
- package/dist/cli-BLbQQIVB.mjs +8054 -0
- package/dist/config-CdVrW85P.mjs +59 -0
- package/dist/config-LK73dJmO.mjs +2 -0
- package/dist/db-ByKPbnP6.mjs +2 -0
- package/dist/db-DhuAJrye.mjs +531 -0
- package/dist/db.d.mts +16 -0
- package/dist/db.mjs +16 -0
- package/dist/dev-BuqklM0k.mjs +85 -0
- package/dist/env-bootstrap-BtVME-CU.d.mts +16 -0
- package/dist/env-bootstrap-rj7I-59x.mjs +53 -0
- package/dist/env-bootstrap.d.mts +2 -0
- package/dist/env-bootstrap.mjs +2 -0
- package/dist/http-IBcLzbYu.mjs +2 -0
- package/dist/index-Bhlbyrn7.d.mts +63 -0
- package/dist/index-CPZ5d6Hl.d.mts +442 -0
- package/dist/index-FtE8MXJ_.d.mts +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +5 -0
- package/dist/launcher.mjs +173 -0
- package/dist/link-6roQ7Cn6.mjs +580 -0
- package/dist/loaders/zenbu.d.mts +22 -0
- package/dist/loaders/zenbu.mjs +267 -0
- package/dist/log-CyKv8hQg.mjs +20 -0
- package/dist/mirror-sync-CodOnwkD.mjs +332 -0
- package/dist/monorepo-CmGPHsVm.mjs +119 -0
- package/dist/node-D4M19_mV.mjs +5 -0
- package/dist/node-loader.d.mts +17 -0
- package/dist/node-loader.mjs +33 -0
- package/dist/pause-DvAUNmKn.mjs +52 -0
- package/dist/publish-source-BVgB62Zj.mjs +131 -0
- package/dist/react.d.mts +76 -0
- package/dist/react.mjs +291 -0
- package/dist/registry-Dh_e7HU1.d.mts +61 -0
- package/dist/registry.d.mts +2 -0
- package/dist/registry.mjs +1 -0
- package/dist/reloader-BCkLjDhS.mjs +2 -0
- package/dist/reloader-lLAJ3lqg.mjs +164 -0
- package/dist/renderer-host-Bg8QdeeH.mjs +1508 -0
- package/dist/renderer-host-DpvBPTHJ.mjs +2 -0
- package/dist/rpc-BwwQK6hD.mjs +71 -0
- package/dist/rpc-CqitnyR4.mjs +2 -0
- package/dist/rpc.d.mts +2 -0
- package/dist/rpc.mjs +2 -0
- package/dist/runtime-CjqDr8Yf.d.mts +109 -0
- package/dist/runtime-DUFKDIe4.mjs +409 -0
- package/dist/runtime.d.mts +2 -0
- package/dist/runtime.mjs +2 -0
- package/dist/schema-CIg4GzHQ.mjs +100 -0
- package/dist/schema-DMoSkwUx.d.mts +62 -0
- package/dist/schema-dGK6qkfR.mjs +28 -0
- package/dist/schema.d.mts +2 -0
- package/dist/schema.mjs +2 -0
- package/dist/server-BXwZEQ-n.mjs +66 -0
- package/dist/server-DjrZUbbu.mjs +2 -0
- package/dist/services/default.d.mts +11 -0
- package/dist/services/default.mjs +22 -0
- package/dist/services/index.d.mts +276 -0
- package/dist/services/index.mjs +7 -0
- package/dist/setup-gate-BeD6WS6d.mjs +110 -0
- package/dist/setup-gate-BqOzm7zp.d.mts +4 -0
- package/dist/setup-gate.d.mts +2 -0
- package/dist/setup-gate.mjs +2 -0
- package/dist/src-pELM4_iH.mjs +376 -0
- package/dist/trace-DCB7qFzT.mjs +10 -0
- package/dist/transform-DJH3vN4b.mjs +84041 -0
- package/dist/transport-BMSzG2-F.mjs +1045 -0
- package/dist/view-registry-BualWgAf.mjs +2 -0
- package/dist/vite-plugins-Bh3SCOw-.mjs +331 -0
- package/dist/vite.d.mts +68 -0
- package/dist/vite.mjs +2 -0
- package/dist/window-CM2a9Kyc.mjs +2 -0
- package/dist/window-CmmpCVX6.mjs +156 -0
- package/dist/write-9dRFczGJ.mjs +1248 -0
- package/migrations/0000_migration.ts +34 -0
- package/migrations/meta/0000_snapshot.json +18 -0
- package/migrations/meta/_journal.json +10 -0
- package/package.json +124 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
import { a as findBuildConfig, o as loadBuildConfig, r as initSeedRepo } from "./mirror-sync-CodOnwkD.mjs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import crypto from "node:crypto";
|
|
8
|
+
import fsp from "node:fs/promises";
|
|
9
|
+
import { execFile, execFileSync, spawn } from "node:child_process";
|
|
10
|
+
import { promisify } from "node:util";
|
|
11
|
+
import https from "node:https";
|
|
12
|
+
//#region src/cli/lib/toolchain.ts
|
|
13
|
+
const execFileAsync = promisify(execFile);
|
|
14
|
+
/**
|
|
15
|
+
* Hardcoded bun + pnpm versions that the .app bundles for its first-launch
|
|
16
|
+
* `pnpm install`. We download these from upstream releases on demand (cached
|
|
17
|
+
* globally per-version), verify against pinned sha256, and stage them into
|
|
18
|
+
* the build's `extraResources/toolchain/` directory.
|
|
19
|
+
*
|
|
20
|
+
* Bumping a version: update the entry, paste the upstream release tarball's
|
|
21
|
+
* sha256, and the next `zen build:electron` will re-fetch into a new cache
|
|
22
|
+
* directory automatically.
|
|
23
|
+
*
|
|
24
|
+
* Currently darwin-only — Linux/Windows support is a future-PR concern.
|
|
25
|
+
*/
|
|
26
|
+
const TOOLCHAIN = {
|
|
27
|
+
bun: {
|
|
28
|
+
version: "1.3.12",
|
|
29
|
+
releaseTag: "bun-v1.3.12",
|
|
30
|
+
targets: {
|
|
31
|
+
"darwin-aarch64": {
|
|
32
|
+
asset: "bun-darwin-aarch64.zip",
|
|
33
|
+
sha256: "6c4bb87dd013ed1a8d6a16e357a3d094959fd5530b4d7061f7f3680c3c7cea1c"
|
|
34
|
+
},
|
|
35
|
+
"darwin-x64": {
|
|
36
|
+
asset: "bun-darwin-x64.zip",
|
|
37
|
+
sha256: "0f58c53a3e7947f1e626d2f8d285f97c14b7cadcca9c09ebafc0ae9d35b58c3d"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
pnpm: {
|
|
42
|
+
version: "10.33.0",
|
|
43
|
+
releaseTag: "v10.33.0",
|
|
44
|
+
targets: {
|
|
45
|
+
"darwin-arm64": {
|
|
46
|
+
asset: "pnpm-macos-arm64",
|
|
47
|
+
sha256: "ed8a1f140f4de457b01ebe0be3ae28e9a7e28863315dcd53d22ff1e5a32d63ae"
|
|
48
|
+
},
|
|
49
|
+
"darwin-x64": {
|
|
50
|
+
asset: "pnpm-macos-x64",
|
|
51
|
+
sha256: "c31e29554b0e3f4e03f4617195c949595e4dca36085922003de4896c3ca4057d"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
TOOLCHAIN.pnpm.version;
|
|
57
|
+
TOOLCHAIN.bun.version;
|
|
58
|
+
function cacheRoot() {
|
|
59
|
+
return path.join(os.homedir(), ".zenbu", "cache", "toolchain");
|
|
60
|
+
}
|
|
61
|
+
function bunTarget() {
|
|
62
|
+
if (process.arch === "arm64") return "darwin-aarch64";
|
|
63
|
+
if (process.arch === "x64") return "darwin-x64";
|
|
64
|
+
throw new Error(`zenbu toolchain: unsupported architecture ${process.arch}`);
|
|
65
|
+
}
|
|
66
|
+
function pnpmTarget() {
|
|
67
|
+
if (process.arch === "arm64") return "darwin-arm64";
|
|
68
|
+
if (process.arch === "x64") return "darwin-x64";
|
|
69
|
+
throw new Error(`zenbu toolchain: unsupported architecture ${process.arch}`);
|
|
70
|
+
}
|
|
71
|
+
function download(url, dest) {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
https.get(url, (res) => {
|
|
74
|
+
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
75
|
+
res.resume();
|
|
76
|
+
download(new URL(res.headers.location, url).href, dest).then(resolve, reject);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (res.statusCode !== 200) {
|
|
80
|
+
reject(/* @__PURE__ */ new Error(`GET ${url} -> ${res.statusCode}`));
|
|
81
|
+
res.resume();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const out = fs.createWriteStream(dest);
|
|
85
|
+
res.pipe(out);
|
|
86
|
+
out.on("finish", () => out.close(() => resolve()));
|
|
87
|
+
out.on("error", reject);
|
|
88
|
+
}).on("error", reject);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
async function sha256(filePath) {
|
|
92
|
+
const hash = crypto.createHash("sha256");
|
|
93
|
+
await new Promise((resolve, reject) => {
|
|
94
|
+
const stream = fs.createReadStream(filePath);
|
|
95
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
96
|
+
stream.on("end", () => resolve());
|
|
97
|
+
stream.on("error", reject);
|
|
98
|
+
});
|
|
99
|
+
return hash.digest("hex");
|
|
100
|
+
}
|
|
101
|
+
async function verify(filePath, expected) {
|
|
102
|
+
const actual = await sha256(filePath);
|
|
103
|
+
if (actual !== expected) throw new Error(`zenbu toolchain: sha256 mismatch for ${path.basename(filePath)} (expected ${expected}, got ${actual})`);
|
|
104
|
+
}
|
|
105
|
+
async function findExecutable(dir, name) {
|
|
106
|
+
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
107
|
+
for (const entry of entries) {
|
|
108
|
+
const full = path.join(dir, entry.name);
|
|
109
|
+
if (entry.isDirectory()) {
|
|
110
|
+
const nested = await findExecutable(full, name);
|
|
111
|
+
if (nested) return nested;
|
|
112
|
+
} else if (entry.isFile() && entry.name === name) return full;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
async function ensureBunCached() {
|
|
117
|
+
const target = bunTarget();
|
|
118
|
+
const info = TOOLCHAIN.bun.targets[target];
|
|
119
|
+
const dir = path.join(cacheRoot(), `bun-${TOOLCHAIN.bun.version}-${target}`);
|
|
120
|
+
const cached = path.join(dir, "bun");
|
|
121
|
+
if (fs.existsSync(cached)) return cached;
|
|
122
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
123
|
+
const tmp = await fsp.mkdtemp(path.join(os.tmpdir(), "zenbu-bun-"));
|
|
124
|
+
try {
|
|
125
|
+
const zipPath = path.join(tmp, info.asset);
|
|
126
|
+
const url = `https://github.com/oven-sh/bun/releases/download/${TOOLCHAIN.bun.releaseTag}/${info.asset}`;
|
|
127
|
+
console.log(` → downloading bun ${TOOLCHAIN.bun.version} (${target})`);
|
|
128
|
+
await download(url, zipPath);
|
|
129
|
+
await verify(zipPath, info.sha256);
|
|
130
|
+
await execFileAsync("unzip", [
|
|
131
|
+
"-q",
|
|
132
|
+
zipPath,
|
|
133
|
+
"-d",
|
|
134
|
+
tmp
|
|
135
|
+
]);
|
|
136
|
+
const extracted = await findExecutable(tmp, "bun");
|
|
137
|
+
if (!extracted) throw new Error(`zenbu toolchain: could not find bun in ${info.asset}`);
|
|
138
|
+
await fsp.copyFile(extracted, cached);
|
|
139
|
+
await fsp.chmod(cached, 493);
|
|
140
|
+
} finally {
|
|
141
|
+
await fsp.rm(tmp, {
|
|
142
|
+
recursive: true,
|
|
143
|
+
force: true
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return cached;
|
|
147
|
+
}
|
|
148
|
+
async function ensurePnpmCached() {
|
|
149
|
+
const target = pnpmTarget();
|
|
150
|
+
const info = TOOLCHAIN.pnpm.targets[target];
|
|
151
|
+
const dir = path.join(cacheRoot(), `pnpm-${TOOLCHAIN.pnpm.version}-${target}`);
|
|
152
|
+
const cached = path.join(dir, "pnpm");
|
|
153
|
+
if (fs.existsSync(cached)) return cached;
|
|
154
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
155
|
+
const tmp = path.join(dir, ".download");
|
|
156
|
+
const url = `https://github.com/pnpm/pnpm/releases/download/${TOOLCHAIN.pnpm.releaseTag}/${info.asset}`;
|
|
157
|
+
console.log(` → downloading pnpm ${TOOLCHAIN.pnpm.version} (${target})`);
|
|
158
|
+
await download(url, tmp);
|
|
159
|
+
await verify(tmp, info.sha256);
|
|
160
|
+
await fsp.chmod(tmp, 493);
|
|
161
|
+
await fsp.rename(tmp, cached);
|
|
162
|
+
return cached;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Stage hardcoded bun + pnpm into `<stagingDir>/{bun, pnpm}` so the build
|
|
166
|
+
* can wire them into electron-builder as extraResources. Returns absolute
|
|
167
|
+
* paths to the staged binaries.
|
|
168
|
+
*
|
|
169
|
+
* The sibling `node` symlink (-> `bun`) is created so that any npm
|
|
170
|
+
* lifecycle script that does `#!/usr/bin/env node` can resolve to bun
|
|
171
|
+
* inside the launched .app.
|
|
172
|
+
*/
|
|
173
|
+
async function provisionToolchain(stagingDir) {
|
|
174
|
+
if (process.platform !== "darwin") throw new Error(`zenbu toolchain: only darwin is supported today (got ${process.platform})`);
|
|
175
|
+
await fsp.mkdir(stagingDir, { recursive: true });
|
|
176
|
+
const cachedBun = await ensureBunCached();
|
|
177
|
+
const cachedPnpm = await ensurePnpmCached();
|
|
178
|
+
const bunOut = path.join(stagingDir, "bun");
|
|
179
|
+
const pnpmOut = path.join(stagingDir, "pnpm");
|
|
180
|
+
const nodeOut = path.join(stagingDir, "node");
|
|
181
|
+
await fsp.copyFile(cachedBun, bunOut);
|
|
182
|
+
await fsp.chmod(bunOut, 493);
|
|
183
|
+
await fsp.copyFile(cachedPnpm, pnpmOut);
|
|
184
|
+
await fsp.chmod(pnpmOut, 493);
|
|
185
|
+
try {
|
|
186
|
+
await fsp.unlink(nodeOut);
|
|
187
|
+
} catch {}
|
|
188
|
+
await fsp.symlink("bun", nodeOut);
|
|
189
|
+
return {
|
|
190
|
+
bun: bunOut,
|
|
191
|
+
pnpm: pnpmOut,
|
|
192
|
+
node: nodeOut
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/cli/commands/build-electron.ts
|
|
197
|
+
const ELECTRON_BUILDER_CONFIG_NAMES = [
|
|
198
|
+
"electron-builder.json",
|
|
199
|
+
"electron-builder.json5",
|
|
200
|
+
"electron-builder.yml",
|
|
201
|
+
"electron-builder.yaml",
|
|
202
|
+
"electron-builder.config.js",
|
|
203
|
+
"electron-builder.config.cjs",
|
|
204
|
+
"electron-builder.config.mjs"
|
|
205
|
+
];
|
|
206
|
+
function resolveProjectDir() {
|
|
207
|
+
const cwd = process.cwd();
|
|
208
|
+
if (fs.existsSync(path.join(cwd, "zenbu.plugin.json"))) return cwd;
|
|
209
|
+
console.error("zen build:electron: no zenbu.plugin.json found in current directory");
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Args use `--` to delimit zen flags from electron-builder pass-through
|
|
214
|
+
* flags. e.g. `pnpm build:electron -- --publish always` forwards
|
|
215
|
+
* `--publish always` to electron-builder. Without `--` everything is treated
|
|
216
|
+
* as a zen flag (and unknown flags error out).
|
|
217
|
+
*/
|
|
218
|
+
function parseFlags(argv) {
|
|
219
|
+
const flags = {
|
|
220
|
+
noSource: false,
|
|
221
|
+
passthrough: []
|
|
222
|
+
};
|
|
223
|
+
let sawSeparator = false;
|
|
224
|
+
for (let i = 0; i < argv.length; i++) {
|
|
225
|
+
const arg = argv[i];
|
|
226
|
+
if (sawSeparator) {
|
|
227
|
+
flags.passthrough.push(arg);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (arg === "--") {
|
|
231
|
+
sawSeparator = true;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (arg === "--config" || arg === "-c") flags.config = argv[++i];
|
|
235
|
+
else if (arg.startsWith("--config=")) flags.config = arg.slice(9);
|
|
236
|
+
else if (arg === "--no-source") flags.noSource = true;
|
|
237
|
+
else {
|
|
238
|
+
console.error(`zen build:electron: unknown flag "${arg}"`);
|
|
239
|
+
console.error(`valid: zen build:electron [--config <zenbu.build.ts>] [--no-source] [-- <electron-builder args>]`);
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return flags;
|
|
244
|
+
}
|
|
245
|
+
function readJson(filePath) {
|
|
246
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
247
|
+
}
|
|
248
|
+
function expandMirrorUrl(target) {
|
|
249
|
+
if (target.startsWith("http://") || target.startsWith("https://") || target.startsWith("git@")) return target;
|
|
250
|
+
if (/^[\w.-]+\/[\w.-]+$/.test(target)) return `https://github.com/${target}.git`;
|
|
251
|
+
return target;
|
|
252
|
+
}
|
|
253
|
+
function resolveCoreVersion() {
|
|
254
|
+
try {
|
|
255
|
+
const pkg = readJson(createRequire(import.meta.url).resolve("@zenbujs/core/package.json"));
|
|
256
|
+
if (pkg.version) return pkg.version;
|
|
257
|
+
} catch {}
|
|
258
|
+
try {
|
|
259
|
+
const here = fileURLToPath(import.meta.url);
|
|
260
|
+
let dir = path.dirname(here);
|
|
261
|
+
while (dir !== path.dirname(dir)) {
|
|
262
|
+
const candidate = path.join(dir, "package.json");
|
|
263
|
+
if (fs.existsSync(candidate)) {
|
|
264
|
+
const pkg = readJson(candidate);
|
|
265
|
+
if (pkg.name === "@zenbujs/core" && pkg.version) return pkg.version;
|
|
266
|
+
if (pkg.version) return pkg.version;
|
|
267
|
+
}
|
|
268
|
+
dir = path.dirname(dir);
|
|
269
|
+
}
|
|
270
|
+
} catch {}
|
|
271
|
+
return "0.0.0";
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Find the bundled `launcher.mjs` shipped inside `@zenbujs/core/dist/`. We
|
|
275
|
+
* resolve it through Node's resolution from the user's project so that the
|
|
276
|
+
* launcher matches the version of `@zenbujs/core` actually installed in the
|
|
277
|
+
* app's `node_modules` (which is what runs in the bundled .app).
|
|
278
|
+
*/
|
|
279
|
+
function resolveLauncher(projectDir) {
|
|
280
|
+
const localRequire = createRequire(path.join(projectDir, "package.json"));
|
|
281
|
+
try {
|
|
282
|
+
const pkgPath = localRequire.resolve("@zenbujs/core/package.json");
|
|
283
|
+
const launcher = path.join(path.dirname(pkgPath), "dist", "launcher.mjs");
|
|
284
|
+
if (fs.existsSync(launcher)) return launcher;
|
|
285
|
+
} catch {}
|
|
286
|
+
const here = fileURLToPath(import.meta.url);
|
|
287
|
+
const candidate = path.resolve(path.dirname(here), "..", "launcher.mjs");
|
|
288
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
289
|
+
throw new Error("zen build:electron: cannot locate `@zenbujs/core/dist/launcher.mjs`. Make sure @zenbujs/core is installed in this project.");
|
|
290
|
+
}
|
|
291
|
+
function resolveElectronBuilder(projectDir) {
|
|
292
|
+
const candidates = [path.join(projectDir, "node_modules", ".bin", "electron-builder"), path.join(projectDir, "node_modules", "electron-builder", "out", "cli", "cli.js")];
|
|
293
|
+
for (const candidate of candidates) if (fs.existsSync(candidate)) return candidate;
|
|
294
|
+
throw new Error("zen build:electron: electron-builder not found in node_modules. Add it to devDependencies and run `pnpm install`.");
|
|
295
|
+
}
|
|
296
|
+
function findElectronBuilderConfig(projectDir) {
|
|
297
|
+
for (const name of ELECTRON_BUILDER_CONFIG_NAMES) {
|
|
298
|
+
const candidate = path.join(projectDir, name);
|
|
299
|
+
if (fs.existsSync(candidate)) return {
|
|
300
|
+
path: candidate,
|
|
301
|
+
format: name.endsWith(".json") ? "json" : "other"
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
305
|
+
if (fs.existsSync(pkgPath)) try {
|
|
306
|
+
if (readJson(pkgPath).build) return {
|
|
307
|
+
path: pkgPath,
|
|
308
|
+
format: "json"
|
|
309
|
+
};
|
|
310
|
+
} catch {}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
function readElectronBuilderConfig(projectDir) {
|
|
314
|
+
const found = findElectronBuilderConfig(projectDir);
|
|
315
|
+
if (!found) throw new Error([
|
|
316
|
+
"zen build:electron: no electron-builder config found.",
|
|
317
|
+
"",
|
|
318
|
+
"Create `electron-builder.json` in the project root, e.g.:",
|
|
319
|
+
"",
|
|
320
|
+
" {",
|
|
321
|
+
" \"appId\": \"dev.you.your-app\",",
|
|
322
|
+
" \"productName\": \"Your App\",",
|
|
323
|
+
" \"asar\": false,",
|
|
324
|
+
" \"directories\": { \"output\": \"dist\" },",
|
|
325
|
+
" \"mac\": { \"category\": \"public.app-category.developer-tools\", \"target\": [\"zip\"] }",
|
|
326
|
+
" }",
|
|
327
|
+
""
|
|
328
|
+
].join("\n"));
|
|
329
|
+
if (found.format !== "json") throw new Error(`zen build:electron: only JSON electron-builder configs are supported right now (got ${path.basename(found.path)}). Convert to electron-builder.json or move the config under package.json#build.`);
|
|
330
|
+
if (path.basename(found.path) === "package.json") return { ...readJson(found.path).build ?? {} };
|
|
331
|
+
return readJson(found.path);
|
|
332
|
+
}
|
|
333
|
+
async function ensureSource(projectDir, config, noSource) {
|
|
334
|
+
const stagingDir = path.resolve(projectDir, config.out);
|
|
335
|
+
const shaPath = path.join(stagingDir, ".sha");
|
|
336
|
+
const currentSha = (() => {
|
|
337
|
+
try {
|
|
338
|
+
return execFileSync("git", ["rev-parse", "HEAD"], {
|
|
339
|
+
cwd: projectDir,
|
|
340
|
+
encoding: "utf8"
|
|
341
|
+
}).trim();
|
|
342
|
+
} catch {
|
|
343
|
+
return "uncommitted";
|
|
344
|
+
}
|
|
345
|
+
})();
|
|
346
|
+
if (fs.existsSync(shaPath)) {
|
|
347
|
+
const meta = readJson(shaPath);
|
|
348
|
+
if (meta.sourceSha === currentSha) return meta;
|
|
349
|
+
if (noSource) {
|
|
350
|
+
console.warn(`[build:electron] --no-source: using stale staging (built from ${meta.sourceSha.slice(0, 7)}, current HEAD ${currentSha.slice(0, 7)})`);
|
|
351
|
+
return meta;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (noSource) {
|
|
355
|
+
console.error("zen build:electron: --no-source given but no staging found. Run `zen build:source` first.");
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
console.log(` → running zen build:source (seed is missing or stale)`);
|
|
359
|
+
const { runBuildSource } = await import("./build-source-_q1n1zTV.mjs");
|
|
360
|
+
await runBuildSource([]);
|
|
361
|
+
return readJson(shaPath);
|
|
362
|
+
}
|
|
363
|
+
async function spawnAsync(cmd, args, cwd, env = process.env) {
|
|
364
|
+
await new Promise((resolve, reject) => {
|
|
365
|
+
const child = spawn(cmd, args, {
|
|
366
|
+
cwd,
|
|
367
|
+
stdio: "inherit",
|
|
368
|
+
env
|
|
369
|
+
});
|
|
370
|
+
child.on("error", reject);
|
|
371
|
+
child.on("close", (code) => {
|
|
372
|
+
if (code === 0) resolve();
|
|
373
|
+
else reject(/* @__PURE__ */ new Error(`${cmd} exited with code ${code}`));
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Compose the user's electron-builder config with the zenbu overlays. The
|
|
379
|
+
* overlays are minimal and targeted:
|
|
380
|
+
*
|
|
381
|
+
* - `directories.app` owned by zen — points at our staged app dir
|
|
382
|
+
* - `files` owned by zen — the staged app dir is fully
|
|
383
|
+
* under our control, so user-side `files`
|
|
384
|
+
* entries would not resolve anyway
|
|
385
|
+
* - `extraResources` additive — we APPEND the toolchain entry to
|
|
386
|
+
* whatever the user already declared
|
|
387
|
+
* - `npmRebuild` forced to false — the seed ships its own
|
|
388
|
+
* lockfile and `pnpm install` runs at first
|
|
389
|
+
* launch, no rebuild step needed at build time
|
|
390
|
+
*
|
|
391
|
+
* Everything else (`appId`, `productName`, `mac`, `win`, `linux`,
|
|
392
|
+
* `publish`, `directories.output`, `directories.buildResources`, `asar`,
|
|
393
|
+
* signing/notarize, target list) is preserved as-is from the user's config.
|
|
394
|
+
*/
|
|
395
|
+
function mergeElectronBuilderConfig(userConfig, overlay) {
|
|
396
|
+
const merged = { ...userConfig };
|
|
397
|
+
merged.directories = {
|
|
398
|
+
...userConfig.directories ?? {},
|
|
399
|
+
app: overlay.appDir,
|
|
400
|
+
output: overlay.output
|
|
401
|
+
};
|
|
402
|
+
merged.files = overlay.seedFiles;
|
|
403
|
+
merged.extraResources = [...Array.isArray(userConfig.extraResources) ? userConfig.extraResources : [], overlay.extraResource];
|
|
404
|
+
if (userConfig.npmRebuild !== false) merged.npmRebuild = false;
|
|
405
|
+
if (userConfig.asar === void 0) merged.asar = false;
|
|
406
|
+
return merged;
|
|
407
|
+
}
|
|
408
|
+
async function copyFile(src, dest) {
|
|
409
|
+
await fsp.mkdir(path.dirname(dest), { recursive: true });
|
|
410
|
+
await fsp.copyFile(src, dest);
|
|
411
|
+
}
|
|
412
|
+
async function runBuildElectron(argv) {
|
|
413
|
+
const projectDir = resolveProjectDir();
|
|
414
|
+
const flags = parseFlags(argv);
|
|
415
|
+
const config = await loadBuildConfig(flags.config ? path.resolve(projectDir, flags.config) : findBuildConfig(projectDir));
|
|
416
|
+
const meta = await ensureSource(projectDir, config, flags.noSource);
|
|
417
|
+
const seedDir = path.resolve(projectDir, config.out);
|
|
418
|
+
const projectPkg = readJson(path.join(projectDir, "package.json"));
|
|
419
|
+
const appName = projectPkg.name ?? path.basename(projectDir);
|
|
420
|
+
const appVersion = projectPkg.version ?? "0.0.1";
|
|
421
|
+
const bundleDir = await fsp.mkdtemp(path.join(os.tmpdir(), `zenbu-electron-${appName}-`));
|
|
422
|
+
const stagedSeed = path.join(bundleDir, "seed");
|
|
423
|
+
const toolchainDir = path.join(bundleDir, "toolchain");
|
|
424
|
+
const launcherOut = path.join(bundleDir, "launcher.mjs");
|
|
425
|
+
const bundlePkgOut = path.join(bundleDir, "package.json");
|
|
426
|
+
const appConfigOut = path.join(bundleDir, "app-config.json");
|
|
427
|
+
const mergedConfigPath = path.join(bundleDir, "electron-builder.merged.json");
|
|
428
|
+
const mirrorTarget = config.mirror?.target ?? null;
|
|
429
|
+
const mirrorBranch = config.mirror?.branch ?? "main";
|
|
430
|
+
const mirrorUrl = mirrorTarget ? expandMirrorUrl(mirrorTarget) : null;
|
|
431
|
+
console.log(`\n zen build:electron`);
|
|
432
|
+
console.log(` name: ${appName}`);
|
|
433
|
+
console.log(` version: ${appVersion}`);
|
|
434
|
+
console.log(` source: ${meta.sourceSha === "uncommitted" ? "uncommitted" : meta.sourceSha.slice(0, 7)}`);
|
|
435
|
+
console.log(` mirror: ${mirrorTarget ?? "(none — set config.mirror.target to enable updates)"}`);
|
|
436
|
+
console.log(` bundle: ${bundleDir}`);
|
|
437
|
+
console.log(" → staging launcher.mjs");
|
|
438
|
+
await copyFile(resolveLauncher(projectDir), launcherOut);
|
|
439
|
+
console.log(" → staging seed/");
|
|
440
|
+
await fsp.cp(seedDir, stagedSeed, {
|
|
441
|
+
recursive: true,
|
|
442
|
+
filter: (src) => path.basename(src) !== ".sha"
|
|
443
|
+
});
|
|
444
|
+
if (mirrorUrl) await initSeedRepo({
|
|
445
|
+
dir: stagedSeed,
|
|
446
|
+
mirrorUrl,
|
|
447
|
+
branch: mirrorBranch,
|
|
448
|
+
sourceSha: meta.sourceSha === "uncommitted" ? "0000000000000000000000000000000000000000" : meta.sourceSha
|
|
449
|
+
});
|
|
450
|
+
console.log(" → provisioning bundled toolchain (bun + pnpm)");
|
|
451
|
+
await provisionToolchain(toolchainDir);
|
|
452
|
+
console.log(" → writing bundle package.json + app-config.json");
|
|
453
|
+
const host = resolveCoreVersion();
|
|
454
|
+
const bundlePkg = {
|
|
455
|
+
name: appName,
|
|
456
|
+
version: appVersion,
|
|
457
|
+
main: "launcher.mjs",
|
|
458
|
+
type: "module",
|
|
459
|
+
zenbu: { host }
|
|
460
|
+
};
|
|
461
|
+
if (mirrorUrl) bundlePkg.repository = {
|
|
462
|
+
type: "git",
|
|
463
|
+
url: mirrorUrl
|
|
464
|
+
};
|
|
465
|
+
await fsp.writeFile(bundlePkgOut, JSON.stringify(bundlePkg, null, 2) + "\n");
|
|
466
|
+
const appConfig = {
|
|
467
|
+
name: appName,
|
|
468
|
+
mirrorUrl,
|
|
469
|
+
branch: mirrorBranch,
|
|
470
|
+
version: appVersion,
|
|
471
|
+
host
|
|
472
|
+
};
|
|
473
|
+
await fsp.writeFile(appConfigOut, JSON.stringify(appConfig, null, 2) + "\n");
|
|
474
|
+
const userConfig = readElectronBuilderConfig(projectDir);
|
|
475
|
+
const userOutput = userConfig.directories?.output ?? "dist";
|
|
476
|
+
const resolvedOutput = path.isAbsolute(userOutput) ? userOutput : path.resolve(projectDir, userOutput);
|
|
477
|
+
const merged = mergeElectronBuilderConfig(userConfig, {
|
|
478
|
+
appDir: bundleDir,
|
|
479
|
+
output: resolvedOutput,
|
|
480
|
+
seedFiles: [
|
|
481
|
+
"package.json",
|
|
482
|
+
"app-config.json",
|
|
483
|
+
"launcher.mjs",
|
|
484
|
+
"seed/**/*",
|
|
485
|
+
"!node_modules",
|
|
486
|
+
"!**/node_modules",
|
|
487
|
+
"!**/node_modules/**"
|
|
488
|
+
],
|
|
489
|
+
extraResource: {
|
|
490
|
+
from: toolchainDir,
|
|
491
|
+
to: "toolchain"
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
await fsp.writeFile(mergedConfigPath, JSON.stringify(merged, null, 2) + "\n");
|
|
495
|
+
console.log(" → injected into electron-builder config:");
|
|
496
|
+
console.log(` directories.app = ${bundleDir}`);
|
|
497
|
+
console.log(` directories.output = ${resolvedOutput}`);
|
|
498
|
+
console.log(` files = [zenbu seed]`);
|
|
499
|
+
console.log(` extraResources += { from: <bundle>/toolchain, to: toolchain }`);
|
|
500
|
+
console.log(` asar = ${merged.asar !== void 0 ? merged.asar : "(unset)"}`);
|
|
501
|
+
console.log(` npmRebuild = false`);
|
|
502
|
+
console.log(" → invoking electron-builder");
|
|
503
|
+
const electronBuilder = resolveElectronBuilder(projectDir);
|
|
504
|
+
const cliArgs = [
|
|
505
|
+
"--config",
|
|
506
|
+
mergedConfigPath,
|
|
507
|
+
...flags.passthrough
|
|
508
|
+
];
|
|
509
|
+
const env = { ...process.env };
|
|
510
|
+
if (!env.GH_TOKEN && env.GITHUB_TOKEN) env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
511
|
+
if (electronBuilder.endsWith(".js")) await spawnAsync(process.execPath, [electronBuilder, ...cliArgs], projectDir, env);
|
|
512
|
+
else await spawnAsync(electronBuilder, cliArgs, projectDir, env);
|
|
513
|
+
console.log(`\n ✓ Built ${appName} ${appVersion} at ${path.relative(projectDir, resolvedOutput) || resolvedOutput}\n`);
|
|
514
|
+
}
|
|
515
|
+
//#endregion
|
|
516
|
+
export { runBuildElectron };
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { a as findBuildConfig, o as loadBuildConfig, t as hashDir } from "./mirror-sync-CodOnwkD.mjs";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fsp from "node:fs/promises";
|
|
5
|
+
import { execFileSync } from "node:child_process";
|
|
6
|
+
//#region src/cli/commands/build-source.ts
|
|
7
|
+
function resolveProjectDir() {
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
if (fs.existsSync(path.join(cwd, "zenbu.plugin.json"))) return cwd;
|
|
10
|
+
console.error("zen build:source: no zenbu.plugin.json found in current directory");
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
function resolveSourceHead(projectDir) {
|
|
14
|
+
try {
|
|
15
|
+
return execFileSync("git", ["rev-parse", "HEAD"], {
|
|
16
|
+
cwd: projectDir,
|
|
17
|
+
encoding: "utf8"
|
|
18
|
+
}).trim();
|
|
19
|
+
} catch {
|
|
20
|
+
return "uncommitted";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function parseFlags(argv) {
|
|
24
|
+
const flags = {};
|
|
25
|
+
for (let i = 0; i < argv.length; i++) {
|
|
26
|
+
const arg = argv[i];
|
|
27
|
+
if (arg === "--config" || arg === "-c") flags.config = argv[++i];
|
|
28
|
+
else if (arg.startsWith("--config=")) flags.config = arg.slice(9);
|
|
29
|
+
else if (arg === "--out" || arg === "-o") flags.out = argv[++i];
|
|
30
|
+
else if (arg.startsWith("--out=")) flags.out = arg.slice(6);
|
|
31
|
+
}
|
|
32
|
+
return flags;
|
|
33
|
+
}
|
|
34
|
+
async function collectFiles(sourceDir, config) {
|
|
35
|
+
const seen = /* @__PURE__ */ new Set();
|
|
36
|
+
for (const pattern of config.include) {
|
|
37
|
+
const iter = fsp.glob(pattern, {
|
|
38
|
+
cwd: sourceDir,
|
|
39
|
+
exclude: config.ignore
|
|
40
|
+
});
|
|
41
|
+
for await (const entry of iter) {
|
|
42
|
+
const rel = entry.split(path.sep).join("/");
|
|
43
|
+
const abs = path.resolve(sourceDir, rel);
|
|
44
|
+
let stat;
|
|
45
|
+
try {
|
|
46
|
+
stat = await fsp.stat(abs);
|
|
47
|
+
} catch {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (!stat.isFile()) continue;
|
|
51
|
+
seen.add(rel);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return [...seen].sort();
|
|
55
|
+
}
|
|
56
|
+
async function applyTransforms(input, transforms) {
|
|
57
|
+
let code = input.code;
|
|
58
|
+
let drop = false;
|
|
59
|
+
for (const transform of transforms) {
|
|
60
|
+
const result = await transform({
|
|
61
|
+
path: input.path,
|
|
62
|
+
code
|
|
63
|
+
});
|
|
64
|
+
if (!result) continue;
|
|
65
|
+
if (result.drop) {
|
|
66
|
+
drop = true;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
if (typeof result.code === "string") code = result.code;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
code,
|
|
73
|
+
drop
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function runBuildSource(argv) {
|
|
77
|
+
const projectDir = resolveProjectDir();
|
|
78
|
+
const flags = parseFlags(argv);
|
|
79
|
+
const configPath = flags.config ? path.resolve(projectDir, flags.config) : findBuildConfig(projectDir);
|
|
80
|
+
const config = await loadBuildConfig(configPath);
|
|
81
|
+
if (flags.out) config.out = flags.out;
|
|
82
|
+
const sourceDir = path.resolve(projectDir, config.source);
|
|
83
|
+
const outDir = path.resolve(projectDir, config.out);
|
|
84
|
+
console.log(`\n zen build:source`);
|
|
85
|
+
console.log(` config: ${path.relative(projectDir, configPath) || configPath}`);
|
|
86
|
+
console.log(` source: ${path.relative(projectDir, sourceDir) || "."}`);
|
|
87
|
+
console.log(` out: ${path.relative(projectDir, outDir) || "."}`);
|
|
88
|
+
await fsp.rm(outDir, {
|
|
89
|
+
recursive: true,
|
|
90
|
+
force: true
|
|
91
|
+
});
|
|
92
|
+
await fsp.mkdir(outDir, { recursive: true });
|
|
93
|
+
const files = await collectFiles(sourceDir, config);
|
|
94
|
+
if (files.length === 0) {
|
|
95
|
+
console.error("zen build:source: no files matched the include/ignore globs");
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
let written = 0;
|
|
99
|
+
let dropped = 0;
|
|
100
|
+
for (const rel of files) {
|
|
101
|
+
const src = path.join(sourceDir, rel);
|
|
102
|
+
const dst = path.join(outDir, rel);
|
|
103
|
+
const isText = isLikelyText(src);
|
|
104
|
+
if (config.transforms.length === 0 || !isText) {
|
|
105
|
+
await fsp.mkdir(path.dirname(dst), { recursive: true });
|
|
106
|
+
await fsp.copyFile(src, dst);
|
|
107
|
+
written += 1;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const { code: nextCode, drop } = await applyTransforms({
|
|
111
|
+
path: rel,
|
|
112
|
+
code: await fsp.readFile(src, "utf8")
|
|
113
|
+
}, config.transforms);
|
|
114
|
+
if (drop) {
|
|
115
|
+
dropped += 1;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
await fsp.mkdir(path.dirname(dst), { recursive: true });
|
|
119
|
+
await fsp.writeFile(dst, nextCode);
|
|
120
|
+
written += 1;
|
|
121
|
+
}
|
|
122
|
+
const sourceSha = resolveSourceHead(projectDir);
|
|
123
|
+
const meta = {
|
|
124
|
+
sourceSha,
|
|
125
|
+
contentHash: await hashDir(outDir),
|
|
126
|
+
builtAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
127
|
+
files: written,
|
|
128
|
+
dropped
|
|
129
|
+
};
|
|
130
|
+
await fsp.writeFile(path.join(outDir, ".sha"), JSON.stringify(meta, null, 2) + "\n");
|
|
131
|
+
console.log(`\n ✓ ${written} file(s) written, ${dropped} dropped by transforms`);
|
|
132
|
+
console.log(` source HEAD: ${sourceSha === "uncommitted" ? sourceSha : sourceSha.slice(0, 7)}\n`);
|
|
133
|
+
}
|
|
134
|
+
const TEXT_EXTENSIONS = new Set([
|
|
135
|
+
".ts",
|
|
136
|
+
".tsx",
|
|
137
|
+
".js",
|
|
138
|
+
".jsx",
|
|
139
|
+
".mjs",
|
|
140
|
+
".cjs",
|
|
141
|
+
".mts",
|
|
142
|
+
".cts",
|
|
143
|
+
".json",
|
|
144
|
+
".md",
|
|
145
|
+
".html",
|
|
146
|
+
".css",
|
|
147
|
+
".scss",
|
|
148
|
+
".sass",
|
|
149
|
+
".less",
|
|
150
|
+
".yml",
|
|
151
|
+
".yaml",
|
|
152
|
+
".toml",
|
|
153
|
+
".sh",
|
|
154
|
+
".env",
|
|
155
|
+
".txt"
|
|
156
|
+
]);
|
|
157
|
+
function isLikelyText(filePath) {
|
|
158
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
159
|
+
return TEXT_EXTENSIONS.has(ext);
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
export { runBuildSource };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
5
|
+
//#endregion
|
|
6
|
+
export { __require as n, __commonJSMin as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|