@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.
Files changed (94) hide show
  1. package/LICENSE +11 -0
  2. package/dist/advice-config-CjgkEf2E.mjs +135 -0
  3. package/dist/advice-config-Cy133IQP.mjs +2 -0
  4. package/dist/advice-runtime.d.mts +35 -0
  5. package/dist/advice-runtime.mjs +131 -0
  6. package/dist/advice.d.mts +36 -0
  7. package/dist/advice.mjs +2 -0
  8. package/dist/base-window-BUt8pwbw.mjs +94 -0
  9. package/dist/base-window-DEIAk618.mjs +2 -0
  10. package/dist/build-config-pbv0w4oN.mjs +17 -0
  11. package/dist/build-electron-B4Gd0Gi4.mjs +516 -0
  12. package/dist/build-source-_q1n1zTV.mjs +162 -0
  13. package/dist/chunk-Dm34NbLt.mjs +6 -0
  14. package/dist/cli/bin.d.mts +1 -0
  15. package/dist/cli/bin.mjs +88 -0
  16. package/dist/cli/build.d.mts +53 -0
  17. package/dist/cli/build.mjs +48 -0
  18. package/dist/cli-BLbQQIVB.mjs +8054 -0
  19. package/dist/config-CdVrW85P.mjs +59 -0
  20. package/dist/config-LK73dJmO.mjs +2 -0
  21. package/dist/db-ByKPbnP6.mjs +2 -0
  22. package/dist/db-DhuAJrye.mjs +531 -0
  23. package/dist/db.d.mts +16 -0
  24. package/dist/db.mjs +16 -0
  25. package/dist/dev-BuqklM0k.mjs +85 -0
  26. package/dist/env-bootstrap-BtVME-CU.d.mts +16 -0
  27. package/dist/env-bootstrap-rj7I-59x.mjs +53 -0
  28. package/dist/env-bootstrap.d.mts +2 -0
  29. package/dist/env-bootstrap.mjs +2 -0
  30. package/dist/http-IBcLzbYu.mjs +2 -0
  31. package/dist/index-Bhlbyrn7.d.mts +63 -0
  32. package/dist/index-CPZ5d6Hl.d.mts +442 -0
  33. package/dist/index-FtE8MXJ_.d.mts +1 -0
  34. package/dist/index.d.mts +6 -0
  35. package/dist/index.mjs +5 -0
  36. package/dist/launcher.mjs +173 -0
  37. package/dist/link-6roQ7Cn6.mjs +580 -0
  38. package/dist/loaders/zenbu.d.mts +22 -0
  39. package/dist/loaders/zenbu.mjs +267 -0
  40. package/dist/log-CyKv8hQg.mjs +20 -0
  41. package/dist/mirror-sync-CodOnwkD.mjs +332 -0
  42. package/dist/monorepo-CmGPHsVm.mjs +119 -0
  43. package/dist/node-D4M19_mV.mjs +5 -0
  44. package/dist/node-loader.d.mts +17 -0
  45. package/dist/node-loader.mjs +33 -0
  46. package/dist/pause-DvAUNmKn.mjs +52 -0
  47. package/dist/publish-source-BVgB62Zj.mjs +131 -0
  48. package/dist/react.d.mts +76 -0
  49. package/dist/react.mjs +291 -0
  50. package/dist/registry-Dh_e7HU1.d.mts +61 -0
  51. package/dist/registry.d.mts +2 -0
  52. package/dist/registry.mjs +1 -0
  53. package/dist/reloader-BCkLjDhS.mjs +2 -0
  54. package/dist/reloader-lLAJ3lqg.mjs +164 -0
  55. package/dist/renderer-host-Bg8QdeeH.mjs +1508 -0
  56. package/dist/renderer-host-DpvBPTHJ.mjs +2 -0
  57. package/dist/rpc-BwwQK6hD.mjs +71 -0
  58. package/dist/rpc-CqitnyR4.mjs +2 -0
  59. package/dist/rpc.d.mts +2 -0
  60. package/dist/rpc.mjs +2 -0
  61. package/dist/runtime-CjqDr8Yf.d.mts +109 -0
  62. package/dist/runtime-DUFKDIe4.mjs +409 -0
  63. package/dist/runtime.d.mts +2 -0
  64. package/dist/runtime.mjs +2 -0
  65. package/dist/schema-CIg4GzHQ.mjs +100 -0
  66. package/dist/schema-DMoSkwUx.d.mts +62 -0
  67. package/dist/schema-dGK6qkfR.mjs +28 -0
  68. package/dist/schema.d.mts +2 -0
  69. package/dist/schema.mjs +2 -0
  70. package/dist/server-BXwZEQ-n.mjs +66 -0
  71. package/dist/server-DjrZUbbu.mjs +2 -0
  72. package/dist/services/default.d.mts +11 -0
  73. package/dist/services/default.mjs +22 -0
  74. package/dist/services/index.d.mts +276 -0
  75. package/dist/services/index.mjs +7 -0
  76. package/dist/setup-gate-BeD6WS6d.mjs +110 -0
  77. package/dist/setup-gate-BqOzm7zp.d.mts +4 -0
  78. package/dist/setup-gate.d.mts +2 -0
  79. package/dist/setup-gate.mjs +2 -0
  80. package/dist/src-pELM4_iH.mjs +376 -0
  81. package/dist/trace-DCB7qFzT.mjs +10 -0
  82. package/dist/transform-DJH3vN4b.mjs +84041 -0
  83. package/dist/transport-BMSzG2-F.mjs +1045 -0
  84. package/dist/view-registry-BualWgAf.mjs +2 -0
  85. package/dist/vite-plugins-Bh3SCOw-.mjs +331 -0
  86. package/dist/vite.d.mts +68 -0
  87. package/dist/vite.mjs +2 -0
  88. package/dist/window-CM2a9Kyc.mjs +2 -0
  89. package/dist/window-CmmpCVX6.mjs +156 -0
  90. package/dist/write-9dRFczGJ.mjs +1248 -0
  91. package/migrations/0000_migration.ts +34 -0
  92. package/migrations/meta/0000_snapshot.json +18 -0
  93. package/migrations/meta/_journal.json +10 -0
  94. 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 { };