everything-dev 1.48.0 → 1.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/app.cjs +66 -86
  2. package/dist/app.cjs.map +1 -1
  3. package/dist/app.mjs +66 -87
  4. package/dist/app.mjs.map +1 -1
  5. package/dist/cli/db-doctor.cjs +6 -23
  6. package/dist/cli/db-doctor.cjs.map +1 -1
  7. package/dist/cli/db-doctor.mjs +7 -24
  8. package/dist/cli/db-doctor.mjs.map +1 -1
  9. package/dist/cli/db-repair.cjs +25 -20
  10. package/dist/cli/db-repair.cjs.map +1 -1
  11. package/dist/cli/db-repair.mjs +25 -20
  12. package/dist/cli/db-repair.mjs.map +1 -1
  13. package/dist/cli/db-studio.cjs +4 -2
  14. package/dist/cli/db-studio.cjs.map +1 -1
  15. package/dist/cli/db-studio.mjs +5 -3
  16. package/dist/cli/db-studio.mjs.map +1 -1
  17. package/dist/cli/framework-version.cjs +45 -9
  18. package/dist/cli/framework-version.cjs.map +1 -1
  19. package/dist/cli/framework-version.mjs +45 -10
  20. package/dist/cli/framework-version.mjs.map +1 -1
  21. package/dist/cli/infra.cjs +89 -3
  22. package/dist/cli/infra.cjs.map +1 -1
  23. package/dist/cli/infra.mjs +83 -4
  24. package/dist/cli/infra.mjs.map +1 -1
  25. package/dist/cli/init.cjs +39 -15
  26. package/dist/cli/init.cjs.map +1 -1
  27. package/dist/cli/init.d.cts +8 -3
  28. package/dist/cli/init.d.cts.map +1 -1
  29. package/dist/cli/init.d.mts +8 -3
  30. package/dist/cli/init.d.mts.map +1 -1
  31. package/dist/cli/init.mjs +39 -16
  32. package/dist/cli/init.mjs.map +1 -1
  33. package/dist/cli/status.cjs +6 -2
  34. package/dist/cli/status.cjs.map +1 -1
  35. package/dist/cli/status.mjs +7 -3
  36. package/dist/cli/status.mjs.map +1 -1
  37. package/dist/cli/sync.cjs +1 -3
  38. package/dist/cli/sync.cjs.map +1 -1
  39. package/dist/cli/sync.mjs +1 -3
  40. package/dist/cli/sync.mjs.map +1 -1
  41. package/dist/cli/upgrade.cjs +8 -4
  42. package/dist/cli/upgrade.cjs.map +1 -1
  43. package/dist/cli/upgrade.mjs +8 -4
  44. package/dist/cli/upgrade.mjs.map +1 -1
  45. package/dist/cli.cjs +73 -9
  46. package/dist/cli.cjs.map +1 -1
  47. package/dist/cli.mjs +74 -10
  48. package/dist/cli.mjs.map +1 -1
  49. package/dist/config.cjs +7 -3
  50. package/dist/config.cjs.map +1 -1
  51. package/dist/config.d.cts.map +1 -1
  52. package/dist/config.d.mts.map +1 -1
  53. package/dist/config.mjs +7 -3
  54. package/dist/config.mjs.map +1 -1
  55. package/dist/contract.cjs +76 -4
  56. package/dist/contract.cjs.map +1 -1
  57. package/dist/contract.d.cts +164 -19
  58. package/dist/contract.d.cts.map +1 -1
  59. package/dist/contract.d.mts +164 -19
  60. package/dist/contract.d.mts.map +1 -1
  61. package/dist/contract.meta.cjs +17 -2
  62. package/dist/contract.meta.cjs.map +1 -1
  63. package/dist/contract.meta.d.cts +23 -2
  64. package/dist/contract.meta.d.mts +23 -2
  65. package/dist/contract.meta.mjs +17 -2
  66. package/dist/contract.meta.mjs.map +1 -1
  67. package/dist/contract.mjs +72 -5
  68. package/dist/contract.mjs.map +1 -1
  69. package/dist/db.cjs +33 -25
  70. package/dist/db.cjs.map +1 -1
  71. package/dist/db.d.cts +16 -9
  72. package/dist/db.d.cts.map +1 -1
  73. package/dist/db.d.mts +16 -9
  74. package/dist/db.d.mts.map +1 -1
  75. package/dist/db.mjs +33 -24
  76. package/dist/db.mjs.map +1 -1
  77. package/dist/dev-session.cjs +28 -0
  78. package/dist/dev-session.cjs.map +1 -1
  79. package/dist/dev-session.mjs +29 -1
  80. package/dist/dev-session.mjs.map +1 -1
  81. package/dist/index.cjs +5 -0
  82. package/dist/index.d.cts +2 -2
  83. package/dist/index.d.mts +2 -2
  84. package/dist/index.mjs +2 -2
  85. package/dist/infra/planner.cjs +337 -0
  86. package/dist/infra/planner.cjs.map +1 -0
  87. package/dist/infra/planner.mjs +336 -0
  88. package/dist/infra/planner.mjs.map +1 -0
  89. package/dist/infra/preflight.cjs +131 -0
  90. package/dist/infra/preflight.cjs.map +1 -0
  91. package/dist/infra/preflight.mjs +130 -0
  92. package/dist/infra/preflight.mjs.map +1 -0
  93. package/dist/infra/types.cjs +9 -0
  94. package/dist/infra/types.cjs.map +1 -0
  95. package/dist/infra/types.mjs +8 -0
  96. package/dist/infra/types.mjs.map +1 -0
  97. package/dist/near-cli.cjs +37 -0
  98. package/dist/near-cli.cjs.map +1 -1
  99. package/dist/near-cli.mjs +36 -1
  100. package/dist/near-cli.mjs.map +1 -1
  101. package/dist/orchestrator.cjs +10 -2
  102. package/dist/orchestrator.cjs.map +1 -1
  103. package/dist/orchestrator.mjs +10 -2
  104. package/dist/orchestrator.mjs.map +1 -1
  105. package/dist/plugin.cjs +160 -43
  106. package/dist/plugin.cjs.map +1 -1
  107. package/dist/plugin.d.cts +64 -8
  108. package/dist/plugin.d.cts.map +1 -1
  109. package/dist/plugin.d.mts +64 -8
  110. package/dist/plugin.d.mts.map +1 -1
  111. package/dist/plugin.mjs +164 -47
  112. package/dist/plugin.mjs.map +1 -1
  113. package/dist/process-registry.cjs +88 -0
  114. package/dist/process-registry.cjs.map +1 -0
  115. package/dist/process-registry.mjs +83 -0
  116. package/dist/process-registry.mjs.map +1 -0
  117. package/dist/publish.cjs +4 -0
  118. package/dist/publish.cjs.map +1 -1
  119. package/dist/publish.mjs +4 -0
  120. package/dist/publish.mjs.map +1 -1
  121. package/dist/service-descriptor.cjs +4 -0
  122. package/dist/service-descriptor.cjs.map +1 -1
  123. package/dist/service-descriptor.mjs +4 -1
  124. package/dist/service-descriptor.mjs.map +1 -1
  125. package/dist/types.d.cts +2 -2
  126. package/dist/types.d.mts +2 -2
  127. package/dist/ui/index.cjs +2 -1
  128. package/dist/ui/index.d.cts +2 -2
  129. package/dist/ui/index.d.mts +2 -2
  130. package/dist/ui/index.mjs +2 -2
  131. package/dist/ui/router.cjs +40 -0
  132. package/dist/ui/router.cjs.map +1 -1
  133. package/dist/ui/router.d.cts +6 -1
  134. package/dist/ui/router.d.cts.map +1 -1
  135. package/dist/ui/router.d.mts +6 -1
  136. package/dist/ui/router.d.mts.map +1 -1
  137. package/dist/ui/router.mjs +40 -1
  138. package/dist/ui/router.mjs.map +1 -1
  139. package/package.json +4 -1
  140. package/skills/cli-reference/SKILL.md +5 -4
  141. package/skills/dev-workflow/SKILL.md +40 -11
  142. package/skills/plugin-development/SKILL.md +9 -2
