everything-dev 0.3.3 → 1.3.3
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/README.md +64 -0
- package/cli.js +10 -0
- package/dist/_virtual/_rolldown/runtime.cjs +29 -0
- package/dist/api-contract.cjs +172 -0
- package/dist/api-contract.cjs.map +1 -0
- package/dist/api-contract.mjs +171 -0
- package/dist/api-contract.mjs.map +1 -0
- package/dist/api.cjs +124 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +36 -0
- package/dist/api.d.cts.map +1 -0
- package/dist/api.d.mts +36 -0
- package/dist/api.d.mts.map +1 -0
- package/dist/api.mjs +119 -0
- package/dist/api.mjs.map +1 -0
- package/dist/app.cjs +156 -0
- package/dist/app.cjs.map +1 -0
- package/dist/app.mjs +153 -0
- package/dist/app.mjs.map +1 -0
- package/dist/cli/catalog.cjs +30 -0
- package/dist/cli/catalog.cjs.map +1 -0
- package/dist/cli/catalog.mjs +29 -0
- package/dist/cli/catalog.mjs.map +1 -0
- package/dist/cli/help.cjs +16 -0
- package/dist/cli/help.cjs.map +1 -0
- package/dist/cli/help.mjs +16 -0
- package/dist/cli/help.mjs.map +1 -0
- package/dist/cli/init.cjs +287 -0
- package/dist/cli/init.cjs.map +1 -0
- package/dist/cli/init.d.cts +36 -0
- package/dist/cli/init.d.cts.map +1 -0
- package/dist/cli/init.d.mts +36 -0
- package/dist/cli/init.d.mts.map +1 -0
- package/dist/cli/init.mjs +279 -0
- package/dist/cli/init.mjs.map +1 -0
- package/dist/cli/parse.cjs +96 -0
- package/dist/cli/parse.cjs.map +1 -0
- package/dist/cli/parse.mjs +95 -0
- package/dist/cli/parse.mjs.map +1 -0
- package/dist/cli/prompts.cjs +42 -0
- package/dist/cli/prompts.cjs.map +1 -0
- package/dist/cli/prompts.mjs +41 -0
- package/dist/cli/prompts.mjs.map +1 -0
- package/dist/cli.cjs +167 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +166 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/components/dev-view.cjs +307 -0
- package/dist/components/dev-view.cjs.map +1 -0
- package/dist/components/dev-view.mjs +306 -0
- package/dist/components/dev-view.mjs.map +1 -0
- package/dist/components/streaming-view.cjs +146 -0
- package/dist/components/streaming-view.cjs.map +1 -0
- package/dist/components/streaming-view.mjs +144 -0
- package/dist/components/streaming-view.mjs.map +1 -0
- package/dist/config.cjs +280 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +35 -0
- package/dist/config.d.cts.map +1 -0
- package/dist/config.d.mts +35 -0
- package/dist/config.d.mts.map +1 -0
- package/dist/config.mjs +266 -0
- package/dist/config.mjs.map +1 -0
- package/dist/contract.cjs +209 -0
- package/dist/contract.cjs.map +1 -0
- package/dist/contract.d.cts +490 -0
- package/dist/contract.d.cts.map +1 -0
- package/dist/contract.d.mts +490 -0
- package/dist/contract.d.mts.map +1 -0
- package/dist/contract.meta.cjs +104 -0
- package/dist/contract.meta.cjs.map +1 -0
- package/dist/contract.meta.d.cts +141 -0
- package/dist/contract.meta.d.cts.map +1 -0
- package/dist/contract.meta.d.mts +141 -0
- package/dist/contract.meta.d.mts.map +1 -0
- package/dist/contract.meta.mjs +102 -0
- package/dist/contract.meta.mjs.map +1 -0
- package/dist/contract.mjs +186 -0
- package/dist/contract.mjs.map +1 -0
- package/dist/dev-logs.cjs +53 -0
- package/dist/dev-logs.cjs.map +1 -0
- package/dist/dev-logs.mjs +51 -0
- package/dist/dev-logs.mjs.map +1 -0
- package/dist/dev-session.cjs +195 -0
- package/dist/dev-session.cjs.map +1 -0
- package/dist/dev-session.mjs +194 -0
- package/dist/dev-session.mjs.map +1 -0
- package/dist/fastkv.cjs +89 -0
- package/dist/fastkv.cjs.map +1 -0
- package/dist/fastkv.d.cts +11 -0
- package/dist/fastkv.d.cts.map +1 -0
- package/dist/fastkv.d.mts +11 -0
- package/dist/fastkv.d.mts.map +1 -0
- package/dist/fastkv.mjs +82 -0
- package/dist/fastkv.mjs.map +1 -0
- package/dist/federation.server.cjs +27 -0
- package/dist/federation.server.cjs.map +1 -0
- package/dist/federation.server.mjs +27 -0
- package/dist/federation.server.mjs.map +1 -0
- package/dist/host.cjs +367 -0
- package/dist/host.cjs.map +1 -0
- package/dist/host.d.cts +22 -0
- package/dist/host.d.cts.map +1 -0
- package/dist/host.d.mts +22 -0
- package/dist/host.d.mts.map +1 -0
- package/dist/host.mjs +364 -0
- package/dist/host.mjs.map +1 -0
- package/dist/index.cjs +122 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +9 -0
- package/dist/integrity.cjs +39 -0
- package/dist/integrity.cjs.map +1 -0
- package/dist/integrity.d.cts +7 -0
- package/dist/integrity.d.cts.map +1 -0
- package/dist/integrity.d.mts +7 -0
- package/dist/integrity.d.mts.map +1 -0
- package/dist/integrity.mjs +35 -0
- package/dist/integrity.mjs.map +1 -0
- package/dist/internal/manifest-normalizer.cjs +140 -0
- package/dist/internal/manifest-normalizer.cjs.map +1 -0
- package/dist/internal/manifest-normalizer.mjs +138 -0
- package/dist/internal/manifest-normalizer.mjs.map +1 -0
- package/dist/mf.cjs +77 -0
- package/dist/mf.cjs.map +1 -0
- package/dist/mf.d.cts +19 -0
- package/dist/mf.d.cts.map +1 -0
- package/dist/mf.d.mts +19 -0
- package/dist/mf.d.mts.map +1 -0
- package/dist/mf.mjs +71 -0
- package/dist/mf.mjs.map +1 -0
- package/dist/near-cli.cjs +196 -0
- package/dist/near-cli.cjs.map +1 -0
- package/dist/near-cli.mjs +193 -0
- package/dist/near-cli.mjs.map +1 -0
- package/dist/network.cjs +9 -0
- package/dist/network.cjs.map +1 -0
- package/dist/network.mjs +8 -0
- package/dist/network.mjs.map +1 -0
- package/dist/orchestrator.cjs +441 -0
- package/dist/orchestrator.cjs.map +1 -0
- package/dist/orchestrator.d.cts +40 -0
- package/dist/orchestrator.d.cts.map +1 -0
- package/dist/orchestrator.d.mts +40 -0
- package/dist/orchestrator.d.mts.map +1 -0
- package/dist/orchestrator.mjs +436 -0
- package/dist/orchestrator.mjs.map +1 -0
- package/dist/plugin.cjs +830 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +347 -0
- package/dist/plugin.d.cts.map +1 -0
- package/dist/plugin.d.mts +348 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +827 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/process-registry.cjs +120 -0
- package/dist/process-registry.cjs.map +1 -0
- package/dist/process-registry.d.cts +25 -0
- package/dist/process-registry.d.cts.map +1 -0
- package/dist/process-registry.d.mts +25 -0
- package/dist/process-registry.d.mts.map +1 -0
- package/dist/process-registry.mjs +119 -0
- package/dist/process-registry.mjs.map +1 -0
- package/dist/sdk.cjs +61 -0
- package/dist/sdk.d.cts +5 -0
- package/dist/sdk.d.mts +5 -0
- package/dist/sdk.mjs +6 -0
- package/dist/shared.cjs +143 -0
- package/dist/shared.cjs.map +1 -0
- package/dist/shared.d.cts +33 -0
- package/dist/shared.d.cts.map +1 -0
- package/dist/shared.d.mts +33 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +140 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/types.cjs +160 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +269 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +269 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +144 -0
- package/dist/types.mjs.map +1 -0
- package/dist/ui/head.cjs +67 -0
- package/dist/ui/head.cjs.map +1 -0
- package/dist/ui/head.d.cts +19 -0
- package/dist/ui/head.d.cts.map +1 -0
- package/dist/ui/head.d.mts +19 -0
- package/dist/ui/head.d.mts.map +1 -0
- package/dist/ui/head.mjs +61 -0
- package/dist/ui/head.mjs.map +1 -0
- package/dist/ui/index.cjs +32 -0
- package/dist/ui/index.d.cts +7 -0
- package/dist/ui/index.d.mts +7 -0
- package/dist/ui/index.mjs +6 -0
- package/dist/ui/metadata.cjs +106 -0
- package/dist/ui/metadata.cjs.map +1 -0
- package/dist/ui/metadata.d.cts +35 -0
- package/dist/ui/metadata.d.cts.map +1 -0
- package/dist/ui/metadata.d.mts +35 -0
- package/dist/ui/metadata.d.mts.map +1 -0
- package/dist/ui/metadata.mjs +100 -0
- package/dist/ui/metadata.mjs.map +1 -0
- package/dist/ui/router.cjs +56 -0
- package/dist/ui/router.cjs.map +1 -0
- package/dist/ui/router.d.cts +11 -0
- package/dist/ui/router.d.cts.map +1 -0
- package/dist/ui/router.d.mts +11 -0
- package/dist/ui/router.d.mts.map +1 -0
- package/dist/ui/router.mjs +51 -0
- package/dist/ui/router.mjs.map +1 -0
- package/dist/ui/runtime.cjs +65 -0
- package/dist/ui/runtime.cjs.map +1 -0
- package/dist/ui/runtime.d.cts +29 -0
- package/dist/ui/runtime.d.cts.map +1 -0
- package/dist/ui/runtime.d.mts +29 -0
- package/dist/ui/runtime.d.mts.map +1 -0
- package/dist/ui/runtime.mjs +53 -0
- package/dist/ui/runtime.mjs.map +1 -0
- package/dist/ui/types.cjs +0 -0
- package/dist/ui/types.d.cts +52 -0
- package/dist/ui/types.d.cts.map +1 -0
- package/dist/ui/types.d.mts +52 -0
- package/dist/ui/types.d.mts.map +1 -0
- package/dist/ui/types.mjs +1 -0
- package/dist/utils/banner.cjs +24 -0
- package/dist/utils/banner.cjs.map +1 -0
- package/dist/utils/banner.mjs +23 -0
- package/dist/utils/banner.mjs.map +1 -0
- package/dist/utils/linkify.cjs +15 -0
- package/dist/utils/linkify.cjs.map +1 -0
- package/dist/utils/linkify.mjs +14 -0
- package/dist/utils/linkify.mjs.map +1 -0
- package/dist/utils/run.cjs +40 -0
- package/dist/utils/run.cjs.map +1 -0
- package/dist/utils/run.mjs +39 -0
- package/dist/utils/run.mjs.map +1 -0
- package/dist/utils/theme.cjs +44 -0
- package/dist/utils/theme.cjs.map +1 -0
- package/dist/utils/theme.mjs +37 -0
- package/dist/utils/theme.mjs.map +1 -0
- package/package.json +269 -80
- package/src/api-contract.ts +309 -0
- package/src/api.ts +181 -0
- package/src/app.ts +346 -0
- package/src/cli/catalog.ts +49 -0
- package/src/cli/help.ts +13 -0
- package/src/cli/init.ts +386 -0
- package/src/cli/parse.ts +130 -0
- package/src/cli/prompts.ts +64 -0
- package/src/cli.ts +203 -1507
- package/src/components/dev-view.tsx +307 -255
- package/src/components/streaming-view.ts +164 -128
- package/src/config.ts +462 -532
- package/src/contract.meta.ts +96 -0
- package/src/contract.ts +164 -561
- package/src/dev-logs.ts +85 -0
- package/src/dev-session.ts +318 -0
- package/src/fastkv.ts +153 -0
- package/src/federation.server.ts +43 -0
- package/src/host.ts +526 -0
- package/src/index.ts +6 -3
- package/src/integrity.ts +54 -0
- package/src/internal/manifest-normalizer.ts +251 -0
- package/src/mf.ts +105 -0
- package/src/near-cli.ts +284 -0
- package/src/network.ts +3 -0
- package/src/orchestrator.ts +648 -0
- package/src/plugin.ts +1130 -2311
- package/src/process-registry.ts +154 -0
- package/src/scripts/sync-api-contract.ts +24 -0
- package/src/sdk.ts +14 -0
- package/src/shared.ts +206 -0
- package/src/types.ts +152 -206
- package/src/ui/head.ts +34 -27
- package/src/ui/index.ts +3 -3
- package/src/ui/metadata.ts +95 -0
- package/src/ui/router.ts +22 -6
- package/src/ui/runtime.ts +55 -6
- package/src/ui/types.ts +24 -11
- package/src/utils/banner.ts +10 -6
- package/src/utils/run.ts +26 -27
- package/src/utils/theme.ts +3 -66
- package/src/components/monitor-view.tsx +0 -475
- package/src/components/status-view.tsx +0 -173
- package/src/lib/env.ts +0 -109
- package/src/lib/near-cli.ts +0 -289
- package/src/lib/nova.ts +0 -266
- package/src/lib/orchestrator.ts +0 -276
- package/src/lib/process-registry.ts +0 -166
- package/src/lib/process.ts +0 -550
- package/src/lib/resource-monitor/assertions.ts +0 -234
- package/src/lib/resource-monitor/command.ts +0 -283
- package/src/lib/resource-monitor/diff.ts +0 -157
- package/src/lib/resource-monitor/errors.ts +0 -127
- package/src/lib/resource-monitor/index.ts +0 -305
- package/src/lib/resource-monitor/platform/darwin.ts +0 -306
- package/src/lib/resource-monitor/platform/index.ts +0 -35
- package/src/lib/resource-monitor/platform/linux.ts +0 -332
- package/src/lib/resource-monitor/platform/windows.ts +0 -298
- package/src/lib/resource-monitor/snapshot.ts +0 -217
- package/src/lib/resource-monitor/types.ts +0 -74
- package/src/lib/session-recorder/errors.ts +0 -102
- package/src/lib/session-recorder/flows/login.ts +0 -210
- package/src/lib/session-recorder/index.ts +0 -361
- package/src/lib/session-recorder/playwright.ts +0 -257
- package/src/lib/session-recorder/report.ts +0 -353
- package/src/lib/session-recorder/server.ts +0 -268
- package/src/lib/session-recorder/types.ts +0 -115
- package/src/lib/sync.ts +0 -1
- package/src/ui/files.ts +0 -134
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
|
|
5
|
+
//#region src/dev-logs.ts
|
|
6
|
+
function getBosDir(configDir) {
|
|
7
|
+
return join(configDir, ".bos");
|
|
8
|
+
}
|
|
9
|
+
function getLogsDir(configDir) {
|
|
10
|
+
return join(getBosDir(configDir), "logs");
|
|
11
|
+
}
|
|
12
|
+
function formatLogLine(entry) {
|
|
13
|
+
const ts = new Date(entry.timestamp).toISOString();
|
|
14
|
+
const prefix = entry.isError ? "ERR" : "OUT";
|
|
15
|
+
return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;
|
|
16
|
+
}
|
|
17
|
+
async function createDevLogger(configDir, description) {
|
|
18
|
+
const dir = getLogsDir(configDir);
|
|
19
|
+
if (!existsSync(dir)) await mkdir(dir, { recursive: true });
|
|
20
|
+
const now = /* @__PURE__ */ new Date();
|
|
21
|
+
const logFile = join(dir, `dev-${now.toISOString().replace(/[:.]/g, "-").slice(0, 19)}.log`);
|
|
22
|
+
const latestFile = join(dir, "dev-latest.log");
|
|
23
|
+
const header = `# everything-dev dev session: ${description}\n# Started: ${now.toISOString()}\n\n`;
|
|
24
|
+
await writeFile(logFile, header, "utf8");
|
|
25
|
+
await writeFile(latestFile, header, "utf8");
|
|
26
|
+
let chain = Promise.resolve();
|
|
27
|
+
const enqueue = (fn) => {
|
|
28
|
+
chain = chain.then(fn, fn);
|
|
29
|
+
return chain;
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
logFile,
|
|
33
|
+
latestFile,
|
|
34
|
+
write: (entry) => enqueue(async () => {
|
|
35
|
+
const line = `${formatLogLine(entry)}\n`;
|
|
36
|
+
await appendFile(logFile, line);
|
|
37
|
+
await appendFile(latestFile, line);
|
|
38
|
+
}),
|
|
39
|
+
readLatest: async (opts) => {
|
|
40
|
+
const text = await readFile(latestFile, "utf8").catch(() => "");
|
|
41
|
+
const tail = opts?.tail;
|
|
42
|
+
if (!tail || tail <= 0) return text;
|
|
43
|
+
const lines = text.split("\n");
|
|
44
|
+
return lines.slice(Math.max(0, lines.length - tail)).join("\n");
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { createDevLogger, getBosDir };
|
|
51
|
+
//# sourceMappingURL=dev-logs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-logs.mjs","names":[],"sources":["../src/dev-logs.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { appendFile, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface LogEntry {\n timestamp: number;\n source: string;\n line: string;\n isError?: boolean;\n}\n\nexport interface DevLogger {\n logFile: string;\n latestFile: string;\n write: (entry: LogEntry) => Promise<void>;\n readLatest: (opts?: { tail?: number }) => Promise<string>;\n}\n\nexport function getBosDir(configDir: string): string {\n return join(configDir, \".bos\");\n}\n\nexport function getLogsDir(configDir: string): string {\n return join(getBosDir(configDir), \"logs\");\n}\n\nfunction formatLogLine(entry: LogEntry): string {\n const ts = new Date(entry.timestamp).toISOString();\n const prefix = entry.isError ? \"ERR\" : \"OUT\";\n return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport async function createDevLogger(configDir: string, description: string): Promise<DevLogger> {\n const dir = getLogsDir(configDir);\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n\n const now = new Date();\n const ts = now.toISOString().replace(/[:.]/g, \"-\").slice(0, 19);\n const logFile = join(dir, `dev-${ts}.log`);\n const latestFile = join(dir, \"dev-latest.log\");\n\n const header =\n `# everything-dev dev session: ${description}\\n` + `# Started: ${now.toISOString()}\\n\\n`;\n // Overwrite each run so dev-latest.log is always actionable.\n await writeFile(logFile, header, \"utf8\");\n await writeFile(latestFile, header, \"utf8\");\n\n let chain = Promise.resolve();\n const enqueue = (fn: () => Promise<void>) => {\n chain = chain.then(fn, fn);\n return chain;\n };\n\n return {\n logFile,\n latestFile,\n write: (entry) =>\n enqueue(async () => {\n const line = `${formatLogLine(entry)}\\n`;\n await appendFile(logFile, line);\n await appendFile(latestFile, line);\n }),\n readLatest: async (opts) => {\n const text = await readFile(latestFile, \"utf8\").catch(() => \"\");\n const tail = opts?.tail;\n if (!tail || tail <= 0) return text;\n const lines = text.split(\"\\n\");\n return lines.slice(Math.max(0, lines.length - tail)).join(\"\\n\");\n },\n };\n}\n\nexport async function readDevLatestLog(\n configDir: string,\n opts?: { tail?: number },\n): Promise<string> {\n const latestFile = join(getLogsDir(configDir), \"dev-latest.log\");\n const text = await readFile(latestFile, \"utf8\").catch(() => \"\");\n const tail = opts?.tail;\n if (!tail || tail <= 0) return text;\n const lines = text.split(\"\\n\");\n return lines.slice(Math.max(0, lines.length - tail)).join(\"\\n\");\n}\n"],"mappings":";;;;;AAkBA,SAAgB,UAAU,WAA2B;AACnD,QAAO,KAAK,WAAW,OAAO;;AAGhC,SAAgB,WAAW,WAA2B;AACpD,QAAO,KAAK,UAAU,UAAU,EAAE,OAAO;;AAG3C,SAAS,cAAc,OAAyB;CAC9C,MAAM,KAAK,IAAI,KAAK,MAAM,UAAU,CAAC,aAAa;CAClD,MAAM,SAAS,MAAM,UAAU,QAAQ;AACvC,QAAO,IAAI,GAAG,KAAK,MAAM,OAAO,KAAK,OAAO,IAAI,MAAM;;AAGxD,eAAsB,gBAAgB,WAAmB,aAAyC;CAChG,MAAM,MAAM,WAAW,UAAU;AACjC,KAAI,CAAC,WAAW,IAAI,CAClB,OAAM,MAAM,KAAK,EAAE,WAAW,MAAM,CAAC;CAGvC,MAAM,sBAAM,IAAI,MAAM;CAEtB,MAAM,UAAU,KAAK,KAAK,OADf,IAAI,aAAa,CAAC,QAAQ,SAAS,IAAI,CAAC,MAAM,GAAG,GAAG,CAC3B,MAAM;CAC1C,MAAM,aAAa,KAAK,KAAK,iBAAiB;CAE9C,MAAM,SACJ,iCAAiC,YAAY,eAAoB,IAAI,aAAa,CAAC;AAErF,OAAM,UAAU,SAAS,QAAQ,OAAO;AACxC,OAAM,UAAU,YAAY,QAAQ,OAAO;CAE3C,IAAI,QAAQ,QAAQ,SAAS;CAC7B,MAAM,WAAW,OAA4B;AAC3C,UAAQ,MAAM,KAAK,IAAI,GAAG;AAC1B,SAAO;;AAGT,QAAO;EACL;EACA;EACA,QAAQ,UACN,QAAQ,YAAY;GAClB,MAAM,OAAO,GAAG,cAAc,MAAM,CAAC;AACrC,SAAM,WAAW,SAAS,KAAK;AAC/B,SAAM,WAAW,YAAY,KAAK;IAClC;EACJ,YAAY,OAAO,SAAS;GAC1B,MAAM,OAAO,MAAM,SAAS,YAAY,OAAO,CAAC,YAAY,GAAG;GAC/D,MAAM,OAAO,MAAM;AACnB,OAAI,CAAC,QAAQ,QAAQ,EAAG,QAAO;GAC/B,MAAM,QAAQ,KAAK,MAAM,KAAK;AAC9B,UAAO,MAAM,MAAM,KAAK,IAAI,GAAG,MAAM,SAAS,KAAK,CAAC,CAAC,KAAK,KAAK;;EAElE"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_config = require('./config.cjs');
|
|
3
|
+
const require_orchestrator = require('./orchestrator.cjs');
|
|
4
|
+
const require_dev_view = require('./components/dev-view.cjs');
|
|
5
|
+
const require_streaming_view = require('./components/streaming-view.cjs');
|
|
6
|
+
const require_dev_logs = require('./dev-logs.cjs');
|
|
7
|
+
const require_process_registry = require('./process-registry.cjs');
|
|
8
|
+
let effect = require("effect");
|
|
9
|
+
|
|
10
|
+
//#region src/dev-session.ts
|
|
11
|
+
const LOG_NOISE_PATTERNS = [
|
|
12
|
+
/\[ Federation Runtime \] Version .* from (host|ui) of shared singleton module/,
|
|
13
|
+
/Executing an Effect versioned \d+\.\d+\.\d+ with a Runtime of version/,
|
|
14
|
+
/you may want to dedupe the effect dependencies/
|
|
15
|
+
];
|
|
16
|
+
const SSR_LOG_ALLOWLIST = [
|
|
17
|
+
/\bready\s+built in\b/i,
|
|
18
|
+
/\bcompiled\b.*successfully/i,
|
|
19
|
+
/\berror\b/i,
|
|
20
|
+
/\bfailed\b/i,
|
|
21
|
+
/\bexception\b/i
|
|
22
|
+
];
|
|
23
|
+
const shouldDisplayLog = (source, line, isError) => {
|
|
24
|
+
if (process.env.DEBUG === "true" || process.env.DEBUG === "1") return true;
|
|
25
|
+
if (source === "ui-ssr") {
|
|
26
|
+
if (isError) return true;
|
|
27
|
+
return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));
|
|
28
|
+
}
|
|
29
|
+
return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));
|
|
30
|
+
};
|
|
31
|
+
const isInteractiveSupported = () => {
|
|
32
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
33
|
+
};
|
|
34
|
+
const STARTUP_ORDER = [
|
|
35
|
+
"ui-ssr",
|
|
36
|
+
"ui",
|
|
37
|
+
"api",
|
|
38
|
+
"plugin",
|
|
39
|
+
"host-build",
|
|
40
|
+
"host"
|
|
41
|
+
];
|
|
42
|
+
const sortByOrder = (packages) => {
|
|
43
|
+
return [...packages].sort((a, b) => {
|
|
44
|
+
const aIdx = a.startsWith("plugin:") ? STARTUP_ORDER.indexOf("plugin") : STARTUP_ORDER.indexOf(a);
|
|
45
|
+
const bIdx = b.startsWith("plugin:") ? STARTUP_ORDER.indexOf("plugin") : STARTUP_ORDER.indexOf(b);
|
|
46
|
+
if (aIdx === -1 && bIdx === -1) return 0;
|
|
47
|
+
if (aIdx === -1) return 1;
|
|
48
|
+
if (bIdx === -1) return -1;
|
|
49
|
+
return aIdx - bIdx;
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
function formatLogLine(entry) {
|
|
53
|
+
const ts = new Date(entry.timestamp).toISOString();
|
|
54
|
+
const prefix = entry.isError ? "ERR" : "OUT";
|
|
55
|
+
return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;
|
|
56
|
+
}
|
|
57
|
+
const runDevSession = (orchestrator, onCleanupReady) => effect.Effect.gen(function* () {
|
|
58
|
+
const configDir = require_config.getProjectRoot();
|
|
59
|
+
const orderedPackages = sortByOrder(orchestrator.packages);
|
|
60
|
+
const initialProcesses = orderedPackages.map((pkg) => {
|
|
61
|
+
const config = require_orchestrator.getProcessConfig(pkg, void 0, pkg === "host" ? orchestrator.port : void 0, orchestrator.bosConfig, orchestrator.runtimeConfig);
|
|
62
|
+
const source = pkg === "host" ? orchestrator.appConfig.host : pkg === "ui" ? orchestrator.appConfig.ui : pkg === "api" ? orchestrator.appConfig.api : void 0;
|
|
63
|
+
return {
|
|
64
|
+
name: pkg,
|
|
65
|
+
status: "pending",
|
|
66
|
+
port: config?.port ?? 0,
|
|
67
|
+
source
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
const registry = yield* require_process_registry.makeProcessRegistry(configDir);
|
|
71
|
+
yield* registry.killAll().pipe(effect.Effect.ignore);
|
|
72
|
+
const logger = yield* effect.Effect.promise(() => require_dev_logs.createDevLogger(configDir, orchestrator.description));
|
|
73
|
+
const handles = [];
|
|
74
|
+
const allLogs = [];
|
|
75
|
+
let view = null;
|
|
76
|
+
let shuttingDown = false;
|
|
77
|
+
const killAll = async () => {
|
|
78
|
+
const reversed = [...handles].reverse();
|
|
79
|
+
for (const handle of reversed) try {
|
|
80
|
+
await handle.kill();
|
|
81
|
+
} catch {}
|
|
82
|
+
await effect.Effect.runPromise(registry.killAll(true)).catch(() => {});
|
|
83
|
+
};
|
|
84
|
+
const exportLogs = async () => {
|
|
85
|
+
console.log("\n");
|
|
86
|
+
console.log("═".repeat(70));
|
|
87
|
+
console.log(` SESSION LOGS: ${orchestrator.description}`);
|
|
88
|
+
console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);
|
|
89
|
+
console.log(` Total entries: ${allLogs.length}`);
|
|
90
|
+
console.log("═".repeat(70));
|
|
91
|
+
console.log("");
|
|
92
|
+
for (const entry of allLogs) console.log(formatLogLine(entry));
|
|
93
|
+
console.log("");
|
|
94
|
+
console.log("═".repeat(70));
|
|
95
|
+
console.log(` Full logs saved to: ${logger.logFile}`);
|
|
96
|
+
console.log("═".repeat(70));
|
|
97
|
+
console.log("");
|
|
98
|
+
};
|
|
99
|
+
const cleanup = async (showLogs = false) => {
|
|
100
|
+
if (shuttingDown) return;
|
|
101
|
+
shuttingDown = true;
|
|
102
|
+
view?.unmount();
|
|
103
|
+
await killAll();
|
|
104
|
+
if (showLogs) await exportLogs();
|
|
105
|
+
};
|
|
106
|
+
onCleanupReady?.(cleanup);
|
|
107
|
+
view = orchestrator.interactive ?? isInteractiveSupported() ? require_dev_view.renderDevView(initialProcesses, orchestrator.description, orchestrator.env, () => cleanup(false), () => cleanup(true)) : require_streaming_view.renderStreamingView(initialProcesses, orchestrator.description, orchestrator.env, () => cleanup(false));
|
|
108
|
+
const callbacks = {
|
|
109
|
+
onStatus: (name, status, message) => {
|
|
110
|
+
view?.updateProcess(name, status, message);
|
|
111
|
+
},
|
|
112
|
+
onLog: (name, line, isError) => {
|
|
113
|
+
const entry = {
|
|
114
|
+
id: `${Date.now()}-${allLogs.length + 1}`,
|
|
115
|
+
source: name,
|
|
116
|
+
line,
|
|
117
|
+
timestamp: Date.now(),
|
|
118
|
+
isError
|
|
119
|
+
};
|
|
120
|
+
allLogs.push(entry);
|
|
121
|
+
if (shouldDisplayLog(name, line, isError)) view?.addLog(name, line, isError);
|
|
122
|
+
if (!orchestrator.noLogs) logger.write(entry);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const startProcess = (pkg) => {
|
|
126
|
+
const portOverride = pkg === "host" ? orchestrator.port : void 0;
|
|
127
|
+
return require_orchestrator.makeDevProcess(pkg, orchestrator.env, callbacks, portOverride, orchestrator.bosConfig, orchestrator.runtimeConfig, registry);
|
|
128
|
+
};
|
|
129
|
+
const startGroup = (packages) => effect.Effect.forEach(packages, startProcess, { concurrency: "unbounded" });
|
|
130
|
+
const awaitReady = (pkg, handle) => effect.Effect.race(handle.waitForReady, effect.Effect.sleep("30 seconds").pipe(effect.Effect.andThen(effect.Effect.sync(() => {
|
|
131
|
+
callbacks.onLog(pkg, "Timeout waiting for ready, continuing...", true);
|
|
132
|
+
}))));
|
|
133
|
+
const nonHostPackages = orderedPackages.filter((pkg) => pkg !== "host");
|
|
134
|
+
const hostPackages = orderedPackages.filter((pkg) => pkg === "host");
|
|
135
|
+
const nonHostHandles = yield* startGroup(nonHostPackages);
|
|
136
|
+
handles.push(...nonHostHandles);
|
|
137
|
+
yield* effect.Effect.forEach(nonHostHandles.map((handle, index) => ({
|
|
138
|
+
handle,
|
|
139
|
+
pkg: nonHostPackages[index] ?? handle.name
|
|
140
|
+
})), ({ handle, pkg }) => awaitReady(pkg, handle), { concurrency: "unbounded" });
|
|
141
|
+
const hostHandles = yield* startGroup(hostPackages);
|
|
142
|
+
handles.push(...hostHandles);
|
|
143
|
+
yield* effect.Effect.forEach(hostHandles.map((handle, index) => ({
|
|
144
|
+
handle,
|
|
145
|
+
pkg: hostPackages[index] ?? handle.name
|
|
146
|
+
})), ({ handle, pkg }) => awaitReady(pkg, handle), { concurrency: "unbounded" });
|
|
147
|
+
yield* effect.Effect.addFinalizer(() => effect.Effect.promise(() => cleanup(false)));
|
|
148
|
+
yield* effect.Effect.never;
|
|
149
|
+
});
|
|
150
|
+
const startApp = (orchestrator) => {
|
|
151
|
+
let activeCleanup = null;
|
|
152
|
+
const program = effect.Effect.scoped(runDevSession(orchestrator, (cleanup) => {
|
|
153
|
+
activeCleanup = cleanup;
|
|
154
|
+
})).pipe(effect.Effect.catchAll((e) => effect.Effect.sync(() => {
|
|
155
|
+
if (e instanceof Error) {
|
|
156
|
+
console.error("App server error:", e.message);
|
|
157
|
+
if (e.stack) console.error(e.stack);
|
|
158
|
+
} else console.error("App server error:", e);
|
|
159
|
+
})));
|
|
160
|
+
const handleSignal = async () => {
|
|
161
|
+
if (activeCleanup) await activeCleanup();
|
|
162
|
+
};
|
|
163
|
+
const forceExit = () => {
|
|
164
|
+
console.log("\n[Dev] Force exit");
|
|
165
|
+
process.exit(0);
|
|
166
|
+
};
|
|
167
|
+
let signalCount = 0;
|
|
168
|
+
process.on("SIGINT", () => {
|
|
169
|
+
signalCount++;
|
|
170
|
+
if (signalCount > 1) {
|
|
171
|
+
forceExit();
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const timeout = setTimeout(forceExit, 5e3);
|
|
175
|
+
handleSignal().finally(() => {
|
|
176
|
+
clearTimeout(timeout);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
process.on("SIGTERM", () => {
|
|
180
|
+
signalCount++;
|
|
181
|
+
if (signalCount > 1) {
|
|
182
|
+
forceExit();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const timeout = setTimeout(forceExit, 5e3);
|
|
186
|
+
handleSignal().finally(() => {
|
|
187
|
+
clearTimeout(timeout);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
effect.Effect.runPromise(program);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
//#endregion
|
|
194
|
+
exports.startApp = startApp;
|
|
195
|
+
//# sourceMappingURL=dev-session.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-session.cjs","names":["Effect","getProjectRoot","getProcessConfig","makeProcessRegistry","createDevLogger","renderDevView","renderStreamingView","makeDevProcess"],"sources":["../src/dev-session.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport {\n type DevViewHandle,\n type LogEntry,\n type ProcessState,\n renderDevView,\n} from \"./components/dev-view\";\nimport { renderStreamingView } from \"./components/streaming-view\";\nimport { getProjectRoot } from \"./config\";\nimport { createDevLogger } from \"./dev-logs\";\nimport {\n getProcessConfig,\n makeDevProcess,\n type ProcessCallbacks,\n type ProcessHandle,\n} from \"./orchestrator\";\nimport { makeProcessRegistry } from \"./process-registry\";\nimport type { BosConfig, RuntimeConfig, SourceMode } from \"./types\";\n\nexport interface AppConfig {\n host: SourceMode;\n ui: SourceMode;\n api: SourceMode;\n proxy?: boolean;\n ssr?: boolean;\n}\n\nexport interface AppOrchestrator {\n packages: string[];\n env: Record<string, string>;\n description: string;\n appConfig: AppConfig;\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig;\n port?: number;\n interactive?: boolean;\n noLogs?: boolean;\n}\n\nconst LOG_NOISE_PATTERNS = [\n /\\[ Federation Runtime \\] Version .* from (host|ui) of shared singleton module/,\n /Executing an Effect versioned \\d+\\.\\d+\\.\\d+ with a Runtime of version/,\n /you may want to dedupe the effect dependencies/,\n];\n\nconst SSR_LOG_ALLOWLIST = [\n /\\bready\\s+built in\\b/i,\n /\\bcompiled\\b.*successfully/i,\n /\\berror\\b/i,\n /\\bfailed\\b/i,\n /\\bexception\\b/i,\n];\n\nconst shouldDisplayLog = (source: string, line: string, isError?: boolean): boolean => {\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") return true;\n if (source === \"ui-ssr\") {\n if (isError) return true;\n return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));\n }\n return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));\n};\n\nconst isInteractiveSupported = (): boolean => {\n return process.stdin.isTTY === true && process.stdout.isTTY === true;\n};\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"api\", \"plugin\", \"host-build\", \"host\"];\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\nfunction formatLogLine(entry: LogEntry): string {\n const ts = new Date(entry.timestamp).toISOString();\n const prefix = entry.isError ? \"ERR\" : \"OUT\";\n return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport const runDevSession = (\n orchestrator: AppOrchestrator,\n onCleanupReady?: (cleanup: () => Promise<void>) => void,\n) =>\n Effect.gen(function* () {\n const configDir = getProjectRoot();\n const orderedPackages = sortByOrder(orchestrator.packages);\n const initialProcesses: ProcessState[] = orderedPackages.map((pkg) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n const config = getProcessConfig(\n pkg,\n undefined,\n portOverride,\n orchestrator.bosConfig,\n orchestrator.runtimeConfig,\n );\n const source =\n pkg === \"host\"\n ? orchestrator.appConfig.host\n : pkg === \"ui\"\n ? orchestrator.appConfig.ui\n : pkg === \"api\"\n ? orchestrator.appConfig.api\n : undefined;\n return {\n name: pkg,\n status: \"pending\" as const,\n port: config?.port ?? 0,\n source,\n };\n });\n\n const registry = yield* makeProcessRegistry(configDir);\n yield* registry.killAll().pipe(Effect.ignore);\n\n const logger = yield* Effect.promise(() =>\n createDevLogger(configDir, orchestrator.description),\n );\n const handles: ProcessHandle[] = [];\n const allLogs: LogEntry[] = [];\n let view: DevViewHandle | null = null;\n let shuttingDown = false;\n\n const killAll = async () => {\n const reversed = [...handles].reverse();\n for (const handle of reversed) {\n try {\n await handle.kill();\n } catch {}\n }\n await Effect.runPromise(registry.killAll(true)).catch(() => {});\n };\n\n const exportLogs = async () => {\n console.log(\"\\n\");\n console.log(\"═\".repeat(70));\n console.log(` SESSION LOGS: ${orchestrator.description}`);\n console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);\n console.log(` Total entries: ${allLogs.length}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n for (const entry of allLogs) {\n console.log(formatLogLine(entry));\n }\n console.log(\"\");\n console.log(\"═\".repeat(70));\n console.log(` Full logs saved to: ${logger.logFile}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n };\n\n const cleanup = async (showLogs = false) => {\n if (shuttingDown) return;\n shuttingDown = true;\n view?.unmount();\n await killAll();\n if (showLogs) {\n await exportLogs();\n }\n };\n\n onCleanupReady?.(cleanup);\n\n const useInteractive = orchestrator.interactive ?? isInteractiveSupported();\n view = useInteractive\n ? renderDevView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => cleanup(false),\n () => cleanup(true),\n )\n : renderStreamingView(initialProcesses, orchestrator.description, orchestrator.env, () =>\n cleanup(false),\n );\n\n const callbacks: ProcessCallbacks = {\n onStatus: (name, status, message) => {\n view?.updateProcess(name, status, message);\n },\n onLog: (name, line, isError) => {\n const entry: LogEntry = {\n id: `${Date.now()}-${allLogs.length + 1}`,\n source: name,\n line,\n timestamp: Date.now(),\n isError,\n };\n allLogs.push(entry);\n if (shouldDisplayLog(name, line, isError)) {\n view?.addLog(name, line, isError);\n }\n if (!orchestrator.noLogs) {\n void logger.write(entry);\n }\n },\n };\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(\n pkg,\n orchestrator.env,\n callbacks,\n portOverride,\n orchestrator.bosConfig,\n orchestrator.runtimeConfig,\n registry,\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (pkg: string, handle: ProcessHandle) =>\n Effect.race(\n handle.waitForReady,\n Effect.sleep(\"30 seconds\").pipe(\n Effect.andThen(\n Effect.sync(() => {\n callbacks.onLog(pkg, \"Timeout waiting for ready, continuing...\", true);\n }),\n ),\n ),\n );\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n handles.push(...nonHostHandles);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n handles.push(...hostHandles);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n yield* Effect.addFinalizer(() => Effect.promise(() => cleanup(false)));\n yield* Effect.never;\n });\n\nexport const startApp = (orchestrator: AppOrchestrator) => {\n let activeCleanup: (() => Promise<void>) | null = null;\n\n const program = Effect.scoped(\n runDevSession(orchestrator, (cleanup) => {\n activeCleanup = cleanup;\n }),\n ).pipe(\n Effect.catchAll((e) =>\n Effect.sync(() => {\n if (e instanceof Error) {\n console.error(\"App server error:\", e.message);\n if (e.stack) console.error(e.stack);\n } else {\n console.error(\"App server error:\", e);\n }\n }),\n ),\n );\n\n const handleSignal = async () => {\n if (activeCleanup) await activeCleanup();\n };\n\n const forceExit = () => {\n console.log(\"\\n[Dev] Force exit\");\n process.exit(0);\n };\n\n let signalCount = 0;\n process.on(\"SIGINT\", () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n const timeout = setTimeout(forceExit, 5000);\n void handleSignal().finally(() => {\n clearTimeout(timeout);\n });\n });\n process.on(\"SIGTERM\", () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n const timeout = setTimeout(forceExit, 5000);\n void handleSignal().finally(() => {\n clearTimeout(timeout);\n });\n });\n\n void Effect.runPromise(program);\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { getProjectRoot } from "./config.mjs";
|
|
2
|
+
import { getProcessConfig, makeDevProcess } from "./orchestrator.mjs";
|
|
3
|
+
import { renderDevView } from "./components/dev-view.mjs";
|
|
4
|
+
import { renderStreamingView } from "./components/streaming-view.mjs";
|
|
5
|
+
import { createDevLogger } from "./dev-logs.mjs";
|
|
6
|
+
import { makeProcessRegistry } from "./process-registry.mjs";
|
|
7
|
+
import { Effect } from "effect";
|
|
8
|
+
|
|
9
|
+
//#region src/dev-session.ts
|
|
10
|
+
const LOG_NOISE_PATTERNS = [
|
|
11
|
+
/\[ Federation Runtime \] Version .* from (host|ui) of shared singleton module/,
|
|
12
|
+
/Executing an Effect versioned \d+\.\d+\.\d+ with a Runtime of version/,
|
|
13
|
+
/you may want to dedupe the effect dependencies/
|
|
14
|
+
];
|
|
15
|
+
const SSR_LOG_ALLOWLIST = [
|
|
16
|
+
/\bready\s+built in\b/i,
|
|
17
|
+
/\bcompiled\b.*successfully/i,
|
|
18
|
+
/\berror\b/i,
|
|
19
|
+
/\bfailed\b/i,
|
|
20
|
+
/\bexception\b/i
|
|
21
|
+
];
|
|
22
|
+
const shouldDisplayLog = (source, line, isError) => {
|
|
23
|
+
if (process.env.DEBUG === "true" || process.env.DEBUG === "1") return true;
|
|
24
|
+
if (source === "ui-ssr") {
|
|
25
|
+
if (isError) return true;
|
|
26
|
+
return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));
|
|
27
|
+
}
|
|
28
|
+
return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));
|
|
29
|
+
};
|
|
30
|
+
const isInteractiveSupported = () => {
|
|
31
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
32
|
+
};
|
|
33
|
+
const STARTUP_ORDER = [
|
|
34
|
+
"ui-ssr",
|
|
35
|
+
"ui",
|
|
36
|
+
"api",
|
|
37
|
+
"plugin",
|
|
38
|
+
"host-build",
|
|
39
|
+
"host"
|
|
40
|
+
];
|
|
41
|
+
const sortByOrder = (packages) => {
|
|
42
|
+
return [...packages].sort((a, b) => {
|
|
43
|
+
const aIdx = a.startsWith("plugin:") ? STARTUP_ORDER.indexOf("plugin") : STARTUP_ORDER.indexOf(a);
|
|
44
|
+
const bIdx = b.startsWith("plugin:") ? STARTUP_ORDER.indexOf("plugin") : STARTUP_ORDER.indexOf(b);
|
|
45
|
+
if (aIdx === -1 && bIdx === -1) return 0;
|
|
46
|
+
if (aIdx === -1) return 1;
|
|
47
|
+
if (bIdx === -1) return -1;
|
|
48
|
+
return aIdx - bIdx;
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
function formatLogLine(entry) {
|
|
52
|
+
const ts = new Date(entry.timestamp).toISOString();
|
|
53
|
+
const prefix = entry.isError ? "ERR" : "OUT";
|
|
54
|
+
return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;
|
|
55
|
+
}
|
|
56
|
+
const runDevSession = (orchestrator, onCleanupReady) => Effect.gen(function* () {
|
|
57
|
+
const configDir = getProjectRoot();
|
|
58
|
+
const orderedPackages = sortByOrder(orchestrator.packages);
|
|
59
|
+
const initialProcesses = orderedPackages.map((pkg) => {
|
|
60
|
+
const config = getProcessConfig(pkg, void 0, pkg === "host" ? orchestrator.port : void 0, orchestrator.bosConfig, orchestrator.runtimeConfig);
|
|
61
|
+
const source = pkg === "host" ? orchestrator.appConfig.host : pkg === "ui" ? orchestrator.appConfig.ui : pkg === "api" ? orchestrator.appConfig.api : void 0;
|
|
62
|
+
return {
|
|
63
|
+
name: pkg,
|
|
64
|
+
status: "pending",
|
|
65
|
+
port: config?.port ?? 0,
|
|
66
|
+
source
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
const registry = yield* makeProcessRegistry(configDir);
|
|
70
|
+
yield* registry.killAll().pipe(Effect.ignore);
|
|
71
|
+
const logger = yield* Effect.promise(() => createDevLogger(configDir, orchestrator.description));
|
|
72
|
+
const handles = [];
|
|
73
|
+
const allLogs = [];
|
|
74
|
+
let view = null;
|
|
75
|
+
let shuttingDown = false;
|
|
76
|
+
const killAll = async () => {
|
|
77
|
+
const reversed = [...handles].reverse();
|
|
78
|
+
for (const handle of reversed) try {
|
|
79
|
+
await handle.kill();
|
|
80
|
+
} catch {}
|
|
81
|
+
await Effect.runPromise(registry.killAll(true)).catch(() => {});
|
|
82
|
+
};
|
|
83
|
+
const exportLogs = async () => {
|
|
84
|
+
console.log("\n");
|
|
85
|
+
console.log("═".repeat(70));
|
|
86
|
+
console.log(` SESSION LOGS: ${orchestrator.description}`);
|
|
87
|
+
console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);
|
|
88
|
+
console.log(` Total entries: ${allLogs.length}`);
|
|
89
|
+
console.log("═".repeat(70));
|
|
90
|
+
console.log("");
|
|
91
|
+
for (const entry of allLogs) console.log(formatLogLine(entry));
|
|
92
|
+
console.log("");
|
|
93
|
+
console.log("═".repeat(70));
|
|
94
|
+
console.log(` Full logs saved to: ${logger.logFile}`);
|
|
95
|
+
console.log("═".repeat(70));
|
|
96
|
+
console.log("");
|
|
97
|
+
};
|
|
98
|
+
const cleanup = async (showLogs = false) => {
|
|
99
|
+
if (shuttingDown) return;
|
|
100
|
+
shuttingDown = true;
|
|
101
|
+
view?.unmount();
|
|
102
|
+
await killAll();
|
|
103
|
+
if (showLogs) await exportLogs();
|
|
104
|
+
};
|
|
105
|
+
onCleanupReady?.(cleanup);
|
|
106
|
+
view = orchestrator.interactive ?? isInteractiveSupported() ? renderDevView(initialProcesses, orchestrator.description, orchestrator.env, () => cleanup(false), () => cleanup(true)) : renderStreamingView(initialProcesses, orchestrator.description, orchestrator.env, () => cleanup(false));
|
|
107
|
+
const callbacks = {
|
|
108
|
+
onStatus: (name, status, message) => {
|
|
109
|
+
view?.updateProcess(name, status, message);
|
|
110
|
+
},
|
|
111
|
+
onLog: (name, line, isError) => {
|
|
112
|
+
const entry = {
|
|
113
|
+
id: `${Date.now()}-${allLogs.length + 1}`,
|
|
114
|
+
source: name,
|
|
115
|
+
line,
|
|
116
|
+
timestamp: Date.now(),
|
|
117
|
+
isError
|
|
118
|
+
};
|
|
119
|
+
allLogs.push(entry);
|
|
120
|
+
if (shouldDisplayLog(name, line, isError)) view?.addLog(name, line, isError);
|
|
121
|
+
if (!orchestrator.noLogs) logger.write(entry);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const startProcess = (pkg) => {
|
|
125
|
+
const portOverride = pkg === "host" ? orchestrator.port : void 0;
|
|
126
|
+
return makeDevProcess(pkg, orchestrator.env, callbacks, portOverride, orchestrator.bosConfig, orchestrator.runtimeConfig, registry);
|
|
127
|
+
};
|
|
128
|
+
const startGroup = (packages) => Effect.forEach(packages, startProcess, { concurrency: "unbounded" });
|
|
129
|
+
const awaitReady = (pkg, handle) => Effect.race(handle.waitForReady, Effect.sleep("30 seconds").pipe(Effect.andThen(Effect.sync(() => {
|
|
130
|
+
callbacks.onLog(pkg, "Timeout waiting for ready, continuing...", true);
|
|
131
|
+
}))));
|
|
132
|
+
const nonHostPackages = orderedPackages.filter((pkg) => pkg !== "host");
|
|
133
|
+
const hostPackages = orderedPackages.filter((pkg) => pkg === "host");
|
|
134
|
+
const nonHostHandles = yield* startGroup(nonHostPackages);
|
|
135
|
+
handles.push(...nonHostHandles);
|
|
136
|
+
yield* Effect.forEach(nonHostHandles.map((handle, index) => ({
|
|
137
|
+
handle,
|
|
138
|
+
pkg: nonHostPackages[index] ?? handle.name
|
|
139
|
+
})), ({ handle, pkg }) => awaitReady(pkg, handle), { concurrency: "unbounded" });
|
|
140
|
+
const hostHandles = yield* startGroup(hostPackages);
|
|
141
|
+
handles.push(...hostHandles);
|
|
142
|
+
yield* Effect.forEach(hostHandles.map((handle, index) => ({
|
|
143
|
+
handle,
|
|
144
|
+
pkg: hostPackages[index] ?? handle.name
|
|
145
|
+
})), ({ handle, pkg }) => awaitReady(pkg, handle), { concurrency: "unbounded" });
|
|
146
|
+
yield* Effect.addFinalizer(() => Effect.promise(() => cleanup(false)));
|
|
147
|
+
yield* Effect.never;
|
|
148
|
+
});
|
|
149
|
+
const startApp = (orchestrator) => {
|
|
150
|
+
let activeCleanup = null;
|
|
151
|
+
const program = Effect.scoped(runDevSession(orchestrator, (cleanup) => {
|
|
152
|
+
activeCleanup = cleanup;
|
|
153
|
+
})).pipe(Effect.catchAll((e) => Effect.sync(() => {
|
|
154
|
+
if (e instanceof Error) {
|
|
155
|
+
console.error("App server error:", e.message);
|
|
156
|
+
if (e.stack) console.error(e.stack);
|
|
157
|
+
} else console.error("App server error:", e);
|
|
158
|
+
})));
|
|
159
|
+
const handleSignal = async () => {
|
|
160
|
+
if (activeCleanup) await activeCleanup();
|
|
161
|
+
};
|
|
162
|
+
const forceExit = () => {
|
|
163
|
+
console.log("\n[Dev] Force exit");
|
|
164
|
+
process.exit(0);
|
|
165
|
+
};
|
|
166
|
+
let signalCount = 0;
|
|
167
|
+
process.on("SIGINT", () => {
|
|
168
|
+
signalCount++;
|
|
169
|
+
if (signalCount > 1) {
|
|
170
|
+
forceExit();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const timeout = setTimeout(forceExit, 5e3);
|
|
174
|
+
handleSignal().finally(() => {
|
|
175
|
+
clearTimeout(timeout);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
process.on("SIGTERM", () => {
|
|
179
|
+
signalCount++;
|
|
180
|
+
if (signalCount > 1) {
|
|
181
|
+
forceExit();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const timeout = setTimeout(forceExit, 5e3);
|
|
185
|
+
handleSignal().finally(() => {
|
|
186
|
+
clearTimeout(timeout);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
Effect.runPromise(program);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
//#endregion
|
|
193
|
+
export { startApp };
|
|
194
|
+
//# sourceMappingURL=dev-session.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-session.mjs","names":[],"sources":["../src/dev-session.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport {\n type DevViewHandle,\n type LogEntry,\n type ProcessState,\n renderDevView,\n} from \"./components/dev-view\";\nimport { renderStreamingView } from \"./components/streaming-view\";\nimport { getProjectRoot } from \"./config\";\nimport { createDevLogger } from \"./dev-logs\";\nimport {\n getProcessConfig,\n makeDevProcess,\n type ProcessCallbacks,\n type ProcessHandle,\n} from \"./orchestrator\";\nimport { makeProcessRegistry } from \"./process-registry\";\nimport type { BosConfig, RuntimeConfig, SourceMode } from \"./types\";\n\nexport interface AppConfig {\n host: SourceMode;\n ui: SourceMode;\n api: SourceMode;\n proxy?: boolean;\n ssr?: boolean;\n}\n\nexport interface AppOrchestrator {\n packages: string[];\n env: Record<string, string>;\n description: string;\n appConfig: AppConfig;\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig;\n port?: number;\n interactive?: boolean;\n noLogs?: boolean;\n}\n\nconst LOG_NOISE_PATTERNS = [\n /\\[ Federation Runtime \\] Version .* from (host|ui) of shared singleton module/,\n /Executing an Effect versioned \\d+\\.\\d+\\.\\d+ with a Runtime of version/,\n /you may want to dedupe the effect dependencies/,\n];\n\nconst SSR_LOG_ALLOWLIST = [\n /\\bready\\s+built in\\b/i,\n /\\bcompiled\\b.*successfully/i,\n /\\berror\\b/i,\n /\\bfailed\\b/i,\n /\\bexception\\b/i,\n];\n\nconst shouldDisplayLog = (source: string, line: string, isError?: boolean): boolean => {\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") return true;\n if (source === \"ui-ssr\") {\n if (isError) return true;\n return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));\n }\n return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));\n};\n\nconst isInteractiveSupported = (): boolean => {\n return process.stdin.isTTY === true && process.stdout.isTTY === true;\n};\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"api\", \"plugin\", \"host-build\", \"host\"];\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\nfunction formatLogLine(entry: LogEntry): string {\n const ts = new Date(entry.timestamp).toISOString();\n const prefix = entry.isError ? \"ERR\" : \"OUT\";\n return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport const runDevSession = (\n orchestrator: AppOrchestrator,\n onCleanupReady?: (cleanup: () => Promise<void>) => void,\n) =>\n Effect.gen(function* () {\n const configDir = getProjectRoot();\n const orderedPackages = sortByOrder(orchestrator.packages);\n const initialProcesses: ProcessState[] = orderedPackages.map((pkg) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n const config = getProcessConfig(\n pkg,\n undefined,\n portOverride,\n orchestrator.bosConfig,\n orchestrator.runtimeConfig,\n );\n const source =\n pkg === \"host\"\n ? orchestrator.appConfig.host\n : pkg === \"ui\"\n ? orchestrator.appConfig.ui\n : pkg === \"api\"\n ? orchestrator.appConfig.api\n : undefined;\n return {\n name: pkg,\n status: \"pending\" as const,\n port: config?.port ?? 0,\n source,\n };\n });\n\n const registry = yield* makeProcessRegistry(configDir);\n yield* registry.killAll().pipe(Effect.ignore);\n\n const logger = yield* Effect.promise(() =>\n createDevLogger(configDir, orchestrator.description),\n );\n const handles: ProcessHandle[] = [];\n const allLogs: LogEntry[] = [];\n let view: DevViewHandle | null = null;\n let shuttingDown = false;\n\n const killAll = async () => {\n const reversed = [...handles].reverse();\n for (const handle of reversed) {\n try {\n await handle.kill();\n } catch {}\n }\n await Effect.runPromise(registry.killAll(true)).catch(() => {});\n };\n\n const exportLogs = async () => {\n console.log(\"\\n\");\n console.log(\"═\".repeat(70));\n console.log(` SESSION LOGS: ${orchestrator.description}`);\n console.log(` Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);\n console.log(` Total entries: ${allLogs.length}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n for (const entry of allLogs) {\n console.log(formatLogLine(entry));\n }\n console.log(\"\");\n console.log(\"═\".repeat(70));\n console.log(` Full logs saved to: ${logger.logFile}`);\n console.log(\"═\".repeat(70));\n console.log(\"\");\n };\n\n const cleanup = async (showLogs = false) => {\n if (shuttingDown) return;\n shuttingDown = true;\n view?.unmount();\n await killAll();\n if (showLogs) {\n await exportLogs();\n }\n };\n\n onCleanupReady?.(cleanup);\n\n const useInteractive = orchestrator.interactive ?? isInteractiveSupported();\n view = useInteractive\n ? renderDevView(\n initialProcesses,\n orchestrator.description,\n orchestrator.env,\n () => cleanup(false),\n () => cleanup(true),\n )\n : renderStreamingView(initialProcesses, orchestrator.description, orchestrator.env, () =>\n cleanup(false),\n );\n\n const callbacks: ProcessCallbacks = {\n onStatus: (name, status, message) => {\n view?.updateProcess(name, status, message);\n },\n onLog: (name, line, isError) => {\n const entry: LogEntry = {\n id: `${Date.now()}-${allLogs.length + 1}`,\n source: name,\n line,\n timestamp: Date.now(),\n isError,\n };\n allLogs.push(entry);\n if (shouldDisplayLog(name, line, isError)) {\n view?.addLog(name, line, isError);\n }\n if (!orchestrator.noLogs) {\n void logger.write(entry);\n }\n },\n };\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(\n pkg,\n orchestrator.env,\n callbacks,\n portOverride,\n orchestrator.bosConfig,\n orchestrator.runtimeConfig,\n registry,\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (pkg: string, handle: ProcessHandle) =>\n Effect.race(\n handle.waitForReady,\n Effect.sleep(\"30 seconds\").pipe(\n Effect.andThen(\n Effect.sync(() => {\n callbacks.onLog(pkg, \"Timeout waiting for ready, continuing...\", true);\n }),\n ),\n ),\n );\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n handles.push(...nonHostHandles);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n handles.push(...hostHandles);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n yield* Effect.addFinalizer(() => Effect.promise(() => cleanup(false)));\n yield* Effect.never;\n });\n\nexport const startApp = (orchestrator: AppOrchestrator) => {\n let activeCleanup: (() => Promise<void>) | null = null;\n\n const program = Effect.scoped(\n runDevSession(orchestrator, (cleanup) => {\n activeCleanup = cleanup;\n }),\n ).pipe(\n Effect.catchAll((e) =>\n Effect.sync(() => {\n if (e instanceof Error) {\n console.error(\"App server error:\", e.message);\n if (e.stack) console.error(e.stack);\n } else {\n console.error(\"App server error:\", e);\n }\n }),\n ),\n );\n\n const handleSignal = async () => {\n if (activeCleanup) await activeCleanup();\n };\n\n const forceExit = () => {\n console.log(\"\\n[Dev] Force exit\");\n process.exit(0);\n };\n\n let signalCount = 0;\n process.on(\"SIGINT\", () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n const timeout = setTimeout(forceExit, 5000);\n void handleSignal().finally(() => {\n clearTimeout(timeout);\n });\n });\n process.on(\"SIGTERM\", () => {\n signalCount++;\n if (signalCount > 1) {\n forceExit();\n return;\n }\n const timeout = setTimeout(forceExit, 5000);\n void handleSignal().finally(() => {\n clearTimeout(timeout);\n });\n });\n\n void Effect.runPromise(program);\n};\n"],"mappings":"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"}
|
package/dist/fastkv.cjs
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/fastkv.ts
|
|
4
|
+
const FASTKV_TIMEOUT_MS = 1e4;
|
|
5
|
+
function getNetworkIdForAccount(accountId) {
|
|
6
|
+
return accountId.endsWith(".testnet") ? "testnet" : "mainnet";
|
|
7
|
+
}
|
|
8
|
+
function getFastKvBaseUrlForNetwork(network) {
|
|
9
|
+
return network === "testnet" ? process.env.REGISTRY_FASTKV_TESTNET_URL || "https://kv.test.fastnear.com" : process.env.REGISTRY_FASTKV_MAINNET_URL || "https://kv.main.fastnear.com";
|
|
10
|
+
}
|
|
11
|
+
function getFastKvBaseUrlForAccount(accountId) {
|
|
12
|
+
return getNetworkIdForAccount(accountId) === "testnet" ? getFastKvBaseUrlForNetwork("testnet") : getFastKvBaseUrlForNetwork("mainnet");
|
|
13
|
+
}
|
|
14
|
+
function buildRegistryConfigUrl(accountId, gatewayId) {
|
|
15
|
+
const baseUrl = getFastKvBaseUrlForAccount(accountId);
|
|
16
|
+
const namespace = getRegistryNamespaceForAccount(accountId);
|
|
17
|
+
const key = encodeURIComponent(getRegistryConfigKey(accountId, gatewayId));
|
|
18
|
+
return `${baseUrl}/v0/latest/${encodeURIComponent(namespace)}/${encodeURIComponent(accountId)}/${key}`;
|
|
19
|
+
}
|
|
20
|
+
function buildRegistryConfigUrlForNetwork(network, accountId, gatewayId) {
|
|
21
|
+
const baseUrl = getFastKvBaseUrlForNetwork(network);
|
|
22
|
+
const namespace = getRegistryNamespaceForNetwork(network);
|
|
23
|
+
const key = encodeURIComponent(getRegistryConfigKey(accountId, gatewayId));
|
|
24
|
+
return `${baseUrl}/v0/latest/${encodeURIComponent(namespace)}/${encodeURIComponent(accountId)}/${key}`;
|
|
25
|
+
}
|
|
26
|
+
function getRegistryNamespaceForAccount(accountId) {
|
|
27
|
+
return accountId.endsWith(".testnet") ? process.env.REGISTRY_FASTKV_TESTNET_NAMESPACE || "dev.everything.near" : process.env.REGISTRY_FASTKV_MAINNET_NAMESPACE || accountId;
|
|
28
|
+
}
|
|
29
|
+
function getRegistryNamespaceForNetwork(network) {
|
|
30
|
+
return network === "testnet" ? process.env.REGISTRY_FASTKV_TESTNET_NAMESPACE || "dev.everything.near" : process.env.REGISTRY_FASTKV_MAINNET_NAMESPACE || "dev.everything.near";
|
|
31
|
+
}
|
|
32
|
+
function getRegistryConfigKey(accountId, gatewayId, pathSegments = []) {
|
|
33
|
+
return `apps/${accountId}/${gatewayId}${pathSegments.length > 0 ? `/${pathSegments.map((segment) => encodeURIComponent(segment)).join("/")}` : ""}/bos.config.json`;
|
|
34
|
+
}
|
|
35
|
+
function parseBosUrl(bosUrl) {
|
|
36
|
+
const match = bosUrl.match(/^bos:\/\/([^/]+)\/(.+)$/);
|
|
37
|
+
if (!match?.[1] || !match[2]) throw new Error(`Invalid BOS URL: ${bosUrl}`);
|
|
38
|
+
const pathSegments = match[2].split("/").filter(Boolean).map((segment) => decodeURIComponent(segment));
|
|
39
|
+
if (pathSegments.length === 0) throw new Error(`Invalid BOS URL: ${bosUrl}`);
|
|
40
|
+
const [gatewayId, ...pathSegmentsTail] = pathSegments;
|
|
41
|
+
if (!gatewayId) throw new Error(`Invalid BOS URL: ${bosUrl}`);
|
|
42
|
+
return {
|
|
43
|
+
accountId: match[1],
|
|
44
|
+
gatewayId,
|
|
45
|
+
pathSegments: pathSegmentsTail
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function fetchBosConfigFromFastKv(bosUrl) {
|
|
49
|
+
const { accountId, gatewayId, pathSegments } = parseBosUrl(bosUrl);
|
|
50
|
+
const value = (await fetchJson(`${getFastKvBaseUrlForAccount(accountId)}/v0/latest/${encodeURIComponent(getRegistryNamespaceForAccount(accountId))}/${encodeURIComponent(accountId)}`, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
body: JSON.stringify({
|
|
53
|
+
key: getRegistryConfigKey(accountId, gatewayId, pathSegments),
|
|
54
|
+
limit: 1
|
|
55
|
+
})
|
|
56
|
+
}))?.entries?.find(Boolean)?.value;
|
|
57
|
+
if (!value) throw new Error(`No config found for ${bosUrl}`);
|
|
58
|
+
if (typeof value === "string") return JSON.parse(value);
|
|
59
|
+
if (typeof value !== "object") throw new Error(`Invalid config value for ${bosUrl}`);
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
async function fetchJson(url, init) {
|
|
63
|
+
const controller = new AbortController();
|
|
64
|
+
const timeout = setTimeout(() => controller.abort(), FASTKV_TIMEOUT_MS);
|
|
65
|
+
try {
|
|
66
|
+
const response = await fetch(url, {
|
|
67
|
+
...init,
|
|
68
|
+
headers: {
|
|
69
|
+
accept: "application/json",
|
|
70
|
+
"content-type": "application/json",
|
|
71
|
+
...init?.headers ?? {}
|
|
72
|
+
},
|
|
73
|
+
signal: controller.signal
|
|
74
|
+
});
|
|
75
|
+
if (!response.ok) return null;
|
|
76
|
+
return await response.json();
|
|
77
|
+
} finally {
|
|
78
|
+
clearTimeout(timeout);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
exports.buildRegistryConfigUrl = buildRegistryConfigUrl;
|
|
84
|
+
exports.buildRegistryConfigUrlForNetwork = buildRegistryConfigUrlForNetwork;
|
|
85
|
+
exports.fetchBosConfigFromFastKv = fetchBosConfigFromFastKv;
|
|
86
|
+
exports.getFastKvBaseUrlForNetwork = getFastKvBaseUrlForNetwork;
|
|
87
|
+
exports.getRegistryNamespaceForAccount = getRegistryNamespaceForAccount;
|
|
88
|
+
exports.getRegistryNamespaceForNetwork = getRegistryNamespaceForNetwork;
|
|
89
|
+
//# sourceMappingURL=fastkv.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastkv.cjs","names":[],"sources":["../src/fastkv.ts"],"sourcesContent":["export type NetworkId = \"mainnet\" | \"testnet\";\n\ninterface FastKvEntry {\n value: unknown;\n}\n\ninterface FastKvListResponse {\n entries?: Array<FastKvEntry | null>;\n}\n\nconst FASTKV_TIMEOUT_MS = 10_000;\n\nfunction getNetworkIdForAccount(accountId: string): NetworkId {\n return accountId.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\";\n}\n\nexport function getFastKvBaseUrlForNetwork(network: NetworkId): string {\n return network === \"testnet\"\n ? process.env.REGISTRY_FASTKV_TESTNET_URL || \"https://kv.test.fastnear.com\"\n : process.env.REGISTRY_FASTKV_MAINNET_URL || \"https://kv.main.fastnear.com\";\n}\n\nfunction getFastKvBaseUrlForAccount(accountId: string): string {\n return getNetworkIdForAccount(accountId) === \"testnet\"\n ? getFastKvBaseUrlForNetwork(\"testnet\")\n : getFastKvBaseUrlForNetwork(\"mainnet\");\n}\n\nexport function buildRegistryConfigUrl(accountId: string, gatewayId: string): string {\n const baseUrl = getFastKvBaseUrlForAccount(accountId);\n const namespace = getRegistryNamespaceForAccount(accountId);\n const key = encodeURIComponent(getRegistryConfigKey(accountId, gatewayId));\n return `${baseUrl}/v0/latest/${encodeURIComponent(namespace)}/${encodeURIComponent(accountId)}/${key}`;\n}\n\nexport function buildRegistryConfigUrlForNetwork(\n network: NetworkId,\n accountId: string,\n gatewayId: string,\n): string {\n const baseUrl = getFastKvBaseUrlForNetwork(network);\n const namespace = getRegistryNamespaceForNetwork(network);\n const key = encodeURIComponent(getRegistryConfigKey(accountId, gatewayId));\n return `${baseUrl}/v0/latest/${encodeURIComponent(namespace)}/${encodeURIComponent(accountId)}/${key}`;\n}\n\nexport function getRegistryNamespaceForAccount(accountId: string): string {\n return accountId.endsWith(\".testnet\")\n ? process.env.REGISTRY_FASTKV_TESTNET_NAMESPACE || \"dev.everything.near\"\n : process.env.REGISTRY_FASTKV_MAINNET_NAMESPACE || accountId;\n}\n\nexport function getRegistryNamespaceForNetwork(network: NetworkId): string {\n return network === \"testnet\"\n ? process.env.REGISTRY_FASTKV_TESTNET_NAMESPACE || \"dev.everything.near\"\n : process.env.REGISTRY_FASTKV_MAINNET_NAMESPACE || \"dev.everything.near\";\n}\n\nfunction getRegistryConfigKey(\n accountId: string,\n gatewayId: string,\n pathSegments: string[] = [],\n): string {\n const suffix =\n pathSegments.length > 0\n ? `/${pathSegments.map((segment) => encodeURIComponent(segment)).join(\"/\")}`\n : \"\";\n return `apps/${accountId}/${gatewayId}${suffix}/bos.config.json`;\n}\n\nfunction parseBosUrl(bosUrl: string): {\n accountId: string;\n gatewayId: string;\n pathSegments: string[];\n} {\n const match = bosUrl.match(/^bos:\\/\\/([^/]+)\\/(.+)$/);\n if (!match?.[1] || !match[2]) {\n throw new Error(`Invalid BOS URL: ${bosUrl}`);\n }\n\n const pathSegments = match[2]\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => decodeURIComponent(segment));\n if (pathSegments.length === 0) {\n throw new Error(`Invalid BOS URL: ${bosUrl}`);\n }\n\n const [gatewayId, ...pathSegmentsTail] = pathSegments;\n if (!gatewayId) {\n throw new Error(`Invalid BOS URL: ${bosUrl}`);\n }\n\n return {\n accountId: match[1],\n gatewayId,\n pathSegments: pathSegmentsTail,\n };\n}\n\nexport async function fetchBosConfigFromFastKv<T>(bosUrl: string): Promise<T> {\n const { accountId, gatewayId, pathSegments } = parseBosUrl(bosUrl);\n const payload = await fetchJson<FastKvListResponse>(\n `${getFastKvBaseUrlForAccount(accountId)}/v0/latest/${encodeURIComponent(getRegistryNamespaceForAccount(accountId))}/${encodeURIComponent(accountId)}`,\n {\n method: \"POST\",\n body: JSON.stringify({\n key: getRegistryConfigKey(accountId, gatewayId, pathSegments),\n limit: 1,\n }),\n },\n );\n const value = payload?.entries?.find(Boolean)?.value;\n\n if (!value) {\n throw new Error(`No config found for ${bosUrl}`);\n }\n\n if (typeof value === \"string\") {\n return JSON.parse(value) as T;\n }\n\n if (typeof value !== \"object\") {\n throw new Error(`Invalid config value for ${bosUrl}`);\n }\n\n return value as T;\n}\n\nasync function fetchJson<T>(url: string, init?: RequestInit): Promise<T | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), FASTKV_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n ...init,\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n ...(init?.headers ?? {}),\n },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as T;\n } finally {\n clearTimeout(timeout);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/fastkv.d.ts
|
|
2
|
+
type NetworkId = "mainnet" | "testnet";
|
|
3
|
+
declare function getFastKvBaseUrlForNetwork(network: NetworkId): string;
|
|
4
|
+
declare function buildRegistryConfigUrl(accountId: string, gatewayId: string): string;
|
|
5
|
+
declare function buildRegistryConfigUrlForNetwork(network: NetworkId, accountId: string, gatewayId: string): string;
|
|
6
|
+
declare function getRegistryNamespaceForAccount(accountId: string): string;
|
|
7
|
+
declare function getRegistryNamespaceForNetwork(network: NetworkId): string;
|
|
8
|
+
declare function fetchBosConfigFromFastKv<T>(bosUrl: string): Promise<T>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { NetworkId, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, fetchBosConfigFromFastKv, getFastKvBaseUrlForNetwork, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork };
|
|
11
|
+
//# sourceMappingURL=fastkv.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastkv.d.cts","names":[],"sources":["../src/fastkv.ts"],"mappings":";KAAY,SAAA;AAAA,iBAgBI,0BAAA,CAA2B,OAAA,EAAS,SAAA;AAAA,iBAYpC,sBAAA,CAAuB,SAAA,UAAmB,SAAA;AAAA,iBAO1C,gCAAA,CACd,OAAA,EAAS,SAAA,EACT,SAAA,UACA,SAAA;AAAA,iBAQc,8BAAA,CAA+B,SAAA;AAAA,iBAM/B,8BAAA,CAA+B,OAAA,EAAS,SAAA;AAAA,iBAgDlC,wBAAA,GAAA,CAA4B,MAAA,WAAiB,OAAA,CAAQ,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/fastkv.d.ts
|
|
2
|
+
type NetworkId = "mainnet" | "testnet";
|
|
3
|
+
declare function getFastKvBaseUrlForNetwork(network: NetworkId): string;
|
|
4
|
+
declare function buildRegistryConfigUrl(accountId: string, gatewayId: string): string;
|
|
5
|
+
declare function buildRegistryConfigUrlForNetwork(network: NetworkId, accountId: string, gatewayId: string): string;
|
|
6
|
+
declare function getRegistryNamespaceForAccount(accountId: string): string;
|
|
7
|
+
declare function getRegistryNamespaceForNetwork(network: NetworkId): string;
|
|
8
|
+
declare function fetchBosConfigFromFastKv<T>(bosUrl: string): Promise<T>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { NetworkId, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, fetchBosConfigFromFastKv, getFastKvBaseUrlForNetwork, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork };
|
|
11
|
+
//# sourceMappingURL=fastkv.d.mts.map
|