@zenbujs/core 0.0.2 → 0.0.4

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 (85) hide show
  1. package/LICENSE +11 -0
  2. package/dist/{advice-config-CjgkEf2E.mjs → advice-config-BLXjqjGN.mjs} +21 -13
  3. package/dist/advice-config-D6K_a7e9.mjs +2 -0
  4. package/dist/advice.mjs +1 -1
  5. package/dist/{base-window-BUt8pwbw.mjs → base-window-D8CpxMU3.mjs} +2 -2
  6. package/dist/base-window-OXg2KSyP.mjs +2 -0
  7. package/dist/{build-config-pbv0w4oN.mjs → build-config-BwnnfrN-.mjs} +8 -2
  8. package/dist/{build-electron-BzHa_hRi.mjs → build-electron-C3Beey84.mjs} +12 -6
  9. package/dist/{build-source-CnTfQBGK.mjs → build-source-BvC4bPqH.mjs} +13 -8
  10. package/dist/cli/bin.mjs +12 -15
  11. package/dist/cli/build.d.mts +1 -52
  12. package/dist/cli/build.mjs +2 -47
  13. package/dist/cli/resolve-config.mjs +36 -0
  14. package/dist/{cli-BLbQQIVB.mjs → cli-F0B4dvSg.mjs} +3 -3
  15. package/dist/config-Ch1FreWU.mjs +2 -0
  16. package/dist/config.d.mts +2 -0
  17. package/dist/config.mjs +3 -0
  18. package/dist/db-Bz_CDIWg.mjs +2 -0
  19. package/dist/{db-BXadETOb.mjs → db-Cd5ETuPG.mjs} +47 -41
  20. package/dist/db.d.mts +1 -1
  21. package/dist/env-bootstrap.d.mts +1 -1
  22. package/dist/http-B36qtsm0.mjs +2 -0
  23. package/dist/index-CKKoxA9V.d.mts +1 -0
  24. package/dist/index.d.mts +5 -5
  25. package/dist/index.mjs +2 -2
  26. package/dist/{link-VOoGs-pY.mjs → link-BJmsKgPa.mjs} +87 -120
  27. package/dist/load-config-BG2tPIfF.mjs +126 -0
  28. package/dist/load-config-CQG4297M.mjs +2 -0
  29. package/dist/loaders/zenbu.d.mts +16 -0
  30. package/dist/loaders/zenbu.mjs +151 -62
  31. package/dist/{monorepo-CQeQBIpa.mjs → monorepo-DCruz9Jx.mjs} +2 -2
  32. package/dist/{publish-source-BJdpDAFH.mjs → publish-source-34Hn9zb0.mjs} +12 -6
  33. package/dist/react.d.mts +3 -3
  34. package/dist/{registry-Dh_e7HU1.d.mts → registry-CioEYLI5.d.mts} +1 -1
  35. package/dist/registry.d.mts +1 -1
  36. package/dist/{reloader-lLAJ3lqg.mjs → reloader-DJoCB0bC.mjs} +2 -2
  37. package/dist/reloader-FeHKV2jd.mjs +2 -0
  38. package/dist/renderer-host-BQpS0ZM2.mjs +2 -0
  39. package/dist/{renderer-host-Bg8QdeeH.mjs → renderer-host-ztaSIOGx.mjs} +71 -205
  40. package/dist/{rpc-BwwQK6hD.mjs → rpc-CsgWnlZx.mjs} +2 -2
  41. package/dist/rpc-D_s7-WZe.mjs +2 -0
  42. package/dist/rpc.d.mts +1 -1
  43. package/dist/{runtime-DUFKDIe4.mjs → runtime-C95iyVn6.mjs} +53 -1
  44. package/dist/{runtime-CjqDr8Yf.d.mts → runtime-CsiDppGF.d.mts} +41 -1
  45. package/dist/runtime.d.mts +2 -2
  46. package/dist/runtime.mjs +2 -2
  47. package/dist/{schema-DMoSkwUx.d.mts → schema-DvT61x2_.d.mts} +1 -1
  48. package/dist/schema.d.mts +1 -1
  49. package/dist/server-CgzQOPSW.mjs +2 -0
  50. package/dist/{server-BXwZEQ-n.mjs → server-DB3Eki_G.mjs} +1 -1
  51. package/dist/services/default.mjs +10 -10
  52. package/dist/services/index.d.mts +3 -3
  53. package/dist/services/index.mjs +6 -6
  54. package/dist/{setup-gate-BcoqWu8S.mjs → setup-gate-D8XfYY52.mjs} +35 -5
  55. package/dist/setup-gate.d.mts +1 -1
  56. package/dist/setup-gate.mjs +1 -1
  57. package/dist/transforms-DVoy8dCu.mjs +47 -0
  58. package/dist/transforms-EVd5Fgyk.d.mts +136 -0
  59. package/dist/view-registry-2zePxTEg.mjs +2 -0
  60. package/dist/{vite-plugins-Bh3SCOw-.mjs → vite-plugins-t4MlFcz3.mjs} +4 -18
  61. package/dist/vite.mjs +1 -1
  62. package/dist/{window-CmmpCVX6.mjs → window-DUvMTons.mjs} +3 -3
  63. package/dist/window-S3TlTXlK.mjs +2 -0
  64. package/package.json +19 -18
  65. package/dist/advice-config-Cy133IQP.mjs +0 -2
  66. package/dist/base-window-DEIAk618.mjs +0 -2
  67. package/dist/config-LK73dJmO.mjs +0 -2
  68. package/dist/db-ByKPbnP6.mjs +0 -2
  69. package/dist/http-IBcLzbYu.mjs +0 -2
  70. package/dist/load-build-config-DozuRhAN.mjs +0 -40
  71. package/dist/reloader-BCkLjDhS.mjs +0 -2
  72. package/dist/renderer-host-DpvBPTHJ.mjs +0 -2
  73. package/dist/rpc-CqitnyR4.mjs +0 -2
  74. package/dist/server-DjrZUbbu.mjs +0 -2
  75. package/dist/view-registry-BualWgAf.mjs +0 -2
  76. package/dist/window-CM2a9Kyc.mjs +0 -2
  77. package/dist/{index-FtE8MXJ_.d.mts → cli/resolve-config.d.mts} +0 -0
  78. package/dist/{config-CdVrW85P.mjs → config-BlRXeUXx.mjs} +0 -0
  79. package/dist/{dev-BU_llQh1.mjs → dev-DLutFPyo.mjs} +0 -0
  80. package/dist/{env-bootstrap-BtVME-CU.d.mts → env-bootstrap-uCKbw2q8.d.mts} +0 -0
  81. package/dist/{index-Bhlbyrn7.d.mts → index-CE0iPntP.d.mts} +0 -0
  82. package/dist/{index-CPZ5d6Hl.d.mts → index-UK58xuoR.d.mts} +0 -0
  83. package/dist/{mirror-sync-BN59kMCG.mjs → mirror-sync-EiWvdzTJ.mjs} +1 -1
  84. /package/dist/{node-D4M19_mV.mjs → node-CvZnTx53.mjs} +0 -0
  85. /package/dist/{setup-gate-BqOzm7zp.d.mts → setup-gate-D62nX5lk.d.mts} +0 -0
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as bootstrapEnv } from "./env-bootstrap-rj7I-59x.mjs";
2
- import { t as setupGate } from "./setup-gate-BcoqWu8S.mjs";
3
- import { a as serviceWithDeps, i as runtime, n as ServiceRuntime, r as optional, t as Service } from "./runtime-DUFKDIe4.mjs";
2
+ import { t as setupGate } from "./setup-gate-D8XfYY52.mjs";
3
+ import { d as serviceWithDeps, n as ServiceRuntime, o as optional, t as Service, u as runtime } from "./runtime-C95iyVn6.mjs";
4
4
  import { t as schema } from "./schema-dGK6qkfR.mjs";