@@ -0,0 +1,83 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { Effect } from "effect";
4
+ import { access } from "node:fs/promises";
5
+ import { homedir } from "node:os";
6
+
7
+ //#region src/process-registry.ts
8
+ function getRegistryDir() {
9
+ return join(homedir(), ".cache", "everything-dev");
10
+ }
11
+ function ensureRegistryDir() {
12
+ const dir = join(getRegistryPath(), "..");
13
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
14
+ }
15
+ function readRegistry() {
16
+ const path = getRegistryPath();
17
+ if (!existsSync(path)) return [];
18
+ try {
19
+ const raw = JSON.parse(readFileSync(path, "utf-8"));
20
+ if (!Array.isArray(raw)) return [];
21
+ return raw.filter((entry) => entry && typeof entry === "object" && typeof entry.pid === "number" && typeof entry.configDir === "string" && typeof entry.role === "string");
22
+ } catch {
23
+ return [];
24
+ }
25
+ }
26
+ function isPidAlive(pid) {
27
+ try {
28
+ process.kill(pid, 0);
29
+ return true;
30
+ } catch (err) {
31
+ return err.code !== "ESRCH";
32
+ }
33
+ }
34
+ function pruneDead(entries) {
35
+ return entries.filter((entry) => entry.pid > 1 && existsSync(entry.configDir) && isPidAlive(entry.pid));
36
+ }
37
+ function pruneDeadEffect(entries) {
38
+ return Effect.forEach(entries, (entry) => {
39
+ if (entry.pid <= 1) return Effect.succeed(null);
40
+ return Effect.gen(function* () {
41
+ if (!(yield* Effect.promise(() => access(entry.configDir).then(() => true).catch(() => false)))) return null;
42
+ if (!isPidAlive(entry.pid)) return null;
43
+ return entry;
44
+ });
45
+ }, { concurrency: "unbounded" }).pipe(Effect.map((results) => results.filter((e) => e !== null)));
46
+ }
47
+ function writeRegistry(entries) {
48
+ ensureRegistryDir();
49
+ const path = getRegistryPath();
50
+ const tmpPath = `${path}.tmp`;
51
+ writeFileSync(tmpPath, `${JSON.stringify(entries, null, 2)}\n`);
52
+ renameSync(tmpPath, path);
53
+ }
54
+ function registerStandalone(entry) {
55
+ const live = pruneDead(readRegistry());
56
+ const full = {
57
+ ...entry,
58
+ role: "standalone"
59
+ };
60
+ const withoutSelf = live.filter((existing) => existing.pid !== entry.pid);
61
+ withoutSelf.push(full);
62
+ writeRegistry(withoutSelf);
63
+ return full;
64
+ }
65
+ function unregisterPid(pid) {
66
+ const live = pruneDead(readRegistry());
67
+ const next = live.filter((entry) => entry.pid !== pid);
68
+ if (next.length === live.length) return;
69
+ writeRegistry(next);
70
+ }
71
+ function getRegistryPath() {
72
+ return process.env.BO_PID_REGISTRY_PATH ?? join(getRegistryDir(), "pids.json");
73
+ }
74
+ function claimedPorts() {
75
+ const live = pruneDead(readRegistry());
76
+ const out = /* @__PURE__ */ new Set();
77
+ for (const entry of live) for (const port of Object.values(entry.ports)) if (typeof port === "number") out.add(port);
78
+ return out;
79
+ }
80
+
81
+ //#endregion
82
+ export { claimedPorts, pruneDeadEffect, readRegistry, registerStandalone, unregisterPid };
83
+ //# sourceMappingURL=process-registry.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-registry.mjs","names":[],"sources":["../src/process-registry.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { access } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { Effect } from \"effect\";\n\nexport type ProcessRole = \"standalone\" | \"workspace-parent\" | \"workspace-child\";\n\nexport interface PidEntry {\n pid: number;\n configDir: string;\n parentPid?: number;\n role: ProcessRole;\n ports: Record<string, number>;\n budget?: { min: number; max: number };\n startedAt: number;\n description: string;\n}\n\nfunction getRegistryDir(): string {\n return join(homedir(), \".cache\", \"everything-dev\");\n}\n\nfunction ensureRegistryDir(): void {\n const path = getRegistryPath();\n const dir = join(path, \"..\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\nexport function readRegistry(): PidEntry[] {\n const path = getRegistryPath();\n if (!existsSync(path)) return [];\n try {\n const raw = JSON.parse(readFileSync(path, \"utf-8\"));\n if (!Array.isArray(raw)) return [];\n return raw.filter(\n (entry): entry is PidEntry =>\n entry &&\n typeof entry === \"object\" &&\n typeof entry.pid === \"number\" &&\n typeof entry.configDir === \"string\" &&\n typeof entry.role === \"string\",\n );\n } catch {\n return [];\n }\n}\n\nexport function isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== \"ESRCH\";\n }\n}\n\nexport function pruneDead(entries: PidEntry[]): PidEntry[] {\n return entries.filter(\n (entry) => entry.pid > 1 && existsSync(entry.configDir) && isPidAlive(entry.pid),\n );\n}\n\nexport function pruneDeadEffect(entries: PidEntry[]): Effect.Effect<PidEntry[]> {\n return Effect.forEach(\n entries,\n (entry) => {\n if (entry.pid <= 1) return Effect.succeed(null);\n return Effect.gen(function* () {\n const dirExists = yield* Effect.promise(() =>\n access(entry.configDir)\n .then(() => true)\n .catch(() => false),\n );\n if (!dirExists) return null;\n if (!isPidAlive(entry.pid)) return null;\n return entry;\n });\n },\n { concurrency: \"unbounded\" },\n ).pipe(Effect.map((results) => results.filter((e): e is PidEntry => e !== null)));\n}\n\nexport function writeRegistry(entries: PidEntry[]): void {\n ensureRegistryDir();\n const path = getRegistryPath();\n const tmpPath = `${path}.tmp`;\n writeFileSync(tmpPath, `${JSON.stringify(entries, null, 2)}\\n`);\n renameSync(tmpPath, path);\n}\n\nexport function registerStandalone(entry: Omit<PidEntry, \"role\">): PidEntry {\n const live = pruneDead(readRegistry());\n const full: PidEntry = { ...entry, role: \"standalone\" };\n const withoutSelf = live.filter((existing) => existing.pid !== entry.pid);\n withoutSelf.push(full);\n writeRegistry(withoutSelf);\n return full;\n}\n\nexport function registerEntry(entry: PidEntry): void {\n const live = pruneDead(readRegistry());\n const withoutSelf = live.filter((existing) => existing.pid !== entry.pid);\n withoutSelf.push(entry);\n writeRegistry(withoutSelf);\n}\n\nexport function unregisterPid(pid: number): void {\n const live = pruneDead(readRegistry());\n const next = live.filter((entry) => entry.pid !== pid);\n if (next.length === live.length) return;\n writeRegistry(next);\n}\n\nexport function removeRegistryFile(): void {\n const path = getRegistryPath();\n if (existsSync(path)) {\n rmSync(path, { force: true });\n }\n}\n\nexport function getRegistryPath(): string {\n return process.env.BO_PID_REGISTRY_PATH ?? join(getRegistryDir(), \"pids.json\");\n}\n\nexport function claimedPorts(): Set<number> {\n const live = pruneDead(readRegistry());\n const out = new Set<number>();\n for (const entry of live) {\n for (const port of Object.values(entry.ports)) {\n if (typeof port === \"number\") out.add(port);\n }\n }\n return out;\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,iBAAyB;AAChC,QAAO,KAAK,SAAS,EAAE,UAAU,iBAAiB;;AAGpD,SAAS,oBAA0B;CAEjC,MAAM,MAAM,KADC,iBACQ,EAAE,KAAK;AAC5B,KAAI,CAAC,WAAW,IAAI,CAClB,WAAU,KAAK,EAAE,WAAW,MAAM,CAAC;;AAIvC,SAAgB,eAA2B;CACzC,MAAM,OAAO,iBAAiB;AAC9B,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,EAAE;AAChC,KAAI;EACF,MAAM,MAAM,KAAK,MAAM,aAAa,MAAM,QAAQ,CAAC;AACnD,MAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,EAAE;AAClC,SAAO,IAAI,QACR,UACC,SACA,OAAO,UAAU,YACjB,OAAO,MAAM,QAAQ,YACrB,OAAO,MAAM,cAAc,YAC3B,OAAO,MAAM,SAAS,SACzB;SACK;AACN,SAAO,EAAE;;;AAIb,SAAgB,WAAW,KAAsB;AAC/C,KAAI;AACF,UAAQ,KAAK,KAAK,EAAE;AACpB,SAAO;UACA,KAAK;AACZ,SAAQ,IAA8B,SAAS;;;AAInD,SAAgB,UAAU,SAAiC;AACzD,QAAO,QAAQ,QACZ,UAAU,MAAM,MAAM,KAAK,WAAW,MAAM,UAAU,IAAI,WAAW,MAAM,IAAI,CACjF;;AAGH,SAAgB,gBAAgB,SAAgD;AAC9E,QAAO,OAAO,QACZ,UACC,UAAU;AACT,MAAI,MAAM,OAAO,EAAG,QAAO,OAAO,QAAQ,KAAK;AAC/C,SAAO,OAAO,IAAI,aAAa;AAM7B,OAAI,EAAC,OALoB,OAAO,cAC9B,OAAO,MAAM,UAAU,CACpB,WAAW,KAAK,CAChB,YAAY,MAAM,CACtB,EACe,QAAO;AACvB,OAAI,CAAC,WAAW,MAAM,IAAI,CAAE,QAAO;AACnC,UAAO;IACP;IAEJ,EAAE,aAAa,aAAa,CAC7B,CAAC,KAAK,OAAO,KAAK,YAAY,QAAQ,QAAQ,MAAqB,MAAM,KAAK,CAAC,CAAC;;AAGnF,SAAgB,cAAc,SAA2B;AACvD,oBAAmB;CACnB,MAAM,OAAO,iBAAiB;CAC9B,MAAM,UAAU,GAAG,KAAK;AACxB,eAAc,SAAS,GAAG,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC,IAAI;AAC/D,YAAW,SAAS,KAAK;;AAG3B,SAAgB,mBAAmB,OAAyC;CAC1E,MAAM,OAAO,UAAU,cAAc,CAAC;CACtC,MAAM,OAAiB;EAAE,GAAG;EAAO,MAAM;EAAc;CACvD,MAAM,cAAc,KAAK,QAAQ,aAAa,SAAS,QAAQ,MAAM,IAAI;AACzE,aAAY,KAAK,KAAK;AACtB,eAAc,YAAY;AAC1B,QAAO;;AAUT,SAAgB,cAAc,KAAmB;CAC/C,MAAM,OAAO,UAAU,cAAc,CAAC;CACtC,MAAM,OAAO,KAAK,QAAQ,UAAU,MAAM,QAAQ,IAAI;AACtD,KAAI,KAAK,WAAW,KAAK,OAAQ;AACjC,eAAc,KAAK;;AAUrB,SAAgB,kBAA0B;AACxC,QAAO,QAAQ,IAAI,wBAAwB,KAAK,gBAAgB,EAAE,YAAY;;AAGhF,SAAgB,eAA4B;CAC1C,MAAM,OAAO,UAAU,cAAc,CAAC;CACtC,MAAM,sBAAM,IAAI,KAAa;AAC7B,MAAK,MAAM,SAAS,KAClB,MAAK,MAAM,QAAQ,OAAO,OAAO,MAAM,MAAM,CAC3C,KAAI,OAAO,SAAS,SAAU,KAAI,IAAI,KAAK;AAG/C,QAAO"}
package/dist/publish.cjs CHANGED
@@ -206,6 +206,10 @@ async function publishToFastKv(input) {
206
206
  }
