everything-dev 1.49.0 → 1.51.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.
- package/dist/app.cjs +66 -86
- package/dist/app.cjs.map +1 -1
- package/dist/app.mjs +66 -87
- package/dist/app.mjs.map +1 -1
- package/dist/cli/db-doctor.cjs +6 -23
- package/dist/cli/db-doctor.cjs.map +1 -1
- package/dist/cli/db-doctor.mjs +7 -24
- package/dist/cli/db-doctor.mjs.map +1 -1
- package/dist/cli/db-repair.cjs +25 -20
- package/dist/cli/db-repair.cjs.map +1 -1
- package/dist/cli/db-repair.mjs +25 -20
- package/dist/cli/db-repair.mjs.map +1 -1
- package/dist/cli/db-studio.cjs +4 -2
- package/dist/cli/db-studio.cjs.map +1 -1
- package/dist/cli/db-studio.mjs +5 -3
- package/dist/cli/db-studio.mjs.map +1 -1
- package/dist/cli/framework-version.cjs +45 -9
- package/dist/cli/framework-version.cjs.map +1 -1
- package/dist/cli/framework-version.mjs +45 -10
- package/dist/cli/framework-version.mjs.map +1 -1
- package/dist/cli/infra.cjs +89 -3
- package/dist/cli/infra.cjs.map +1 -1
- package/dist/cli/infra.mjs +83 -4
- package/dist/cli/infra.mjs.map +1 -1
- package/dist/cli/init.cjs +39 -15
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +8 -3
- package/dist/cli/init.d.cts.map +1 -1
- package/dist/cli/init.d.mts +8 -3
- package/dist/cli/init.d.mts.map +1 -1
- package/dist/cli/init.mjs +39 -16
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/parse.cjs +4 -1
- package/dist/cli/parse.cjs.map +1 -1
- package/dist/cli/parse.mjs +4 -1
- package/dist/cli/parse.mjs.map +1 -1
- package/dist/cli/status.cjs +6 -2
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.mjs +7 -3
- package/dist/cli/status.mjs.map +1 -1
- package/dist/cli/sync.cjs +9 -3
- package/dist/cli/sync.cjs.map +1 -1
- package/dist/cli/sync.mjs +9 -3
- package/dist/cli/sync.mjs.map +1 -1
- package/dist/cli/upgrade.cjs +59 -5
- package/dist/cli/upgrade.cjs.map +1 -1
- package/dist/cli/upgrade.mjs +59 -5
- package/dist/cli/upgrade.mjs.map +1 -1
- package/dist/cli.cjs +73 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +74 -10
- package/dist/cli.mjs.map +1 -1
- package/dist/config.cjs +13 -5
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +13 -5
- package/dist/config.mjs.map +1 -1
- package/dist/contract.cjs +76 -4
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +148 -3
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +148 -3
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.meta.cjs +17 -2
- package/dist/contract.meta.cjs.map +1 -1
- package/dist/contract.meta.d.cts +23 -2
- package/dist/contract.meta.d.mts +23 -2
- package/dist/contract.meta.mjs +17 -2
- package/dist/contract.meta.mjs.map +1 -1
- package/dist/contract.mjs +72 -5
- package/dist/contract.mjs.map +1 -1
- package/dist/db.cjs +32 -24
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +16 -9
- package/dist/db.d.cts.map +1 -1
- package/dist/db.d.mts +16 -9
- package/dist/db.d.mts.map +1 -1
- package/dist/db.mjs +32 -23
- package/dist/db.mjs.map +1 -1
- package/dist/dev-session.cjs +28 -0
- package/dist/dev-session.cjs.map +1 -1
- package/dist/dev-session.mjs +29 -1
- package/dist/dev-session.mjs.map +1 -1
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/infra/planner.cjs +344 -0
- package/dist/infra/planner.cjs.map +1 -0
- package/dist/infra/planner.mjs +343 -0
- package/dist/infra/planner.mjs.map +1 -0
- package/dist/infra/preflight.cjs +131 -0
- package/dist/infra/preflight.cjs.map +1 -0
- package/dist/infra/preflight.mjs +130 -0
- package/dist/infra/preflight.mjs.map +1 -0
- package/dist/infra/types.cjs +9 -0
- package/dist/infra/types.cjs.map +1 -0
- package/dist/infra/types.mjs +8 -0
- package/dist/infra/types.mjs.map +1 -0
- package/dist/near-cli.cjs +37 -0
- package/dist/near-cli.cjs.map +1 -1
- package/dist/near-cli.mjs +36 -1
- package/dist/near-cli.mjs.map +1 -1
- package/dist/orchestrator.cjs +10 -2
- package/dist/orchestrator.cjs.map +1 -1
- package/dist/orchestrator.mjs +10 -2
- package/dist/orchestrator.mjs.map +1 -1
- package/dist/plugin.cjs +161 -44
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +57 -1
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +57 -1
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +165 -48
- package/dist/plugin.mjs.map +1 -1
- package/dist/process-registry.cjs +88 -0
- package/dist/process-registry.cjs.map +1 -0
- package/dist/process-registry.mjs +83 -0
- package/dist/process-registry.mjs.map +1 -0
- package/dist/publish.cjs +4 -0
- package/dist/publish.cjs.map +1 -1
- package/dist/publish.mjs +4 -0
- package/dist/publish.mjs.map +1 -1
- package/dist/service-descriptor.cjs +4 -0
- package/dist/service-descriptor.cjs.map +1 -1
- package/dist/service-descriptor.mjs +4 -1
- package/dist/service-descriptor.mjs.map +1 -1
- package/dist/ui/index.cjs +2 -1
- package/dist/ui/index.d.cts +2 -2
- package/dist/ui/index.d.mts +2 -2
- package/dist/ui/index.mjs +2 -2
- package/dist/ui/router.cjs +40 -0
- package/dist/ui/router.cjs.map +1 -1
- package/dist/ui/router.d.cts +6 -1
- package/dist/ui/router.d.cts.map +1 -1
- package/dist/ui/router.d.mts +6 -1
- package/dist/ui/router.d.mts.map +1 -1
- package/dist/ui/router.mjs +40 -1
- package/dist/ui/router.mjs.map +1 -1
- package/package.json +5 -2
- package/skills/api-and-auth/SKILL.md +38 -16
- package/skills/cli-reference/SKILL.md +5 -4
- package/skills/dev-workflow/SKILL.md +40 -11
- package/skills/plugin-development/SKILL.md +17 -6
|
@@ -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;
|
package/dist/publish.cjs.map
CHANGED
|
@@ -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":"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"}
|
|
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;
|
package/dist/publish.mjs.map
CHANGED
|
@@ -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":";;;AAyBA,IAAa,uBAAb,cAA0C,QAAQ,IAAI,uBAAuB,EAG1E,CAAC;AAEJ,IAAa,mBAAb,cAAsC,QAAQ,IAAI,mBAAmB,EAGlE,CAAC;AAEJ,MAAM,wBAAwB;CAAC;CAAa;CAA2B;CAAc;CAAW;AAEhG,MAAM,wBAAwB,CAAC,UAAU,UAAU;AAEnD,MAAM,kBAMF;CACF,MAAM;EACJ,SAAS;EACT,MAAM,CAAC,OAAO,MAAM;EACpB,eAAe,CAAC,4CAA4C,qBAAqB;EACjF,eAAe;GAAC;GAAW;GAAW;GAAa;EACnD,aAAa;EACb,eAAe;EAChB;CACD,MAAM;EACJ,SAAS;EACT,MAAM,CAAC,OAAO,MAAM;EACpB,eAAe;EACf,eAAe;EACf,aAAa;EACb,eAAe;EAChB;CACD,IAAI;EACF,SAAS;EACT,MAAM,CAAC,OAAO,MAAM;EACpB,eAAe;GAAC;GAAyB;GAAe;GAA8B;EACtF,eAAe,CAAC,UAAU,qBAAqB;EAC/C,aAAa;EACb,eAAe;EAChB;CACD,UAAU;EACR,SAAS;EACT,MAAM,CAAC,OAAO,UAAU;EACxB,eAAe,CAAC,yBAAyB,8BAA8B;EACvE,eAAe,CAAC,UAAU,UAAU;EACpC,aAAa;EACb,eAAe;EAChB;CACD,KAAK;EACH,SAAS;EACT,MAAM,CAAC,OAAO,MAAM;EACpB,eAAe;EACf,eAAe;EACf,aAAa;EACb,eAAe;EAChB;CACF;AAED,SAAgB,0BACd,eACA,SACgC;CAChC,MAAM,sBAAM,IAAI,KAAgC;CAChD,MAAM,MAAM,SAAS,OAAO;CAE5B,MAAM,eAAe,cAAc,KAAK,WAAW;CACnD,MAAM,eAAe,eAChB,cAAc,KAAK,aAAa,cAAc,KAAK,MACpD,cAAc,KAAK;AACvB,KAAI,IAAI,QAAQ;EACd,KAAK;EACL,QAAQ,cAAc,KAAK;EAC3B,KAAK;EACL,WAAW,cAAc,KAAK;EAC9B,OAAO,eACH,eACE,GAAG,aAAa,qBAChB,sBACF,cAAc,KAAK;EACvB,MAAM,cAAc,KAAK;EACzB,WAAW,cAAc,KAAK;EAC9B,MAAM,cAAc,KAAK;EACzB,WAAW,cAAc,KAAK;EAC9B,SAAS,cAAc,KAAK;EAC5B,GAAG,gBAAgB;EACpB,CAAC;AAEF,KAAI,IAAI,MAAM;EACZ,KAAK;EACL,QAAQ,cAAc,GAAG;EACzB,KAAK,cAAc,GAAG;EACtB,WAAW,cAAc,GAAG,WAAW,WAAW,cAAc,GAAG,MAAM;EACzE,OAAO,cAAc,GAAG;EACxB,MAAM,cAAc,GAAG;EACvB,WAAW,cAAc,GAAG;EAC5B,MAAM,cAAc,GAAG;EACvB,WAAW,cAAc,GAAG;EAC5B;EACA,GAAG,gBAAgB;EACpB,CAAC;AAEF,KAAI,OAAO,cAAc,GAAG,WAAW,QACrC,KAAI,IAAI,UAAU;EAChB,KAAK;EACL,QAAQ,cAAc,GAAG;EACzB,KAAK,cAAc,GAAG,UAAU;EAChC,OAAO;EACP,MAAM;EACN,WAAW,cAAc,GAAG;EAC5B,MAAM,cAAc,GAAG,SACnB,OAAO,SAAS,IAAI,IAAI,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IACzD,cAAc,GAAG,QAAQ,QAAQ;EACtC,GAAG,gBAAgB;EACpB,CAAC;AAGJ,KAAI,IAAI,OAAO;EACb,KAAK;EACL,QAAQ,cAAc,IAAI;EAC1B,KAAK,cAAc,IAAI;EACvB,WAAW,cAAc,IAAI,WAAW,WAAW,cAAc,IAAI,MAAM;EAC3E,OAAO,cAAc,IAAI;EACzB,MAAM,cAAc,IAAI;EACxB,WAAW,cAAc,IAAI;EAC7B,MAAM,cAAc,IAAI;EACxB,WAAW,cAAc,IAAI;EAC7B,OAAO,cAAc,IAAI;EACzB,WAAW,cAAc,IAAI;EAC7B,SAAS,cAAc,IAAI;EAC3B,GAAG,gBAAgB;EACpB,CAAC;AAEF,KAAI,cAAc,KAChB,KAAI,IAAI,QAAQ;EACd,KAAK;EACL,QAAQ,cAAc,KAAK;EAC3B,KAAK,cAAc,KAAK;EACxB,WAAW,cAAc,KAAK,WAAW,WAAW,cAAc,KAAK,MAAM;EAC7E,OAAO,cAAc,KAAK;EAC1B,MAAM,cAAc,KAAK;EACzB,WAAW,cAAc,KAAK;EAC9B,MAAM,cAAc,KAAK;EACzB,WAAW,cAAc,KAAK;EAC9B,OAAO,cAAc,KAAK;EAC1B,WAAW,cAAc,KAAK;EAC9B,SAAS,cAAc,KAAK;EAC5B,GAAG,gBAAgB;EACpB,CAAC;AAGJ,KAAI,cAAc,SAAS;EACzB,IAAI,iBAAiB;AACrB,OAAK,MAAM,CAAC,UAAU,iBAAiB,OAAO,QAAQ,cAAc,QAAQ,EAAE;GAC5E,MAAM,YAAY,UAAU;GAC5B,MAAM,eAAe,aAAa,QAAQ;AAC1C,oBAAiB,eAAe;AAEhC,OAAI,IAAI,WAAW;IACjB,KAAK;IACL,QAAQ,aAAa;IACrB,KAAK,aAAa;IAClB,WAAW,aAAa,WAAW,WAAW,aAAa,MAAM;IACjE,OAAO,aAAa;IACpB,MAAM,aAAa;IACnB,WAAW,aAAa;IACxB,MAAM;IACN,WAAW,aAAa;IACxB,OAAO,aAAa;IACpB,WAAW,aAAa;IACxB,SAAS,aAAa;IACtB,SAAS;IACT,MAAM,CAAC,OAAO,MAAM;IACpB,eAAe;IACf,eAAe;IACf,aAAa;IACb,eAAe;IAChB,CAAC;AAEF,OAAI,aAAa,IAAI,aAAa,aAAa,GAAG,WAAW,SAAS;IACpE,MAAM,QAAQ,aAAa;IAC3B,MAAM,SAAS,aAAa,GAAG,QAAQ;AACvC,qBAAiB,SAAS;AAE1B,QAAI,IAAI,OAAO;KACb,KAAK;KACL,QAAQ,aAAa,GAAG;KACxB,KAAK,aAAa,GAAG;KACrB,OAAO,aAAa,GAAG;KACvB,MAAM,aAAa,GAAG;KACtB,WAAW,aAAa,GAAG;KAC3B,MAAM;KACN,WAAW,aAAa,GAAG;KAC3B,SAAS;KACT,MAAM,CAAC,OAAO,MAAM;KACpB,eAAe;KACf,eAAe;KACf,aAAa;KACb,eAAe;KAChB,CAAC;;;;AAKR,QAAO;;AAYT,MAAa,4BAA4B,QACvC,MAAM,QAAQ,sBAAsB,IAAI;AAE1C,MAAa,wBAAwB,WACnC,MAAM,QAAQ,kBAAkB,OAAO;AAEzC,SAAgB,iBAAiB,KAA6C;CAC5E,MAAM,cAAc,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC,QACnC,MAAM,EAAE,QAAQ,YAAY,CAAC,EAAE,IAAI,WAAW,UAAU,CAC1D;CAED,MAAM,WAAW,YAAY,OAAO,MAAM,EAAE,WAAW,QAAQ;CAC/D,MAAM,WAAW,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC,MAAM,MAAM,EAAE,SAAS,EAAE,WAAW,QAAQ;AAC/E,KAAI,YAAY,CAAC,SAAU,QAAO;CAElC,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,KAAK,YACd,KAAI,EAAE,WAAW,UAAU;EACzB,MAAM,QACJ,EAAE,QAAQ,SACN,gBACA,EAAE,QAAQ,OACR,cACA,EAAE,QAAQ,QACR,WACE,SACA,eACF,EAAE,QAAQ,SACR,gBACA;AACZ,MAAI,MAAO,OAAM,KAAK,MAAM;;AAGhC,KAAI,SAAU,OAAM,KAAK,yBAAyB;AAClD,QAAO,MAAM,KAAK,MAAM,IAAI"}
|
|
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/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;
|
package/dist/ui/index.d.cts
CHANGED
|
@@ -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 };
|
package/dist/ui/index.d.mts
CHANGED
|
@@ -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 };
|
package/dist/ui/router.cjs
CHANGED
|
@@ -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, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
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
|
package/dist/ui/router.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs","names":[],"sources":["../../src/ui/router.ts"],"sourcesContent":["import type { AnyRouter } from \"@tanstack/react-router\";\nimport type { HeadData, HeadLink, HeadMeta, HeadScript } from \"./types\";\n\nexport function getMetaKey(meta: HeadMeta): string {\n if (!meta) return \"null\";\n if (\"title\" in meta) return \"title\";\n if (\"charSet\" in meta) return \"charSet\";\n if (\"name\" in meta) return `name:${(meta as { name: string }).name}`;\n if (\"property\" in meta) {\n return `property:${(meta as { property: string }).property}`;\n }\n if (\"httpEquiv\" in meta) {\n return `httpEquiv:${(meta as { httpEquiv: string }).httpEquiv}`;\n }\n return JSON.stringify(meta);\n}\n\nexport function getLinkKey(link: HeadLink): string {\n const rel = (link as { rel?: string }).rel ?? \"\";\n const href = (link as { href?: string }).href ?? \"\";\n return `${rel}:${href}`;\n}\n\nexport function getScriptKey(script: HeadScript): string {\n if (!script) return \"null\";\n if (\"src\" in script && script.src) return `src:${script.src}`;\n if (\"children\" in script && script.children) {\n return `children:${typeof script.children === \"string\" ? script.children : JSON.stringify(script.children)}`;\n }\n return JSON.stringify(script);\n}\n\nexport async function collectHeadData(router: AnyRouter): Promise<HeadData> {\n await router.load();\n\n const metaMap = new Map<string, HeadMeta>();\n const linkMap = new Map<string, HeadLink>();\n const scriptMap = new Map<string, HeadScript>();\n\n for (const match of router.state.matches) {\n const route =\n (\n router as AnyRouter & {\n routesById?: Record<string, { options?: { head?: (...args: unknown[]) => unknown } }>;\n }\n ).routesById?.[(match as { routeId: string }).routeId] ??\n (match as { route?: { options?: { head?: (...args: unknown[]) => unknown } } }).route;\n const headFn = route?.options?.head;\n if (!headFn) continue;\n\n try {\n const headResult = (await headFn({\n loaderData: match.loaderData,\n matches: router.state.matches,\n match,\n params: match.params,\n })) as {\n meta?: HeadMeta[];\n links?: HeadLink[];\n scripts?: HeadScript[];\n };\n\n if (headResult?.meta) {\n for (const meta of headResult.meta) {\n metaMap.set(getMetaKey(meta), meta);\n }\n }\n if (headResult?.links) {\n for (const link of headResult.links) {\n linkMap.set(getLinkKey(link), link);\n }\n }\n if (headResult?.scripts) {\n for (const script of headResult.scripts) {\n scriptMap.set(getScriptKey(script), script);\n }\n }\n } catch (error) {\n console.warn(`[collectHeadData] head() failed for ${match.routeId}:`, error);\n }\n }\n\n return {\n meta: [...metaMap.values()],\n links: [...linkMap.values()],\n scripts: [...scriptMap.values()],\n };\n}\n"],"mappings":";;;AAGA,SAAgB,WAAW,MAAwB;AACjD,KAAI,CAAC,KAAM,QAAO;AAClB,KAAI,WAAW,KAAM,QAAO;AAC5B,KAAI,aAAa,KAAM,QAAO;AAC9B,KAAI,UAAU,KAAM,QAAO,QAAS,KAA0B;AAC9D,KAAI,cAAc,KAChB,QAAO,YAAa,KAA8B;AAEpD,KAAI,eAAe,KACjB,QAAO,aAAc,KAA+B;AAEtD,QAAO,KAAK,UAAU,KAAK;;AAG7B,SAAgB,WAAW,MAAwB;AAGjD,QAAO,GAFM,KAA0B,OAAO,GAEhC,GADA,KAA2B,QAAQ;;AAInD,SAAgB,aAAa,QAA4B;AACvD,KAAI,CAAC,OAAQ,QAAO;AACpB,KAAI,SAAS,UAAU,OAAO,IAAK,QAAO,OAAO,OAAO;AACxD,KAAI,cAAc,UAAU,OAAO,SACjC,QAAO,YAAY,OAAO,OAAO,aAAa,WAAW,OAAO,WAAW,KAAK,UAAU,OAAO,SAAS;AAE5G,QAAO,KAAK,UAAU,OAAO;;AAG/B,eAAsB,gBAAgB,QAAsC;AAC1E,OAAM,OAAO,MAAM;CAEnB,MAAM,0BAAU,IAAI,KAAuB;CAC3C,MAAM,0BAAU,IAAI,KAAuB;CAC3C,MAAM,4BAAY,IAAI,KAAyB;AAE/C,MAAK,MAAM,SAAS,OAAO,MAAM,SAAS;EAQxC,MAAM,UALF,OAGA,aAAc,MAA8B,YAC7C,MAA+E,QAC5D,SAAS;AAC/B,MAAI,CAAC,OAAQ;AAEb,MAAI;GACF,MAAM,aAAc,MAAM,OAAO;IAC/B,YAAY,MAAM;IAClB,SAAS,OAAO,MAAM;IACtB;IACA,QAAQ,MAAM;IACf,CAAC;AAMF,OAAI,YAAY,KACd,MAAK,MAAM,QAAQ,WAAW,KAC5B,SAAQ,IAAI,WAAW,KAAK,EAAE,KAAK;AAGvC,OAAI,YAAY,MACd,MAAK,MAAM,QAAQ,WAAW,MAC5B,SAAQ,IAAI,WAAW,KAAK,EAAE,KAAK;AAGvC,OAAI,YAAY,QACd,MAAK,MAAM,UAAU,WAAW,QAC9B,WAAU,IAAI,aAAa,OAAO,EAAE,OAAO;WAGxC,OAAO;AACd,WAAQ,KAAK,uCAAuC,MAAM,QAAQ,IAAI,MAAM;;;AAIhF,QAAO;EACL,MAAM,CAAC,GAAG,QAAQ,QAAQ,CAAC;EAC3B,OAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC;EAC5B,SAAS,CAAC,GAAG,UAAU,QAAQ,CAAC;EACjC"}
|
|
1
|
+
{"version":3,"file":"router.cjs","names":[],"sources":["../../src/ui/router.ts"],"sourcesContent":["import type { AnyRouter } from \"@tanstack/react-router\";\nimport type { HeadData, HeadLink, HeadMeta, HeadScript } from \"./types\";\n\nexport function getMetaKey(meta: HeadMeta): string {\n if (!meta) return \"null\";\n if (\"title\" in meta) return \"title\";\n if (\"charSet\" in meta) return \"charSet\";\n if (\"name\" in meta) return `name:${(meta as { name: string }).name}`;\n if (\"property\" in meta) {\n return `property:${(meta as { property: string }).property}`;\n }\n if (\"httpEquiv\" in meta) {\n return `httpEquiv:${(meta as { httpEquiv: string }).httpEquiv}`;\n }\n return JSON.stringify(meta);\n}\n\nexport function getLinkKey(link: HeadLink): string {\n const rel = (link as { rel?: string }).rel ?? \"\";\n const href = (link as { href?: string }).href ?? \"\";\n return `${rel}:${href}`;\n}\n\nexport function getScriptKey(script: HeadScript): string {\n if (!script) return \"null\";\n if (\"src\" in script && script.src) return `src:${script.src}`;\n if (\"children\" in script && script.children) {\n return `children:${typeof script.children === \"string\" ? script.children : JSON.stringify(script.children)}`;\n }\n return JSON.stringify(script);\n}\n\nexport async function collectHeadData(router: AnyRouter): Promise<HeadData> {\n await router.load();\n\n const metaMap = new Map<string, HeadMeta>();\n const linkMap = new Map<string, HeadLink>();\n const scriptMap = new Map<string, HeadScript>();\n\n for (const match of router.state.matches) {\n const route =\n (\n router as AnyRouter & {\n routesById?: Record<string, { options?: { head?: (...args: unknown[]) => unknown } }>;\n }\n ).routesById?.[(match as { routeId: string }).routeId] ??\n (match as { route?: { options?: { head?: (...args: unknown[]) => unknown } } }).route;\n const headFn = route?.options?.head;\n if (!headFn) continue;\n\n try {\n const headResult = (await headFn({\n loaderData: match.loaderData,\n matches: router.state.matches,\n match,\n params: match.params,\n })) as {\n meta?: HeadMeta[];\n links?: HeadLink[];\n scripts?: HeadScript[];\n };\n\n if (headResult?.meta) {\n for (const meta of headResult.meta) {\n metaMap.set(getMetaKey(meta), meta);\n }\n }\n if (headResult?.links) {\n for (const link of headResult.links) {\n linkMap.set(getLinkKey(link), link);\n }\n }\n if (headResult?.scripts) {\n for (const script of headResult.scripts) {\n scriptMap.set(getScriptKey(script), script);\n }\n }\n } catch (error) {\n console.warn(`[collectHeadData] head() failed for ${match.routeId}:`, error);\n }\n }\n\n return {\n meta: [...metaMap.values()],\n links: [...linkMap.values()],\n scripts: [...scriptMap.values()],\n };\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction serializeMeta(meta: HeadMeta): string {\n if (!meta) return \"\";\n if (\"charSet\" in meta) return `<meta charset=\"${escapeHtml(String(meta.charSet))}\">`;\n if (\"title\" in meta) return `<title>${escapeHtml(String(meta.title))}</title>`;\n const attrs = Object.entries(meta as Record<string, unknown>)\n .filter(([, v]) => v != null)\n .map(([k, v]) => `${k}=\"${escapeHtml(String(v))}\"`)\n .join(\" \");\n return `<meta ${attrs}>`;\n}\n\nfunction serializeLink(link: HeadLink): string {\n if (!link) return \"\";\n const attrs = Object.entries(link as Record<string, unknown>)\n .filter(([, v]) => v != null)\n .map(([k, v]) => `${k}=\"${escapeHtml(String(v))}\"`)\n .join(\" \");\n return `<link ${attrs}>`;\n}\n\nfunction serializeScript(script: HeadScript, cspNonce?: string): string {\n if (!script) return \"\";\n if (\"src\" in script && script.src) {\n const attrs: string[] = [`src=\"${escapeHtml(script.src)}\"`];\n if (script.integrity) attrs.push(`integrity=\"${escapeHtml(script.integrity)}\"`);\n if (script.crossOrigin) attrs.push(`crossorigin=\"${escapeHtml(script.crossOrigin)}\"`);\n if (script.type) attrs.push(`type=\"${escapeHtml(script.type)}\"`);\n if (cspNonce) attrs.push(`nonce=\"${cspNonce}\"`);\n return `<script ${attrs.join(\" \")}></script>`;\n }\n if (\"children\" in script) {\n const attrs: string[] = [];\n if (script.type) attrs.push(`type=\"${escapeHtml(script.type)}\"`);\n if (cspNonce) attrs.push(`nonce=\"${cspNonce}\"`);\n const content =\n typeof script.children === \"string\" ? script.children : JSON.stringify(script.children);\n return `<script${attrs.length ? ` ${attrs.join(\" \")}` : \"\"}>${content}</script>`;\n }\n return \"\";\n}\n\nexport function serializeHeadData(\n headData: HeadData,\n cspNonce?: string,\n): { metaHtml: string; linkHtml: string; scriptHtml: string } {\n return {\n metaHtml: headData.meta\n .filter(Boolean)\n .map((m) => serializeMeta(m))\n .join(\"\\n\"),\n linkHtml: headData.links\n .filter(Boolean)\n .map((l) => serializeLink(l))\n .join(\"\\n\"),\n scriptHtml: headData.scripts\n .filter(Boolean)\n .map((s) => serializeScript(s, cspNonce))\n .join(\"\\n\"),\n };\n}\n"],"mappings":"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"}
|
package/dist/ui/router.d.cts
CHANGED
|
@@ -6,6 +6,11 @@ declare function getMetaKey(meta: HeadMeta): string;
|
|
|
6
6
|
declare function getLinkKey(link: HeadLink): string;
|
|
7
7
|
declare function getScriptKey(script: HeadScript): string;
|
|
8
8
|
declare function collectHeadData(router: AnyRouter): Promise<HeadData>;
|
|
9
|
+
declare function serializeHeadData(headData: HeadData, cspNonce?: string): {
|
|
10
|
+
metaHtml: string;
|
|
11
|
+
linkHtml: string;
|
|
12
|
+
scriptHtml: string;
|
|
13
|
+
};
|
|
9
14
|
//#endregion
|
|
10
|
-
export { collectHeadData, getLinkKey, getMetaKey, getScriptKey };
|
|
15
|
+
export { collectHeadData, getLinkKey, getMetaKey, getScriptKey, serializeHeadData };
|
|
11
16
|
//# sourceMappingURL=router.d.cts.map
|
package/dist/ui/router.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.cts","names":[],"sources":["../../src/ui/router.ts"],"mappings":";;;;iBAGgB,UAAA,CAAW,IAAA,EAAM,QAAA;AAAA,iBAcjB,UAAA,CAAW,IAAA,EAAM,QAAA;AAAA,iBAMjB,YAAA,CAAa,MAAA,EAAQ,UAAA;AAAA,iBASf,eAAA,CAAgB,MAAA,EAAQ,SAAA,GAAY,OAAA,CAAQ,QAAA"}
|
|
1
|
+
{"version":3,"file":"router.d.cts","names":[],"sources":["../../src/ui/router.ts"],"mappings":";;;;iBAGgB,UAAA,CAAW,IAAA,EAAM,QAAA;AAAA,iBAcjB,UAAA,CAAW,IAAA,EAAM,QAAA;AAAA,iBAMjB,YAAA,CAAa,MAAA,EAAQ,UAAA;AAAA,iBASf,eAAA,CAAgB,MAAA,EAAQ,SAAA,GAAY,OAAA,CAAQ,QAAA;AAAA,iBA0GlD,iBAAA,CACd,QAAA,EAAU,QAAA,EACV,QAAA;EACG,QAAA;EAAkB,QAAA;EAAkB,UAAA;AAAA"}
|
package/dist/ui/router.d.mts
CHANGED
|
@@ -6,6 +6,11 @@ declare function getMetaKey(meta: HeadMeta): string;
|
|
|
6
6
|
declare function getLinkKey(link: HeadLink): string;
|
|
7
7
|
declare function getScriptKey(script: HeadScript): string;
|
|
8
8
|
declare function collectHeadData(router: AnyRouter): Promise<HeadData>;
|
|
9
|
+
declare function serializeHeadData(headData: HeadData, cspNonce?: string): {
|
|
10
|
+
metaHtml: string;
|
|
11
|
+
linkHtml: string;
|
|
12
|
+
scriptHtml: string;
|
|
13
|
+
};
|
|
9
14
|
//#endregion
|
|
10
|
-
export { collectHeadData, getLinkKey, getMetaKey, getScriptKey };
|
|
15
|
+
export { collectHeadData, getLinkKey, getMetaKey, getScriptKey, serializeHeadData };
|
|
11
16
|
//# sourceMappingURL=router.d.mts.map
|