5
5
  export { Service, ServiceRuntime, bootstrapEnv, schema as coreSchema, optional, runtime, serviceWithDeps, setupGate };
@@ -1,11 +1,17 @@
1
+ import { n as loadConfig } from "./load-config-BG2tPIfF.mjs";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  //#region src/cli/commands/link.ts
4
- function findManifest(from) {
5
+ const CONFIG_NAMES = [
6
+ "zenbu.config.ts",
7
+ "zenbu.config.mts",
8
+ "zenbu.config.js",
9
+ "zenbu.config.mjs"
10
+ ];
11
+ function findProjectDir(from) {
5
12
  let dir = path.resolve(from);
6
13
  while (true) {
7
- const candidate = path.join(dir, "zenbu.plugin.json");
8
- if (fs.existsSync(candidate)) return candidate;
14
+ for (const name of CONFIG_NAMES) if (fs.existsSync(path.join(dir, name))) return dir;
9
15
  const parent = path.dirname(dir);
10
16
  if (parent === dir) return null;
11
17
  dir = parent;
@@ -44,23 +50,12 @@ function readRegistryDirFromTsconfig(tsconfigPath) {
44
50
  }
45
51
  }
46
52
  /**
47
- * An app root is the nearest ancestor (or self) that contains BOTH a
48
- * `zenbu.plugin.json` and a `config.json` whose `plugins` is an array.
49
- * That signature distinguishes the app from a bare plugin manifest.
53
+ * An app root is the nearest ancestor (or self) that contains a
54
+ * `zenbu.config.ts` (or its .mts/.js/.mjs variants). That single file
55
+ * uniquely identifies a Zenbu project root.
50
56
  */
51
57
  function findAppRoot(from) {
52
- let dir = path.resolve(from);
53
- while (true) {
54
- const manifest = path.join(dir, "zenbu.plugin.json");
55
- const config = path.join(dir, "config.json");
56
- if (fs.existsSync(manifest) && fs.existsSync(config)) try {
57
- const parsed = JSON.parse(fs.readFileSync(config, "utf8"));
58
- if (Array.isArray(parsed?.plugins)) return dir;
59
- } catch {}
60
- const parent = path.dirname(dir);
61
- if (parent === dir) return null;
62
- dir = parent;
63
- }
58
+ return findProjectDir(from);
64
59
  }
65
60
  /**
66
61
  * Pick the directory `zen link` should write registry types into.
@@ -86,10 +81,10 @@ function resolveRegistryDir(opts) {
86
81
  if (appRoot) return path.join(appRoot, "types");
87
82
  console.error(`zen link: could not determine target types directory for ${opts.manifestPath}.`);
88
83
  console.error(` Try one of:`);
89
- console.error(` run from inside an app dir (with both zenbu.plugin.json and config.json),`);
90
- console.error(` add a "devAppPath" field to ${path.basename(opts.manifestPath)} pointing at the host app,`);
91
- console.error(` create a tsconfig.local.json with a "#registry/*" path mapping,`);
92
- console.error(` or pass --registry <dir>.`);
84
+ console.error(` - run from inside an app dir (with a zenbu.config.ts),`);
85
+ console.error(` - add a "devAppPath" field to ${path.basename(opts.manifestPath)} pointing at the host app,`);
86
+ console.error(` - create a tsconfig.local.json with a "#registry/*" path mapping,`);
87
+ console.error(` - or pass --registry <dir>.`);
93
88
  process.exit(1);
94
89
  }
95
90
  function expandGlob(baseDir, pattern) {
@@ -307,7 +302,6 @@ function readExistingRegistry(registryDir) {
307
302
  if (fs.existsSync(servicesPath)) {
308
303
  const content = fs.readFileSync(servicesPath, "utf8");
309
304
  const importRe = /import type \{ (\w+)(?:\s+as\s+(\w+))? \} from "([^"]+)"/g;
310
- const routerRe = /^\s+(?:"([^"]+)"|(\w+)):\s+ExtractRpcMethods<(\w+)>/gm;
311
305
  const importMap = /* @__PURE__ */ new Map();
312
306
  for (const m of content.matchAll(importRe)) {
313
307
  const className = m[1];
@@ -319,31 +313,6 @@ function readExistingRegistry(registryDir) {
319
313
  filePath: absPath
320
314
  });
321
315
  }
322
- for (const m of content.matchAll(routerRe)) {
323
- const key = m[1] ?? m[2];
324
- const alias = m[3];
325
- const imp = importMap.get(alias);
326
- if (!imp) continue;
327
- let pluginName = null;
328
- let dir = path.dirname(imp.filePath);
329
- while (dir !== path.dirname(dir)) {
330
- const candidate = path.join(dir, "zenbu.plugin.json");
331
- if (fs.existsSync(candidate)) {
332
- try {
333
- pluginName = JSON.parse(fs.readFileSync(candidate, "utf8")).name;
334
- } catch {}
335
- break;
336
- }
337
- dir = path.dirname(dir);
338
- }
339
- if (!pluginName) continue;
340
- if (!services.has(pluginName)) services.set(pluginName, []);
341
- services.get(pluginName).push({
342
- className: imp.className,
343
- key,
344
- filePath: imp.filePath
345
- });
346
- }
347
316
  }
