everything-dev 1.49.0 → 1.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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 +1 -3
- package/dist/cli/sync.cjs.map +1 -1
- package/dist/cli/sync.mjs +1 -3
- package/dist/cli/sync.mjs.map +1 -1
- package/dist/cli/upgrade.cjs +8 -4
- package/dist/cli/upgrade.cjs.map +1 -1
- package/dist/cli/upgrade.mjs +8 -4
- 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 +7 -3
- 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 +7 -3
- 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 +164 -19
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +164 -19
- 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 +337 -0
- package/dist/infra/planner.cjs.map +1 -0
- package/dist/infra/planner.mjs +336 -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 +160 -43
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +64 -8
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +64 -8
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +164 -47
- 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/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- 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 +4 -1
- package/skills/cli-reference/SKILL.md +5 -4
- package/skills/dev-workflow/SKILL.md +40 -11
- package/skills/plugin-development/SKILL.md +9 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.mjs","names":[],"sources":["../../src/infra/preflight.ts"],"sourcesContent":["import { createConnection } from \"node:net\";\nimport { Effect } from \"effect\";\n\nexport interface PreflightTarget {\n secret: string;\n host: string;\n port: number;\n kind: \"postgres\" | \"redis\";\n url: string;\n}\n\nexport interface PreflightFailure {\n secret: string;\n host: string;\n port: number;\n error: string;\n}\n\nfunction parseLocalUrl(url: string): { host: string; port: number } | null {\n try {\n const match = url.match(/:\\/\\/([^:/]+):(\\d+)/);\n if (!match) return null;\n const host = match[1];\n const port = Number.parseInt(match[2], 10);\n if (Number.isNaN(port)) return null;\n if (host !== \"localhost\" && host !== \"127.0.0.1\") return null;\n return { host, port };\n } catch {\n return null;\n }\n}\n\nfunction checkTcpReachable(host: string, port: number, timeoutMs = 2000): Effect.Effect<boolean> {\n return Effect.async<boolean>((resume) => {\n const socket = createConnection({ host, port });\n const timer = setTimeout(() => {\n socket.destroy();\n resume(Effect.succeed(false));\n }, timeoutMs);\n\n socket.once(\"connect\", () => {\n clearTimeout(timer);\n socket.destroy();\n resume(Effect.succeed(true));\n });\n\n socket.once(\"error\", () => {\n clearTimeout(timer);\n socket.destroy();\n resume(Effect.succeed(false));\n });\n });\n}\n\nfunction checkPgConnection(url: string): Effect.Effect<boolean> {\n return Effect.gen(function* () {\n const reachable = yield* checkTcpReachable(\n new URL(url).hostname,\n Number(new URL(url).port) || 5432,\n 4000,\n );\n if (!reachable) return false;\n\n try {\n const { Pool } = yield* Effect.promise(() => import(\"pg\"));\n const pool = new Pool({ connectionString: url, connectionTimeoutMillis: 3000 });\n const client = yield* Effect.promise(() => pool.connect().then((c) => ({ client: c, pool })));\n try {\n yield* Effect.promise(() => client.client.query(\"SELECT 1\"));\n return true;\n } finally {\n client.client.release();\n yield* Effect.promise(() => client.pool.end().catch(() => {}));\n }\n } catch {\n return false;\n }\n });\n}\n\nfunction preflightTargetsFromEnv(env: Record<string, string>): PreflightTarget[] {\n const targets: PreflightTarget[] = [];\n for (const [secret, value] of Object.entries(env)) {\n if (!value) continue;\n if (secret.endsWith(\"_DATABASE_URL\")) {\n const parsed = parseLocalUrl(value);\n if (parsed) {\n targets.push({\n secret,\n host: parsed.host,\n port: parsed.port,\n kind: \"postgres\",\n url: value,\n });\n }\n } else if (secret.endsWith(\"_REDIS_URL\")) {\n const parsed = parseLocalUrl(value);\n if (parsed) {\n targets.push({ secret, host: parsed.host, port: parsed.port, kind: \"redis\", url: value });\n }\n }\n }\n return targets;\n}\n\nexport function preflightLocalInfra(\n env: Record<string, string>,\n overrides?: Record<string, string>,\n): Effect.Effect<PreflightFailure[], never> {\n const merged = overrides ? { ...env, ...overrides } : env;\n const targets = preflightTargetsFromEnv(merged);\n if (targets.length === 0) return Effect.succeed([]);\n\n return Effect.forEach(\n targets,\n (target) =>\n Effect.gen(function* () {\n if (target.kind === \"postgres\") {\n const ok = yield* checkPgConnection(target.url);\n if (ok) return null;\n const tcpOk = yield* checkTcpReachable(target.host, target.port);\n const pluginContext = target.secret.endsWith(\"_DATABASE_URL\")\n ? ` The plugin for ${target.secret} runs inside the local host process, so this DB must be reachable. Run \\`docker compose up -d --wait\\` to start local Postgres/Redis.`\n : \"\";\n if (tcpOk) {\n return {\n secret: target.secret,\n host: target.host,\n port: target.port,\n error: `${target.secret} at ${target.host}:${target.port} is reachable but Postgres connection failed. Check credentials and database name.${pluginContext}`,\n } satisfies PreflightFailure;\n }\n return {\n secret: target.secret,\n host: target.host,\n port: target.port,\n error: `${target.secret} points to ${target.host}:${target.port} but nothing is listening.${pluginContext}`,\n } satisfies PreflightFailure;\n }\n\n const reachable = yield* checkTcpReachable(target.host, target.port);\n if (reachable) return null;\n return {\n secret: target.secret,\n host: target.host,\n port: target.port,\n error: `${target.secret} points to ${target.host}:${target.port} but nothing is listening`,\n } satisfies PreflightFailure;\n }),\n { concurrency: \"unbounded\" },\n ).pipe(Effect.map((results) => results.filter((r): r is PreflightFailure => r !== null)));\n}\n"],"mappings":";;;;AAkBA,SAAS,cAAc,KAAoD;AACzE,KAAI;EACF,MAAM,QAAQ,IAAI,MAAM,sBAAsB;AAC9C,MAAI,CAAC,MAAO,QAAO;EACnB,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,OAAO,SAAS,MAAM,IAAI,GAAG;AAC1C,MAAI,OAAO,MAAM,KAAK,CAAE,QAAO;AAC/B,MAAI,SAAS,eAAe,SAAS,YAAa,QAAO;AACzD,SAAO;GAAE;GAAM;GAAM;SACf;AACN,SAAO;;;AAIX,SAAS,kBAAkB,MAAc,MAAc,YAAY,KAA8B;AAC/F,QAAO,OAAO,OAAgB,WAAW;EACvC,MAAM,SAAS,iBAAiB;GAAE;GAAM;GAAM,CAAC;EAC/C,MAAM,QAAQ,iBAAiB;AAC7B,UAAO,SAAS;AAChB,UAAO,OAAO,QAAQ,MAAM,CAAC;KAC5B,UAAU;AAEb,SAAO,KAAK,iBAAiB;AAC3B,gBAAa,MAAM;AACnB,UAAO,SAAS;AAChB,UAAO,OAAO,QAAQ,KAAK,CAAC;IAC5B;AAEF,SAAO,KAAK,eAAe;AACzB,gBAAa,MAAM;AACnB,UAAO,SAAS;AAChB,UAAO,OAAO,QAAQ,MAAM,CAAC;IAC7B;GACF;;AAGJ,SAAS,kBAAkB,KAAqC;AAC9D,QAAO,OAAO,IAAI,aAAa;AAM7B,MAAI,EAAC,OALoB,kBACvB,IAAI,IAAI,IAAI,CAAC,UACb,OAAO,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,MAC7B,IACD,EACe,QAAO;AAEvB,MAAI;GACF,MAAM,EAAE,SAAS,OAAO,OAAO,cAAc,OAAO,oCAAM;GAC1D,MAAM,OAAO,IAAI,KAAK;IAAE,kBAAkB;IAAK,yBAAyB;IAAM,CAAC;GAC/E,MAAM,SAAS,OAAO,OAAO,cAAc,KAAK,SAAS,CAAC,MAAM,OAAO;IAAE,QAAQ;IAAG;IAAM,EAAE,CAAC;AAC7F,OAAI;AACF,WAAO,OAAO,cAAc,OAAO,OAAO,MAAM,WAAW,CAAC;AAC5D,WAAO;aACC;AACR,WAAO,OAAO,SAAS;AACvB,WAAO,OAAO,cAAc,OAAO,KAAK,KAAK,CAAC,YAAY,GAAG,CAAC;;UAE1D;AACN,UAAO;;GAET;;AAGJ,SAAS,wBAAwB,KAAgD;CAC/E,MAAM,UAA6B,EAAE;AACrC,MAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,IAAI,EAAE;AACjD,MAAI,CAAC,MAAO;AACZ,MAAI,OAAO,SAAS,gBAAgB,EAAE;GACpC,MAAM,SAAS,cAAc,MAAM;AACnC,OAAI,OACF,SAAQ,KAAK;IACX;IACA,MAAM,OAAO;IACb,MAAM,OAAO;IACb,MAAM;IACN,KAAK;IACN,CAAC;aAEK,OAAO,SAAS,aAAa,EAAE;GACxC,MAAM,SAAS,cAAc,MAAM;AACnC,OAAI,OACF,SAAQ,KAAK;IAAE;IAAQ,MAAM,OAAO;IAAM,MAAM,OAAO;IAAM,MAAM;IAAS,KAAK;IAAO,CAAC;;;AAI/F,QAAO;;AAGT,SAAgB,oBACd,KACA,WAC0C;CAE1C,MAAM,UAAU,wBADD,YAAY;EAAE,GAAG;EAAK,GAAG;EAAW,GAAG,IACP;AAC/C,KAAI,QAAQ,WAAW,EAAG,QAAO,OAAO,QAAQ,EAAE,CAAC;AAEnD,QAAO,OAAO,QACZ,UACC,WACC,OAAO,IAAI,aAAa;AACtB,MAAI,OAAO,SAAS,YAAY;AAE9B,OAAI,OADc,kBAAkB,OAAO,IAAI,CACvC,QAAO;GACf,MAAM,QAAQ,OAAO,kBAAkB,OAAO,MAAM,OAAO,KAAK;GAChE,MAAM,gBAAgB,OAAO,OAAO,SAAS,gBAAgB,GACzD,mBAAmB,OAAO,OAAO,yIACjC;AACJ,OAAI,MACF,QAAO;IACL,QAAQ,OAAO;IACf,MAAM,OAAO;IACb,MAAM,OAAO;IACb,OAAO,GAAG,OAAO,OAAO,MAAM,OAAO,KAAK,GAAG,OAAO,KAAK,oFAAoF;IAC9I;AAEH,UAAO;IACL,QAAQ,OAAO;IACf,MAAM,OAAO;IACb,MAAM,OAAO;IACb,OAAO,GAAG,OAAO,OAAO,aAAa,OAAO,KAAK,GAAG,OAAO,KAAK,4BAA4B;IAC7F;;AAIH,MAAI,OADqB,kBAAkB,OAAO,MAAM,OAAO,KAAK,CACrD,QAAO;AACtB,SAAO;GACL,QAAQ,OAAO;GACf,MAAM,OAAO;GACb,MAAM,OAAO;GACb,OAAO,GAAG,OAAO,OAAO,aAAa,OAAO,KAAK,GAAG,OAAO,KAAK;GACjE;GACD,EACJ,EAAE,aAAa,aAAa,CAC7B,CAAC,KAAK,OAAO,KAAK,YAAY,QAAQ,QAAQ,MAA6B,MAAM,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
let effect = require("effect");
|
|
3
|
+
|
|
4
|
+
//#region src/infra/types.ts
|
|
5
|
+
var InfraError = class extends effect.Data.TaggedError("InfraError") {};
|
|
6
|
+
|
|
7
|
+
//#endregion
|
|
8
|
+
exports.InfraError = InfraError;
|
|
9
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs","names":["Data"],"sources":["../../src/infra/types.ts"],"sourcesContent":["import { Data } from \"effect\";\nimport type { AppOrchestrator } from \"../service-descriptor\";\nimport type { RuntimeConfig } from \"../types\";\n\nexport interface CliPorts {\n host?: number;\n api?: number;\n auth?: number;\n ui?: number;\n uiSsr?: number;\n pluginsStart?: number;\n plugins?: Record<string, { api?: number; ui?: number }>;\n}\n\nexport interface ResolvedPorts {\n host?: number;\n api?: number;\n auth?: number;\n ui?: number;\n uiSsr?: number;\n plugins: Record<string, { api?: number; ui?: number }>;\n postgres: Record<string, number>;\n redis: Record<string, number>;\n}\n\nexport interface RuntimeLaunchSpec {\n port?: number;\n hostUrl?: string;\n corsOrigin?: string;\n trustedOrigins?: string[];\n env: Record<string, string>;\n runtimeConfig: RuntimeConfig;\n}\n\nexport interface ClaimRecord {\n resourceKey: string;\n pid: number;\n configDir: string;\n ports: Record<string, number>;\n startedAt: number;\n}\n\nexport interface InfraPlan {\n workspaceKey: string;\n cliPorts: CliPorts;\n resolvedPorts: ResolvedPorts;\n runtimeConfig: RuntimeConfig;\n launch: RuntimeLaunchSpec;\n description: string;\n serviceDescriptors: Map<string, ServiceDescriptorPlan>;\n envGenerated: Record<string, string>;\n composeModel: ComposeModelPlan;\n claims: ClaimRecord[];\n orchestrator: AppOrchestrator;\n}\n\nexport interface ServiceDescriptorPlan {\n key: string;\n source: \"local\" | \"remote\";\n url: string;\n port?: number;\n localPath?: string;\n}\n\nexport interface ComposeModelPlan {\n databases: DatabasePlan[];\n redis: RedisPlan[];\n}\n\nexport interface DatabasePlan {\n secret: string;\n slug: string;\n port: number;\n dbName: string;\n containerName: string;\n volumeName: string;\n url: string;\n}\n\nexport interface RedisPlan {\n secret: string;\n slug: string;\n port: number;\n containerName: string;\n volumeName: string;\n url: string;\n}\n\nexport type InfraPhase =\n | \"resolve-config\"\n | \"allocate-services\"\n | \"allocate-databases\"\n | \"claim\"\n | \"materialize-env\"\n | \"materialize-compose\"\n | \"launch\";\n\nexport class InfraError extends Data.TaggedError(\"InfraError\")<{\n phase: InfraPhase;\n message: string;\n cause?: unknown;\n}> {}\n\nexport interface InfraInput {\n configDir: string;\n bosConfig: RuntimeConfig;\n cli: {\n port?: number;\n apiPort?: number;\n authPort?: number;\n uiPort?: number;\n pluginPortStart?: number;\n plugins?: Record<string, { api?: number; ui?: number }>;\n ssr?: boolean;\n proxy?: boolean;\n hostSource?: \"local\" | \"remote\";\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n authSource?: \"local\" | \"remote\";\n interactive?: boolean;\n };\n}\n"],"mappings":";;;;AAiGA,IAAa,aAAb,cAAgCA,YAAK,YAAY,aAAa,CAI3D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../src/infra/types.ts"],"sourcesContent":["import { Data } from \"effect\";\nimport type { AppOrchestrator } from \"../service-descriptor\";\nimport type { RuntimeConfig } from \"../types\";\n\nexport interface CliPorts {\n host?: number;\n api?: number;\n auth?: number;\n ui?: number;\n uiSsr?: number;\n pluginsStart?: number;\n plugins?: Record<string, { api?: number; ui?: number }>;\n}\n\nexport interface ResolvedPorts {\n host?: number;\n api?: number;\n auth?: number;\n ui?: number;\n uiSsr?: number;\n plugins: Record<string, { api?: number; ui?: number }>;\n postgres: Record<string, number>;\n redis: Record<string, number>;\n}\n\nexport interface RuntimeLaunchSpec {\n port?: number;\n hostUrl?: string;\n corsOrigin?: string;\n trustedOrigins?: string[];\n env: Record<string, string>;\n runtimeConfig: RuntimeConfig;\n}\n\nexport interface ClaimRecord {\n resourceKey: string;\n pid: number;\n configDir: string;\n ports: Record<string, number>;\n startedAt: number;\n}\n\nexport interface InfraPlan {\n workspaceKey: string;\n cliPorts: CliPorts;\n resolvedPorts: ResolvedPorts;\n runtimeConfig: RuntimeConfig;\n launch: RuntimeLaunchSpec;\n description: string;\n serviceDescriptors: Map<string, ServiceDescriptorPlan>;\n envGenerated: Record<string, string>;\n composeModel: ComposeModelPlan;\n claims: ClaimRecord[];\n orchestrator: AppOrchestrator;\n}\n\nexport interface ServiceDescriptorPlan {\n key: string;\n source: \"local\" | \"remote\";\n url: string;\n port?: number;\n localPath?: string;\n}\n\nexport interface ComposeModelPlan {\n databases: DatabasePlan[];\n redis: RedisPlan[];\n}\n\nexport interface DatabasePlan {\n secret: string;\n slug: string;\n port: number;\n dbName: string;\n containerName: string;\n volumeName: string;\n url: string;\n}\n\nexport interface RedisPlan {\n secret: string;\n slug: string;\n port: number;\n containerName: string;\n volumeName: string;\n url: string;\n}\n\nexport type InfraPhase =\n | \"resolve-config\"\n | \"allocate-services\"\n | \"allocate-databases\"\n | \"claim\"\n | \"materialize-env\"\n | \"materialize-compose\"\n | \"launch\";\n\nexport class InfraError extends Data.TaggedError(\"InfraError\")<{\n phase: InfraPhase;\n message: string;\n cause?: unknown;\n}> {}\n\nexport interface InfraInput {\n configDir: string;\n bosConfig: RuntimeConfig;\n cli: {\n port?: number;\n apiPort?: number;\n authPort?: number;\n uiPort?: number;\n pluginPortStart?: number;\n plugins?: Record<string, { api?: number; ui?: number }>;\n ssr?: boolean;\n proxy?: boolean;\n hostSource?: \"local\" | \"remote\";\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n authSource?: \"local\" | \"remote\";\n interactive?: boolean;\n };\n}\n"],"mappings":";;;AAiGA,IAAa,aAAb,cAAgC,KAAK,YAAY,aAAa,CAI3D"}
|
package/dist/near-cli.cjs
CHANGED
|
@@ -162,6 +162,41 @@ const executeTransaction = (config, signingMode) => effect.Effect.gen(function*
|
|
|
162
162
|
output: output.output
|
|
163
163
|
};
|
|
164
164
|
});
|
|
165
|
+
async function listPublishKeys(config) {
|
|
166
|
+
const listResult = await (0, execa.execa)("near", [
|
|
167
|
+
"account",
|
|
168
|
+
"list-keys",
|
|
169
|
+
config.account,
|
|
170
|
+
"network-config",
|
|
171
|
+
config.network,
|
|
172
|
+
"now"
|
|
173
|
+
], {
|
|
174
|
+
stdout: "pipe",
|
|
175
|
+
stderr: "pipe",
|
|
176
|
+
reject: false
|
|
177
|
+
});
|
|
178
|
+
if (listResult.exitCode !== 0) throw new NearTransactionError(`Failed to list account keys: ${listResult.stderr || listResult.stdout || "unknown error"}`);
|
|
179
|
+
const output = listResult.stdout ?? "";
|
|
180
|
+
const oldKeys = [];
|
|
181
|
+
for (const line of output.split("\n")) if (line.includes(config.contract) && line.includes("__fastdata_kv")) {
|
|
182
|
+
const match = line.match(/ed25519:[A-Za-z0-9]+/);
|
|
183
|
+
if (match) oldKeys.push(match[0]);
|
|
184
|
+
}
|
|
185
|
+
return oldKeys;
|
|
186
|
+
}
|
|
187
|
+
async function deleteAccessKeys(account, publicKeys, network) {
|
|
188
|
+
await runNearCommand([
|
|
189
|
+
"account",
|
|
190
|
+
"delete-keys",
|
|
191
|
+
account,
|
|
192
|
+
"public-keys",
|
|
193
|
+
publicKeys.join(","),
|
|
194
|
+
"network-config",
|
|
195
|
+
network,
|
|
196
|
+
"sign-with-keychain",
|
|
197
|
+
"send"
|
|
198
|
+
]);
|
|
199
|
+
}
|
|
165
200
|
async function addFunctionCallAccessKey(config) {
|
|
166
201
|
const keyPair = generateNearKeyPair();
|
|
167
202
|
await runNearCommand([
|
|
@@ -187,7 +222,9 @@ async function addFunctionCallAccessKey(config) {
|
|
|
187
222
|
|
|
188
223
|
//#endregion
|
|
189
224
|
exports.addFunctionCallAccessKey = addFunctionCallAccessKey;
|
|
225
|
+
exports.deleteAccessKeys = deleteAccessKeys;
|
|
190
226
|
exports.ensureNearCli = ensureNearCli;
|
|
191
227
|
exports.executeTransaction = executeTransaction;
|
|
228
|
+
exports.listPublishKeys = listPublishKeys;
|
|
192
229
|
exports.resolveNearSigningMode = resolveNearSigningMode;
|
|
193
230
|
//# sourceMappingURL=near-cli.cjs.map
|
package/dist/near-cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"near-cli.cjs","names":["Effect","colors"],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n verbose?: boolean;\n}\n\nexport interface NearTransactionResult {\n success: true;\n txHash?: string;\n output?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nexport type NearSigningMode =\n | { _tag: \"privateKey\"; privateKey: string }\n | { _tag: \"interactiveKeychain\" };\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n await execa(\"near\", args, { stdin: \"inherit\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport function resolveNearSigningMode(privateKey?: string): NearSigningMode {\n if (privateKey) {\n return { _tag: \"privateKey\", privateKey };\n }\n\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n return { _tag: \"interactiveKeychain\" };\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nfunction combineNearOutput(stdout?: string, stderr?: string): string {\n return [stdout, stderr].filter((value) => value && value.trim().length > 0).join(\"\\n\");\n}\n\nfunction extractTransactionHash(output: string): string | undefined {\n const match = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n signingMode?: NearSigningMode,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (resolvedSigningMode._tag === \"privateKey\") {\n args.push(\"sign-with-plaintext-private-key\", resolvedSigningMode.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const isPrivateKeyMode = resolvedSigningMode._tag === \"privateKey\";\n const verbose = config.verbose ?? false;\n\n const proc = execa(\"near\", args, {\n stdin: isPrivateKeyMode ? \"ignore\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stdout.write(chunk);\n }\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stderr.write(chunk);\n }\n });\n\n const result = await proc;\n const stdoutStr = result.stdout ?? \"\";\n const stderrStr = result.stderr ?? \"\";\n const combined = combineNearOutput(stdoutStr, stderrStr);\n const txHash = extractTransactionHash(combined);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n\n if (result.exitCode === 0 || hasCodeDoesNotExist) {\n if (hasCodeDoesNotExist) {\n console.log(\n ` ${colors.green(\"✓\")} Transaction confirmed${txHash ? ` ${colors.dim(txHash)}` : \"\"}`,\n );\n }\n return {\n success: true,\n txHash,\n output: combined || undefined,\n };\n }\n\n throw new NearTransactionError(\n combined || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n return {\n success: true,\n txHash: output.txHash,\n output: output.output,\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":";;;;;;;AAqCA,MAAM,gBAAgB;AACtB,MAAM,kBAAkB;AAExB,IAAa,uBAAb,cAA0C,MAAM;CAC9C,AAAS,OAAO;CAChB,cAAc;AACZ,QAAM,qBAAqB;;;AAI/B,IAAa,uBAAb,cAA0C,MAAM;CAC9C,AAAS,OAAO;;AAOlB,SAAS,iBAAiB,OAA2B;CACnD,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI;AAC9D,QAAO,IAAI,WAAW,OAAO,KAAK,YAAY,SAAS,CAAC;;AAG1D,SAAS,aAAa,OAA2B;AAC/C,KAAI,MAAM,WAAW,EAAG,QAAO;CAE/B,MAAM,SAAmB,CAAC,EAAE;AAC5B,MAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,QAAQ;AACZ,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAS,OAAO,MAAO;AACvB,UAAO,KAAK,QAAQ;AACpB,WAAQ,KAAK,MAAM,QAAQ,GAAG;;AAEhC,SAAO,QAAQ,GAAG;AAChB,UAAO,KAAK,QAAQ,GAAG;AACvB,WAAQ,KAAK,MAAM,QAAQ,GAAG;;;CAIlC,IAAI,SAAS;AACb,MAAK,MAAM,QAAQ,MACjB,KAAI,SAAS,EAAG,WAAU,gBAAgB;KACrC;AAGP,MAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,IACtC,WAAU,gBAAgB,OAAO;AAGnC,QAAO;;AAGT,SAAgB,sBAAmC;CACjD,MAAM,EAAE,WAAW,oDAAmC,UAAU;CAChE,MAAM,YAAY,UAAU,OAAO,EAAE,QAAQ,OAAO,CAAC;CACrD,MAAM,aAAa,WAAW,OAAO,EAAE,QAAQ,OAAO,CAAC;AAEvD,KAAI,CAAC,UAAU,KAAK,CAAC,WAAW,EAC9B,OAAM,IAAI,MAAM,kCAAkC;CAGpD,MAAM,cAAc,iBAAiB,UAAU,EAAE;CACjD,MAAM,cAAc,iBAAiB,WAAW,EAAE;CAClD,MAAM,cAAc,IAAI,WAAW,YAAY,SAAS,YAAY,OAAO;AAC3E,aAAY,IAAI,aAAa,EAAE;AAC/B,aAAY,IAAI,aAAa,YAAY,OAAO;AAEhD,QAAO;EACL,WAAW,WAAW,aAAa,YAAY;EAC/C,YAAY,WAAW,aAAa,YAAY;EACjD;;AAGH,MAAM,wBAAwBA,cAAO,WAAW;CAC9C,KAAK,YAAY;AACf,MAAI;AACF,0BAAY,QAAQ,CAAC,YAAY,EAAE,EAAE,OAAO,QAAQ,CAAC;AACrD,UAAO;UACD;AACN,UAAO;;;CAGX,6BAAa,IAAI,MAAM,2BAA2B;CACnD,CAAC;AAEF,eAAe,eAAe,MAA+B;AAC3D,KAAI,CAAC,QAAQ,MAAM,MACjB,OAAM,IAAI,qBACR,oGACD;AAGH,wBAAY,QAAQ,MAAM;EAAE,OAAO;EAAW,QAAQ;EAAW,QAAQ;EAAW,CAAC;;AAGvF,SAAgB,uBAAuB,YAAsC;AAC3E,KAAI,WACF,QAAO;EAAE,MAAM;EAAc;EAAY;AAG3C,KAAI,CAAC,QAAQ,MAAM,MACjB,OAAM,IAAI,qBACR,gIACD;AAGH,SAAQ,IACNC,qBAAO,OACL,qFACD,CACF;AACD,QAAO,EAAE,MAAM,uBAAuB;;AAGxC,MAAa,gBAAgBD,cAAO,IAAI,aAAa;AAEnD,KAAI,OADuB,sBACV;AAEjB,SAAQ,KAAK;AACb,SAAQ,IAAI,uBAAuB;AAEnC,SAAQ,KAAK;AACb,SAAQ,IAAI,gEAAgE,cAAc,OAAO;AACjG,SAAQ,KAAK;AACb,QAAOA,cAAO,KAAK,IAAI,sBAAsB,CAAC;EAC9C;AAEF,SAAS,kBAAkB,QAAiB,QAAyB;AACnE,QAAO,CAAC,QAAQ,OAAO,CAAC,QAAQ,UAAU,SAAS,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,KAAK;;AAGxF,SAAS,uBAAuB,QAAoC;AAElE,QADc,OAAO,MAAM,oCACf,GAAG;;AAGjB,MAAa,sBACX,QACA,gBAEAA,cAAO,IAAI,aAAa;CACtB,MAAM,sBAAsB,eAAe,uBAAuB,OAAO,WAAW;CACpF,MAAM,OAAO,OAAO,OAAO,WAAW,QAAQ,QAAQ,GAAG;CACzD,MAAM,WAAW,OAAO,WAAW,SAAS,QAAQ,QAAQ,GAAG;CAC/D,MAAM,UAAU,OAAO,YAAY,OAAO,QAAQ,SAAS,WAAW,GAAG,YAAY;CAErF,MAAM,OAAO;EACX;EACA;EACA;EACA,OAAO;EACP,OAAO;EACP;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;EACD;AAED,KAAI,oBAAoB,SAAS,aAC/B,MAAK,KAAK,mCAAmC,oBAAoB,YAAY,OAAO;KAEpF,MAAK,KAAK,sBAAsB,OAAO;CAGzC,MAAM,SAAS,OAAOA,cAAO,WAAW;EACtC,KAAK,YAAY;GACf,MAAM,mBAAmB,oBAAoB,SAAS;GACtD,MAAM,UAAU,OAAO,WAAW;GAElC,MAAM,wBAAa,QAAQ,MAAM;IAC/B,OAAO,mBAAmB,WAAW;IACrC,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS,MAAS;IACnB,CAAC;AAEF,QAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,QAAI,QACF,SAAQ,OAAO,MAAM,MAAM;KAE7B;AAEF,QAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,QAAI,QACF,SAAQ,OAAO,MAAM,MAAM;KAE7B;GAEF,MAAM,SAAS,MAAM;GAGrB,MAAM,WAAW,kBAFC,OAAO,UAAU,IACjB,OAAO,UAAU,GACqB;GACxD,MAAM,SAAS,uBAAuB,SAAS;GAC/C,MAAM,sBAAsB,oBAAoB,KAAK,SAAS;AAE9D,OAAI,OAAO,aAAa,KAAK,qBAAqB;AAChD,QAAI,oBACF,SAAQ,IACN,KAAKC,qBAAO,MAAM,IAAI,CAAC,wBAAwB,SAAS,IAAIA,qBAAO,IAAI,OAAO,KAAK,KACpF;AAEH,WAAO;KACL,SAAS;KACT;KACA,QAAQ,YAAY;KACrB;;AAGH,SAAM,IAAI,qBACR,YAAY,gCAAgC,OAAO,WACpD;;EAEH,QAAQ,UAAU;EACnB,CAAC;AAEF,QAAO;EACL,SAAS;EACT,QAAQ,OAAO;EACf,QAAQ,OAAO;EAChB;EACD;AAEJ,eAAsB,yBACpB,QACsB;CACtB,MAAM,UAAU,qBAAqB;AAoBrC,OAAM,eAAe;EAlBnB;EACA;EACA,OAAO;EACP;EACA;EACA,OAAO;EACP;EACA,OAAO;EACP;EACA,OAAO,cAAc,KAAK,KAAK;EAC/B;EACA,QAAQ;EACR;EACA,OAAO,YAAY,OAAO,QAAQ,SAAS,WAAW,GAAG,YAAY;EACrE;EACA;EAGuB,CAAC;AAC1B,QAAO"}
|
|
1
|
+
{"version":3,"file":"near-cli.cjs","names":["Effect","colors"],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n verbose?: boolean;\n}\n\nexport interface NearTransactionResult {\n success: true;\n txHash?: string;\n output?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nexport type NearSigningMode =\n | { _tag: \"privateKey\"; privateKey: string }\n | { _tag: \"interactiveKeychain\" };\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n await execa(\"near\", args, { stdin: \"inherit\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport function resolveNearSigningMode(privateKey?: string): NearSigningMode {\n if (privateKey) {\n return { _tag: \"privateKey\", privateKey };\n }\n\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n return { _tag: \"interactiveKeychain\" };\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nfunction combineNearOutput(stdout?: string, stderr?: string): string {\n return [stdout, stderr].filter((value) => value && value.trim().length > 0).join(\"\\n\");\n}\n\nfunction extractTransactionHash(output: string): string | undefined {\n const match = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n signingMode?: NearSigningMode,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (resolvedSigningMode._tag === \"privateKey\") {\n args.push(\"sign-with-plaintext-private-key\", resolvedSigningMode.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const isPrivateKeyMode = resolvedSigningMode._tag === \"privateKey\";\n const verbose = config.verbose ?? false;\n\n const proc = execa(\"near\", args, {\n stdin: isPrivateKeyMode ? \"ignore\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stdout.write(chunk);\n }\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stderr.write(chunk);\n }\n });\n\n const result = await proc;\n const stdoutStr = result.stdout ?? \"\";\n const stderrStr = result.stderr ?? \"\";\n const combined = combineNearOutput(stdoutStr, stderrStr);\n const txHash = extractTransactionHash(combined);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n\n if (result.exitCode === 0 || hasCodeDoesNotExist) {\n if (hasCodeDoesNotExist) {\n console.log(\n ` ${colors.green(\"✓\")} Transaction confirmed${txHash ? ` ${colors.dim(txHash)}` : \"\"}`,\n );\n }\n return {\n success: true,\n txHash,\n output: combined || undefined,\n };\n }\n\n throw new NearTransactionError(\n combined || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n return {\n success: true,\n txHash: output.txHash,\n output: output.output,\n };\n });\n\nexport async function listPublishKeys(config: {\n account: string;\n contract: string;\n network: \"mainnet\" | \"testnet\";\n}): Promise<string[]> {\n const listResult = await execa(\n \"near\",\n [\"account\", \"list-keys\", config.account, \"network-config\", config.network, \"now\"],\n { stdout: \"pipe\", stderr: \"pipe\", reject: false },\n );\n\n if (listResult.exitCode !== 0) {\n throw new NearTransactionError(\n `Failed to list account keys: ${listResult.stderr || listResult.stdout || \"unknown error\"}`,\n );\n }\n\n const output = listResult.stdout ?? \"\";\n const oldKeys: string[] = [];\n\n for (const line of output.split(\"\\n\")) {\n if (line.includes(config.contract) && line.includes(\"__fastdata_kv\")) {\n const match = line.match(/ed25519:[A-Za-z0-9]+/);\n if (match) {\n oldKeys.push(match[0]);\n }\n }\n }\n\n return oldKeys;\n}\n\nexport async function deleteAccessKeys(\n account: string,\n publicKeys: string[],\n network: \"mainnet\" | \"testnet\",\n): Promise<void> {\n const args = [\n \"account\",\n \"delete-keys\",\n account,\n \"public-keys\",\n publicKeys.join(\",\"),\n \"network-config\",\n network,\n \"sign-with-keychain\",\n \"send\",\n ];\n await runNearCommand(args);\n}\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
|
package/dist/near-cli.mjs
CHANGED
|
@@ -161,6 +161,41 @@ const executeTransaction = (config, signingMode) => Effect.gen(function* () {
|
|
|
161
161
|
output: output.output
|
|
162
162
|
};
|
|
163
163
|
});
|
|
164
|
+
async function listPublishKeys(config) {
|
|
165
|
+
const listResult = await execa("near", [
|
|
166
|
+
"account",
|
|
167
|
+
"list-keys",
|
|
168
|
+
config.account,
|
|
169
|
+
"network-config",
|
|
170
|
+
config.network,
|
|
171
|
+
"now"
|
|
172
|
+
], {
|
|
173
|
+
stdout: "pipe",
|
|
174
|
+
stderr: "pipe",
|
|
175
|
+
reject: false
|
|
176
|
+
});
|
|
177
|
+
if (listResult.exitCode !== 0) throw new NearTransactionError(`Failed to list account keys: ${listResult.stderr || listResult.stdout || "unknown error"}`);
|
|
178
|
+
const output = listResult.stdout ?? "";
|
|
179
|
+
const oldKeys = [];
|
|
180
|
+
for (const line of output.split("\n")) if (line.includes(config.contract) && line.includes("__fastdata_kv")) {
|
|
181
|
+
const match = line.match(/ed25519:[A-Za-z0-9]+/);
|
|
182
|
+
if (match) oldKeys.push(match[0]);
|
|
183
|
+
}
|
|
184
|
+
return oldKeys;
|
|
185
|
+
}
|
|
186
|
+
async function deleteAccessKeys(account, publicKeys, network) {
|
|
187
|
+
await runNearCommand([
|
|
188
|
+
"account",
|
|
189
|
+
"delete-keys",
|
|
190
|
+
account,
|
|
191
|
+
"public-keys",
|
|
192
|
+
publicKeys.join(","),
|
|
193
|
+
"network-config",
|
|
194
|
+
network,
|
|
195
|
+
"sign-with-keychain",
|
|
196
|
+
"send"
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
164
199
|
async function addFunctionCallAccessKey(config) {
|
|
165
200
|
const keyPair = generateNearKeyPair();
|
|
166
201
|
await runNearCommand([
|
|
@@ -185,5 +220,5 @@ async function addFunctionCallAccessKey(config) {
|
|
|
185
220
|
}
|
|
186
221
|
|
|
187
222
|
//#endregion
|
|
188
|
-
export { addFunctionCallAccessKey, ensureNearCli, executeTransaction, resolveNearSigningMode };
|
|
223
|
+
export { addFunctionCallAccessKey, deleteAccessKeys, ensureNearCli, executeTransaction, listPublishKeys, resolveNearSigningMode };
|
|
189
224
|
//# sourceMappingURL=near-cli.mjs.map
|
package/dist/near-cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"near-cli.mjs","names":[],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n verbose?: boolean;\n}\n\nexport interface NearTransactionResult {\n success: true;\n txHash?: string;\n output?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nexport type NearSigningMode =\n | { _tag: \"privateKey\"; privateKey: string }\n | { _tag: \"interactiveKeychain\" };\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n await execa(\"near\", args, { stdin: \"inherit\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport function resolveNearSigningMode(privateKey?: string): NearSigningMode {\n if (privateKey) {\n return { _tag: \"privateKey\", privateKey };\n }\n\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n return { _tag: \"interactiveKeychain\" };\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nfunction combineNearOutput(stdout?: string, stderr?: string): string {\n return [stdout, stderr].filter((value) => value && value.trim().length > 0).join(\"\\n\");\n}\n\nfunction extractTransactionHash(output: string): string | undefined {\n const match = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n signingMode?: NearSigningMode,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (resolvedSigningMode._tag === \"privateKey\") {\n args.push(\"sign-with-plaintext-private-key\", resolvedSigningMode.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const isPrivateKeyMode = resolvedSigningMode._tag === \"privateKey\";\n const verbose = config.verbose ?? false;\n\n const proc = execa(\"near\", args, {\n stdin: isPrivateKeyMode ? \"ignore\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stdout.write(chunk);\n }\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stderr.write(chunk);\n }\n });\n\n const result = await proc;\n const stdoutStr = result.stdout ?? \"\";\n const stderrStr = result.stderr ?? \"\";\n const combined = combineNearOutput(stdoutStr, stderrStr);\n const txHash = extractTransactionHash(combined);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n\n if (result.exitCode === 0 || hasCodeDoesNotExist) {\n if (hasCodeDoesNotExist) {\n console.log(\n ` ${colors.green(\"✓\")} Transaction confirmed${txHash ? ` ${colors.dim(txHash)}` : \"\"}`,\n );\n }\n return {\n success: true,\n txHash,\n output: combined || undefined,\n };\n }\n\n throw new NearTransactionError(\n combined || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n return {\n success: true,\n txHash: output.txHash,\n output: output.output,\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"near-cli.mjs","names":[],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n verbose?: boolean;\n}\n\nexport interface NearTransactionResult {\n success: true;\n txHash?: string;\n output?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nexport type NearSigningMode =\n | { _tag: \"privateKey\"; privateKey: string }\n | { _tag: \"interactiveKeychain\" };\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n await execa(\"near\", args, { stdin: \"inherit\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport function resolveNearSigningMode(privateKey?: string): NearSigningMode {\n if (privateKey) {\n return { _tag: \"privateKey\", privateKey };\n }\n\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n return { _tag: \"interactiveKeychain\" };\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nfunction combineNearOutput(stdout?: string, stderr?: string): string {\n return [stdout, stderr].filter((value) => value && value.trim().length > 0).join(\"\\n\");\n}\n\nfunction extractTransactionHash(output: string): string | undefined {\n const match = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n signingMode?: NearSigningMode,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (resolvedSigningMode._tag === \"privateKey\") {\n args.push(\"sign-with-plaintext-private-key\", resolvedSigningMode.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const isPrivateKeyMode = resolvedSigningMode._tag === \"privateKey\";\n const verbose = config.verbose ?? false;\n\n const proc = execa(\"near\", args, {\n stdin: isPrivateKeyMode ? \"ignore\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stdout.write(chunk);\n }\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n if (verbose) {\n process.stderr.write(chunk);\n }\n });\n\n const result = await proc;\n const stdoutStr = result.stdout ?? \"\";\n const stderrStr = result.stderr ?? \"\";\n const combined = combineNearOutput(stdoutStr, stderrStr);\n const txHash = extractTransactionHash(combined);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n\n if (result.exitCode === 0 || hasCodeDoesNotExist) {\n if (hasCodeDoesNotExist) {\n console.log(\n ` ${colors.green(\"✓\")} Transaction confirmed${txHash ? ` ${colors.dim(txHash)}` : \"\"}`,\n );\n }\n return {\n success: true,\n txHash,\n output: combined || undefined,\n };\n }\n\n throw new NearTransactionError(\n combined || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n return {\n success: true,\n txHash: output.txHash,\n output: output.output,\n };\n });\n\nexport async function listPublishKeys(config: {\n account: string;\n contract: string;\n network: \"mainnet\" | \"testnet\";\n}): Promise<string[]> {\n const listResult = await execa(\n \"near\",\n [\"account\", \"list-keys\", config.account, \"network-config\", config.network, \"now\"],\n { stdout: \"pipe\", stderr: \"pipe\", reject: false },\n );\n\n if (listResult.exitCode !== 0) {\n throw new NearTransactionError(\n `Failed to list account keys: ${listResult.stderr || listResult.stdout || \"unknown error\"}`,\n );\n }\n\n const output = listResult.stdout ?? \"\";\n const oldKeys: string[] = [];\n\n for (const line of output.split(\"\\n\")) {\n if (line.includes(config.contract) && line.includes(\"__fastdata_kv\")) {\n const match = line.match(/ed25519:[A-Za-z0-9]+/);\n if (match) {\n oldKeys.push(match[0]);\n }\n }\n }\n\n return oldKeys;\n}\n\nexport async function deleteAccessKeys(\n account: string,\n publicKeys: string[],\n network: \"mainnet\" | \"testnet\",\n): Promise<void> {\n const args = [\n \"account\",\n \"delete-keys\",\n account,\n \"public-keys\",\n publicKeys.join(\",\"),\n \"network-config\",\n network,\n \"sign-with-keychain\",\n \"send\",\n ];\n await runNearCommand(args);\n}\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
|
package/dist/orchestrator.cjs
CHANGED
|
@@ -128,7 +128,9 @@ const spawnRemoteHost = (descriptor, callbacks) => effect.Effect.gen(function* (
|
|
|
128
128
|
if (!res.ok) return remoteEntryUrl;
|
|
129
129
|
const json = await res.json();
|
|
130
130
|
if (json && typeof json === "object" && "metaData" in json && "exposes" in json && "shared" in json) return manifestUrl;
|
|
131
|
-
} catch {
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.warn(`[Orchestrator] Failed to fetch or parse manifest from ${manifestUrl}, falling back to remoteEntryUrl: ${e}`);
|
|
133
|
+
}
|
|
132
134
|
return remoteEntryUrl;
|
|
133
135
|
},
|
|
134
136
|
catch: () => remoteEntryUrl
|
|
@@ -144,7 +146,13 @@ const spawnRemoteHost = (descriptor, callbacks) => effect.Effect.gen(function* (
|
|
|
144
146
|
});
|
|
145
147
|
if (!hostModule?.runServer) return yield* effect.Effect.fail(/* @__PURE__ */ new Error("Host module does not export runServer function"));
|
|
146
148
|
callbacks.onLog(descriptor.key, "Starting server...");
|
|
147
|
-
const
|
|
149
|
+
const hostPort = runtimeConfig.host?.port;
|
|
150
|
+
const hostEnv = hostPort ? { PORT: String(hostPort) } : void 0;
|
|
151
|
+
const serverHandle = hostModule.runServer({
|
|
152
|
+
config: runtimeConfig,
|
|
153
|
+
port: hostPort,
|
|
154
|
+
env: hostEnv
|
|
155
|
+
});
|
|
148
156
|
yield* effect.Effect.tryPromise({
|
|
149
157
|
try: () => serverHandle.ready,
|
|
150
158
|
catch: (e) => /* @__PURE__ */ new Error(`Server failed to start: ${e}`)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.cjs","names":["Effect","DevRuntimeConfig","Deferred","Ref","Command","Stream","Option","ServiceDescriptorMap"],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { Command } from \"@effect/platform\";\nimport type { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport { Deferred, Effect, Option, Ref, Stream } from \"effect\";\nimport { patchManifestFetchForSsrPublicPath } from \"./mf\";\nimport {\n DevRuntimeConfig,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nprocess.on(\"unhandledRejection\", (reason) => {\n console.error(\"[Orchestrator] Unhandled rejection:\", reason);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n console.error(\"[Orchestrator] Uncaught exception:\", err);\n});\n\nexport interface ProcessCallbacks {\n onStatus: (name: string, status: ProcessStatus, message?: string) => void;\n onLog: (name: string, line: string, isError?: boolean) => void;\n}\n\nexport interface ProcessHandle {\n name: string;\n pid: number | undefined;\n kill: Effect.Effect<void, unknown>;\n waitForReady: Effect.Effect<void, Error>;\n waitForExit: Effect.Effect<ExitCode, unknown>;\n}\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\nexport interface ProcessState {\n name: string;\n status: ProcessStatus;\n port: number;\n message?: string;\n source?: \"local\" | \"remote\";\n}\n\nconst stripAnsi = (input: string): string => {\n const ESC = String.fromCharCode(27);\n const BEL = String.fromCharCode(7);\n return input\n .replace(new RegExp(`${ESC}\\\\][^${BEL}]*${BEL}`, \"g\"), \"\")\n .replace(new RegExp(`${ESC}\\\\[[0-?]*[ -/]*[@-~]`, \"g\"), \"\");\n};\n\nconst probeHttpOk = (url: string, timeoutMs = 400) =>\n Effect.tryPromise({\n try: async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n },\n catch: () => false,\n });\n\nconst LOCAL_PROBE_DEADLINE_MS = 90_000;\nconst LOCAL_PROBE_INTERVAL_MS = 200;\n\nconst REMOTE_PROBE_TIMEOUT_MS = 5000;\nconst REMOTE_PROBE_DEADLINE_MS = 60_000;\nconst REMOTE_PROBE_BACKOFF_INITIAL_MS = 1000;\nconst REMOTE_PROBE_BACKOFF_MAX_MS = 15_000;\n\nconst detectStatus = (\n line: string,\n descriptor: ServiceDescriptor,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n const errorPatterns = descriptor.errorPatterns ?? [];\n const readyPatterns = descriptor.readyPatterns ?? [];\n for (const pattern of errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n for (const pattern of readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n return null;\n};\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n}\n\nconst patchConsole = (name: string, callbacks: ProcessCallbacks): (() => void) => {\n const originalLog = console.log;\n const originalError = console.error;\n const originalWarn = console.warn;\n const originalInfo = console.info;\n\n const formatArgs = (args: unknown[], isError = false): string => {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n const parts = [`${arg.name}: ${arg.message}`];\n if (arg.cause instanceof Error)\n parts.push(`(cause: ${arg.cause.name}: ${arg.cause.message})`);\n else if (arg.cause) parts.push(`(cause: ${String(arg.cause)})`);\n if (isError && arg.stack) parts.push(arg.stack);\n return parts.join(\"\\n\");\n }\n return typeof arg === \"object\" ? JSON.stringify(arg, null, 2) : String(arg);\n })\n .join(\" \");\n };\n\n console.log = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.error = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args, true), true);\n };\n console.warn = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.info = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n\n return () => {\n console.log = originalLog;\n console.error = originalError;\n console.warn = originalWarn;\n console.info = originalInfo;\n };\n};\n\nconst spawnRemoteHost = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n const remoteUrl = descriptor.remoteUrl;\n if (!remoteUrl) {\n return yield* Effect.fail(new Error(\"remoteUrl not provided on host descriptor\"));\n }\n\n callbacks.onStatus(descriptor.key, \"starting\");\n callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(descriptor.key, callbacks);\n callbacks.onLog(descriptor.key, \"Loading Module Federation runtime...\");\n\n const mfRuntime = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/enhanced/runtime\"),\n catch: (e) => new Error(`Failed to load MF runtime: ${e}`),\n });\n\n const mfCore = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/runtime-core\"),\n catch: (e) => new Error(`Failed to load MF core: ${e}`),\n });\n\n let mf = mfRuntime.getInstance();\n if (!mf) {\n mf = mfRuntime.createInstance({ name: \"cli-host\", remotes: [] });\n mfCore.setGlobalFederationInstance(mf);\n }\n patchManifestFetchForSsrPublicPath(mf as any);\n\n const baseUrl = remoteUrl\n .replace(/\\/remoteEntry\\.js$/, \"\")\n .replace(/\\/mf-manifest\\.json$/, \"\")\n .replace(/\\/$/, \"\");\n const remoteEntryUrl = `${baseUrl}/remoteEntry.js`;\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 10_000);\n let res: Response;\n try {\n res = await fetch(manifestUrl, { signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n if (!res.ok) return remoteEntryUrl;\n const json = (await res.json()) as Record<string, unknown>;\n if (\n json &&\n typeof json === \"object\" &&\n \"metaData\" in json &&\n \"exposes\" in json &&\n \"shared\" in json\n ) {\n return manifestUrl;\n }\n } catch {}\n return remoteEntryUrl;\n },\n catch: () => remoteEntryUrl,\n });\n\n (mf as any).registerRemotes([{ name: \"host\", entry: entryUrl }]);\n callbacks.onLog(descriptor.key, `Loading host from ${entryUrl}...`);\n\n const hostModule = yield* Effect.tryPromise({\n try: () =>\n (mf as any).loadRemote(\"host/Server\") as Promise<{\n runServer: (input: ServerInput) => ServerHandle;\n }>,\n catch: (e) => new Error(`Failed to load host module: ${e}`),\n });\n\n if (!hostModule?.runServer) {\n return yield* Effect.fail(new Error(\"Host module does not export runServer function\"));\n }\n\n callbacks.onLog(descriptor.key, \"Starting server...\");\n const serverHandle = hostModule.runServer({ config: runtimeConfig });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (e) => new Error(`Server failed to start: ${e}`),\n });\n\n callbacks.onStatus(descriptor.key, \"ready\");\n\n return {\n name: descriptor.key,\n pid: process.pid,\n kill: Effect.gen(function* () {\n callbacks.onLog(descriptor.key, \"Shutting down remote host...\");\n restoreConsole();\n yield* Effect.tryPromise({\n try: () => serverHandle.shutdown(),\n catch: () => {},\n }).pipe(Effect.ignore);\n }),\n waitForReady: Effect.succeed(undefined),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nconst spawnDevProcess = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n\n if (!descriptor.localPath) {\n return yield* Effect.fail(new Error(`No localPath for local service: ${descriptor.key}`));\n }\n\n const fullCwd = descriptor.localPath;\n const command = descriptor.command ?? \"bun\";\n const args = descriptor.args ?? [\"run\", \"dev\"];\n const port = descriptor.port ?? descriptor.defaultPort;\n const name = descriptor.key;\n\n const readyDeferred = yield* Deferred.make<void, Error>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(name, \"starting\");\n\n const envVars: Record<string, string> = {\n ...(process.env as Record<string, string>),\n FORCE_COLOR: \"1\",\n ...(port > 0 ? { PORT: String(port) } : {}),\n };\n\n if (name === \"host\") {\n envVars.BOS_RUNTIME_CONFIG = JSON.stringify(runtimeConfig);\n }\n\n const cmd = Command.make(command, ...args).pipe(\n Command.workingDirectory(fullCwd),\n Command.env(envVars),\n );\n\n const proc = yield* Command.start(cmd);\n\n const markReady = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"ready\");\n callbacks.onStatus(name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n const markError = (message: string) =>\n Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(name, \"error\");\n yield* Deferred.fail(readyDeferred, new Error(message)).pipe(Effect.ignore);\n });\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const deadline = Date.now() + LOCAL_PROBE_DEADLINE_MS;\n\n if (port > 0) {\n const readinessPath = descriptor.readinessPath;\n const url = `http://127.0.0.1:${port}${readinessPath}`;\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n const ok = yield* probeHttpOk(url);\n if (ok) {\n yield* markReady;\n return;\n }\n yield* Effect.sleep(`${LOCAL_PROBE_INTERVAL_MS} millis`);\n }\n } else {\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n yield* Effect.sleep(\"500 millis\");\n }\n }\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\" && status !== \"error\") {\n callbacks.onLog(name, \"Probe deadline exceeded after 90s\", true);\n yield* markError(`Probe deadline exceeded: ${name}`);\n }\n }),\n );\n\n const pid = Number(proc.pid);\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const exitCode = yield* proc.exitCode;\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n callbacks.onLog(name, `Process exited before ready (exit code: ${exitCode})`, true);\n yield* markError(`Process exited before ready: ${name}`);\n }),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n const cleanLine = stripAnsi(line);\n const looksLikeError =\n isStderr &&\n /^(error|fail|fatal|exception|unhandled|reject)/i.test(cleanLine) &&\n !/^\\$/.test(cleanLine);\n callbacks.onLog(name, line, looksLikeError);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n\n const detected = detectStatus(line, descriptor);\n if (detected) {\n if (detected.status === \"ready\") {\n yield* markReady;\n } else {\n yield* markError(`Process failed: ${name}`);\n }\n }\n });\n\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, false))(\n Stream.splitLines(Stream.decodeText(proc.stdout, \"utf-8\")),\n ),\n );\n\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, true))(\n Stream.splitLines(Stream.decodeText(proc.stderr, \"utf-8\")),\n ),\n );\n\n return {\n name,\n pid,\n kill: Effect.gen(function* () {\n const result = yield* proc.kill(\"SIGTERM\").pipe(Effect.timeout(\"3 seconds\"), Effect.option);\n if (Option.isNone(result)) {\n const pid = Number(proc.pid);\n yield* Effect.try(() => process.kill(-pid, \"SIGKILL\")).pipe(Effect.ignore);\n yield* Effect.sleep(\"250 millis\");\n }\n }).pipe(Effect.ignore),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: proc.exitCode,\n } satisfies ProcessHandle;\n });\n\nconst spawnRemoteProbe = (\n pkg: string,\n descriptor: ServiceDescriptor,\n callbacks: ProcessCallbacks,\n) =>\n Effect.gen(function* () {\n callbacks.onStatus(pkg, \"starting\");\n const readyDeferred = yield* Deferred.make<void, Error>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n const markReady = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"ready\", \"loaded\");\n });\n\n const markError = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(readyDeferred, new Error(`Remote ${pkg} unreachable`)).pipe(\n Effect.ignore,\n );\n callbacks.onStatus(pkg, \"error\", \"unreachable\");\n });\n\n const baseUrl = descriptor.url.replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n const entryUrl = `${baseUrl}${descriptor.readinessPath}`;\n const probeUrl = descriptor.readinessPath === \"/health\" ? `${baseUrl}/health` : manifestUrl;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const deadline = Date.now() + REMOTE_PROBE_DEADLINE_MS;\n let delay = REMOTE_PROBE_BACKOFF_INITIAL_MS;\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n\n const ok = yield* probeHttpOk(probeUrl, REMOTE_PROBE_TIMEOUT_MS);\n\n if (ok) {\n yield* markReady;\n return;\n }\n\n const fallbackOk = yield* probeHttpOk(entryUrl, REMOTE_PROBE_TIMEOUT_MS);\n\n if (fallbackOk) {\n yield* markReady;\n return;\n }\n\n yield* Effect.sleep(`${delay} millis`);\n delay = Math.min(Math.round(delay * 1.5), REMOTE_PROBE_BACKOFF_MAX_MS);\n }\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\") {\n yield* markError;\n }\n }),\n );\n\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.gen(function* () {\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(readyDeferred, new Error(\"Killed\")).pipe(Effect.ignore);\n }),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const makeDevProcess = (pkg: string, callbacks: ProcessCallbacks, portOverride?: number) =>\n Effect.gen(function* () {\n const services = yield* ServiceDescriptorMap;\n const descriptor = services.get(pkg);\n\n if (!descriptor) {\n callbacks.onStatus(pkg, \"ready\", \"Remote\");\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n }\n\n if (pkg === \"host\" && descriptor.source === \"remote\") {\n return yield* spawnRemoteHost(descriptor, callbacks);\n }\n\n if (descriptor.source === \"remote\" || !descriptor.localPath) {\n return yield* spawnRemoteProbe(pkg, descriptor, callbacks);\n }\n\n const resolvedDescriptor = portOverride ? { ...descriptor, port: portOverride } : descriptor;\n\n return yield* spawnDevProcess(resolvedDescriptor, callbacks);\n });\n\nexport function getProcessStates(\n packages: string[],\n services: Map<string, ServiceDescriptor>,\n portOverride?: number,\n): ProcessState[] {\n return packages.map((pkg) => {\n const descriptor = services.get(pkg);\n return {\n name: pkg,\n status: \"pending\" as const,\n port:\n portOverride && pkg === \"host\"\n ? portOverride\n : (descriptor?.port ?? descriptor?.defaultPort ?? 0),\n source: descriptor?.source,\n };\n });\n}\n"],"mappings":";;;;;;;AAWA,QAAQ,GAAG,uBAAuB,WAAW;AAC3C,SAAQ,MAAM,uCAAuC,OAAO;EAC5D;AAEF,QAAQ,GAAG,sBAAsB,QAAQ;AACvC,SAAQ,MAAM,sCAAsC,IAAI;EACxD;AAyBF,MAAM,aAAa,UAA0B;CAC3C,MAAM,MAAM,OAAO,aAAa,GAAG;CACnC,MAAM,MAAM,OAAO,aAAa,EAAE;AAClC,QAAO,MACJ,QAAQ,IAAI,OAAO,GAAG,IAAI,OAAO,IAAI,IAAI,OAAO,IAAI,EAAE,GAAG,CACzD,QAAQ,IAAI,OAAO,GAAG,IAAI,uBAAuB,IAAI,EAAE,GAAG;;AAG/D,MAAM,eAAe,KAAa,YAAY,QAC5CA,cAAO,WAAW;CAChB,KAAK,YAAY;EACf,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,UAAU;AAC7D,MAAI;AAEF,WAAO,MADW,MAAM,KAAK,EAAE,QAAQ,WAAW,QAAQ,CAAC,EAChD;UACL;AACN,UAAO;YACC;AACR,gBAAa,MAAM;;;CAGvB,aAAa;CACd,CAAC;AAEJ,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAEhC,MAAM,0BAA0B;AAChC,MAAM,2BAA2B;AACjC,MAAM,kCAAkC;AACxC,MAAM,8BAA8B;AAEpC,MAAM,gBACJ,MACA,eACuD;CACvD,MAAM,YAAY,UAAU,KAAK;CACjC,MAAM,gBAAgB,WAAW,iBAAiB,EAAE;CACpD,MAAM,gBAAgB,WAAW,iBAAiB,EAAE;AACpD,MAAK,MAAM,WAAW,cACpB,KAAI,QAAQ,KAAK,UAAU,CACzB,QAAO;EAAE,QAAQ;EAAS,SAAS;EAAM;AAG7C,MAAK,MAAM,WAAW,cACpB,KAAI,QAAQ,KAAK,UAAU,CACzB,QAAO;EAAE,QAAQ;EAAS,SAAS;EAAO;AAG9C,QAAO;;AAYT,MAAM,gBAAgB,MAAc,cAA8C;CAChF,MAAM,cAAc,QAAQ;CAC5B,MAAM,gBAAgB,QAAQ;CAC9B,MAAM,eAAe,QAAQ;CAC7B,MAAM,eAAe,QAAQ;CAE7B,MAAM,cAAc,MAAiB,UAAU,UAAkB;AAC/D,SAAO,KACJ,KAAK,QAAQ;AACZ,OAAI,eAAe,OAAO;IACxB,MAAM,QAAQ,CAAC,GAAG,IAAI,KAAK,IAAI,IAAI,UAAU;AAC7C,QAAI,IAAI,iBAAiB,MACvB,OAAM,KAAK,WAAW,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,GAAG;aACvD,IAAI,MAAO,OAAM,KAAK,WAAW,OAAO,IAAI,MAAM,CAAC,GAAG;AAC/D,QAAI,WAAW,IAAI,MAAO,OAAM,KAAK,IAAI,MAAM;AAC/C,WAAO,MAAM,KAAK,KAAK;;AAEzB,UAAO,OAAO,QAAQ,WAAW,KAAK,UAAU,KAAK,MAAM,EAAE,GAAG,OAAO,IAAI;IAC3E,CACD,KAAK,IAAI;;AAGd,SAAQ,OAAO,GAAG,SAAoB;AACpC,YAAU,MAAM,MAAM,WAAW,KAAK,EAAE,MAAM;;AAEhD,SAAQ,SAAS,GAAG,SAAoB;AACtC,YAAU,MAAM,MAAM,WAAW,MAAM,KAAK,EAAE,KAAK;;AAErD,SAAQ,QAAQ,GAAG,SAAoB;AACrC,YAAU,MAAM,MAAM,WAAW,KAAK,EAAE,MAAM;;AAEhD,SAAQ,QAAQ,GAAG,SAAoB;AACrC,YAAU,MAAM,MAAM,WAAW,KAAK,EAAE,MAAM;;AAGhD,cAAa;AACX,UAAQ,MAAM;AACd,UAAQ,QAAQ;AAChB,UAAQ,OAAO;AACf,UAAQ,OAAO;;;AAInB,MAAM,mBAAmB,YAA+B,cACtDA,cAAO,IAAI,aAAa;CACtB,MAAM,gBAAgB,OAAOC;CAC7B,MAAM,YAAY,WAAW;AAC7B,KAAI,CAAC,UACH,QAAO,OAAOD,cAAO,qBAAK,IAAI,MAAM,4CAA4C,CAAC;AAGnF,WAAU,SAAS,WAAW,KAAK,WAAW;AAC9C,WAAU,MAAM,WAAW,KAAK,WAAW,YAAY;CACvD,MAAM,iBAAiB,aAAa,WAAW,KAAK,UAAU;AAC9D,WAAU,MAAM,WAAW,KAAK,uCAAuC;CAEvE,MAAM,YAAY,OAAOA,cAAO,WAAW;EACzC,WAAW,OAAO;EAClB,QAAQ,sBAAM,IAAI,MAAM,8BAA8B,IAAI;EAC3D,CAAC;CAEF,MAAM,SAAS,OAAOA,cAAO,WAAW;EACtC,WAAW,OAAO;EAClB,QAAQ,sBAAM,IAAI,MAAM,2BAA2B,IAAI;EACxD,CAAC;CAEF,IAAI,KAAK,UAAU,aAAa;AAChC,KAAI,CAAC,IAAI;AACP,OAAK,UAAU,eAAe;GAAE,MAAM;GAAY,SAAS,EAAE;GAAE,CAAC;AAChE,SAAO,4BAA4B,GAAG;;AAExC,+CAAmC,GAAU;CAE7C,MAAM,UAAU,UACb,QAAQ,sBAAsB,GAAG,CACjC,QAAQ,wBAAwB,GAAG,CACnC,QAAQ,OAAO,GAAG;CACrB,MAAM,iBAAiB,GAAG,QAAQ;CAClC,MAAM,cAAc,GAAG,QAAQ;CAE/B,MAAM,WAAW,OAAOA,cAAO,WAAW;EACxC,KAAK,YAAY;AACf,OAAI;IACF,MAAM,aAAa,IAAI,iBAAiB;IACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,IAAO;IAC1D,IAAI;AACJ,QAAI;AACF,WAAM,MAAM,MAAM,aAAa,EAAE,QAAQ,WAAW,QAAQ,CAAC;cACrD;AACR,kBAAa,MAAM;;AAErB,QAAI,CAAC,IAAI,GAAI,QAAO;IACpB,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,QACE,QACA,OAAO,SAAS,YAChB,cAAc,QACd,aAAa,QACb,YAAY,KAEZ,QAAO;WAEH;AACR,UAAO;;EAET,aAAa;EACd,CAAC;AAEF,CAAC,GAAW,gBAAgB,CAAC;EAAE,MAAM;EAAQ,OAAO;EAAU,CAAC,CAAC;AAChE,WAAU,MAAM,WAAW,KAAK,qBAAqB,SAAS,KAAK;CAEnE,MAAM,aAAa,OAAOA,cAAO,WAAW;EAC1C,WACG,GAAW,WAAW,cAAc;EAGvC,QAAQ,sBAAM,IAAI,MAAM,+BAA+B,IAAI;EAC5D,CAAC;AAEF,KAAI,CAAC,YAAY,UACf,QAAO,OAAOA,cAAO,qBAAK,IAAI,MAAM,iDAAiD,CAAC;AAGxF,WAAU,MAAM,WAAW,KAAK,qBAAqB;CACrD,MAAM,eAAe,WAAW,UAAU,EAAE,QAAQ,eAAe,CAAC;AACpE,QAAOA,cAAO,WAAW;EACvB,WAAW,aAAa;EACxB,QAAQ,sBAAM,IAAI,MAAM,2BAA2B,IAAI;EACxD,CAAC;AAEF,WAAU,SAAS,WAAW,KAAK,QAAQ;AAE3C,QAAO;EACL,MAAM,WAAW;EACjB,KAAK,QAAQ;EACb,MAAMA,cAAO,IAAI,aAAa;AAC5B,aAAU,MAAM,WAAW,KAAK,+BAA+B;AAC/D,mBAAgB;AAChB,UAAOA,cAAO,WAAW;IACvB,WAAW,aAAa,UAAU;IAClC,aAAa;IACd,CAAC,CAAC,KAAKA,cAAO,OAAO;IACtB;EACF,cAAcA,cAAO,QAAQ,OAAU;EACvC,aAAaA,cAAO;EACrB;EACD;AAEJ,MAAM,mBAAmB,YAA+B,cACtDA,cAAO,IAAI,aAAa;CACtB,MAAM,gBAAgB,OAAOC;AAE7B,KAAI,CAAC,WAAW,UACd,QAAO,OAAOD,cAAO,qBAAK,IAAI,MAAM,mCAAmC,WAAW,MAAM,CAAC;CAG3F,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,WAAW,WAAW;CACtC,MAAM,OAAO,WAAW,QAAQ,CAAC,OAAO,MAAM;CAC9C,MAAM,OAAO,WAAW,QAAQ,WAAW;CAC3C,MAAM,OAAO,WAAW;CAExB,MAAM,gBAAgB,OAAOE,gBAAS,MAAmB;CACzD,MAAM,YAAY,OAAOC,WAAI,KAAoB,WAAW;AAE5D,WAAU,SAAS,MAAM,WAAW;CAEpC,MAAM,UAAkC;EACtC,GAAI,QAAQ;EACZ,aAAa;EACb,GAAI,OAAO,IAAI,EAAE,MAAM,OAAO,KAAK,EAAE,GAAG,EAAE;EAC3C;AAED,KAAI,SAAS,OACX,SAAQ,qBAAqB,KAAK,UAAU,cAAc;CAG5D,MAAM,MAAMC,yBAAQ,KAAK,SAAS,GAAG,KAAK,CAAC,KACzCA,yBAAQ,iBAAiB,QAAQ,EACjCA,yBAAQ,IAAI,QAAQ,CACrB;CAED,MAAM,OAAO,OAAOA,yBAAQ,MAAM,IAAI;CAEtC,MAAM,YAAYJ,cAAO,IAAI,aAAa;EACxC,MAAM,gBAAgB,OAAOG,WAAI,IAAI,UAAU;AAC/C,MAAI,kBAAkB,WAAW,kBAAkB,QAAS;AAC5D,SAAOA,WAAI,IAAI,WAAW,QAAQ;AAClC,YAAU,SAAS,MAAM,QAAQ;AACjC,SAAOD,gBAAS,QAAQ,eAAe,OAAU,CAAC,KAAKF,cAAO,OAAO;GACrE;CAEF,MAAM,aAAa,YACjBA,cAAO,IAAI,aAAa;EACtB,MAAM,gBAAgB,OAAOG,WAAI,IAAI,UAAU;AAC/C,MAAI,kBAAkB,WAAW,kBAAkB,QAAS;AAC5D,SAAOA,WAAI,IAAI,WAAW,QAAQ;AAClC,YAAU,SAAS,MAAM,QAAQ;AACjC,SAAOD,gBAAS,KAAK,eAAe,IAAI,MAAM,QAAQ,CAAC,CAAC,KAAKF,cAAO,OAAO;GAC3E;AAEJ,QAAOA,cAAO,WACZA,cAAO,IAAI,aAAa;EACtB,MAAM,WAAW,KAAK,KAAK,GAAG;AAE9B,MAAI,OAAO,GAAG;GAEZ,MAAM,MAAM,oBAAoB,OADV,WAAW;AAEjC,UAAO,KAAK,KAAK,GAAG,UAAU;IAC5B,MAAM,SAAS,OAAOG,WAAI,IAAI,UAAU;AACxC,QAAI,WAAW,WAAW,WAAW,QAAS;AAE9C,QAAI,OADc,YAAY,IAAI,EAC1B;AACN,YAAO;AACP;;AAEF,WAAOH,cAAO,MAAM,GAAG,wBAAwB,SAAS;;QAG1D,QAAO,KAAK,KAAK,GAAG,UAAU;GAC5B,MAAM,SAAS,OAAOG,WAAI,IAAI,UAAU;AACxC,OAAI,WAAW,WAAW,WAAW,QAAS;AAC9C,UAAOH,cAAO,MAAM,aAAa;;EAIrC,MAAM,SAAS,OAAOG,WAAI,IAAI,UAAU;AACxC,MAAI,WAAW,WAAW,WAAW,SAAS;AAC5C,aAAU,MAAM,MAAM,qCAAqC,KAAK;AAChE,UAAO,UAAU,4BAA4B,OAAO;;GAEtD,CACH;CAED,MAAM,MAAM,OAAO,KAAK,IAAI;AAE5B,QAAOH,cAAO,WACZA,cAAO,IAAI,aAAa;EACtB,MAAM,WAAW,OAAO,KAAK;EAC7B,MAAM,gBAAgB,OAAOG,WAAI,IAAI,UAAU;AAC/C,MAAI,kBAAkB,WAAW,kBAAkB,QAAS;AAC5D,YAAU,MAAM,MAAM,2CAA2C,SAAS,IAAI,KAAK;AACnF,SAAO,UAAU,gCAAgC,OAAO;GACxD,CACH;CAED,MAAM,cAAc,MAAc,aAChCH,cAAO,IAAI,aAAa;AACtB,MAAI,CAAC,KAAK,MAAM,CAAE;EAElB,MAAM,YAAY,UAAU,KAAK;EACjC,MAAM,iBACJ,YACA,kDAAkD,KAAK,UAAU,IACjE,CAAC,MAAM,KAAK,UAAU;AACxB,YAAU,MAAM,MAAM,MAAM,eAAe;EAE3C,MAAM,gBAAgB,OAAOG,WAAI,IAAI,UAAU;AAC/C,MAAI,kBAAkB,WAAW,kBAAkB,QAAS;EAE5D,MAAM,WAAW,aAAa,MAAM,WAAW;AAC/C,MAAI,SACF,KAAI,SAAS,WAAW,QACtB,QAAO;MAEP,QAAO,UAAU,mBAAmB,OAAO;GAG/C;AAEJ,QAAOH,cAAO,WACZK,cAAO,YAAY,SAAiB,WAAW,MAAM,MAAM,CAAC,CAC1DA,cAAO,WAAWA,cAAO,WAAW,KAAK,QAAQ,QAAQ,CAAC,CAC3D,CACF;AAED,QAAOL,cAAO,WACZK,cAAO,YAAY,SAAiB,WAAW,MAAM,KAAK,CAAC,CACzDA,cAAO,WAAWA,cAAO,WAAW,KAAK,QAAQ,QAAQ,CAAC,CAC3D,CACF;AAED,QAAO;EACL;EACA;EACA,MAAML,cAAO,IAAI,aAAa;GAC5B,MAAM,SAAS,OAAO,KAAK,KAAK,UAAU,CAAC,KAAKA,cAAO,QAAQ,YAAY,EAAEA,cAAO,OAAO;AAC3F,OAAIM,cAAO,OAAO,OAAO,EAAE;IACzB,MAAM,MAAM,OAAO,KAAK,IAAI;AAC5B,WAAON,cAAO,UAAU,QAAQ,KAAK,CAAC,KAAK,UAAU,CAAC,CAAC,KAAKA,cAAO,OAAO;AAC1E,WAAOA,cAAO,MAAM,aAAa;;IAEnC,CAAC,KAAKA,cAAO,OAAO;EACtB,cAAcE,gBAAS,MAAM,cAAc;EAC3C,aAAa,KAAK;EACnB;EACD;AAEJ,MAAM,oBACJ,KACA,YACA,cAEAF,cAAO,IAAI,aAAa;AACtB,WAAU,SAAS,KAAK,WAAW;CACnC,MAAM,gBAAgB,OAAOE,gBAAS,MAAmB;CACzD,MAAM,YAAY,OAAOC,WAAI,KAAoB,WAAW;CAE5D,MAAM,YAAYH,cAAO,IAAI,aAAa;EACxC,MAAM,gBAAgB,OAAOG,WAAI,IAAI,UAAU;AAC/C,MAAI,kBAAkB,WAAW,kBAAkB,QAAS;AAC5D,SAAOA,WAAI,IAAI,WAAW,QAAQ;AAClC,SAAOD,gBAAS,QAAQ,eAAe,OAAU,CAAC,KAAKF,cAAO,OAAO;AACrE,YAAU,SAAS,KAAK,SAAS,SAAS;GAC1C;CAEF,MAAM,YAAYA,cAAO,IAAI,aAAa;EACxC,MAAM,gBAAgB,OAAOG,WAAI,IAAI,UAAU;AAC/C,MAAI,kBAAkB,WAAW,kBAAkB,QAAS;AAC5D,SAAOA,WAAI,IAAI,WAAW,QAAQ;AAClC,SAAOD,gBAAS,KAAK,+BAAe,IAAI,MAAM,UAAU,IAAI,cAAc,CAAC,CAAC,KAC1EF,cAAO,OACR;AACD,YAAU,SAAS,KAAK,SAAS,cAAc;GAC/C;CAEF,MAAM,UAAU,WAAW,IAAI,QAAQ,OAAO,GAAG;CACjD,MAAM,cAAc,GAAG,QAAQ;CAC/B,MAAM,WAAW,GAAG,UAAU,WAAW;CACzC,MAAM,WAAW,WAAW,kBAAkB,YAAY,GAAG,QAAQ,WAAW;AAEhF,QAAOA,cAAO,WACZA,cAAO,IAAI,aAAa;EACtB,MAAM,WAAW,KAAK,KAAK,GAAG;EAC9B,IAAI,QAAQ;AACZ,SAAO,KAAK,KAAK,GAAG,UAAU;GAC5B,MAAM,SAAS,OAAOG,WAAI,IAAI,UAAU;AACxC,OAAI,WAAW,WAAW,WAAW,QAAS;AAI9C,OAAI,OAFc,YAAY,UAAU,wBAAwB,EAExD;AACN,WAAO;AACP;;AAKF,OAAI,OAFsB,YAAY,UAAU,wBAAwB,EAExD;AACd,WAAO;AACP;;AAGF,UAAOH,cAAO,MAAM,GAAG,MAAM,SAAS;AACtC,WAAQ,KAAK,IAAI,KAAK,MAAM,QAAQ,IAAI,EAAE,4BAA4B;;AAIxE,OAAI,OADkBG,WAAI,IAAI,UAAU,MACzB,QACb,QAAO;GAET,CACH;AAED,QAAO;EACL,MAAM;EACN,KAAK;EACL,MAAMH,cAAO,IAAI,aAAa;AAC5B,UAAOG,WAAI,IAAI,WAAW,QAAQ;AAClC,UAAOD,gBAAS,KAAK,+BAAe,IAAI,MAAM,SAAS,CAAC,CAAC,KAAKF,cAAO,OAAO;IAC5E;EACF,cAAcE,gBAAS,MAAM,cAAc;EAC3C,aAAaF,cAAO;EACrB;EACD;AAEJ,MAAa,kBAAkB,KAAa,WAA6B,iBACvEA,cAAO,IAAI,aAAa;CAEtB,MAAM,cAAa,OADKO,iDACI,IAAI,IAAI;AAEpC,KAAI,CAAC,YAAY;AACf,YAAU,SAAS,KAAK,SAAS,SAAS;AAC1C,SAAO;GACL,MAAM;GACN,KAAK;GACL,MAAMP,cAAO;GACb,cAAcA,cAAO;GACrB,aAAaA,cAAO;GACrB;;AAGH,KAAI,QAAQ,UAAU,WAAW,WAAW,SAC1C,QAAO,OAAO,gBAAgB,YAAY,UAAU;AAGtD,KAAI,WAAW,WAAW,YAAY,CAAC,WAAW,UAChD,QAAO,OAAO,iBAAiB,KAAK,YAAY,UAAU;AAK5D,QAAO,OAAO,gBAFa,eAAe;EAAE,GAAG;EAAY,MAAM;EAAc,GAAG,YAEhC,UAAU;EAC5D;AAEJ,SAAgB,iBACd,UACA,UACA,cACgB;AAChB,QAAO,SAAS,KAAK,QAAQ;EAC3B,MAAM,aAAa,SAAS,IAAI,IAAI;AACpC,SAAO;GACL,MAAM;GACN,QAAQ;GACR,MACE,gBAAgB,QAAQ,SACpB,eACC,YAAY,QAAQ,YAAY,eAAe;GACtD,QAAQ,YAAY;GACrB;GACD"}
|
|
1
|
+
{"version":3,"file":"orchestrator.cjs","names":["Effect","DevRuntimeConfig","Deferred","Ref","Command","Stream","Option","ServiceDescriptorMap"],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { Command } from \"@effect/platform\";\nimport type { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport { Deferred, Effect, Option, Ref, Stream } from \"effect\";\nimport { patchManifestFetchForSsrPublicPath } from \"./mf\";\nimport {\n DevRuntimeConfig,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nprocess.on(\"unhandledRejection\", (reason) => {\n console.error(\"[Orchestrator] Unhandled rejection:\", reason);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n console.error(\"[Orchestrator] Uncaught exception:\", err);\n});\n\nexport interface ProcessCallbacks {\n onStatus: (name: string, status: ProcessStatus, message?: string) => void;\n onLog: (name: string, line: string, isError?: boolean) => void;\n}\n\nexport interface ProcessHandle {\n name: string;\n pid: number | undefined;\n kill: Effect.Effect<void, unknown>;\n waitForReady: Effect.Effect<void, Error>;\n waitForExit: Effect.Effect<ExitCode, unknown>;\n}\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\nexport interface ProcessState {\n name: string;\n status: ProcessStatus;\n port: number;\n message?: string;\n source?: \"local\" | \"remote\";\n}\n\nconst stripAnsi = (input: string): string => {\n const ESC = String.fromCharCode(27);\n const BEL = String.fromCharCode(7);\n return input\n .replace(new RegExp(`${ESC}\\\\][^${BEL}]*${BEL}`, \"g\"), \"\")\n .replace(new RegExp(`${ESC}\\\\[[0-?]*[ -/]*[@-~]`, \"g\"), \"\");\n};\n\nconst probeHttpOk = (url: string, timeoutMs = 400) =>\n Effect.tryPromise({\n try: async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n },\n catch: () => false,\n });\n\nconst LOCAL_PROBE_DEADLINE_MS = 90_000;\nconst LOCAL_PROBE_INTERVAL_MS = 200;\n\nconst REMOTE_PROBE_TIMEOUT_MS = 5000;\nconst REMOTE_PROBE_DEADLINE_MS = 60_000;\nconst REMOTE_PROBE_BACKOFF_INITIAL_MS = 1000;\nconst REMOTE_PROBE_BACKOFF_MAX_MS = 15_000;\n\nconst detectStatus = (\n line: string,\n descriptor: ServiceDescriptor,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n const errorPatterns = descriptor.errorPatterns ?? [];\n const readyPatterns = descriptor.readyPatterns ?? [];\n for (const pattern of errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n for (const pattern of readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n return null;\n};\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n port?: number;\n env?: Record<string, string>;\n}\n\nconst patchConsole = (name: string, callbacks: ProcessCallbacks): (() => void) => {\n const originalLog = console.log;\n const originalError = console.error;\n const originalWarn = console.warn;\n const originalInfo = console.info;\n\n const formatArgs = (args: unknown[], isError = false): string => {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n const parts = [`${arg.name}: ${arg.message}`];\n if (arg.cause instanceof Error)\n parts.push(`(cause: ${arg.cause.name}: ${arg.cause.message})`);\n else if (arg.cause) parts.push(`(cause: ${String(arg.cause)})`);\n if (isError && arg.stack) parts.push(arg.stack);\n return parts.join(\"\\n\");\n }\n return typeof arg === \"object\" ? JSON.stringify(arg, null, 2) : String(arg);\n })\n .join(\" \");\n };\n\n console.log = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.error = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args, true), true);\n };\n console.warn = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.info = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n\n return () => {\n console.log = originalLog;\n console.error = originalError;\n console.warn = originalWarn;\n console.info = originalInfo;\n };\n};\n\nconst spawnRemoteHost = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n const remoteUrl = descriptor.remoteUrl;\n if (!remoteUrl) {\n return yield* Effect.fail(new Error(\"remoteUrl not provided on host descriptor\"));\n }\n\n callbacks.onStatus(descriptor.key, \"starting\");\n callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(descriptor.key, callbacks);\n callbacks.onLog(descriptor.key, \"Loading Module Federation runtime...\");\n\n const mfRuntime = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/enhanced/runtime\"),\n catch: (e) => new Error(`Failed to load MF runtime: ${e}`),\n });\n\n const mfCore = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/runtime-core\"),\n catch: (e) => new Error(`Failed to load MF core: ${e}`),\n });\n\n let mf = mfRuntime.getInstance();\n if (!mf) {\n mf = mfRuntime.createInstance({ name: \"cli-host\", remotes: [] });\n mfCore.setGlobalFederationInstance(mf);\n }\n patchManifestFetchForSsrPublicPath(mf as any);\n\n const baseUrl = remoteUrl\n .replace(/\\/remoteEntry\\.js$/, \"\")\n .replace(/\\/mf-manifest\\.json$/, \"\")\n .replace(/\\/$/, \"\");\n const remoteEntryUrl = `${baseUrl}/remoteEntry.js`;\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 10_000);\n let res: Response;\n try {\n res = await fetch(manifestUrl, { signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n if (!res.ok) return remoteEntryUrl;\n const json = (await res.json()) as Record<string, unknown>;\n if (\n json &&\n typeof json === \"object\" &&\n \"metaData\" in json &&\n \"exposes\" in json &&\n \"shared\" in json\n ) {\n return manifestUrl;\n }\n } catch (e) {\n console.warn(\n `[Orchestrator] Failed to fetch or parse manifest from ${manifestUrl}, falling back to remoteEntryUrl: ${e}`,\n );\n }\n return remoteEntryUrl;\n },\n catch: () => remoteEntryUrl,\n });\n\n (mf as any).registerRemotes([{ name: \"host\", entry: entryUrl }]);\n callbacks.onLog(descriptor.key, `Loading host from ${entryUrl}...`);\n\n const hostModule = yield* Effect.tryPromise({\n try: () =>\n (mf as any).loadRemote(\"host/Server\") as Promise<{\n runServer: (input: ServerInput) => ServerHandle;\n }>,\n catch: (e) => new Error(`Failed to load host module: ${e}`),\n });\n\n if (!hostModule?.runServer) {\n return yield* Effect.fail(new Error(\"Host module does not export runServer function\"));\n }\n\n callbacks.onLog(descriptor.key, \"Starting server...\");\n const hostPort = runtimeConfig.host?.port;\n const hostEnv: Record<string, string> | undefined = hostPort\n ? { PORT: String(hostPort) }\n : undefined;\n const serverHandle = hostModule.runServer({\n config: runtimeConfig,\n port: hostPort,\n env: hostEnv,\n });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (e) => new Error(`Server failed to start: ${e}`),\n });\n\n callbacks.onStatus(descriptor.key, \"ready\");\n\n return {\n name: descriptor.key,\n pid: process.pid,\n kill: Effect.gen(function* () {\n callbacks.onLog(descriptor.key, \"Shutting down remote host...\");\n restoreConsole();\n yield* Effect.tryPromise({\n try: () => serverHandle.shutdown(),\n catch: () => {},\n }).pipe(Effect.ignore);\n }),\n waitForReady: Effect.succeed(undefined),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nconst spawnDevProcess = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n\n if (!descriptor.localPath) {\n return yield* Effect.fail(new Error(`No localPath for local service: ${descriptor.key}`));\n }\n\n const fullCwd = descriptor.localPath;\n const command = descriptor.command ?? \"bun\";\n const args = descriptor.args ?? [\"run\", \"dev\"];\n const port = descriptor.port ?? descriptor.defaultPort;\n const name = descriptor.key;\n\n const readyDeferred = yield* Deferred.make<void, Error>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(name, \"starting\");\n\n const envVars: Record<string, string> = {\n ...(process.env as Record<string, string>),\n FORCE_COLOR: \"1\",\n ...(port > 0 ? { PORT: String(port) } : {}),\n };\n\n if (name === \"host\") {\n envVars.BOS_RUNTIME_CONFIG = JSON.stringify(runtimeConfig);\n }\n\n const cmd = Command.make(command, ...args).pipe(\n Command.workingDirectory(fullCwd),\n Command.env(envVars),\n );\n\n const proc = yield* Command.start(cmd);\n\n const markReady = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"ready\");\n callbacks.onStatus(name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n const markError = (message: string) =>\n Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(name, \"error\");\n yield* Deferred.fail(readyDeferred, new Error(message)).pipe(Effect.ignore);\n });\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const deadline = Date.now() + LOCAL_PROBE_DEADLINE_MS;\n\n if (port > 0) {\n const readinessPath = descriptor.readinessPath;\n const url = `http://127.0.0.1:${port}${readinessPath}`;\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n const ok = yield* probeHttpOk(url);\n if (ok) {\n yield* markReady;\n return;\n }\n yield* Effect.sleep(`${LOCAL_PROBE_INTERVAL_MS} millis`);\n }\n } else {\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n yield* Effect.sleep(\"500 millis\");\n }\n }\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\" && status !== \"error\") {\n callbacks.onLog(name, \"Probe deadline exceeded after 90s\", true);\n yield* markError(`Probe deadline exceeded: ${name}`);\n }\n }),\n );\n\n const pid = Number(proc.pid);\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const exitCode = yield* proc.exitCode;\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n callbacks.onLog(name, `Process exited before ready (exit code: ${exitCode})`, true);\n yield* markError(`Process exited before ready: ${name}`);\n }),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n const cleanLine = stripAnsi(line);\n const looksLikeError =\n isStderr &&\n /^(error|fail|fatal|exception|unhandled|reject)/i.test(cleanLine) &&\n !/^\\$/.test(cleanLine);\n callbacks.onLog(name, line, looksLikeError);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n\n const detected = detectStatus(line, descriptor);\n if (detected) {\n if (detected.status === \"ready\") {\n yield* markReady;\n } else {\n yield* markError(`Process failed: ${name}`);\n }\n }\n });\n\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, false))(\n Stream.splitLines(Stream.decodeText(proc.stdout, \"utf-8\")),\n ),\n );\n\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, true))(\n Stream.splitLines(Stream.decodeText(proc.stderr, \"utf-8\")),\n ),\n );\n\n return {\n name,\n pid,\n kill: Effect.gen(function* () {\n const result = yield* proc.kill(\"SIGTERM\").pipe(Effect.timeout(\"3 seconds\"), Effect.option);\n if (Option.isNone(result)) {\n const pid = Number(proc.pid);\n yield* Effect.try(() => process.kill(-pid, \"SIGKILL\")).pipe(Effect.ignore);\n yield* Effect.sleep(\"250 millis\");\n }\n }).pipe(Effect.ignore),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: proc.exitCode,\n } satisfies ProcessHandle;\n });\n\nconst spawnRemoteProbe = (\n pkg: string,\n descriptor: ServiceDescriptor,\n callbacks: ProcessCallbacks,\n) =>\n Effect.gen(function* () {\n callbacks.onStatus(pkg, \"starting\");\n const readyDeferred = yield* Deferred.make<void, Error>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n const markReady = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"ready\", \"loaded\");\n });\n\n const markError = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(readyDeferred, new Error(`Remote ${pkg} unreachable`)).pipe(\n Effect.ignore,\n );\n callbacks.onStatus(pkg, \"error\", \"unreachable\");\n });\n\n const baseUrl = descriptor.url.replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n const entryUrl = `${baseUrl}${descriptor.readinessPath}`;\n const probeUrl = descriptor.readinessPath === \"/health\" ? `${baseUrl}/health` : manifestUrl;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const deadline = Date.now() + REMOTE_PROBE_DEADLINE_MS;\n let delay = REMOTE_PROBE_BACKOFF_INITIAL_MS;\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n\n const ok = yield* probeHttpOk(probeUrl, REMOTE_PROBE_TIMEOUT_MS);\n\n if (ok) {\n yield* markReady;\n return;\n }\n\n const fallbackOk = yield* probeHttpOk(entryUrl, REMOTE_PROBE_TIMEOUT_MS);\n\n if (fallbackOk) {\n yield* markReady;\n return;\n }\n\n yield* Effect.sleep(`${delay} millis`);\n delay = Math.min(Math.round(delay * 1.5), REMOTE_PROBE_BACKOFF_MAX_MS);\n }\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\") {\n yield* markError;\n }\n }),\n );\n\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.gen(function* () {\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(readyDeferred, new Error(\"Killed\")).pipe(Effect.ignore);\n }),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const makeDevProcess = (pkg: string, callbacks: ProcessCallbacks, portOverride?: number) =>\n Effect.gen(function* () {\n const services = yield* ServiceDescriptorMap;\n const descriptor = services.get(pkg);\n\n if (!descriptor) {\n callbacks.onStatus(pkg, \"ready\", \"Remote\");\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n }\n\n if (pkg === \"host\" && descriptor.source === \"remote\") {\n return yield* spawnRemoteHost(descriptor, callbacks);\n }\n\n if (descriptor.source === \"remote\" || !descriptor.localPath) {\n return yield* spawnRemoteProbe(pkg, descriptor, callbacks);\n }\n\n const resolvedDescriptor = portOverride ? { ...descriptor, port: portOverride } : descriptor;\n\n return yield* spawnDevProcess(resolvedDescriptor, callbacks);\n });\n\nexport function getProcessStates(\n packages: string[],\n services: Map<string, ServiceDescriptor>,\n portOverride?: number,\n): ProcessState[] {\n return packages.map((pkg) => {\n const descriptor = services.get(pkg);\n return {\n name: pkg,\n status: \"pending\" as const,\n port:\n portOverride && pkg === \"host\"\n ? portOverride\n : (descriptor?.port ?? descriptor?.defaultPort ?? 0),\n source: descriptor?.source,\n };\n });\n}\n"],"mappings":"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"}
|
package/dist/orchestrator.mjs
CHANGED
|
@@ -127,7 +127,9 @@ const spawnRemoteHost = (descriptor, callbacks) => Effect.gen(function* () {
|
|
|
127
127
|
if (!res.ok) return remoteEntryUrl;
|
|
128
128
|
const json = await res.json();
|
|
129
129
|
if (json && typeof json === "object" && "metaData" in json && "exposes" in json && "shared" in json) return manifestUrl;
|
|
130
|
-
} catch {
|
|
130
|
+
} catch (e) {
|
|
131
|
+
console.warn(`[Orchestrator] Failed to fetch or parse manifest from ${manifestUrl}, falling back to remoteEntryUrl: ${e}`);
|
|
132
|
+
}
|
|
131
133
|
return remoteEntryUrl;
|
|
132
134
|
},
|
|
133
135
|
catch: () => remoteEntryUrl
|
|
@@ -143,7 +145,13 @@ const spawnRemoteHost = (descriptor, callbacks) => Effect.gen(function* () {
|
|
|
143
145
|
});
|
|
144
146
|
if (!hostModule?.runServer) return yield* Effect.fail(/* @__PURE__ */ new Error("Host module does not export runServer function"));
|
|
145
147
|
callbacks.onLog(descriptor.key, "Starting server...");
|
|
146
|
-
const
|
|
148
|
+
const hostPort = runtimeConfig.host?.port;
|
|
149
|
+
const hostEnv = hostPort ? { PORT: String(hostPort) } : void 0;
|
|
150
|
+
const serverHandle = hostModule.runServer({
|
|
151
|
+
config: runtimeConfig,
|
|
152
|
+
port: hostPort,
|
|
153
|
+
env: hostEnv
|
|
154
|
+
});
|
|
147
155
|
yield* Effect.tryPromise({
|
|
148
156
|
try: () => serverHandle.ready,
|
|
149
157
|
catch: (e) => /* @__PURE__ */ new Error(`Server failed to start: ${e}`)
|