207
207
  function formatNearError(error) {
208
208
  const message = error instanceof Error ? error.message : String(error);
209
+ if (message.includes("does not have enough allowance")) return `The publish access key has insufficient allowance to cover this transaction.
210
+ Regenerate your key with a higher allowance:
211
+ bos key generate
212
+ Original: ${message}`;
209
213
  if (message.includes("exceeded gas") || message.includes("GasLimitExceeded")) return `Transaction exceeded gas limit.\n Original: ${message}`;
210
214
  if (message.includes("timeout") || message.includes("Timeout")) return `Transaction timed out. Check NEAR network status.\n Original: ${message}`;
211
215
  return message;
@@ -1 +1 @@
1
- {"version":3,"file":"publish.cjs","names":["process","fetchBosConfigFromFastKv","getNetworkIdForAccount","buildRegistryConfigUrlForNetwork","selectWorkspaceTargets","resolveNearSigningMode","Effect","ensureNearCli","generateCodeArtifacts","buildWorkspaceTargets","colors","icons","padRight","loadResolvedConfig","executeTransaction","getRegistryNamespaceForNetwork"],"sources":["../src/publish.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { buildWorkspaceTargets, selectWorkspaceTargets } from \"./build\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { loadResolvedConfig } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n} from \"./fastkv\";\nimport { ensureNearCli, executeTransaction, resolveNearSigningMode } from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type { BosConfig, BosConfigInput, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function extractPublishedUrl(output: string): string | null {\n const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n if (deployMatch) return deployMatch[1];\n const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n if (!match || match.length === 0) return null;\n return match[match.length - 1] ?? null;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n}\n\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const { env, dryRun, configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n\n const isStaging = env === \"staging\";\n const account = bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n status: \"error\",\n registryUrl: \"\",\n error: \"bos.config.json must define domain to publish\",\n };\n }\n\n const network = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);\n const targets = selectWorkspaceTargets(input.packages, bosConfig);\n\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n\n if (dryRun) {\n return { status: \"dry-run\", registryUrl, built, skipped };\n }\n\n const privateKey =\n input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;\n let signingMode: ReturnType<typeof resolveNearSigningMode>;\n try {\n signingMode = resolveNearSigningMode(privateKey);\n } catch (error) {\n return {\n status: \"error\" as const,\n registryUrl,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n\n if (input.build) {\n console.log(\" Ensuring NEAR CLI...\");\n await Effect.runPromise(ensureNearCli);\n console.log(\" NEAR CLI ready\");\n\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await loadResolvedConfig({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload bos.config.json after build\",\n };\n }\n\n bosConfig = refreshed.config;\n }\n\n const rawConfigPath = join(configDir, \"bos.config.json\");\n const rawConfig = JSON.parse(readFileSync(rawConfigPath, \"utf-8\")) as BosConfigInput;\n const publishPayload: BosConfigInput = isStaging ? { ...rawConfig, domain: gateway } : rawConfig;\n\n const registryEntries: Record<string, string> = {\n [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload),\n };\n\n const payload = JSON.stringify(registryEntries);\n const argsBase64 = Buffer.from(payload).toString(\"base64\");\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n\n try {\n let txHash: string | undefined;\n\n console.log(` Submitting transaction on ${network}...`);\n\n try {\n const tx = await Effect.runPromise(\n executeTransaction(\n {\n account,\n contract: getRegistryNamespaceForNetwork(network),\n method: \"__fastdata_kv\",\n argsBase64,\n network,\n privateKey: signingMode._tag === \"privateKey\" ? signingMode.privateKey : undefined,\n gas: \"300Tgas\",\n deposit: \"0NEAR\",\n verbose: input.verbose,\n },\n signingMode,\n ),\n );\n txHash = tx.txHash;\n if (txHash && !tx.output?.includes(\"CodeDoesNotExist\")) {\n console.log(` Transaction submitted: ${colors.dim(txHash)}`);\n }\n } catch (error) {\n console.log(colors.dim(\" Transaction reported an error — verifying publish...\"));\n try {\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n timeoutMs: 30_000,\n intervalMs: 2_000,\n });\n txHash = extractTransactionHash(error);\n } catch {\n throw error;\n }\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n });\n\n return {\n status: \"published\",\n registryUrl,\n txHash,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n\nfunction extractTransactionHash(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n const match = message.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,SAAS,MAAM,IAA2B;AACxC,QAAO,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;AAG1D,SAAgB,oBAAoB,QAA+B;CACjE,MAAM,cAAc,OAAO,MAAM,+BAA+B;AAChE,KAAI,YAAa,QAAO,YAAY;CACpC,MAAM,QAAQ,OAAO,MAAM,yBAAyB;AACpD,KAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,QAAO,MAAM,MAAM,SAAS,MAAM;;AAGpC,eAAsB,uBAAuB,MAM3B;CAChB,MAAM,eAAe,OAAOA,qBAAQ,IAAI,oCAAoC;CAC5E,MAAM,gBAAgB,OAAOA,qBAAQ,IAAI,qCAAqC;CAC9E,MAAM,YACJ,KAAK,cAAc,OAAO,SAAS,aAAa,GAAG,eAAe,WAAc;CAClF,MAAM,aACJ,KAAK,eAAe,OAAO,SAAS,cAAc,GAAG,gBAAgB,WAAc;CACrF,MAAM,YAAY,KAAK,KAAK;CAC5B,IAAI;AAEJ,QAAO,KAAK,KAAK,GAAG,YAAY,WAAW;AACzC,MAAI;GACF,MAAM,iBAAiB,MAAMC,wCAC3B,SAAS,KAAK,QAAQ,GAAG,KAAK,UAC/B;AAED,OAAI,KAAK,UAAU,eAAe,KAAK,KAAK,UAAU,KAAK,cAAc,CACvE;WAEK,OAAO;AACd,eAAY;;AAGd,QAAM,MAAM,WAAW;;CAGzB,MAAM,SAAS,qBAAqB,QAAQ,gBAAgB,UAAU,YAAY;AAClF,OAAM,IAAI,MACR,uDAAuD,KAAK,QAAQ,GAAG,KAAK,QAAQ,GAAG,SACxF;;AA2BH,eAAsB,gBAAgB,OAA6D;CACjG,MAAM,EAAE,KAAK,QAAQ,cAAc;CACnC,IAAI,YAAY,MAAM;CACtB,MAAM,gBAAgB,MAAM;CAE5B,MAAM,YAAY,QAAQ;CAC1B,MAAM,UAAU,UAAU;CAC1B,MAAM,UAAU,YAAa,UAAU,SAAS,UAAU,UAAU,SAAU,UAAU;AACxF,KAAI,CAAC,QACH,QAAO;EACL,QAAQ;EACR,aAAa;EACb,OAAO;EACR;CAGH,MAAM,UAAU,MAAM,WAAWC,uCAAuB,QAAQ;CAChE,MAAM,cAAcC,gDAAiC,SAAS,SAAS,QAAQ;CAC/E,MAAM,UAAUC,qCAAuB,MAAM,UAAU,UAAU;CAEjE,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,KAAI,OACF,QAAO;EAAE,QAAQ;EAAW;EAAa;EAAO;EAAS;CAG3D,MAAM,aACJ,MAAM,cAAcJ,qBAAQ,IAAI,oBAAoBA,qBAAQ,IAAI;CAClE,IAAI;AACJ,KAAI;AACF,gBAAcK,wCAAuB,WAAW;UACzC,OAAO;AACd,SAAO;GACL,QAAQ;GACR;GACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU;GACjD;;AAGH,KAAI,MAAM,OAAO;AACf,UAAQ,IAAI,yBAAyB;AACrC,QAAMC,cAAO,WAAWC,+BAAc;AACtC,UAAQ,IAAI,mBAAmB;AAE/B,QAAMC,6CAAsB,WAAW,WAAW;GAChD,KAAK;GACL,eAAe,iBAAiB;GACjC,CAAC;EAEF,MAAM,SAAS,MAAMC,oCAAsB;GACzC;GACA;GACA;GACA;GACA,QAAQ;GACR,SAAS,MAAM;GAChB,CAAC;AACF,UAAQ,OAAO;AACf,YAAU,OAAO;AACjB,kBAAgB,OAAO;AAEvB,MAAI,eAAe;GACjB,MAAM,WAAW,cAAc,QAAQ,MAAM,CAAC,EAAE,QAAQ;AACxD,OAAI,SAAS,SAAS,GAAG;IACvB,MAAM,QAAQ,cAAc;AAC5B,YAAQ,KAAK;AACb,YAAQ,IACNC,qBAAO,MACL,KAAKC,oBAAM,IAAI,mBAAmB,SAAS,OAAO,MAAM,MAAM,YAAY,QAAQ,IAAI,MAAM,GAAG,SAChG,CACF;AACD,YAAQ,KAAK;AACb,SAAK,MAAM,KAAK,UAAU;KACxB,MAAM,aAAa,EAAE,SAAS,UAAU,MAAM,KAAK,CAAC;AACpD,aAAQ,IAAI,OAAOD,qBAAO,MAAMC,oBAAM,IAAI,CAAC,GAAGC,wBAAS,EAAE,KAAK,GAAG,CAAC,GAAG,YAAY;;AAEnF,YAAQ,KAAK;AACb,QAAI,CAAC,MAAM,SAAS;AAClB,aAAQ,IAAIF,qBAAO,IAAI,8CAA8C,CAAC;AACtE,aAAQ,KAAK;;AAEf,WAAO;KACL,QAAQ;KACR;KACA;KACA;KACA;KACA,OAAO,GAAG,SAAS,OAAO,MAAM,MAAM;KACvC;;;EAIL,MAAM,YAAY,MAAMG,kCAAmB,EAAE,KAAK,WAAW,CAAC;AAC9D,MAAI,CAAC,WAAW,OACd,QAAO;GACL,QAAQ;GACR;GACA;GACA;GACA;GACA,OAAO;GACR;AAGH,cAAY,UAAU;;CAGxB,MAAM,oCAAqB,WAAW,kBAAkB;CACxD,MAAM,YAAY,KAAK,gCAAmB,eAAe,QAAQ,CAAC;CAClE,MAAM,iBAAiC,YAAY;EAAE,GAAG;EAAW,QAAQ;EAAS,GAAG;CAEvF,MAAM,kBAA0C,GAC7C,QAAQ,QAAQ,GAAG,QAAQ,oBAAoB,KAAK,UAAU,eAAe,EAC/E;CAED,MAAM,UAAU,KAAK,UAAU,gBAAgB;CAC/C,MAAM,aAAa,OAAO,KAAK,QAAQ,CAAC,SAAS,SAAS;AAE1D,SAAQ,KAAK;AACb,SAAQ,IAAI,mBAAmB;AAC/B,SAAQ,IAAI,OAAOH,qBAAO,KAAK,YAAY,GAAG;AAE9C,KAAI;EACF,IAAI;AAEJ,UAAQ,IAAI,+BAA+B,QAAQ,KAAK;AAExD,MAAI;GACF,MAAM,KAAK,MAAMJ,cAAO,WACtBQ,oCACE;IACE;IACA,UAAUC,8CAA+B,QAAQ;IACjD,QAAQ;IACR;IACA;IACA,YAAY,YAAY,SAAS,eAAe,YAAY,aAAa;IACzE,KAAK;IACL,SAAS;IACT,SAAS,MAAM;IAChB,EACD,YACD,CACF;AACD,YAAS,GAAG;AACZ,OAAI,UAAU,CAAC,GAAG,QAAQ,SAAS,mBAAmB,CACpD,SAAQ,IAAI,4BAA4BL,qBAAO,IAAI,OAAO,GAAG;WAExD,OAAO;AACd,WAAQ,IAAIA,qBAAO,IAAI,yDAAyD,CAAC;AACjF,OAAI;AACF,UAAM,uBAAuB;KAC3B;KACA;KACA,eAAe;KACf,WAAW;KACX,YAAY;KACb,CAAC;AACF,aAAS,uBAAuB,MAAM;WAChC;AACN,UAAM;;;AAIV,UAAQ,IAAI,wCAAwC;AACpD,QAAM,uBAAuB;GAC3B;GACA;GACA,eAAe;GAChB,CAAC;AAEF,SAAO;GACL,QAAQ;GACR;GACA;GACA;GACA;GACA;GACA,eAAe;GAChB;UACM,OAAO;AACd,SAAO;GACL,QAAQ;GACR;GACA,OAAO,gBAAgB,MAAM;GAC7B;GACA;GACA;GACD;;;AAIL,SAAS,gBAAgB,OAAwB;CAC/C,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAEtE,KAAI,QAAQ,SAAS,eAAe,IAAI,QAAQ,SAAS,mBAAmB,CAC1E,QAAO,gDAAgD;AAGzD,KAAI,QAAQ,SAAS,UAAU,IAAI,QAAQ,SAAS,UAAU,CAC5D,QAAO,kEAAkE;AAG3E,QAAO;;AAGT,SAAS,uBAAuB,OAAgB;AAG9C,SAFgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAChD,MAAM,oCAChB,GAAG"}
1
+ {"version":3,"file":"publish.cjs","names":["process","fetchBosConfigFromFastKv","getNetworkIdForAccount","buildRegistryConfigUrlForNetwork","selectWorkspaceTargets","resolveNearSigningMode","Effect","ensureNearCli","generateCodeArtifacts","buildWorkspaceTargets","colors","icons","padRight","loadResolvedConfig","executeTransaction","getRegistryNamespaceForNetwork"],"sources":["../src/publish.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { buildWorkspaceTargets, selectWorkspaceTargets } from \"./build\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { loadResolvedConfig } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n} from \"./fastkv\";\nimport { ensureNearCli, executeTransaction, resolveNearSigningMode } from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type { BosConfig, BosConfigInput, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function extractPublishedUrl(output: string): string | null {\n const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n if (deployMatch) return deployMatch[1];\n const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n if (!match || match.length === 0) return null;\n return match[match.length - 1] ?? null;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n}\n\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const { env, dryRun, configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n\n const isStaging = env === \"staging\";\n const account = bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n status: \"error\",\n registryUrl: \"\",\n error: \"bos.config.json must define domain to publish\",\n };\n }\n\n const network = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);\n const targets = selectWorkspaceTargets(input.packages, bosConfig);\n\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n\n if (dryRun) {\n return { status: \"dry-run\", registryUrl, built, skipped };\n }\n\n const privateKey =\n input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;\n let signingMode: ReturnType<typeof resolveNearSigningMode>;\n try {\n signingMode = resolveNearSigningMode(privateKey);\n } catch (error) {\n return {\n status: \"error\" as const,\n registryUrl,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n\n if (input.build) {\n console.log(\" Ensuring NEAR CLI...\");\n await Effect.runPromise(ensureNearCli);\n console.log(\" NEAR CLI ready\");\n\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await loadResolvedConfig({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload bos.config.json after build\",\n };\n }\n\n bosConfig = refreshed.config;\n }\n\n const rawConfigPath = join(configDir, \"bos.config.json\");\n const rawConfig = JSON.parse(readFileSync(rawConfigPath, \"utf-8\")) as BosConfigInput;\n const publishPayload: BosConfigInput = isStaging ? { ...rawConfig, domain: gateway } : rawConfig;\n\n const registryEntries: Record<string, string> = {\n [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload),\n };\n\n const payload = JSON.stringify(registryEntries);\n const argsBase64 = Buffer.from(payload).toString(\"base64\");\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n\n try {\n let txHash: string | undefined;\n\n console.log(` Submitting transaction on ${network}...`);\n\n try {\n const tx = await Effect.runPromise(\n executeTransaction(\n {\n account,\n contract: getRegistryNamespaceForNetwork(network),\n method: \"__fastdata_kv\",\n argsBase64,\n network,\n privateKey: signingMode._tag === \"privateKey\" ? signingMode.privateKey : undefined,\n gas: \"300Tgas\",\n deposit: \"0NEAR\",\n verbose: input.verbose,\n },\n signingMode,\n ),\n );\n txHash = tx.txHash;\n if (txHash && !tx.output?.includes(\"CodeDoesNotExist\")) {\n console.log(` Transaction submitted: ${colors.dim(txHash)}`);\n }\n } catch (error) {\n console.log(colors.dim(\" Transaction reported an error — verifying publish...\"));\n try {\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n timeoutMs: 30_000,\n intervalMs: 2_000,\n });\n txHash = extractTransactionHash(error);\n } catch {\n throw error;\n }\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n });\n\n return {\n status: \"published\",\n registryUrl,\n txHash,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"does not have enough allowance\")) {\n return (\n \"The publish access key has insufficient allowance to cover this transaction.\\n\" +\n \" Regenerate your key with a higher allowance:\\n\" +\n \" bos key generate\\n\" +\n ` Original: ${message}`\n );\n }\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n\nfunction extractTransactionHash(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n const match = message.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n"],"mappings":"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"}
package/dist/publish.mjs CHANGED
@@ -204,6 +204,10 @@ async function publishToFastKv(input) {
204
204
  }
205
205
  function formatNearError(error) {
206
206
  const message = error instanceof Error ? error.message : String(error);
207
+ if (message.includes("does not have enough allowance")) return `The publish access key has insufficient allowance to cover this transaction.
208
+ Regenerate your key with a higher allowance:
209
+ bos key generate
210
+ Original: ${message}`;
207
211
  if (message.includes("exceeded gas") || message.includes("GasLimitExceeded")) return `Transaction exceeded gas limit.\n Original: ${message}`;
208
212
  if (message.includes("timeout") || message.includes("Timeout")) return `Transaction timed out. Check NEAR network status.\n Original: ${message}`;
209
213
  return message;
@@ -1 +1 @@
1
- {"version":3,"file":"publish.mjs","names":[],"sources":["../src/publish.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { buildWorkspaceTargets, selectWorkspaceTargets } from \"./build\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { loadResolvedConfig } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n} from \"./fastkv\";\nimport { ensureNearCli, executeTransaction, resolveNearSigningMode } from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type { BosConfig, BosConfigInput, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function extractPublishedUrl(output: string): string | null {\n const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n if (deployMatch) return deployMatch[1];\n const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n if (!match || match.length === 0) return null;\n return match[match.length - 1] ?? null;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n}\n\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const { env, dryRun, configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n\n const isStaging = env === \"staging\";\n const account = bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n status: \"error\",\n registryUrl: \"\",\n error: \"bos.config.json must define domain to publish\",\n };\n }\n\n const network = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);\n const targets = selectWorkspaceTargets(input.packages, bosConfig);\n\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n\n if (dryRun) {\n return { status: \"dry-run\", registryUrl, built, skipped };\n }\n\n const privateKey =\n input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;\n let signingMode: ReturnType<typeof resolveNearSigningMode>;\n try {\n signingMode = resolveNearSigningMode(privateKey);\n } catch (error) {\n return {\n status: \"error\" as const,\n registryUrl,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n\n if (input.build) {\n console.log(\" Ensuring NEAR CLI...\");\n await Effect.runPromise(ensureNearCli);\n console.log(\" NEAR CLI ready\");\n\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await loadResolvedConfig({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload bos.config.json after build\",\n };\n }\n\n bosConfig = refreshed.config;\n }\n\n const rawConfigPath = join(configDir, \"bos.config.json\");\n const rawConfig = JSON.parse(readFileSync(rawConfigPath, \"utf-8\")) as BosConfigInput;\n const publishPayload: BosConfigInput = isStaging ? { ...rawConfig, domain: gateway } : rawConfig;\n\n const registryEntries: Record<string, string> = {\n [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload),\n };\n\n const payload = JSON.stringify(registryEntries);\n const argsBase64 = Buffer.from(payload).toString(\"base64\");\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n\n try {\n let txHash: string | undefined;\n\n console.log(` Submitting transaction on ${network}...`);\n\n try {\n const tx = await Effect.runPromise(\n executeTransaction(\n {\n account,\n contract: getRegistryNamespaceForNetwork(network),\n method: \"__fastdata_kv\",\n argsBase64,\n network,\n privateKey: signingMode._tag === \"privateKey\" ? signingMode.privateKey : undefined,\n gas: \"300Tgas\",\n deposit: \"0NEAR\",\n verbose: input.verbose,\n },\n signingMode,\n ),\n );\n txHash = tx.txHash;\n if (txHash && !tx.output?.includes(\"CodeDoesNotExist\")) {\n console.log(` Transaction submitted: ${colors.dim(txHash)}`);\n }\n } catch (error) {\n console.log(colors.dim(\" Transaction reported an error — verifying publish...\"));\n try {\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n timeoutMs: 30_000,\n intervalMs: 2_000,\n });\n txHash = extractTransactionHash(error);\n } catch {\n throw error;\n }\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n });\n\n return {\n status: \"published\",\n registryUrl,\n txHash,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n\nfunction extractTransactionHash(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n const match = message.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"publish.mjs","names":[],"sources":["../src/publish.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { buildWorkspaceTargets, selectWorkspaceTargets } from \"./build\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { loadResolvedConfig } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n} from \"./fastkv\";\nimport { ensureNearCli, executeTransaction, resolveNearSigningMode } from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type { BosConfig, BosConfigInput, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function extractPublishedUrl(output: string): string | null {\n const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n if (deployMatch) return deployMatch[1];\n const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n if (!match || match.length === 0) return null;\n return match[match.length - 1] ?? null;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n}\n\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const { env, dryRun, configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n\n const isStaging = env === \"staging\";\n const account = bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n status: \"error\",\n registryUrl: \"\",\n error: \"bos.config.json must define domain to publish\",\n };\n }\n\n const network = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);\n const targets = selectWorkspaceTargets(input.packages, bosConfig);\n\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n\n if (dryRun) {\n return { status: \"dry-run\", registryUrl, built, skipped };\n }\n\n const privateKey =\n input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;\n let signingMode: ReturnType<typeof resolveNearSigningMode>;\n try {\n signingMode = resolveNearSigningMode(privateKey);\n } catch (error) {\n return {\n status: \"error\" as const,\n registryUrl,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n\n if (input.build) {\n console.log(\" Ensuring NEAR CLI...\");\n await Effect.runPromise(ensureNearCli);\n console.log(\" NEAR CLI ready\");\n\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await loadResolvedConfig({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload bos.config.json after build\",\n };\n }\n\n bosConfig = refreshed.config;\n }\n\n const rawConfigPath = join(configDir, \"bos.config.json\");\n const rawConfig = JSON.parse(readFileSync(rawConfigPath, \"utf-8\")) as BosConfigInput;\n const publishPayload: BosConfigInput = isStaging ? { ...rawConfig, domain: gateway } : rawConfig;\n\n const registryEntries: Record<string, string> = {\n [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload),\n };\n\n const payload = JSON.stringify(registryEntries);\n const argsBase64 = Buffer.from(payload).toString(\"base64\");\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n\n try {\n let txHash: string | undefined;\n\n console.log(` Submitting transaction on ${network}...`);\n\n try {\n const tx = await Effect.runPromise(\n executeTransaction(\n {\n account,\n contract: getRegistryNamespaceForNetwork(network),\n method: \"__fastdata_kv\",\n argsBase64,\n network,\n privateKey: signingMode._tag === \"privateKey\" ? signingMode.privateKey : undefined,\n gas: \"300Tgas\",\n deposit: \"0NEAR\",\n verbose: input.verbose,\n },\n signingMode,\n ),\n );\n txHash = tx.txHash;\n if (txHash && !tx.output?.includes(\"CodeDoesNotExist\")) {\n console.log(` Transaction submitted: ${colors.dim(txHash)}`);\n }\n } catch (error) {\n console.log(colors.dim(\" Transaction reported an error — verifying publish...\"));\n try {\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n timeoutMs: 30_000,\n intervalMs: 2_000,\n });\n txHash = extractTransactionHash(error);\n } catch {\n throw error;\n }\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n });\n\n return {\n status: \"published\",\n registryUrl,\n txHash,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"does not have enough allowance\")) {\n return (\n \"The publish access key has insufficient allowance to cover this transaction.\\n\" +\n \" Regenerate your key with a higher allowance:\\n\" +\n \" bos key generate\\n\" +\n ` Original: ${message}`\n );\n }\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n\nfunction extractTransactionHash(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n const match = message.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n"],"mappings":"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"}
@@ -185,6 +185,9 @@ function buildServiceDescriptorMap(runtimeConfig, options) {
185
185
  }
186
186
  const ServiceDescriptorMapLive = (map) => effect.Layer.succeed(ServiceDescriptorMap, map);
187
187
  const DevRuntimeConfigLive = (config) => effect.Layer.succeed(DevRuntimeConfig, config);
188
+ function buildServiceDescriptorMapFromPlan(plan, options) {
189
+ return buildServiceDescriptorMap(plan.runtimeConfig, options);
190
+ }
188
191
  function buildDescription(map) {
189
192
  const descriptors = [...map.values()].filter((d) => d.key !== "ui-ssr" && !d.key.startsWith("plugin:"));
190
193
  const allLocal = descriptors.every((d) => d.source === "local");
@@ -206,4 +209,5 @@ exports.ServiceDescriptorMap = ServiceDescriptorMap;
206
209
  exports.ServiceDescriptorMapLive = ServiceDescriptorMapLive;
207
210
  exports.buildDescription = buildDescription;
208
211
  exports.buildServiceDescriptorMap = buildServiceDescriptorMap;
212
+ exports.buildServiceDescriptorMapFromPlan = buildServiceDescriptorMapFromPlan;
209
213
  //# sourceMappingURL=service-descriptor.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-descriptor.cjs","names":["Context","Layer"],"sources":["../src/service-descriptor.ts"],"sourcesContent":["import { Context, Layer } from \"effect\";\nimport type { JsonObject, RuntimeConfig, SourceMode } from \"./types\";\n\nexport interface ServiceDescriptor {\n key: string;\n source: SourceMode;\n url: string;\n remoteUrl?: string;\n entry: string;\n name: string;\n localPath?: string;\n port?: number;\n readinessPath: string;\n defaultPort: number;\n integrity?: string;\n proxy?: string;\n variables?: JsonObject;\n secrets?: string[];\n ssr?: boolean;\n command?: string;\n args?: string[];\n readyPatterns?: RegExp[];\n errorPatterns?: RegExp[];\n}\n\nexport class ServiceDescriptorMap extends Context.Tag(\"ServiceDescriptorMap\")<\n ServiceDescriptorMap,\n Map<string, ServiceDescriptor>\n>() {}\n\nexport class DevRuntimeConfig extends Context.Tag(\"DevRuntimeConfig\")<\n DevRuntimeConfig,\n RuntimeConfig\n>() {}\n\nconst PLUGIN_READY_PATTERNS = [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i];\n\nconst PLUGIN_ERROR_PATTERNS = [/error/i, /failed/i];\n\nconst SERVICE_CONFIGS: Record<\n string,\n Pick<\n ServiceDescriptor,\n \"command\" | \"args\" | \"readyPatterns\" | \"errorPatterns\" | \"defaultPort\" | \"readinessPath\"\n >\n> = {\n host: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n defaultPort: 3000,\n readinessPath: \"/health\",\n },\n auth: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3002,\n readinessPath: \"/remoteEntry.js\",\n },\n ui: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bLocal:\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed to compile/i],\n defaultPort: 3003,\n readinessPath: \"/remoteEntry.js\",\n },\n \"ui-ssr\": {\n command: \"bun\",\n args: [\"run\", \"dev:ssr\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed/i],\n defaultPort: 3004,\n readinessPath: \"/\",\n },\n api: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3001,\n readinessPath: \"/remoteEntry.js\",\n },\n};\n\nexport function buildServiceDescriptorMap(\n runtimeConfig: RuntimeConfig,\n options?: { ssr?: boolean; proxy?: boolean },\n): Map<string, ServiceDescriptor> {\n const map = new Map<string, ServiceDescriptor>();\n const ssr = options?.ssr ?? false;\n\n const hostIsRemote = runtimeConfig.host.source === \"remote\";\n const hostProbeUrl = hostIsRemote\n ? (runtimeConfig.host.remoteUrl ?? runtimeConfig.host.url)\n : runtimeConfig.host.url;\n map.set(\"host\", {\n key: \"host\",\n source: runtimeConfig.host.source,\n url: hostProbeUrl,\n remoteUrl: runtimeConfig.host.remoteUrl,\n entry: hostIsRemote\n ? hostProbeUrl\n ? `${hostProbeUrl}/mf-manifest.json`\n : \"/mf-manifest.json\"\n : runtimeConfig.host.entry,\n name: runtimeConfig.host.name,\n localPath: runtimeConfig.host.localPath,\n port: runtimeConfig.host.port,\n integrity: runtimeConfig.host.integrity,\n secrets: runtimeConfig.host.secrets,\n ...SERVICE_CONFIGS.host,\n });\n\n map.set(\"ui\", {\n key: \"ui\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.url,\n remoteUrl: runtimeConfig.ui.source === \"remote\" ? runtimeConfig.ui.url : undefined,\n entry: runtimeConfig.ui.entry,\n name: runtimeConfig.ui.name,\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.port,\n integrity: runtimeConfig.ui.integrity,\n ssr,\n ...SERVICE_CONFIGS.ui,\n });\n\n if (ssr && runtimeConfig.ui.source === \"local\") {\n map.set(\"ui-ssr\", {\n key: \"ui-ssr\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.ssrUrl ?? \"\",\n entry: \"\",\n name: \"ui-ssr\",\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.ssrUrl\n ? Number.parseInt(new URL(runtimeConfig.ui.ssrUrl).port, 10)\n : (runtimeConfig.ui.port ?? 3003) + 1,\n ...SERVICE_CONFIGS[\"ui-ssr\"],\n });\n }\n\n map.set(\"api\", {\n key: \"api\",\n source: runtimeConfig.api.source,\n url: runtimeConfig.api.url,\n remoteUrl: runtimeConfig.api.source === \"remote\" ? runtimeConfig.api.url : undefined,\n entry: runtimeConfig.api.entry,\n name: runtimeConfig.api.name,\n localPath: runtimeConfig.api.localPath,\n port: runtimeConfig.api.port,\n integrity: runtimeConfig.api.integrity,\n proxy: runtimeConfig.api.proxy,\n variables: runtimeConfig.api.variables,\n secrets: runtimeConfig.api.secrets,\n ...SERVICE_CONFIGS.api,\n });\n\n if (runtimeConfig.auth) {\n map.set(\"auth\", {\n key: \"auth\",\n source: runtimeConfig.auth.source,\n url: runtimeConfig.auth.url,\n remoteUrl: runtimeConfig.auth.source === \"remote\" ? runtimeConfig.auth.url : undefined,\n entry: runtimeConfig.auth.entry,\n name: runtimeConfig.auth.name,\n localPath: runtimeConfig.auth.localPath,\n port: runtimeConfig.auth.port,\n integrity: runtimeConfig.auth.integrity,\n proxy: runtimeConfig.auth.proxy,\n variables: runtimeConfig.auth.variables,\n secrets: runtimeConfig.auth.secrets,\n ...SERVICE_CONFIGS.auth,\n });\n }\n\n if (runtimeConfig.plugins) {\n let pluginBasePort = 3010;\n for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig.plugins)) {\n const pluginKey = `plugin:${pluginId}`;\n const resolvedPort = pluginConfig.port ?? pluginBasePort;\n pluginBasePort = resolvedPort + 1;\n\n map.set(pluginKey, {\n key: pluginKey,\n source: pluginConfig.source,\n url: pluginConfig.url,\n remoteUrl: pluginConfig.source === \"remote\" ? pluginConfig.url : undefined,\n entry: pluginConfig.entry,\n name: pluginConfig.name,\n localPath: pluginConfig.localPath,\n port: resolvedPort,\n integrity: pluginConfig.integrity,\n proxy: pluginConfig.proxy,\n variables: pluginConfig.variables,\n secrets: pluginConfig.secrets,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: resolvedPort,\n readinessPath: \"/remoteEntry.js\",\n });\n\n if (pluginConfig.ui?.localPath && pluginConfig.ui.source === \"local\") {\n const uiKey = `plugin-ui:${pluginId}`;\n const uiPort = pluginConfig.ui.port ?? pluginBasePort;\n pluginBasePort = uiPort + 1;\n\n map.set(uiKey, {\n key: uiKey,\n source: pluginConfig.ui.source,\n url: pluginConfig.ui.url,\n entry: pluginConfig.ui.entry,\n name: pluginConfig.ui.name,\n localPath: pluginConfig.ui.localPath,\n port: uiPort,\n integrity: pluginConfig.ui.integrity,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: uiPort,\n readinessPath: \"/remoteEntry.js\",\n });\n }\n }\n }\n\n return map;\n}\n\nexport interface AppOrchestrator {\n packages: string[];\n description: string;\n env: Record<string, string>;\n port?: number;\n interactive?: boolean;\n noLogs?: boolean;\n}\n\nexport const ServiceDescriptorMapLive = (map: Map<string, ServiceDescriptor>) =>\n Layer.succeed(ServiceDescriptorMap, map);\n\nexport const DevRuntimeConfigLive = (config: RuntimeConfig) =>\n Layer.succeed(DevRuntimeConfig, config);\n\nexport function buildDescription(map: Map<string, ServiceDescriptor>): string {\n const descriptors = [...map.values()].filter(\n (d) => d.key !== \"ui-ssr\" && !d.key.startsWith(\"plugin:\"),\n );\n\n const allLocal = descriptors.every((d) => d.source === \"local\");\n const hasProxy = [...map.values()].some((d) => d.proxy && d.source === \"local\");\n if (allLocal && !hasProxy) return \"Full Local Development\";\n\n const parts: string[] = [];\n for (const d of descriptors) {\n if (d.source === \"remote\") {\n const label =\n d.key === \"host\"\n ? \"Remote Host\"\n : d.key === \"ui\"\n ? \"Remote UI\"\n : d.key === \"api\"\n ? hasProxy\n ? undefined\n : \"Remote API\"\n : d.key === \"auth\"\n ? \"Remote Auth\"\n : undefined;\n if (label) parts.push(label);\n }\n }\n if (hasProxy) parts.push(\"Proxy API → Production\");\n return parts.join(\" + \") || \"Remote Mode\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service-descriptor.cjs","names":["Context","Layer"],"sources":["../src/service-descriptor.ts"],"sourcesContent":["import { Context, Layer } from \"effect\";\nimport type { JsonObject, RuntimeConfig, SourceMode } from \"./types\";\n\nexport interface ServiceDescriptor {\n key: string;\n source: SourceMode;\n url: string;\n remoteUrl?: string;\n entry: string;\n name: string;\n localPath?: string;\n port?: number;\n readinessPath: string;\n defaultPort: number;\n integrity?: string;\n proxy?: string;\n variables?: JsonObject;\n secrets?: string[];\n ssr?: boolean;\n command?: string;\n args?: string[];\n readyPatterns?: RegExp[];\n errorPatterns?: RegExp[];\n}\n\nexport class ServiceDescriptorMap extends Context.Tag(\"ServiceDescriptorMap\")<\n ServiceDescriptorMap,\n Map<string, ServiceDescriptor>\n>() {}\n\nexport class DevRuntimeConfig extends Context.Tag(\"DevRuntimeConfig\")<\n DevRuntimeConfig,\n RuntimeConfig\n>() {}\n\nconst PLUGIN_READY_PATTERNS = [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i];\n\nconst PLUGIN_ERROR_PATTERNS = [/error/i, /failed/i];\n\nconst SERVICE_CONFIGS: Record<\n string,\n Pick<\n ServiceDescriptor,\n \"command\" | \"args\" | \"readyPatterns\" | \"errorPatterns\" | \"defaultPort\" | \"readinessPath\"\n >\n> = {\n host: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n defaultPort: 3000,\n readinessPath: \"/health\",\n },\n auth: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3002,\n readinessPath: \"/remoteEntry.js\",\n },\n ui: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bLocal:\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed to compile/i],\n defaultPort: 3003,\n readinessPath: \"/remoteEntry.js\",\n },\n \"ui-ssr\": {\n command: \"bun\",\n args: [\"run\", \"dev:ssr\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed/i],\n defaultPort: 3004,\n readinessPath: \"/\",\n },\n api: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3001,\n readinessPath: \"/remoteEntry.js\",\n },\n};\n\nexport function buildServiceDescriptorMap(\n runtimeConfig: RuntimeConfig,\n options?: { ssr?: boolean; proxy?: boolean },\n): Map<string, ServiceDescriptor> {\n const map = new Map<string, ServiceDescriptor>();\n const ssr = options?.ssr ?? false;\n\n const hostIsRemote = runtimeConfig.host.source === \"remote\";\n const hostProbeUrl = hostIsRemote\n ? (runtimeConfig.host.remoteUrl ?? runtimeConfig.host.url)\n : runtimeConfig.host.url;\n map.set(\"host\", {\n key: \"host\",\n source: runtimeConfig.host.source,\n url: hostProbeUrl,\n remoteUrl: runtimeConfig.host.remoteUrl,\n entry: hostIsRemote\n ? hostProbeUrl\n ? `${hostProbeUrl}/mf-manifest.json`\n : \"/mf-manifest.json\"\n : runtimeConfig.host.entry,\n name: runtimeConfig.host.name,\n localPath: runtimeConfig.host.localPath,\n port: runtimeConfig.host.port,\n integrity: runtimeConfig.host.integrity,\n secrets: runtimeConfig.host.secrets,\n ...SERVICE_CONFIGS.host,\n });\n\n map.set(\"ui\", {\n key: \"ui\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.url,\n remoteUrl: runtimeConfig.ui.source === \"remote\" ? runtimeConfig.ui.url : undefined,\n entry: runtimeConfig.ui.entry,\n name: runtimeConfig.ui.name,\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.port,\n integrity: runtimeConfig.ui.integrity,\n ssr,\n ...SERVICE_CONFIGS.ui,\n });\n\n if (ssr && runtimeConfig.ui.source === \"local\") {\n map.set(\"ui-ssr\", {\n key: \"ui-ssr\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.ssrUrl ?? \"\",\n entry: \"\",\n name: \"ui-ssr\",\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.ssrUrl\n ? Number.parseInt(new URL(runtimeConfig.ui.ssrUrl).port, 10)\n : (runtimeConfig.ui.port ?? 3003) + 1,\n ...SERVICE_CONFIGS[\"ui-ssr\"],\n });\n }\n\n map.set(\"api\", {\n key: \"api\",\n source: runtimeConfig.api.source,\n url: runtimeConfig.api.url,\n remoteUrl: runtimeConfig.api.source === \"remote\" ? runtimeConfig.api.url : undefined,\n entry: runtimeConfig.api.entry,\n name: runtimeConfig.api.name,\n localPath: runtimeConfig.api.localPath,\n port: runtimeConfig.api.port,\n integrity: runtimeConfig.api.integrity,\n proxy: runtimeConfig.api.proxy,\n variables: runtimeConfig.api.variables,\n secrets: runtimeConfig.api.secrets,\n ...SERVICE_CONFIGS.api,\n });\n\n if (runtimeConfig.auth) {\n map.set(\"auth\", {\n key: \"auth\",\n source: runtimeConfig.auth.source,\n url: runtimeConfig.auth.url,\n remoteUrl: runtimeConfig.auth.source === \"remote\" ? runtimeConfig.auth.url : undefined,\n entry: runtimeConfig.auth.entry,\n name: runtimeConfig.auth.name,\n localPath: runtimeConfig.auth.localPath,\n port: runtimeConfig.auth.port,\n integrity: runtimeConfig.auth.integrity,\n proxy: runtimeConfig.auth.proxy,\n variables: runtimeConfig.auth.variables,\n secrets: runtimeConfig.auth.secrets,\n ...SERVICE_CONFIGS.auth,\n });\n }\n\n if (runtimeConfig.plugins) {\n let pluginBasePort = 3010;\n for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig.plugins)) {\n const pluginKey = `plugin:${pluginId}`;\n const resolvedPort = pluginConfig.port ?? pluginBasePort;\n pluginBasePort = resolvedPort + 1;\n\n map.set(pluginKey, {\n key: pluginKey,\n source: pluginConfig.source,\n url: pluginConfig.url,\n remoteUrl: pluginConfig.source === \"remote\" ? pluginConfig.url : undefined,\n entry: pluginConfig.entry,\n name: pluginConfig.name,\n localPath: pluginConfig.localPath,\n port: resolvedPort,\n integrity: pluginConfig.integrity,\n proxy: pluginConfig.proxy,\n variables: pluginConfig.variables,\n secrets: pluginConfig.secrets,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: resolvedPort,\n readinessPath: \"/remoteEntry.js\",\n });\n\n if (pluginConfig.ui?.localPath && pluginConfig.ui.source === \"local\") {\n const uiKey = `plugin-ui:${pluginId}`;\n const uiPort = pluginConfig.ui.port ?? pluginBasePort;\n pluginBasePort = uiPort + 1;\n\n map.set(uiKey, {\n key: uiKey,\n source: pluginConfig.ui.source,\n url: pluginConfig.ui.url,\n entry: pluginConfig.ui.entry,\n name: pluginConfig.ui.name,\n localPath: pluginConfig.ui.localPath,\n port: uiPort,\n integrity: pluginConfig.ui.integrity,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: uiPort,\n readinessPath: \"/remoteEntry.js\",\n });\n }\n }\n }\n\n return map;\n}\n\nexport interface AppOrchestrator {\n packages: string[];\n description: string;\n env: Record<string, string>;\n port?: number;\n interactive?: boolean;\n noLogs?: boolean;\n}\n\nexport const ServiceDescriptorMapLive = (map: Map<string, ServiceDescriptor>) =>\n Layer.succeed(ServiceDescriptorMap, map);\n\nexport const DevRuntimeConfigLive = (config: RuntimeConfig) =>\n Layer.succeed(DevRuntimeConfig, config);\n\nexport function buildServiceDescriptorMapFromPlan(\n plan: {\n runtimeConfig: RuntimeConfig;\n resolvedPorts: { host?: number; api?: number; auth?: number; ui?: number; uiSsr?: number };\n },\n options?: { ssr?: boolean; proxy?: boolean },\n): Map<string, ServiceDescriptor> {\n return buildServiceDescriptorMap(plan.runtimeConfig, options);\n}\n\ninterface ServiceDescriptorInfo {\n key: string;\n source: string;\n proxy?: string;\n}\n\nexport function buildDescription(map: Map<string, ServiceDescriptorInfo>): string {\n const descriptors = [...map.values()].filter(\n (d) => d.key !== \"ui-ssr\" && !d.key.startsWith(\"plugin:\"),\n );\n\n const allLocal = descriptors.every((d) => d.source === \"local\");\n const hasProxy = [...map.values()].some((d) => d.proxy && d.source === \"local\");\n if (allLocal && !hasProxy) return \"Full Local Development\";\n\n const parts: string[] = [];\n for (const d of descriptors) {\n if (d.source === \"remote\") {\n const label =\n d.key === \"host\"\n ? \"Remote Host\"\n : d.key === \"ui\"\n ? \"Remote UI\"\n : d.key === \"api\"\n ? hasProxy\n ? undefined\n : \"Remote API\"\n : d.key === \"auth\"\n ? \"Remote Auth\"\n : undefined;\n if (label) parts.push(label);\n }\n }\n if (hasProxy) parts.push(\"Proxy API → Production\");\n return parts.join(\" + \") || \"Remote Mode\";\n}\n"],"mappings":"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"}
@@ -184,6 +184,9 @@ function buildServiceDescriptorMap(runtimeConfig, options) {
184
184
  }
185
185
  const ServiceDescriptorMapLive = (map) => Layer.succeed(ServiceDescriptorMap, map);
186
186
  const DevRuntimeConfigLive = (config) => Layer.succeed(DevRuntimeConfig, config);
187
+ function buildServiceDescriptorMapFromPlan(plan, options) {
188
+ return buildServiceDescriptorMap(plan.runtimeConfig, options);
189
+ }
187
190
  function buildDescription(map) {
188
191
  const descriptors = [...map.values()].filter((d) => d.key !== "ui-ssr" && !d.key.startsWith("plugin:"));
189
192
  const allLocal = descriptors.every((d) => d.source === "local");
@@ -199,5 +202,5 @@ function buildDescription(map) {
199
202
  }
200
203
 
201
204
  //#endregion
202
- export { DevRuntimeConfig, DevRuntimeConfigLive, ServiceDescriptorMap, ServiceDescriptorMapLive, buildDescription, buildServiceDescriptorMap };
205
+ export { DevRuntimeConfig, DevRuntimeConfigLive, ServiceDescriptorMap, ServiceDescriptorMapLive, buildDescription, buildServiceDescriptorMap, buildServiceDescriptorMapFromPlan };
203
206
  //# sourceMappingURL=service-descriptor.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-descriptor.mjs","names":[],"sources":["../src/service-descriptor.ts"],"sourcesContent":["import { Context, Layer } from \"effect\";\nimport type { JsonObject, RuntimeConfig, SourceMode } from \"./types\";\n\nexport interface ServiceDescriptor {\n key: string;\n source: SourceMode;\n url: string;\n remoteUrl?: string;\n entry: string;\n name: string;\n localPath?: string;\n port?: number;\n readinessPath: string;\n defaultPort: number;\n integrity?: string;\n proxy?: string;\n variables?: JsonObject;\n secrets?: string[];\n ssr?: boolean;\n command?: string;\n args?: string[];\n readyPatterns?: RegExp[];\n errorPatterns?: RegExp[];\n}\n\nexport class ServiceDescriptorMap extends Context.Tag(\"ServiceDescriptorMap\")<\n ServiceDescriptorMap,\n Map<string, ServiceDescriptor>\n>() {}\n\nexport class DevRuntimeConfig extends Context.Tag(\"DevRuntimeConfig\")<\n DevRuntimeConfig,\n RuntimeConfig\n>() {}\n\nconst PLUGIN_READY_PATTERNS = [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i];\n\nconst PLUGIN_ERROR_PATTERNS = [/error/i, /failed/i];\n\nconst SERVICE_CONFIGS: Record<\n string,\n Pick<\n ServiceDescriptor,\n \"command\" | \"args\" | \"readyPatterns\" | \"errorPatterns\" | \"defaultPort\" | \"readinessPath\"\n >\n> = {\n host: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n defaultPort: 3000,\n readinessPath: \"/health\",\n },\n auth: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3002,\n readinessPath: \"/remoteEntry.js\",\n },\n ui: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bLocal:\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed to compile/i],\n defaultPort: 3003,\n readinessPath: \"/remoteEntry.js\",\n },\n \"ui-ssr\": {\n command: \"bun\",\n args: [\"run\", \"dev:ssr\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed/i],\n defaultPort: 3004,\n readinessPath: \"/\",\n },\n api: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3001,\n readinessPath: \"/remoteEntry.js\",\n },\n};\n\nexport function buildServiceDescriptorMap(\n runtimeConfig: RuntimeConfig,\n options?: { ssr?: boolean; proxy?: boolean },\n): Map<string, ServiceDescriptor> {\n const map = new Map<string, ServiceDescriptor>();\n const ssr = options?.ssr ?? false;\n\n const hostIsRemote = runtimeConfig.host.source === \"remote\";\n const hostProbeUrl = hostIsRemote\n ? (runtimeConfig.host.remoteUrl ?? runtimeConfig.host.url)\n : runtimeConfig.host.url;\n map.set(\"host\", {\n key: \"host\",\n source: runtimeConfig.host.source,\n url: hostProbeUrl,\n remoteUrl: runtimeConfig.host.remoteUrl,\n entry: hostIsRemote\n ? hostProbeUrl\n ? `${hostProbeUrl}/mf-manifest.json`\n : \"/mf-manifest.json\"\n : runtimeConfig.host.entry,\n name: runtimeConfig.host.name,\n localPath: runtimeConfig.host.localPath,\n port: runtimeConfig.host.port,\n integrity: runtimeConfig.host.integrity,\n secrets: runtimeConfig.host.secrets,\n ...SERVICE_CONFIGS.host,\n });\n\n map.set(\"ui\", {\n key: \"ui\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.url,\n remoteUrl: runtimeConfig.ui.source === \"remote\" ? runtimeConfig.ui.url : undefined,\n entry: runtimeConfig.ui.entry,\n name: runtimeConfig.ui.name,\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.port,\n integrity: runtimeConfig.ui.integrity,\n ssr,\n ...SERVICE_CONFIGS.ui,\n });\n\n if (ssr && runtimeConfig.ui.source === \"local\") {\n map.set(\"ui-ssr\", {\n key: \"ui-ssr\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.ssrUrl ?? \"\",\n entry: \"\",\n name: \"ui-ssr\",\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.ssrUrl\n ? Number.parseInt(new URL(runtimeConfig.ui.ssrUrl).port, 10)\n : (runtimeConfig.ui.port ?? 3003) + 1,\n ...SERVICE_CONFIGS[\"ui-ssr\"],\n });\n }\n\n map.set(\"api\", {\n key: \"api\",\n source: runtimeConfig.api.source,\n url: runtimeConfig.api.url,\n remoteUrl: runtimeConfig.api.source === \"remote\" ? runtimeConfig.api.url : undefined,\n entry: runtimeConfig.api.entry,\n name: runtimeConfig.api.name,\n localPath: runtimeConfig.api.localPath,\n port: runtimeConfig.api.port,\n integrity: runtimeConfig.api.integrity,\n proxy: runtimeConfig.api.proxy,\n variables: runtimeConfig.api.variables,\n secrets: runtimeConfig.api.secrets,\n ...SERVICE_CONFIGS.api,\n });\n\n if (runtimeConfig.auth) {\n map.set(\"auth\", {\n key: \"auth\",\n source: runtimeConfig.auth.source,\n url: runtimeConfig.auth.url,\n remoteUrl: runtimeConfig.auth.source === \"remote\" ? runtimeConfig.auth.url : undefined,\n entry: runtimeConfig.auth.entry,\n name: runtimeConfig.auth.name,\n localPath: runtimeConfig.auth.localPath,\n port: runtimeConfig.auth.port,\n integrity: runtimeConfig.auth.integrity,\n proxy: runtimeConfig.auth.proxy,\n variables: runtimeConfig.auth.variables,\n secrets: runtimeConfig.auth.secrets,\n ...SERVICE_CONFIGS.auth,\n });\n }\n\n if (runtimeConfig.plugins) {\n let pluginBasePort = 3010;\n for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig.plugins)) {\n const pluginKey = `plugin:${pluginId}`;\n const resolvedPort = pluginConfig.port ?? pluginBasePort;\n pluginBasePort = resolvedPort + 1;\n\n map.set(pluginKey, {\n key: pluginKey,\n source: pluginConfig.source,\n url: pluginConfig.url,\n remoteUrl: pluginConfig.source === \"remote\" ? pluginConfig.url : undefined,\n entry: pluginConfig.entry,\n name: pluginConfig.name,\n localPath: pluginConfig.localPath,\n port: resolvedPort,\n integrity: pluginConfig.integrity,\n proxy: pluginConfig.proxy,\n variables: pluginConfig.variables,\n secrets: pluginConfig.secrets,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: resolvedPort,\n readinessPath: \"/remoteEntry.js\",\n });\n\n if (pluginConfig.ui?.localPath && pluginConfig.ui.source === \"local\") {\n const uiKey = `plugin-ui:${pluginId}`;\n const uiPort = pluginConfig.ui.port ?? pluginBasePort;\n pluginBasePort = uiPort + 1;\n\n map.set(uiKey, {\n key: uiKey,\n source: pluginConfig.ui.source,\n url: pluginConfig.ui.url,\n entry: pluginConfig.ui.entry,\n name: pluginConfig.ui.name,\n localPath: pluginConfig.ui.localPath,\n port: uiPort,\n integrity: pluginConfig.ui.integrity,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: uiPort,\n readinessPath: \"/remoteEntry.js\",\n });\n }\n }\n }\n\n return map;\n}\n\nexport interface AppOrchestrator {\n packages: string[];\n description: string;\n env: Record<string, string>;\n port?: number;\n interactive?: boolean;\n noLogs?: boolean;\n}\n\nexport const ServiceDescriptorMapLive = (map: Map<string, ServiceDescriptor>) =>\n Layer.succeed(ServiceDescriptorMap, map);\n\nexport const DevRuntimeConfigLive = (config: RuntimeConfig) =>\n Layer.succeed(DevRuntimeConfig, config);\n\nexport function buildDescription(map: Map<string, ServiceDescriptor>): string {\n const descriptors = [...map.values()].filter(\n (d) => d.key !== \"ui-ssr\" && !d.key.startsWith(\"plugin:\"),\n );\n\n const allLocal = descriptors.every((d) => d.source === \"local\");\n const hasProxy = [...map.values()].some((d) => d.proxy && d.source === \"local\");\n if (allLocal && !hasProxy) return \"Full Local Development\";\n\n const parts: string[] = [];\n for (const d of descriptors) {\n if (d.source === \"remote\") {\n const label =\n d.key === \"host\"\n ? \"Remote Host\"\n : d.key === \"ui\"\n ? \"Remote UI\"\n : d.key === \"api\"\n ? hasProxy\n ? undefined\n : \"Remote API\"\n : d.key === \"auth\"\n ? \"Remote Auth\"\n : undefined;\n if (label) parts.push(label);\n }\n }\n if (hasProxy) parts.push(\"Proxy API → Production\");\n return parts.join(\" + \") || \"Remote Mode\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service-descriptor.mjs","names":[],"sources":["../src/service-descriptor.ts"],"sourcesContent":["import { Context, Layer } from \"effect\";\nimport type { JsonObject, RuntimeConfig, SourceMode } from \"./types\";\n\nexport interface ServiceDescriptor {\n key: string;\n source: SourceMode;\n url: string;\n remoteUrl?: string;\n entry: string;\n name: string;\n localPath?: string;\n port?: number;\n readinessPath: string;\n defaultPort: number;\n integrity?: string;\n proxy?: string;\n variables?: JsonObject;\n secrets?: string[];\n ssr?: boolean;\n command?: string;\n args?: string[];\n readyPatterns?: RegExp[];\n errorPatterns?: RegExp[];\n}\n\nexport class ServiceDescriptorMap extends Context.Tag(\"ServiceDescriptorMap\")<\n ServiceDescriptorMap,\n Map<string, ServiceDescriptor>\n>() {}\n\nexport class DevRuntimeConfig extends Context.Tag(\"DevRuntimeConfig\")<\n DevRuntimeConfig,\n RuntimeConfig\n>() {}\n\nconst PLUGIN_READY_PATTERNS = [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i];\n\nconst PLUGIN_ERROR_PATTERNS = [/error/i, /failed/i];\n\nconst SERVICE_CONFIGS: Record<\n string,\n Pick<\n ServiceDescriptor,\n \"command\" | \"args\" | \"readyPatterns\" | \"errorPatterns\" | \"defaultPort\" | \"readinessPath\"\n >\n> = {\n host: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n defaultPort: 3000,\n readinessPath: \"/health\",\n },\n auth: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3002,\n readinessPath: \"/remoteEntry.js\",\n },\n ui: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bLocal:\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed to compile/i],\n defaultPort: 3003,\n readinessPath: \"/remoteEntry.js\",\n },\n \"ui-ssr\": {\n command: \"bun\",\n args: [\"run\", \"dev:ssr\"],\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed/i],\n defaultPort: 3004,\n readinessPath: \"/\",\n },\n api: {\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: 3001,\n readinessPath: \"/remoteEntry.js\",\n },\n};\n\nexport function buildServiceDescriptorMap(\n runtimeConfig: RuntimeConfig,\n options?: { ssr?: boolean; proxy?: boolean },\n): Map<string, ServiceDescriptor> {\n const map = new Map<string, ServiceDescriptor>();\n const ssr = options?.ssr ?? false;\n\n const hostIsRemote = runtimeConfig.host.source === \"remote\";\n const hostProbeUrl = hostIsRemote\n ? (runtimeConfig.host.remoteUrl ?? runtimeConfig.host.url)\n : runtimeConfig.host.url;\n map.set(\"host\", {\n key: \"host\",\n source: runtimeConfig.host.source,\n url: hostProbeUrl,\n remoteUrl: runtimeConfig.host.remoteUrl,\n entry: hostIsRemote\n ? hostProbeUrl\n ? `${hostProbeUrl}/mf-manifest.json`\n : \"/mf-manifest.json\"\n : runtimeConfig.host.entry,\n name: runtimeConfig.host.name,\n localPath: runtimeConfig.host.localPath,\n port: runtimeConfig.host.port,\n integrity: runtimeConfig.host.integrity,\n secrets: runtimeConfig.host.secrets,\n ...SERVICE_CONFIGS.host,\n });\n\n map.set(\"ui\", {\n key: \"ui\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.url,\n remoteUrl: runtimeConfig.ui.source === \"remote\" ? runtimeConfig.ui.url : undefined,\n entry: runtimeConfig.ui.entry,\n name: runtimeConfig.ui.name,\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.port,\n integrity: runtimeConfig.ui.integrity,\n ssr,\n ...SERVICE_CONFIGS.ui,\n });\n\n if (ssr && runtimeConfig.ui.source === \"local\") {\n map.set(\"ui-ssr\", {\n key: \"ui-ssr\",\n source: runtimeConfig.ui.source,\n url: runtimeConfig.ui.ssrUrl ?? \"\",\n entry: \"\",\n name: \"ui-ssr\",\n localPath: runtimeConfig.ui.localPath,\n port: runtimeConfig.ui.ssrUrl\n ? Number.parseInt(new URL(runtimeConfig.ui.ssrUrl).port, 10)\n : (runtimeConfig.ui.port ?? 3003) + 1,\n ...SERVICE_CONFIGS[\"ui-ssr\"],\n });\n }\n\n map.set(\"api\", {\n key: \"api\",\n source: runtimeConfig.api.source,\n url: runtimeConfig.api.url,\n remoteUrl: runtimeConfig.api.source === \"remote\" ? runtimeConfig.api.url : undefined,\n entry: runtimeConfig.api.entry,\n name: runtimeConfig.api.name,\n localPath: runtimeConfig.api.localPath,\n port: runtimeConfig.api.port,\n integrity: runtimeConfig.api.integrity,\n proxy: runtimeConfig.api.proxy,\n variables: runtimeConfig.api.variables,\n secrets: runtimeConfig.api.secrets,\n ...SERVICE_CONFIGS.api,\n });\n\n if (runtimeConfig.auth) {\n map.set(\"auth\", {\n key: \"auth\",\n source: runtimeConfig.auth.source,\n url: runtimeConfig.auth.url,\n remoteUrl: runtimeConfig.auth.source === \"remote\" ? runtimeConfig.auth.url : undefined,\n entry: runtimeConfig.auth.entry,\n name: runtimeConfig.auth.name,\n localPath: runtimeConfig.auth.localPath,\n port: runtimeConfig.auth.port,\n integrity: runtimeConfig.auth.integrity,\n proxy: runtimeConfig.auth.proxy,\n variables: runtimeConfig.auth.variables,\n secrets: runtimeConfig.auth.secrets,\n ...SERVICE_CONFIGS.auth,\n });\n }\n\n if (runtimeConfig.plugins) {\n let pluginBasePort = 3010;\n for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig.plugins)) {\n const pluginKey = `plugin:${pluginId}`;\n const resolvedPort = pluginConfig.port ?? pluginBasePort;\n pluginBasePort = resolvedPort + 1;\n\n map.set(pluginKey, {\n key: pluginKey,\n source: pluginConfig.source,\n url: pluginConfig.url,\n remoteUrl: pluginConfig.source === \"remote\" ? pluginConfig.url : undefined,\n entry: pluginConfig.entry,\n name: pluginConfig.name,\n localPath: pluginConfig.localPath,\n port: resolvedPort,\n integrity: pluginConfig.integrity,\n proxy: pluginConfig.proxy,\n variables: pluginConfig.variables,\n secrets: pluginConfig.secrets,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: resolvedPort,\n readinessPath: \"/remoteEntry.js\",\n });\n\n if (pluginConfig.ui?.localPath && pluginConfig.ui.source === \"local\") {\n const uiKey = `plugin-ui:${pluginId}`;\n const uiPort = pluginConfig.ui.port ?? pluginBasePort;\n pluginBasePort = uiPort + 1;\n\n map.set(uiKey, {\n key: uiKey,\n source: pluginConfig.ui.source,\n url: pluginConfig.ui.url,\n entry: pluginConfig.ui.entry,\n name: pluginConfig.ui.name,\n localPath: pluginConfig.ui.localPath,\n port: uiPort,\n integrity: pluginConfig.ui.integrity,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n readyPatterns: PLUGIN_READY_PATTERNS,\n errorPatterns: PLUGIN_ERROR_PATTERNS,\n defaultPort: uiPort,\n readinessPath: \"/remoteEntry.js\",\n });\n }\n }\n }\n\n return map;\n}\n\nexport interface AppOrchestrator {\n packages: string[];\n description: string;\n env: Record<string, string>;\n port?: number;\n interactive?: boolean;\n noLogs?: boolean;\n}\n\nexport const ServiceDescriptorMapLive = (map: Map<string, ServiceDescriptor>) =>\n Layer.succeed(ServiceDescriptorMap, map);\n\nexport const DevRuntimeConfigLive = (config: RuntimeConfig) =>\n Layer.succeed(DevRuntimeConfig, config);\n\nexport function buildServiceDescriptorMapFromPlan(\n plan: {\n runtimeConfig: RuntimeConfig;\n resolvedPorts: { host?: number; api?: number; auth?: number; ui?: number; uiSsr?: number };\n },\n options?: { ssr?: boolean; proxy?: boolean },\n): Map<string, ServiceDescriptor> {\n return buildServiceDescriptorMap(plan.runtimeConfig, options);\n}\n\ninterface ServiceDescriptorInfo {\n key: string;\n source: string;\n proxy?: string;\n}\n\nexport function buildDescription(map: Map<string, ServiceDescriptorInfo>): string {\n const descriptors = [...map.values()].filter(\n (d) => d.key !== \"ui-ssr\" && !d.key.startsWith(\"plugin:\"),\n );\n\n const allLocal = descriptors.every((d) => d.source === \"local\");\n const hasProxy = [...map.values()].some((d) => d.proxy && d.source === \"local\");\n if (allLocal && !hasProxy) return \"Full Local Development\";\n\n const parts: string[] = [];\n for (const d of descriptors) {\n if (d.source === \"remote\") {\n const label =\n d.key === \"host\"\n ? \"Remote Host\"\n : d.key === \"ui\"\n ? \"Remote UI\"\n : d.key === \"api\"\n ? hasProxy\n ? undefined\n : \"Remote API\"\n : d.key === \"auth\"\n ? \"Remote Auth\"\n : undefined;\n if (label) parts.push(label);\n }\n }\n if (hasProxy) parts.push(\"Proxy API → Production\");\n return parts.join(\" + \") || \"Remote Mode\";\n}\n"],"mappings":"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"}
package/dist/types.d.cts CHANGED
@@ -379,9 +379,9 @@ declare const BosConfigSchema: z.ZodObject<{
379
379
  type BosConfig = z.infer<typeof BosConfigSchema>;
380
380
  declare const RuntimeConfigSchema: z.ZodObject<{
381
381
  env: z.ZodEnum<{
382
- development: "development";
383
382
  production: "production";
384
383
  staging: "staging";
384
+ development: "development";
385
385
  }>;
386
386
  account: z.ZodString;
387
387
  domain: z.ZodOptional<z.ZodString>;
@@ -508,9 +508,9 @@ declare const RuntimeConfigSchema: z.ZodObject<{
508
508
  type RuntimeConfig = z.infer<typeof RuntimeConfigSchema>;
509
509
  declare const ClientRuntimeConfigSchema: z.ZodObject<{
510
510
  env: z.ZodEnum<{
511
- development: "development";
512
511
  production: "production";
513
512
  staging: "staging";
513
+ development: "development";
514
514
  }>;
515
515
  account: z.ZodString;
516
516
  networkId: z.ZodEnum<{
package/dist/types.d.mts CHANGED
@@ -379,9 +379,9 @@ declare const BosConfigSchema: z.ZodObject<{
379
379
  type BosConfig = z.infer<typeof BosConfigSchema>;
380
380
  declare const RuntimeConfigSchema: z.ZodObject<{
381
381
  env: z.ZodEnum<{
382
- development: "development";
383
382
  production: "production";
384
383
  staging: "staging";
384
+ development: "development";
385
385
  }>;
386
386
  account: z.ZodString;
387
387
  domain: z.ZodOptional<z.ZodString>;
@@ -508,9 +508,9 @@ declare const RuntimeConfigSchema: z.ZodObject<{
508
508
  type RuntimeConfig = z.infer<typeof RuntimeConfigSchema>;
509
509
  declare const ClientRuntimeConfigSchema: z.ZodObject<{
510
510
  env: z.ZodEnum<{
511
- development: "development";
512
511
  production: "production";
513
512
  staging: "staging";
513
+ development: "development";
514
514
  }>;
515
515
  account: z.ZodString;
516
516
  networkId: z.ZodEnum<{
package/dist/ui/index.cjs CHANGED
@@ -21,4 +21,5 @@ exports.getRemoteScripts = require_ui_head.getRemoteScripts;
21
21
  exports.getRuntimeConfig = require_ui_runtime.getRuntimeConfig;
22
22
  exports.getScriptKey = require_ui_router.getScriptKey;
23
23
  exports.getSocialImageMeta = require_ui_metadata.getSocialImageMeta;
24
- exports.getThemeInitScript = require_ui_head.getThemeInitScript;
24
+ exports.getThemeInitScript = require_ui_head.getThemeInitScript;
25
+ exports.serializeHeadData = require_ui_router.serializeHeadData;
@@ -2,6 +2,6 @@ import { ClientRuntimeInfo } from "../types.cjs";
2
2
  import { CreateRouterOptions, HeadData, HeadLink, HeadMeta, HeadScript, RenderOptions, RenderOptionsWithApi, RenderResult, RouterContext, RouterContextWithApi, RouterModule } from "./types.cjs";
3
3
  import { RemoteScriptsOptions, getBaseStyles, getHydrateScript, getRemoteScripts, getThemeInitScript } from "./head.cjs";
4
4
  import { DotIconSvgOptions, SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, SocialImageMetaOptions, createDotIconSvg, createPngIcoBuffer, getSocialImageMeta } from "./metadata.cjs";
5
- import { collectHeadData, getLinkKey, getMetaKey, getScriptKey } from "./router.cjs";
5
+ import { collectHeadData, getLinkKey, getMetaKey, getScriptKey, serializeHeadData } from "./router.cjs";
6
6
  import { buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, getCspNonce, getRuntimeConfig } from "./runtime.cjs";
7
- export { ClientRuntimeInfo, CreateRouterOptions, DotIconSvgOptions, HeadData, HeadLink, HeadMeta, HeadScript, RemoteScriptsOptions, RenderOptions, RenderOptionsWithApi, RenderResult, RouterContext, RouterContextWithApi, RouterModule, SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, SocialImageMetaOptions, buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, collectHeadData, createDotIconSvg, createPngIcoBuffer, getBaseStyles, getCspNonce, getHydrateScript, getLinkKey, getMetaKey, getRemoteScripts, getRuntimeConfig, getScriptKey, getSocialImageMeta, getThemeInitScript };
7
+ export { ClientRuntimeInfo, CreateRouterOptions, DotIconSvgOptions, HeadData, HeadLink, HeadMeta, HeadScript, RemoteScriptsOptions, RenderOptions, RenderOptionsWithApi, RenderResult, RouterContext, RouterContextWithApi, RouterModule, SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, SocialImageMetaOptions, buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, collectHeadData, createDotIconSvg, createPngIcoBuffer, getBaseStyles, getCspNonce, getHydrateScript, getLinkKey, getMetaKey, getRemoteScripts, getRuntimeConfig, getScriptKey, getSocialImageMeta, getThemeInitScript, serializeHeadData };
@@ -2,6 +2,6 @@ import { ClientRuntimeInfo } from "../types.mjs";
2
2
  import { CreateRouterOptions, HeadData, HeadLink, HeadMeta, HeadScript, RenderOptions, RenderOptionsWithApi, RenderResult, RouterContext, RouterContextWithApi, RouterModule } from "./types.mjs";
3
3
  import { RemoteScriptsOptions, getBaseStyles, getHydrateScript, getRemoteScripts, getThemeInitScript } from "./head.mjs";
4
4
  import { DotIconSvgOptions, SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, SocialImageMetaOptions, createDotIconSvg, createPngIcoBuffer, getSocialImageMeta } from "./metadata.mjs";
5
- import { collectHeadData, getLinkKey, getMetaKey, getScriptKey } from "./router.mjs";
5
+ import { collectHeadData, getLinkKey, getMetaKey, getScriptKey, serializeHeadData } from "./router.mjs";
6
6
  import { buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, getCspNonce, getRuntimeConfig } from "./runtime.mjs";
7
- export { ClientRuntimeInfo, CreateRouterOptions, DotIconSvgOptions, HeadData, HeadLink, HeadMeta, HeadScript, RemoteScriptsOptions, RenderOptions, RenderOptionsWithApi, RenderResult, RouterContext, RouterContextWithApi, RouterModule, SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, SocialImageMetaOptions, buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, collectHeadData, createDotIconSvg, createPngIcoBuffer, getBaseStyles, getCspNonce, getHydrateScript, getLinkKey, getMetaKey, getRemoteScripts, getRuntimeConfig, getScriptKey, getSocialImageMeta, getThemeInitScript };
7
+ export { ClientRuntimeInfo, CreateRouterOptions, DotIconSvgOptions, HeadData, HeadLink, HeadMeta, HeadScript, RemoteScriptsOptions, RenderOptions, RenderOptionsWithApi, RenderResult, RouterContext, RouterContextWithApi, RouterModule, SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, SocialImageMetaOptions, buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, collectHeadData, createDotIconSvg, createPngIcoBuffer, getBaseStyles, getCspNonce, getHydrateScript, getLinkKey, getMetaKey, getRemoteScripts, getRuntimeConfig, getScriptKey, getSocialImageMeta, getThemeInitScript, serializeHeadData };
package/dist/ui/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getBaseStyles, getHydrateScript, getRemoteScripts, getThemeInitScript } from "./head.mjs";
2
2
  import { SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, createDotIconSvg, createPngIcoBuffer, getSocialImageMeta } from "./metadata.mjs";
3
- import { collectHeadData, getLinkKey, getMetaKey, getScriptKey } from "./router.mjs";
3
+ import { collectHeadData, getLinkKey, getMetaKey, getScriptKey, serializeHeadData } from "./router.mjs";
4
4
  import { buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, getCspNonce, getRuntimeConfig } from "./runtime.mjs";
5
5
 
6
- export { SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, collectHeadData, createDotIconSvg, createPngIcoBuffer, getBaseStyles, getCspNonce, getHydrateScript, getLinkKey, getMetaKey, getRemoteScripts, getRuntimeConfig, getScriptKey, getSocialImageMeta, getThemeInitScript };
6
+ export { SOCIAL_IMAGE_HEIGHT, SOCIAL_IMAGE_WIDTH, buildPublishedAccountHref, buildPublishedGatewayHref, buildRuntimeHref, collectHeadData, createDotIconSvg, createPngIcoBuffer, getBaseStyles, getCspNonce, getHydrateScript, getLinkKey, getMetaKey, getRemoteScripts, getRuntimeConfig, getScriptKey, getSocialImageMeta, getThemeInitScript, serializeHeadData };
@@ -47,10 +47,50 @@ async function collectHeadData(router) {
47
47
  scripts: [...scriptMap.values()]
48
48
  };
49
49
  }
50
+ function escapeHtml(s) {
51
+ return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
52
+ }
53
+ function serializeMeta(meta) {
54
+ if (!meta) return "";
55
+ if ("charSet" in meta) return `<meta charset="${escapeHtml(String(meta.charSet))}">`;
56
+ if ("title" in meta) return `<title>${escapeHtml(String(meta.title))}</title>`;
57
+ return `<meta ${Object.entries(meta).filter(([, v]) => v != null).map(([k, v]) => `${k}="${escapeHtml(String(v))}"`).join(" ")}>`;
58
+ }
59
+ function serializeLink(link) {
60
+ if (!link) return "";
61
+ return `<link ${Object.entries(link).filter(([, v]) => v != null).map(([k, v]) => `${k}="${escapeHtml(String(v))}"`).join(" ")}>`;
62
+ }
63
+ function serializeScript(script, cspNonce) {
64
+ if (!script) return "";
65
+ if ("src" in script && script.src) {
66
+ const attrs = [`src="${escapeHtml(script.src)}"`];
67
+ if (script.integrity) attrs.push(`integrity="${escapeHtml(script.integrity)}"`);
68
+ if (script.crossOrigin) attrs.push(`crossorigin="${escapeHtml(script.crossOrigin)}"`);
69
+ if (script.type) attrs.push(`type="${escapeHtml(script.type)}"`);
70
+ if (cspNonce) attrs.push(`nonce="${cspNonce}"`);
71
+ return `<script ${attrs.join(" ")}><\/script>`;
72
+ }
73
+ if ("children" in script) {
74
+ const attrs = [];
75
+ if (script.type) attrs.push(`type="${escapeHtml(script.type)}"`);
76
+ if (cspNonce) attrs.push(`nonce="${cspNonce}"`);
77
+ const content = typeof script.children === "string" ? script.children : JSON.stringify(script.children);
78
+ return `<script${attrs.length ? ` ${attrs.join(" ")}` : ""}>${content}<\/script>`;
79
+ }
80
+ return "";
81
+ }
82
+ function serializeHeadData(headData, cspNonce) {
83
+ return {
84
+ metaHtml: headData.meta.filter(Boolean).map((m) => serializeMeta(m)).join("\n"),
85
+ linkHtml: headData.links.filter(Boolean).map((l) => serializeLink(l)).join("\n"),
86
+ scriptHtml: headData.scripts.filter(Boolean).map((s) => serializeScript(s, cspNonce)).join("\n")
87
+ };
88
+ }
50
89
 
51
90
  //#endregion
52
91
  exports.collectHeadData = collectHeadData;
53
92
  exports.getLinkKey = getLinkKey;
54
93
  exports.getMetaKey = getMetaKey;
55
94
  exports.getScriptKey = getScriptKey;
95
+ exports.serializeHeadData = serializeHeadData;
56
96
  //# sourceMappingURL=router.cjs.map