348
317
  const dbPath = path.join(registryDir, "db-sections.ts");
349
318
  if (fs.existsSync(dbPath)) {
@@ -387,32 +356,6 @@ function readExistingRegistry(registryDir) {
387
356
  });
388
357
  }
389
358
  }
390
- const eventsRegistryPath = path.join(registryDir, "events.ts");
391
- if (fs.existsSync(eventsRegistryPath)) {
392
- const content = fs.readFileSync(eventsRegistryPath, "utf8");
393
- for (const m of content.matchAll(/import type \{ Events as (\w+) \} from "([^"]+)"/g)) {
394
- m[1];
395
- const relPath = m[2];
396
- const eventsPath = path.resolve(registryDir, relPath) + ".ts";
397
- let pluginName = null;
398
- let dir = path.dirname(eventsPath);
399
- while (dir !== path.dirname(dir)) {
400
- const candidate = path.join(dir, "zenbu.plugin.json");
401
- if (fs.existsSync(candidate)) {
402
- try {
403
- pluginName = JSON.parse(fs.readFileSync(candidate, "utf8")).name;
404
- } catch {}
405
- break;
406
- }
407
- dir = path.dirname(dir);
408
- }
409
- if (!pluginName) continue;
410
- events.set(pluginName, {
411
- name: pluginName,
412
- eventsPath
413
- });
414
- }
415
- }
416
359
  return {
417
360
  services,
418
361
  schemas,
@@ -438,10 +381,48 @@ function parseLinkArgs(argv) {
438
381
  registryOverride
439
382
  };
440
383
  }
441
- function linkOne(manifestPath, existing) {
442
- const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
384
+ /**
385
+ * Variant for path-based plugin sources (a `zenbu.plugin.ts` whose default
386
+ * export is a `definePlugin({...})`). Resolved upstream by `loadConfig` so
387
+ * we just consume the resolved record here.
388
+ */
389
+ function linkResolvedPlugin(plugin, existing) {
390
+ console.log(`Linking types "${plugin.name}" from ${plugin.dir}`);
391
+ const serviceGlobs = plugin.services.map((abs) => path.relative(plugin.dir, abs).split(path.sep).join("/"));
392
+ const serviceEntries = discoverServices(plugin.dir, serviceGlobs);
393
+ console.log(` Found ${serviceEntries.length} service(s)`);
394
+ const schemaEntry = plugin.schemaPath ? {
395
+ name: plugin.name,
396
+ schemaPath: plugin.schemaPath
397
+ } : null;
398
+ if (schemaEntry) console.log(` Schema: ${schemaEntry.schemaPath}`);
399
+ const preloadEntry = plugin.preloadPath ? {
400
+ name: plugin.name,
401
+ preloadPath: plugin.preloadPath
402
+ } : null;
403
+ if (preloadEntry) console.log(` Preload: ${preloadEntry.preloadPath}`);
404
+ const eventsEntry = plugin.eventsPath ? {
405
+ name: plugin.name,
406
+ eventsPath: plugin.eventsPath
407
+ } : null;
408
+ if (eventsEntry) console.log(` Events: ${eventsEntry.eventsPath}`);
409
+ existing.services.set(plugin.name, serviceEntries);
410
+ if (schemaEntry) existing.schemas.set(plugin.name, schemaEntry);
411
+ if (preloadEntry) existing.preloads.set(plugin.name, preloadEntry);
412
+ else existing.preloads.delete(plugin.name);
413
+ if (eventsEntry) existing.events.set(plugin.name, eventsEntry);
414
+ else existing.events.delete(plugin.name);
415
+ }
416
+ /**
417
+ * Variant for the framework-internal `--types-config <path>` flow where the
418
+ * input is a small JSON file (e.g. `packages/core/zenbu-types.config.json`).
419
+ * Used by `pnpm link:types` inside core to bake its own services/registry
420
+ * types without going through a `zenbu.config.ts`.
421
+ */
422
+ function linkTypesConfig(jsonPath, existing) {
423
+ const manifest = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
443
424
  const pluginName = manifest.name;
444
- const baseDir = path.dirname(manifestPath);
425
+ const baseDir = path.dirname(jsonPath);
445
426
  console.log(`Linking types "${pluginName}" from ${baseDir}`);
446
427
  const serviceEntries = discoverServices(baseDir, manifest.services ?? []);
447
428
  console.log(` Found ${serviceEntries.length} service(s)`);
@@ -491,11 +472,10 @@ function linkOne(manifestPath, existing) {
491
472
  * `"extends": "./tsconfig.local.json"`. The generated file then carries
492
473
  * `paths` + `include`, which TS merges into the IDE's resolved program.
493
474
  */
494
- function writePluginTsconfigLocal(pluginManifestPath, registryDir) {
495
- const pluginDir = path.dirname(pluginManifestPath);
475
+ function writePluginTsconfigLocal(pluginDir, registryDir) {
496
476
  const ownTsconfig = path.join(pluginDir, "tsconfig.json");
497
477
  if (!fs.existsSync(ownTsconfig)) return;
498
- if (fs.existsSync(path.join(pluginDir, "config.json"))) return;
478
+ for (const name of CONFIG_NAMES) if (fs.existsSync(path.join(pluginDir, name))) return;
499
479
  const target = path.join(pluginDir, "tsconfig.local.json");
500
480
  let registryRel = path.relative(pluginDir, registryDir);
501
481
  if (!registryRel.startsWith(".")) registryRel = "./" + registryRel;
@@ -512,55 +492,44 @@ function writePluginTsconfigLocal(pluginManifestPath, registryDir) {
512
492
  fs.writeFileSync(target, next);
513
493
  console.log(` Wrote ${target}`);
514
494
  }
515
- /**
516
- * When the manifest being linked is the host app's own manifest (sitting
517
- * next to its `config.json`), expand the work list to also include every
518
- * plugin path declared in `config.json#plugins`. For any other manifest
519
- * (a plugin sitting inside or outside the app), only that single manifest
520
- * is returned — the caller decides not to touch sibling plugins.
521
- */
522
- function expandAppManifests(manifestPath) {
523
- const manifestDir = path.dirname(manifestPath);
524
- const appRoot = findAppRoot(manifestDir);
525
- if (appRoot !== manifestDir) return [manifestPath];
526
- const configPath = path.join(appRoot, "config.json");
527
- let pluginEntries = [];
528
- try {
529
- const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
530
- if (Array.isArray(config?.plugins)) pluginEntries = config.plugins;
531
- } catch {}
532
- const all = [manifestPath];
533
- for (const entry of pluginEntries) {
534
- const resolved = path.isAbsolute(entry) ? entry : path.resolve(appRoot, entry);
535
- if (path.resolve(resolved) === path.resolve(manifestPath)) continue;
536
- if (!fs.existsSync(resolved)) {
537
- console.warn(` ⚠ skipping ${entry} (not found at ${resolved})`);
538
- continue;
539
- }
540
- all.push(resolved);
541
- }
542
- return all;
543
- }
544
495
  async function runLink(argv) {
545
496
  const { manifestArg, typesConfigArg, registryOverride } = parseLinkArgs(argv);
546
- const typeConfigPath = typesConfigArg ? path.resolve(typesConfigArg) : null;
547
- const manifestPath = typeConfigPath ? null : manifestArg ? path.resolve(manifestArg) : findManifest(process.cwd());
548
- if (!typeConfigPath && !manifestPath) {
549
- console.error("zen link: could not find zenbu.plugin.json in current directory or any parent.");
497
+ if (typesConfigArg) {
498
+ const typeConfigPath = path.resolve(typesConfigArg);
499
+ const registryDir = resolveRegistryDir({
500
+ manifestPath: typeConfigPath,
501
+ manifest: JSON.parse(fs.readFileSync(typeConfigPath, "utf8")),
502
+ registryOverride
503
+ });
504
+ console.log(`Registry: ${registryDir}`);
505
+ fs.mkdirSync(registryDir, { recursive: true });
506
+ const existing = readExistingRegistry(registryDir);
507
+ linkTypesConfig(typeConfigPath, existing);
508
+ writeRegistryFiles(registryDir, existing);
509
+ console.log("Done.");
510
+ return;
511
+ }
512
+ const projectDir = manifestArg ? path.resolve(manifestArg) : findProjectDir(process.cwd());
513
+ if (!projectDir) {
514
+ console.error("zen link: could not find zenbu.config.ts in current directory or any parent.");
550
515
  console.error(" For internal framework types, pass --types-config <path>.");
551
516
  process.exit(1);
552
517
  }
553
- const rootConfigPath = typeConfigPath ?? manifestPath;
518
+ const { resolved } = await loadConfig(projectDir);
554
519
  const registryDir = resolveRegistryDir({
555
- manifestPath: rootConfigPath,
556
- manifest: JSON.parse(fs.readFileSync(rootConfigPath, "utf8")),
520
+ manifestPath: resolved.configPath,
521
+ manifest: {},
557
522
  registryOverride
558
523
  });
559
524
  console.log(`Registry: ${registryDir}`);
560
- const manifestPaths = typeConfigPath ? [typeConfigPath] : expandAppManifests(manifestPath);
561
525
  fs.mkdirSync(registryDir, { recursive: true });
562
526
  const existing = readExistingRegistry(registryDir);
563
- for (const mp of manifestPaths) linkOne(mp, existing);
527
+ for (const plugin of resolved.plugins) linkResolvedPlugin(plugin, existing);
528
+ writeRegistryFiles(registryDir, existing);
529
+ for (const plugin of resolved.plugins) writePluginTsconfigLocal(plugin.dir, registryDir);
530
+ console.log("Done.");
531
+ }
532
+ function writeRegistryFiles(registryDir, existing) {
564
533
  const writes = [
565
534
  ["services.ts", generateServicesFile(registryDir, existing.services)],
566
535
  ["db-sections.ts", generateDbSectionsFile(registryDir, existing.schemas)],
@@ -573,8 +542,6 @@ async function runLink(argv) {
573
542
  fs.writeFileSync(target, body);
574
543
  console.log(` Wrote ${target}`);
575
544
  }
576
- for (const mp of manifestPaths) writePluginTsconfigLocal(mp, registryDir);
577
- console.log("Done.");
578
545
  }
579
546
  //#endregion
580
547
  export { runLink };
@@ -0,0 +1,126 @@
1
+ import { i as resolveBuildConfig } from "./build-config-BwnnfrN-.mjs";
2
+ import { createRequire } from "node:module";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ //#region src/cli/lib/load-config.ts
7
+ const localRequire = createRequire(import.meta.url);
8
+ const CONFIG_NAMES = [
9
+ "zenbu.config.ts",
10
+ "zenbu.config.mts",
11
+ "zenbu.config.js",
12
+ "zenbu.config.mjs"
13
+ ];
14
+ const PLUGIN_FILE_RE = /\.(?:ts|mts|js|mjs|cjs)$/;
15
+ function findConfigPath(projectDir) {
16
+ for (const name of CONFIG_NAMES) {
17
+ const candidate = path.join(projectDir, name);
18
+ if (fs.existsSync(candidate)) return candidate;
19
+ }
20
+ throw new Error(`No zenbu config found at ${projectDir}. Expected one of: ${CONFIG_NAMES.join(", ")}`);
21
+ }
22
+ let tsxRegistered = null;
23
+ function ensureTsxRegistered() {
24
+ if (tsxRegistered) return tsxRegistered;
25
+ tsxRegistered = (async () => {
26
+ try {
27
+ const tsxApi = localRequire("tsx/esm/api");
28
+ if (typeof tsxApi.register === "function") tsxApi.register();
29
+ } catch {}
30
+ })();
31
+ return tsxRegistered;
32
+ }
33
+ /**
34
+ * Dynamically import a TS module with a cache-busting query string. Each call
35
+ * forces tsx + Node's ESM loader to re-evaluate the file. Used to rebuild
36
+ * the resolved config + plugin set every time the loader is invoked, so a
37
+ * change to the source TS triggers a fresh `default` export.
38
+ *
39
+ * The returned object is whatever the module's default export is. Older
40
+ * defineConfig-style files that exported the object directly (no `default`)
41
+ * also work via the `mod.default ?? mod` fallback.
42
+ */
43
+ async function importFresh(absPath) {
44
+ await ensureTsxRegistered();
45
+ const mod = await import(pathToFileURL(absPath).href + "?t=" + Date.now());
46
+ return mod.default ?? mod;
47
+ }
48
+ function assertPluginShape(p, source) {
49
+ if (!p || typeof p !== "object") throw new Error(`${source} did not export a Plugin object.`);
50
+ const obj = p;
51
+ if (typeof obj.name !== "string" || obj.name.length === 0) throw new Error(`${source}: plugin missing required string \`name\`.`);
52
+ if (!Array.isArray(obj.services)) throw new Error(`${source}: plugin \`services\` must be an array of glob strings.`);
53
+ }
54
+ function resolvePluginPaths(plugin, dir) {
55
+ const abs = (rel) => path.isAbsolute(rel) ? rel : path.resolve(dir, rel);
56
+ return {
57
+ name: plugin.name,
58
+ dir,
59
+ services: plugin.services.map((s) => path.isAbsolute(s) ? s : path.resolve(dir, s)),
60
+ schemaPath: plugin.schema ? abs(plugin.schema) : void 0,
61
+ migrationsPath: plugin.migrations ? abs(plugin.migrations) : void 0,
62
+ preloadPath: plugin.preload ? abs(plugin.preload) : void 0,
63
+ eventsPath: plugin.events ? abs(plugin.events) : void 0,
64
+ icons: plugin.icons
65
+ };
66
+ }
67
+ async function resolvePluginEntry(entry, configDir) {
68
+ if (typeof entry === "string") {
69
+ const absPath = path.isAbsolute(entry) ? entry : path.resolve(configDir, entry);
70
+ if (!PLUGIN_FILE_RE.test(absPath)) throw new Error(`Plugin entry "${entry}" must point at a .ts/.js file (got ${path.basename(absPath)}). JSON plugin manifests are not supported in the new config; convert to \`zenbu.plugin.ts\`.`);
71
+ if (!fs.existsSync(absPath)) throw new Error(`Plugin entry "${entry}" does not exist at ${absPath}.`);
72
+ const plugin = await importFresh(absPath);
73
+ assertPluginShape(plugin, absPath);
74
+ return {
75
+ resolved: resolvePluginPaths(plugin, path.dirname(absPath)),
76
+ sourceFile: absPath
77
+ };
78
+ }
79
+ assertPluginShape(entry, "(inline plugin)");
80
+ return {
81
+ resolved: resolvePluginPaths(entry, configDir),
82
+ sourceFile: null
83
+ };
84
+ }
85
+ /**
86
+ * Read `<projectDir>/zenbu.config.ts`, resolve all plugin entries (inline +
87
+ * path), make every relative path absolute, and fill in `build` defaults.
88
+ *
89
+ * Used both by the loader (to generate the plugin barrel; cache-busted on
90
+ * every invocation) and by CLI commands (`build:source`, `build:electron`,
91
+ * `link`, `db generate`, `publish:source`).
92
+ */
93
+ async function loadConfig(projectDir) {
94
+ const configPath = findConfigPath(projectDir);
95
+ const config = await importFresh(configPath);
96
+ if (!config || typeof config !== "object") throw new Error(`${configPath} default export is not a Config object.`);
97
+ if (typeof config.db !== "string" || config.db.length === 0) throw new Error(`${configPath}: missing required \`db\` field (path to the database directory).`);
98
+ if (typeof config.uiEntrypoint !== "string" || config.uiEntrypoint.length === 0) throw new Error(`${configPath}: missing required \`uiEntrypoint\` field (path to the boot-window HTML file).`);
99
+ if (!Array.isArray(config.plugins)) throw new Error(`${configPath}: \`plugins\` must be an array.`);
100
+ const configDir = path.dirname(configPath);
101
+ const dbPath = path.isAbsolute(config.db) ? config.db : path.resolve(configDir, config.db);
102
+ const uiEntrypointPath = path.isAbsolute(config.uiEntrypoint) ? config.uiEntrypoint : path.resolve(configDir, config.uiEntrypoint);
103
+ const plugins = [];
104
+ const pluginSourceFiles = [];
105
+ for (const entry of config.plugins) {
106
+ const { resolved, sourceFile } = await resolvePluginEntry(entry, configDir);
107
+ plugins.push(resolved);
108
+ if (sourceFile) pluginSourceFiles.push(sourceFile);
109
+ }
110
+ return {
111
+ resolved: {
112
+ configPath,
113
+ projectDir: configDir,
114
+ dbPath,
115
+ uiEntrypointPath,
116
+ plugins,
117
+ build: resolveBuildConfig(config.build ?? {
118
+ source: ".",
119
+ include: ["**/*"]
120
+ })
121
+ },
122
+ pluginSourceFiles
123
+ };
124
+ }
125
+ //#endregion
126
+ export { loadConfig as n, findConfigPath as t };
@@ -0,0 +1,2 @@
1
+ import { n as loadConfig } from "./load-config-BG2tPIfF.mjs";
2
+ export { loadConfig };
@@ -14,8 +14,24 @@ type TracePort = {
14
14
  };
15
15
  type InitializeData = {
16
16
  tracePort?: TracePort;
17
+ payload?: RegistryPayload;
18
+ pluginSourceFiles?: string[];
17
19
  };
18
20
  declare function initialize(data?: InitializeData): void;
21
+ interface ResolvedPluginRecord {
22
+ name: string;
23
+ dir: string;
24
+ services: string[];
25
+ schemaPath?: string;
26
+ migrationsPath?: string;
27
+ preloadPath?: string;
28
+ eventsPath?: string;
29
+ icons?: Record<string, string>;
30
+ }
31
+ interface RegistryPayload {
32
+ plugins: ResolvedPluginRecord[];
33
+ appEntrypoint: string;
34
+ }
19
35
  declare function resolve(specifier: string, context: LoaderContext, nextResolve: NextResolve): unknown;
20
36
  declare function load(url: string, context: LoaderContext, nextLoad: NextLoad): unknown;
21
37
  //#endregion