everything-dev 2.0.0-rc.0 → 2.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/auth-login.cjs +1 -1
  2. package/dist/auth-login.mjs +1 -1
  3. package/dist/build.cjs +2 -2
  4. package/dist/build.mjs +2 -2
  5. package/dist/bundle-fs-resolve.cjs +9 -17
  6. package/dist/bundle-fs-resolve.cjs.map +1 -1
  7. package/dist/bundle-fs-resolve.d.cts +6 -0
  8. package/dist/bundle-fs-resolve.d.mts +6 -0
  9. package/dist/bundle-fs-resolve.mjs +9 -17
  10. package/dist/bundle-fs-resolve.mjs.map +1 -1
  11. package/dist/bundle-path.cjs +48 -0
  12. package/dist/bundle-path.cjs.map +1 -0
  13. package/dist/bundle-path.mjs +45 -0
  14. package/dist/bundle-path.mjs.map +1 -0
  15. package/dist/cli/init.cjs +13 -13
  16. package/dist/cli/init.cjs.map +1 -1
  17. package/dist/cli/init.mjs +13 -13
  18. package/dist/cli/init.mjs.map +1 -1
  19. package/dist/cli/status.cjs +69 -3
  20. package/dist/cli/status.cjs.map +1 -1
  21. package/dist/cli/status.mjs +67 -4
  22. package/dist/cli/status.mjs.map +1 -1
  23. package/dist/cli/sync.cjs +1 -1
  24. package/dist/cli/sync.cjs.map +1 -1
  25. package/dist/cli/sync.mjs +1 -1
  26. package/dist/cli/sync.mjs.map +1 -1
  27. package/dist/cli/upgrade.cjs +2 -2
  28. package/dist/cli/upgrade.cjs.map +1 -1
  29. package/dist/cli/upgrade.mjs +2 -2
  30. package/dist/cli/upgrade.mjs.map +1 -1
  31. package/dist/cli.cjs +5 -7
  32. package/dist/cli.cjs.map +1 -1
  33. package/dist/cli.mjs +5 -7
  34. package/dist/cli.mjs.map +1 -1
  35. package/dist/commands/deploy.cjs +26 -16
  36. package/dist/commands/deploy.cjs.map +1 -1
  37. package/dist/commands/deploy.mjs +26 -16
  38. package/dist/commands/deploy.mjs.map +1 -1
  39. package/dist/commands/init.cjs +1 -1
  40. package/dist/commands/init.cjs.map +1 -1
  41. package/dist/commands/init.mjs +1 -1
  42. package/dist/commands/init.mjs.map +1 -1
  43. package/dist/commands/plugins.cjs +2 -2
  44. package/dist/commands/plugins.cjs.map +1 -1
  45. package/dist/commands/plugins.mjs +2 -2
  46. package/dist/commands/plugins.mjs.map +1 -1
  47. package/dist/commands/upgrade.cjs +1 -1
  48. package/dist/commands/upgrade.mjs +1 -1
  49. package/dist/components/dev-render.cjs +1 -1
  50. package/dist/components/dev-render.mjs +1 -1
  51. package/dist/config.cjs +3 -3
  52. package/dist/config.cjs.map +1 -1
  53. package/dist/config.mjs +3 -3
  54. package/dist/config.mjs.map +1 -1
  55. package/dist/contract.cjs +2 -0
  56. package/dist/contract.cjs.map +1 -1
  57. package/dist/contract.d.cts +3 -0
  58. package/dist/contract.d.mts +3 -0
  59. package/dist/contract.meta.cjs +2 -1
  60. package/dist/contract.meta.cjs.map +1 -1
  61. package/dist/contract.meta.d.cts +4 -1
  62. package/dist/contract.meta.d.mts +4 -1
  63. package/dist/contract.meta.mjs +2 -1
  64. package/dist/contract.meta.mjs.map +1 -1
  65. package/dist/contract.mjs +2 -0
  66. package/dist/contract.mjs.map +1 -1
  67. package/dist/db/driver.cjs +22 -2
  68. package/dist/db/driver.cjs.map +1 -1
  69. package/dist/db/driver.d.cts +13 -2
  70. package/dist/db/driver.d.mts +13 -2
  71. package/dist/db/driver.mjs +22 -3
  72. package/dist/db/driver.mjs.map +1 -1
  73. package/dist/db/index.cjs +1 -0
  74. package/dist/db/index.d.cts +2 -2
  75. package/dist/db/index.d.mts +2 -2
  76. package/dist/db/index.mjs +2 -2
  77. package/dist/deploy-diff.cjs +1 -1
  78. package/dist/deploy-diff.cjs.map +1 -1
  79. package/dist/deploy-diff.mjs +1 -1
  80. package/dist/deploy-diff.mjs.map +1 -1
  81. package/dist/dev-program.cjs +10 -2
  82. package/dist/dev-program.cjs.map +1 -1
  83. package/dist/dev-program.mjs +10 -2
  84. package/dist/dev-program.mjs.map +1 -1
  85. package/dist/image-deploy.cjs +65 -17
  86. package/dist/image-deploy.cjs.map +1 -1
  87. package/dist/image-deploy.mjs +64 -18
  88. package/dist/image-deploy.mjs.map +1 -1
  89. package/dist/internal/manifest-normalizer.cjs.map +1 -1
  90. package/dist/internal/manifest-normalizer.mjs.map +1 -1
  91. package/dist/plugin.d.cts +902 -1
  92. package/dist/plugin.d.mts +902 -1
  93. package/dist/publish.cjs +51 -2
  94. package/dist/publish.cjs.map +1 -1
  95. package/dist/publish.mjs +51 -4
  96. package/dist/publish.mjs.map +1 -1
  97. package/dist/resolution/session.cjs.map +1 -1
  98. package/dist/resolution/session.d.cts +5 -5
  99. package/dist/resolution/session.d.mts +5 -5
  100. package/dist/resolution/session.mjs.map +1 -1
  101. package/dist/types.d.cts +31 -1
  102. package/dist/types.d.mts +31 -1
  103. package/dist/ui/auth-guards.d.cts +78 -2
  104. package/dist/ui/auth-guards.d.mts +78 -2
  105. package/dist/ui/auth.cjs.map +1 -1
  106. package/dist/ui/auth.d.cts +4133 -7
  107. package/dist/ui/auth.d.mts +4133 -7
  108. package/dist/ui/auth.mjs.map +1 -1
  109. package/dist/ui/hydrate.cjs +2 -2
  110. package/dist/ui/hydrate.cjs.map +1 -1
  111. package/dist/ui/hydrate.mjs +2 -2
  112. package/dist/ui/hydrate.mjs.map +1 -1
  113. package/dist/utils/theme.cjs +2 -2
  114. package/dist/utils/theme.cjs.map +1 -1
  115. package/dist/utils/theme.mjs +2 -2
  116. package/dist/utils/theme.mjs.map +1 -1
  117. package/dist/version-manifest-resolve.cjs +55 -10
  118. package/dist/version-manifest-resolve.cjs.map +1 -1
  119. package/dist/version-manifest-resolve.mjs +53 -10
  120. package/dist/version-manifest-resolve.mjs.map +1 -1
  121. package/dist/workspace.cjs +26 -13
  122. package/dist/workspace.cjs.map +1 -1
  123. package/dist/workspace.mjs +26 -14
  124. package/dist/workspace.mjs.map +1 -1
  125. package/package.json +11 -10
@@ -1 +1 @@
1
- {"version":3,"file":"publish.mjs","names":[],"sources":["../src/publish.ts"],"sourcesContent":["import { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { hasFolderFormUi } from \"every-plugin/build/ui\";\nimport { readSessionHandle } from \"./auth-session\";\nimport { buildWorkspaceTargets, resolveWorkspaceTarget, selectWorkspaceTargets } from \"./build\";\nimport { type CdnDeployInputs, probeStorageOrigin, resolveCdnDeployInputs } from \"./cdn-deploy\";\nimport { formatDuration } from \"./cli/timing\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { findConfigPath, isAppDescriptorPath, resolveUiRuntimeName } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport { ensureDelegateKey, submitRegistryWriteDelegated } from \"./delegate-signer\";\nimport {\n diffWorkspaceFiles,\n localSriMap,\n mergedFileIntegrity,\n type PreviousPin,\n pinsFromDeployState,\n pinsFromPublishedConfig,\n upsertDeployStatePins,\n} from \"./deploy-diff\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n type NetworkId,\n} from \"./fastkv\";\nimport { pointerFingerprint, slotPins } from \"./fingerprint\";\nimport { applyDeployResults, type DeployResultEntry } from \"./integrity\";\nimport { mergeAuthoredOverPublished } from \"./merge\";\nimport {\n describeSigningStrategy,\n resolveSigningStrategy,\n type SigningStrategy,\n submitRegistryWrite,\n} from \"./near-signer\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport { platformUrlDeployEntries, pluginUiUrlDeployEntries } from \"./platform-deploy\";\nimport { openResolution } from \"./resolution/session\";\nimport { verifyRollbackSnapshot } from \"./rollback\";\nimport {\n collectDistFiles,\n type DistFile,\n uploadBundle,\n uploadWorkspaceDist,\n} from \"./storage-upload\";\nimport type { BosConfig, BosConfigInput, PublishConfig, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\nimport { composeWorkspaceVersionManifest, readBuildReport } from \"./version-manifest-deploy\";\nimport { resolveSlotVersion } from \"./version-manifest-resolve\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Compose + upload the workspace's version manifest (atomic-deploys 03): the\n * manifest is built from the dist build report + the **server-computed** SRI\n * map of the just-finished upload, uploaded additively at\n * `versions/<version>.json`, and returned as the slot's pointer. Returns\n * undefined when the dist predates hashed entry names (no report / no entry\n * SRI) — the caller aborts the train: uploaded workspaces must pin.\n */\n/**\n * The manifest's own storage backend — when every dist file was diff-skipped\n * it is the only upload of the leg, so it is the only signal for the\n * memory-backend abort below.\n */\nexport interface VersionManifestPin {\n file: string;\n integrity: string;\n storage?: \"s3\" | \"memory\";\n}\n\nasync function pinWorkspaceVersionManifest(input: {\n origin: string;\n apiKey?: string;\n account: string;\n gateway: string;\n workspace: string;\n report: ReturnType<typeof readBuildReport>;\n ssrReport: ReturnType<typeof readBuildReport>;\n integrityMap: Record<string, string>;\n /** full per-file SRI map of the dist — recorded for the next deploy's diff */\n files?: Record<string, string>;\n}): Promise<VersionManifestPin | undefined> {\n if (!input.report) return undefined;\n const versionManifest = composeWorkspaceVersionManifest({\n report: input.report,\n ssrReport: input.ssrReport,\n integrityMap: input.integrityMap,\n ...(input.files ? { files: input.files } : {}),\n });\n if (!versionManifest) return undefined;\n\n const manifestFile = `versions/${versionManifest.version}.json`;\n const manifestUpload = await uploadBundle({\n origin: input.origin,\n apiKey: input.apiKey,\n account: input.account,\n gateway: input.gateway,\n workspace: input.workspace,\n files: [\n {\n path: manifestFile,\n bytes: new TextEncoder().encode(`${JSON.stringify(versionManifest, null, 2)}\\n`),\n },\n ],\n });\n const manifestIntegrity = manifestUpload.integrity[manifestFile];\n if (!manifestIntegrity) return undefined;\n console.log(\n ` ${colors.dim(`${padRight(\"\", 28)} version manifest ${manifestFile} (SRI pinned)`)}`,\n );\n return { file: manifestFile, integrity: manifestIntegrity, storage: manifestUpload.storage };\n}\n\ninterface DiffUploadOutcome {\n result: {\n stored: number;\n totalBytes: number;\n integrity: Record<string, string>;\n storage?: \"s3\" | \"memory\";\n };\n /** per-file SRI map covering the whole dist (uploaded → server SRI, skipped → previous manifest SRI) */\n fileIntegrity: Record<string, string>;\n uploaded: number;\n skipped: number;\n total: number;\n}\n\n/**\n * One workspace's upload leg with skip-unchanged diffing: resolve the previous\n * manifest's `files` map, hash the local dist, upload only new/changed files,\n * and return the merged per-file SRI map for the version manifest. Any failure\n * to resolve the previous map degrades to a full upload.\n */\nasync function diffUploadWorkspace(input: {\n origin: string;\n apiKey?: string;\n account: string;\n gateway: string;\n workspace: string;\n files: DistFile[];\n base: string;\n previousPin: PreviousPin | undefined;\n}): Promise<DiffUploadOutcome> {\n const localSri = localSriMap(input.files);\n let uploadFiles = input.files;\n let prevFiles: Record<string, string> | undefined;\n if (input.previousPin) {\n try {\n const resolved = await resolveSlotVersion({ base: input.base, pin: input.previousPin });\n if (resolved.files) {\n const diff = diffWorkspaceFiles(input.files, localSri, resolved.files);\n prevFiles = resolved.files;\n uploadFiles = diff.upload;\n if (diff.skipped > 0) {\n console.log(\n ` ${colors.dim(`${padRight(input.workspace, 28)} ${diff.skipped} unchanged file(s) — skipping (manifest diff)`)}`,\n );\n }\n }\n } catch {\n console.log(\n ` ${colors.dim(`${padRight(input.workspace, 28)} previous manifest unusable — uploading everything`)}`,\n );\n }\n }\n\n console.log(\n ` ${padRight(input.workspace, 28)} uploading ${uploadFiles.length} of ${input.files.length} files (${formatBundleMb(uploadFiles)}) → ${input.base}`,\n );\n const result =\n uploadFiles.length > 0\n ? await uploadWorkspaceDist({\n origin: input.origin,\n apiKey: input.apiKey,\n account: input.account,\n gateway: input.gateway,\n workspace: input.workspace,\n files: uploadFiles,\n })\n : { stored: 0, totalBytes: 0, integrity: {}, storage: undefined };\n return {\n result,\n fileIntegrity: mergedFileIntegrity(input.files, result.integrity, prevFiles),\n uploaded: result.stored,\n skipped: input.files.length - uploadFiles.length,\n total: input.files.length,\n };\n}\n\nfunction formatBundleMb(files: Array<{ bytes: Uint8Array }>): string {\n const total = files.reduce((sum, file) => sum + file.bytes.byteLength, 0);\n return `${(total / 1024 / 1024).toFixed(1)} MB`;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n registry?: string;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n opts.registry,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\nexport async function isConfigAlreadyPublished(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n registry?: string;\n}): Promise<boolean> {\n try {\n const current = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n opts.registry,\n );\n return JSON.stringify(current) === JSON.stringify(opts.publishConfig);\n } catch {\n return false;\n }\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n wallet?: boolean;\n registry?: string;\n /** Skip the diff upload and re-upload every dist file (escape hatch). */\n fullUpload?: boolean;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n fingerprint?: string;\n slotPins?: Record<string, string>;\n}\n\nexport type PublishedConfigState = \"fetched\" | \"missing\" | \"unreachable\";\n\nexport interface PublishPreflightPlan {\n isStaging: boolean;\n account: string;\n gateway: string;\n network: NetworkId;\n registryUrl: string;\n registryNamespace: string;\n targets: string[];\n useWallet: boolean;\n strategy?: SigningStrategy;\n cdnOrigin: string | undefined;\n storageOrigin: string;\n storageApiKey?: string;\n /** The config currently published to FastKV (null when missing or unreachable). */\n publishedConfig: Record<string, unknown> | null;\n /** Whether the preflight FastKV read succeeded, found nothing, or failed. */\n publishedConfigState: PublishedConfigState;\n}\n\nexport type PublishPreflight =\n | { kind: \"dry-run\"; registryUrl: string }\n | { kind: \"error\"; registryUrl: string; error: string }\n | { kind: \"ready\"; plan: PublishPreflightPlan };\n\n// Pure preflight (resolve, don't mutate) — every failure returns before the\n// build train runs (issue #287). Dry-run exits after the auth guards, before\n// any signing (keychain/TTY side effects).\nexport async function preflightPublish(input: PublishToFastKvInput): Promise<PublishPreflight> {\n const { configDir } = input;\n const bosConfig = input.bosConfig;\n\n const isStaging = input.env === \"staging\";\n const account = isStaging ? (bosConfig.staging?.account ?? bosConfig.account) : bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n kind: \"error\",\n registryUrl: \"\",\n error: \"authored config must define domain to publish\",\n };\n }\n\n const network: NetworkId = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway, input.registry);\n const fail = (error: string): PublishPreflight => ({ kind: \"error\", registryUrl, error });\n\n const publishAuth: PublishConfig[\"auth\"] = bosConfig.publish?.auth;\n const governsWalletPublish = (publishAuth === \"session\" || input.wallet) && !input.privateKey;\n if (governsWalletPublish) {\n const session = readSessionHandle(configDir);\n if (!session?.credential) {\n return fail(\n (input.wallet\n ? \"--wallet requires\"\n : 'the authored config sets publish.auth = \"session\", but') +\n \" no CLI session is stored in .bos/ for this project. Run bos login to create one.\",\n );\n }\n if (session.credential.accountId && session.credential.accountId !== account) {\n return fail(\n `The CLI session was created for ${session.credential.accountId}, but the configured ` +\n `account is ${account}. Gasless wallet publish relays the FastKV write under the session's ` +\n \"NEAR account. Run bos login again under the matching account.\",\n );\n }\n }\n if (publishAuth && !input.privateKey) {\n if (publishAuth === \"custody\") {\n return fail(\n 'the authored config sets publish.auth = \"custody\", but custody publish is not implemented yet (see NEARBuilders/everything-dev#291).',\n );\n }\n }\n\n if (input.dryRun) {\n return { kind: \"dry-run\", registryUrl };\n }\n\n const useWallet = input.wallet === true;\n let strategy: SigningStrategy | undefined;\n if (useWallet) {\n console.log(\n ` Signing via ${colors.cyan(\"gasless NEP-366 delegate action (relayed by the platform relayer)\")}`,\n );\n } else {\n try {\n strategy = await resolveSigningStrategy({ privateKey: input.privateKey, account, network });\n console.log(` Signing via ${colors.cyan(describeSigningStrategy(strategy))}`);\n } catch (error) {\n return fail(error instanceof Error ? error.message : \"Unknown error\");\n }\n }\n\n // CDN deploy credentials (ADR 0020) — resolved before the build train so a\n // missing bundle origin or BOS_STORAGE_API_KEY fails fast instead of after\n // the full build. Config-only publishes ship the committed config verbatim;\n // nothing is uploaded, so no deploy origins are required.\n const session = readSessionHandle(configDir);\n let cdnDeploy: CdnDeployInputs = {\n cdnOrigin: undefined,\n storageOrigin: \"\",\n apiKey: undefined,\n };\n if (input.build) {\n cdnDeploy = resolveCdnDeployInputs({\n env: process.env as Record<string, string | undefined>,\n bosConfig,\n session: session?.credential ?? null,\n account,\n gateway,\n uploadsPlanned: input.build,\n });\n if (cdnDeploy.error) {\n return fail(cdnDeploy.error);\n }\n if (cdnDeploy.warning) {\n console.log(colors.yellow(` ! ${cdnDeploy.warning}`));\n }\n const cdnOrigin = cdnDeploy.cdnOrigin;\n if (!cdnOrigin) {\n return fail(\"CDN deploy resolved no bundle origin\");\n }\n const probeError = await probeStorageOrigin(cdnDeploy.storageOrigin);\n if (probeError) {\n return fail(\n `The bundle upload origin ${cdnDeploy.storageOrigin} is not running the platform API — ` +\n `${probeError}. Check BOS_STORAGE_ORIGIN / the bos login session, then re-run.`,\n );\n }\n }\n\n // Registry reachability + published-state capture: one FastKV read. A\n // missing config is fine for a first publish — an early signal, not a hard\n // gate. The captured config is the merge base for a config-only publish on\n // a TS-form project (authored hand-edits win; live pipeline state carries).\n let publishedConfig: Record<string, unknown> | null = null;\n let publishedConfigState: PublishedConfigState = \"missing\";\n try {\n publishedConfig = await fetchBosConfigFromFastKv<Record<string, unknown>>(\n registryUrl,\n input.registry,\n );\n publishedConfigState = \"fetched\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.startsWith(\"No config found\")) {\n console.log(colors.dim(\" Note: no published config found yet (first publish) — continuing\"));\n } else {\n publishedConfigState = \"unreachable\";\n console.log(colors.dim(\" Note: registry read failed — continuing\"));\n }\n }\n\n return {\n kind: \"ready\",\n plan: {\n isStaging,\n account,\n gateway,\n network,\n registryUrl,\n registryNamespace: getRegistryNamespaceForNetwork(network, input.registry),\n targets: selectWorkspaceTargets(input.packages, bosConfig),\n useWallet,\n strategy,\n cdnOrigin: cdnDeploy.cdnOrigin,\n storageOrigin: cdnDeploy.storageOrigin,\n storageApiKey: cdnDeploy.apiKey,\n publishedConfig,\n publishedConfigState,\n },\n };\n}\n\n/**\n * The deploy-train publish core (ADR 0020, as amended): preflight\n * (storage/CDN creds + signing) fails fast before the build, then build →\n * upload → version-manifest pin → config write-back → FastKV publish +\n * read-back. Scoped to one plugin via `packages`, a single-plugin redeploy\n * ships real bytes to the storage origin — same as the full train, nothing\n * image-native left.\n */\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const preflight = await preflightPublish(input);\n if (preflight.kind === \"error\") {\n return { status: \"error\", registryUrl: preflight.registryUrl, error: preflight.error };\n }\n if (preflight.kind === \"dry-run\") {\n return { status: \"dry-run\", registryUrl: preflight.registryUrl };\n }\n const plan = preflight.plan;\n const {\n isStaging,\n account,\n gateway,\n network,\n registryUrl,\n registryNamespace,\n targets,\n useWallet,\n strategy,\n } = plan;\n const storageOrigin = plan.storageOrigin;\n const storageApiKey = plan.storageApiKey;\n\n const { configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n let refreshedRawConfig: BosConfigInput | null = null;\n\n if (input.build) {\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await openResolution({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload the config after build\",\n };\n }\n\n bosConfig = refreshed.config;\n refreshedRawConfig = refreshed.rawConfig;\n }\n\n const authoredPath = findConfigPath(configDir);\n const tsForm = authoredPath !== null && isAppDescriptorPath(authoredPath);\n let rawConfig: BosConfigInput;\n if (refreshedRawConfig) {\n rawConfig = refreshedRawConfig;\n } else {\n const opened = await openResolution({ cwd: configDir });\n if (!opened?.rawConfig) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to load the authored config for publish\",\n };\n }\n rawConfig = opened.rawConfig;\n }\n if (tsForm && !input.build && plan.publishedConfigState === \"unreachable\") {\n // A config-only TS-form publish derives its pipeline state from the live\n // published config — publishing without it would wipe bundle URLs.\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error:\n \"Cannot read the currently published config from the registry — a config-only publish would overwrite live bundle URLs. Retry when the registry is reachable, or run a full deploy.\",\n };\n }\n let publishPayload: BosConfigInput =\n tsForm && !input.build\n ? // Config-only publish on a TS-form project: the authored config owns\n // composition (hand-edits win) while live pipeline state (bundle\n // URLs, integrity) carries over from the published config.\n mergeAuthoredOverPublished((plan.publishedConfig ?? {}) as BosConfigInput, rawConfig)\n : rawConfig;\n\n const urlOrigin = plan.cdnOrigin ?? `https://${gateway}`;\n const deployTargets = (built ?? []).filter((key) => targets.includes(key));\n const platformEntries: DeployResultEntry[] = [];\n const fullUpload = input.fullUpload === true || process.env.BOS_FULL_UPLOAD === \"1\";\n // Previous per-workspace pins for the diff upload: the local pointer wins\n // (written after every confirmed publish), the published config is the\n // fallback. Neither → full upload.\n const prevPins: Record<string, PreviousPin> = fullUpload\n ? {}\n : {\n ...pinsFromPublishedConfig(\n (plan.publishedConfig ?? {}) as BosConfigInput,\n account,\n gateway,\n ),\n ...pinsFromDeployState(configDir, account, gateway),\n };\n\n console.log();\n console.log(` CDN deploy — uploading workspace dists to ${storageOrigin}...`);\n for (const key of deployTargets) {\n const ws = resolveWorkspaceTarget(key, bosConfig, runtimeConfig, configDir);\n if (!ws) continue;\n\n const distFiles = await collectDistFiles(join(ws.path, \"dist\"));\n const workspaceBase = `${urlOrigin}/bundles/${account}/${gateway}/${key}/`;\n const startedAt = Date.now();\n // an upload failure aborts the train as a structured error — the\n // previously published version stays fully live (ticket 05)\n let outcome: DiffUploadOutcome;\n try {\n outcome = await diffUploadWorkspace({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: key,\n files: distFiles,\n base: workspaceBase,\n previousPin: prevPins[key],\n });\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: error instanceof Error ? error.message : `[publish] bundle upload for ${key} failed`,\n };\n }\n const report = readBuildReport(join(ws.path, \"dist\"));\n const ssrReport = readBuildReport(join(ws.path, \"dist\", \"ssr\"));\n // the entry SRI keyed by the build report's hashed name\n const integrity = report ? outcome.fileIntegrity[report.entry] : undefined;\n const ssrIntegrity = ssrReport?.entry\n ? outcome.fileIntegrity[`ssr/${ssrReport.entry}`]\n : undefined;\n\n const manifestPointer = await pinWorkspaceVersionManifest({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: key,\n report,\n ssrReport,\n integrityMap: outcome.fileIntegrity,\n files: outcome.fileIntegrity,\n });\n if (!manifestPointer) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `bundle upload for ${key}: version manifest missing — the dist predates hashed entry names (rebuild required; atomic-deploys hard break)`,\n };\n }\n\n if (outcome.result.storage === \"memory\" || manifestPointer.storage === \"memory\") {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error:\n \"The receiving instance is serving bundle storage from memory (BOS_STORAGE_* R2 credentials are not configured there) — uploaded bytes would be lost on restart. Aborting before publish.\",\n };\n }\n\n console.log(\n ` ${colors.green(icons.ok)} ${padRight(key, 28)} → ${urlOrigin}/bundles/${account}/${gateway}/${key}/ (${outcome.uploaded} uploaded, ${outcome.skipped} skipped, ${formatDuration(Date.now() - startedAt)})`,\n );\n\n platformEntries.push(\n ...platformUrlDeployEntries({\n origin: urlOrigin,\n account,\n gateway,\n key,\n kind: ws.kind,\n integrity,\n ssrIntegrity,\n pin: manifestPointer,\n }),\n );\n\n // Folder-form plugin ui: the workspace build also produces <plugin>/ui/dist\n // (web remoteEntry + ssr container) — upload it as its own bundle key and\n // pin <slot>.<key>.ui.* so the host can compose the ui surface in production.\n if (hasFolderFormUi(ws.path)) {\n const uiDistDir = join(ws.path, \"ui\", \"dist\");\n const uiSlot = ws.kind === \"app\" ? \"app\" : \"plugins\";\n const rawSlot = (uiSlot === \"app\" ? rawConfig.app : rawConfig.plugins) as\n | Record<string, Record<string, unknown> | undefined>\n | undefined;\n const rawUi = rawSlot?.[key]?.ui as Record<string, unknown> | undefined;\n const uiName = resolveUiRuntimeName(rawUi, join(ws.path, \"ui\"), key);\n let uiIntegrity: string | undefined;\n let uiSsrIntegrity: string | undefined;\n let uiManifestPointer: VersionManifestPin | undefined;\n if (existsSync(uiDistDir)) {\n const uiDistFiles = await collectDistFiles(uiDistDir);\n const uiStartedAt = Date.now();\n const uiOutcome = await diffUploadWorkspace({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: `${key}-ui`,\n files: uiDistFiles,\n base: `${urlOrigin}/bundles/${account}/${gateway}/${key}-ui/`,\n previousPin: prevPins[`${key}-ui`],\n });\n const uiReport = readBuildReport(uiDistDir);\n const uiSsrReport = readBuildReport(join(uiDistDir, \"ssr\"));\n uiIntegrity = uiReport ? uiOutcome.fileIntegrity[uiReport.entry] : undefined;\n uiSsrIntegrity = uiSsrReport?.entry\n ? uiOutcome.fileIntegrity[`ssr/${uiSsrReport.entry}`]\n : undefined;\n\n uiManifestPointer = await pinWorkspaceVersionManifest({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: `${key}-ui`,\n report: uiReport,\n ssrReport: uiSsrReport,\n integrityMap: uiOutcome.fileIntegrity,\n files: uiOutcome.fileIntegrity,\n });\n if (!uiManifestPointer) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `bundle upload for ${key}-ui: version manifest missing — the dist predates hashed entry names (rebuild required; atomic-deploys hard break)`,\n };\n }\n\n if (uiOutcome.result.storage === \"memory\" || uiManifestPointer.storage === \"memory\") {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error:\n \"The receiving instance is serving bundle storage from memory (BOS_STORAGE_* R2 credentials are not configured there) — uploaded bytes would be lost on restart. Aborting before publish.\",\n };\n }\n\n console.log(\n ` ${colors.green(icons.ok)} ${padRight(`${key}-ui`, 28)} → ${urlOrigin}/bundles/${account}/${gateway}/${key}-ui/ (${uiOutcome.uploaded} uploaded, ${uiOutcome.skipped} skipped, ${formatDuration(Date.now() - uiStartedAt)})`,\n );\n } else {\n console.log(\n ` ${colors.green(icons.ok)} ${padRight(`${key}-ui`, 28)} → ${urlOrigin}/bundles/${account}/${gateway}/${key}-ui/`,\n );\n }\n\n platformEntries.push(\n ...pluginUiUrlDeployEntries({\n origin: urlOrigin,\n account,\n gateway,\n key,\n kind: ws.kind,\n integrity: uiIntegrity,\n ssrIntegrity: uiSsrIntegrity,\n name: uiName,\n pin: uiManifestPointer,\n }),\n );\n }\n }\n\n if (platformEntries.length > 0) {\n const merged = applyDeployResults(rawConfig as Record<string, unknown>, platformEntries);\n if (!tsForm) {\n // Legacy JSON-form children keep their local write-back; TS-form keeps\n // pipeline state in FastKV only — a write-back would shadow the\n // authored bos.app.ts descriptor.\n try {\n writeFileSync(join(configDir, \"bos.config.json\"), `${JSON.stringify(merged, null, 2)}\\n`);\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `Failed to write bundle URLs to bos.config.json: ${error instanceof Error ? error.message : error}`,\n };\n }\n }\n publishPayload = merged as BosConfigInput;\n }\n if (isStaging) {\n publishPayload = { ...publishPayload, domain: gateway };\n }\n\n const pinVerification = await verifyRollbackSnapshot(publishPayload);\n if (pinVerification.verifiable && !pinVerification.ok) {\n const failures = pinVerification.slots\n .filter((check) => !check.ok)\n .map((check) => ` ${check.slot}: ${check.reason}`)\n .join(\"\\n\");\n console.error(\n ` ${colors.error(icons.err)} Publish blocked — a pinned slot's bytes do not serve at its production URL:\\n${failures}`,\n );\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `Publish blocked — pinned slot bytes missing or SRI mismatched:\\n${failures}`,\n };\n }\n\n const registryKey = `apps/${account}/${gateway}/bos.config.json`;\n const publishedAt = new Date().toISOString();\n // version identity printed + returned for every deploy (atomic-deploys 12)\n const fingerprint = pointerFingerprint(publishPayload as never);\n const publishSlotPins = slotPins(publishPayload as never);\n const registryEntries: Record<string, string> = {\n [registryKey]: JSON.stringify(publishPayload),\n };\n const manifestKey = `apps/${account}/${gateway}/manifests/${publishedAt.replace(/[:.]/g, \"-\")}.json`;\n registryEntries[manifestKey] = JSON.stringify({\n account,\n gateway,\n network,\n publishedAt,\n registryUrl,\n });\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n console.log(` ${colors.dim(\"Fingerprint:\")} ${fingerprint}`);\n for (const [slot, pin] of Object.entries(publishSlotPins)) {\n console.log(` ${colors.dim(`${slot}:`)}`);\n console.log(` ${pin}`);\n }\n console.log(\n ` ${colors.dim(`+ per-deploy manifest ${manifestKey.split(\"/\").pop()} (audit trail)`)}`,\n );\n\n // Record the live pins for the next deploy's diff upload — only after the\n // config is confirmed published, so the pointer never claims undeployed state.\n const persistDeployState = () => {\n try {\n const pins = pinsFromPublishedConfig(publishPayload as BosConfigInput, account, gateway);\n if (Object.keys(pins).length > 0) {\n upsertDeployStatePins(configDir, account, gateway, pins);\n }\n } catch (error) {\n console.log(\n colors.dim(\n ` Note: could not update .bos/deploy-state.json — ${error instanceof Error ? error.message : String(error)}`,\n ),\n );\n }\n };\n\n try {\n const alreadyPublished = await isConfigAlreadyPublished({\n account,\n gateway,\n publishConfig: publishPayload,\n registry: input.registry,\n });\n if (alreadyPublished) {\n console.log(\" Already up to date — skipping transaction\");\n persistDeployState();\n return {\n status: \"published\",\n registryUrl,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n }\n\n console.log(` Submitting transaction on ${network}...`);\n\n let result: { success: boolean; txHash?: string };\n if (useWallet) {\n const session = readSessionHandle(configDir);\n const credential = session?.credential;\n if (!credential || credential.accountId !== account) {\n return {\n status: \"error\",\n registryUrl,\n error: `--wallet requires a CLI session under ${account}. Run bos login first.`,\n };\n }\n const record = await ensureDelegateKey({\n configDir,\n account,\n contract: registryNamespace,\n network,\n siteUrl: credential.siteUrl,\n });\n result = await submitRegistryWriteDelegated({\n account,\n contract: registryNamespace,\n network,\n args: registryEntries,\n delegatePrivateKey: record.privateKey,\n relayEndpoint: `${credential.siteUrl}/api/auth/near/relay`,\n apiKey: credential.apiKey,\n });\n } else {\n if (!strategy) {\n return {\n status: \"error\",\n registryUrl,\n error: \"non-wallet publish requires a resolved signing strategy\",\n };\n }\n result = await submitRegistryWrite(\n {\n account,\n contract: registryNamespace,\n method: \"__fastdata_kv\",\n args: registryEntries,\n network,\n privateKey: input.privateKey,\n },\n strategy,\n );\n }\n\n if (result.txHash) {\n console.log(` Transaction submitted: ${colors.dim(result.txHash)}`);\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n registry: input.registry,\n });\n persistDeployState();\n\n return {\n status: \"published\",\n registryUrl,\n txHash: result.txHash,\n fingerprint,\n slotPins: publishSlotPins,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"does not have enough allowance\")) {\n return (\n \"The publish access key has insufficient allowance to cover this transaction.\\n\" +\n \" Regenerate your key with a higher allowance:\\n\" +\n \" bos key generate\\n\" +\n ` Original: ${message}`\n );\n }\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"publish.mjs","names":[],"sources":["../src/publish.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { hasFolderFormUi } from \"every-plugin/build/ui\";\nimport { readSessionHandle } from \"./auth-session\";\nimport { buildWorkspaceTargets, resolveWorkspaceTarget, selectWorkspaceTargets } from \"./build\";\nimport { type CdnDeployInputs, probeStorageOrigin, resolveCdnDeployInputs } from \"./cdn-deploy\";\nimport { formatDuration } from \"./cli/timing\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { findConfigPath, isAppDescriptorPath, resolveUiRuntimeName } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport { ensureDelegateKey, submitRegistryWriteDelegated } from \"./delegate-signer\";\nimport {\n diffWorkspaceFiles,\n localSriMap,\n mergedFileIntegrity,\n type PreviousPin,\n pinsFromDeployState,\n pinsFromPublishedConfig,\n upsertDeployStatePins,\n} from \"./deploy-diff\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n type NetworkId,\n} from \"./fastkv\";\nimport { pointerFingerprint, slotPins } from \"./fingerprint\";\nimport { fetchResponse } from \"./http-client\";\nimport { applyDeployResults, type DeployResultEntry } from \"./integrity\";\nimport { mergeAuthoredOverPublished } from \"./merge\";\nimport {\n describeSigningStrategy,\n resolveSigningStrategy,\n type SigningStrategy,\n submitRegistryWrite,\n} from \"./near-signer\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport { platformUrlDeployEntries, pluginUiUrlDeployEntries } from \"./platform-deploy\";\nimport { openResolution } from \"./resolution/session\";\nimport { verifyRollbackSnapshot } from \"./rollback\";\nimport {\n collectDistFiles,\n type DistFile,\n uploadBundle,\n uploadWorkspaceDist,\n} from \"./storage-upload\";\nimport type { BosConfig, BosConfigInput, PublishConfig, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\nimport { composeWorkspaceVersionManifest, readBuildReport } from \"./version-manifest-deploy\";\nimport { resolveSlotVersion } from \"./version-manifest-resolve\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Compose + upload the workspace's version manifest (atomic-deploys 03): the\n * manifest is built from the dist build report + the **server-computed** SRI\n * map of the just-finished upload, uploaded additively at\n * `versions/<version>.json`, and returned as the slot's pointer. Returns\n * undefined when the dist predates hashed entry names (no report / no entry\n * SRI) — the caller aborts the train: uploaded workspaces must pin.\n */\n/**\n * The manifest's own storage backend — when every dist file was diff-skipped\n * it is the only upload of the leg, so it is the only signal for the\n * memory-backend abort below.\n */\nexport interface VersionManifestPin {\n file: string;\n integrity: string;\n storage?: \"s3\" | \"memory\";\n}\n\nasync function pinWorkspaceVersionManifest(input: {\n origin: string;\n apiKey?: string;\n account: string;\n gateway: string;\n workspace: string;\n report: ReturnType<typeof readBuildReport>;\n ssrReport: ReturnType<typeof readBuildReport>;\n integrityMap: Record<string, string>;\n /** full per-file SRI map of the dist — recorded for the next deploy's diff */\n files?: Record<string, string>;\n}): Promise<VersionManifestPin | undefined> {\n if (!input.report) return undefined;\n const versionManifest = composeWorkspaceVersionManifest({\n report: input.report,\n ssrReport: input.ssrReport,\n integrityMap: input.integrityMap,\n ...(input.files ? { files: input.files } : {}),\n });\n if (!versionManifest) return undefined;\n\n const manifestFile = `versions/${versionManifest.version}.json`;\n const manifestUpload = await uploadBundle({\n origin: input.origin,\n apiKey: input.apiKey,\n account: input.account,\n gateway: input.gateway,\n workspace: input.workspace,\n files: [\n {\n path: manifestFile,\n bytes: new TextEncoder().encode(`${JSON.stringify(versionManifest, null, 2)}\\n`),\n },\n ],\n });\n const manifestIntegrity = manifestUpload.integrity[manifestFile];\n if (!manifestIntegrity) return undefined;\n console.log(\n ` ${colors.dim(`${padRight(\"\", 28)} version manifest ${manifestFile} (SRI pinned)`)}`,\n );\n return { file: manifestFile, integrity: manifestIntegrity, storage: manifestUpload.storage };\n}\n\ninterface DiffUploadOutcome {\n result: {\n stored: number;\n totalBytes: number;\n integrity: Record<string, string>;\n storage?: \"s3\" | \"memory\";\n };\n /** per-file SRI map covering the whole dist (uploaded → server SRI, skipped → previous manifest SRI) */\n fileIntegrity: Record<string, string>;\n uploaded: number;\n skipped: number;\n total: number;\n}\n\n/**\n * One workspace's upload leg with skip-unchanged diffing: resolve the previous\n * manifest's `files` map, hash the local dist, upload only new/changed files,\n * and return the merged per-file SRI map for the version manifest. Any failure\n * to resolve the previous map degrades to a full upload.\n */\nasync function diffUploadWorkspace(input: {\n origin: string;\n apiKey?: string;\n account: string;\n gateway: string;\n workspace: string;\n files: DistFile[];\n base: string;\n previousPin: PreviousPin | undefined;\n}): Promise<DiffUploadOutcome> {\n const localSri = localSriMap(input.files);\n let uploadFiles = input.files;\n let prevFiles: Record<string, string> | undefined;\n if (input.previousPin) {\n try {\n const resolved = await resolveSlotVersion({ base: input.base, pin: input.previousPin });\n if (resolved.files) {\n const diff = diffWorkspaceFiles(input.files, localSri, resolved.files);\n prevFiles = resolved.files;\n uploadFiles = diff.upload;\n if (diff.skipped > 0) {\n console.log(\n ` ${colors.dim(`${padRight(input.workspace, 28)} ${diff.skipped} unchanged file(s) — skipping (manifest diff)`)}`,\n );\n }\n }\n } catch {\n console.log(\n ` ${colors.dim(`${padRight(input.workspace, 28)} previous manifest unusable — uploading everything`)}`,\n );\n }\n }\n\n console.log(\n ` ${padRight(input.workspace, 28)} uploading ${uploadFiles.length} of ${input.files.length} files (${formatBundleMb(uploadFiles)}) → ${input.base}`,\n );\n const result =\n uploadFiles.length > 0\n ? await uploadWorkspaceDist({\n origin: input.origin,\n apiKey: input.apiKey,\n account: input.account,\n gateway: input.gateway,\n workspace: input.workspace,\n files: uploadFiles,\n })\n : { stored: 0, totalBytes: 0, integrity: {}, storage: undefined };\n return {\n result,\n fileIntegrity: mergedFileIntegrity(input.files, result.integrity, prevFiles),\n uploaded: result.stored,\n skipped: input.files.length - uploadFiles.length,\n total: input.files.length,\n };\n}\n\nfunction formatBundleMb(files: Array<{ bytes: Uint8Array }>): string {\n const total = files.reduce((sum, file) => sum + file.bytes.byteLength, 0);\n return `${(total / 1024 / 1024).toFixed(1)} MB`;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n registry?: string;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n opts.registry,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\nexport async function isConfigAlreadyPublished(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n registry?: string;\n}): Promise<boolean> {\n try {\n const current = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n opts.registry,\n );\n return JSON.stringify(current) === JSON.stringify(opts.publishConfig);\n } catch {\n return false;\n }\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n wallet?: boolean;\n registry?: string;\n /** Skip the diff upload and re-upload every dist file (escape hatch). */\n fullUpload?: boolean;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n fingerprint?: string;\n slotPins?: Record<string, string>;\n}\n\nexport type PublishedConfigState = \"fetched\" | \"missing\" | \"unreachable\";\n\nexport interface PublishPreflightPlan {\n isStaging: boolean;\n account: string;\n gateway: string;\n network: NetworkId;\n registryUrl: string;\n registryNamespace: string;\n targets: string[];\n useWallet: boolean;\n strategy?: SigningStrategy;\n cdnOrigin: string | undefined;\n storageOrigin: string;\n storageApiKey?: string;\n /** The config currently published to FastKV (null when missing or unreachable). */\n publishedConfig: Record<string, unknown> | null;\n /** Whether the preflight FastKV read succeeded, found nothing, or failed. */\n publishedConfigState: PublishedConfigState;\n}\n\nexport type PublishPreflight =\n | { kind: \"dry-run\"; registryUrl: string }\n | { kind: \"error\"; registryUrl: string; error: string }\n | { kind: \"ready\"; plan: PublishPreflightPlan };\n\nconst FRAMEWORK_PACKAGE_NAMES = [\"better-near-auth\", \"every-plugin\", \"everything-dev\"] as const;\n\n/**\n * Whether npm serves `name@version` (true), definitively does not (404 —\n * false), or whether publishability could not be determined (network error,\n * unexpected status — null; callers must not block on that).\n */\nexport async function npmVersionPublished(name: string, version: string): Promise<boolean | null> {\n try {\n const res = await fetchResponse(`https://registry.npmjs.org/${name}/${version}`, {\n headers: { Accept: \"application/json\" },\n });\n if (res.status === 200) return true;\n if (res.status === 404) return false;\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * The npm-publish gate: a workspace that vendors the framework packages'\n * sources must not ship bundles ahead of npm — the update check, child\n * scaffolds (`bos init`), and template syncs all read those versions from\n * the registry. Reads only apply when the sources are workspace-local (the\n * parent repo); child projects install the framework from npm and are\n * inherently in sync.\n */\nexport async function findUnpublishedFrameworkPackages(\n configDir: string,\n): Promise<Array<{ name: string; version: string }>> {\n const unpublished: Array<{ name: string; version: string }> = [];\n for (const name of FRAMEWORK_PACKAGE_NAMES) {\n const manifestPath = join(configDir, \"packages\", name, \"package.json\");\n if (!existsSync(manifestPath)) continue;\n const version = (JSON.parse(readFileSync(manifestPath, \"utf-8\")) as { version?: string })\n .version;\n if (!version) continue;\n const published = await npmVersionPublished(name, version);\n if (published === false) {\n unpublished.push({ name, version });\n } else if (published === null) {\n console.log(\n colors.yellow(\n ` ! Could not verify ${name}@${version} on npm (registry unreachable) — continuing`,\n ),\n );\n }\n }\n return unpublished;\n}\n\n// Pure preflight (resolve, don't mutate) — every failure returns before the\n// build train runs (issue #287). Dry-run exits after the auth guards, before\n// any signing (keychain/TTY side effects).\nexport async function preflightPublish(input: PublishToFastKvInput): Promise<PublishPreflight> {\n const { configDir } = input;\n const bosConfig = input.bosConfig;\n\n const isStaging = input.env === \"staging\";\n const account = isStaging ? (bosConfig.staging?.account ?? bosConfig.account) : bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n kind: \"error\",\n registryUrl: \"\",\n error: \"authored config must define domain to publish\",\n };\n }\n\n const network: NetworkId = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway, input.registry);\n const fail = (error: string): PublishPreflight => ({ kind: \"error\", registryUrl, error });\n\n const publishAuth: PublishConfig[\"auth\"] = bosConfig.publish?.auth;\n const governsWalletPublish = (publishAuth === \"session\" || input.wallet) && !input.privateKey;\n if (governsWalletPublish) {\n const session = readSessionHandle(configDir);\n if (!session?.credential) {\n return fail(\n (input.wallet\n ? \"--wallet requires\"\n : 'the authored config sets publish.auth = \"session\", but') +\n \" no CLI session is stored in .bos/ for this project. Run bos login to create one.\",\n );\n }\n if (session.credential.accountId && session.credential.accountId !== account) {\n return fail(\n `The CLI session was created for ${session.credential.accountId}, but the configured ` +\n `account is ${account}. Gasless wallet publish relays the FastKV write under the session's ` +\n \"NEAR account. Run bos login again under the matching account.\",\n );\n }\n }\n if (publishAuth && !input.privateKey) {\n if (publishAuth === \"custody\") {\n return fail(\n 'the authored config sets publish.auth = \"custody\", but custody publish is not implemented yet (see NEARBuilders/everything-dev#291).',\n );\n }\n }\n\n if (input.dryRun) {\n return { kind: \"dry-run\", registryUrl };\n }\n\n const useWallet = input.wallet === true;\n let strategy: SigningStrategy | undefined;\n if (useWallet) {\n console.log(\n ` Signing via ${colors.cyan(\"gasless NEP-366 delegate action (relayed by the platform relayer)\")}`,\n );\n } else {\n try {\n strategy = await resolveSigningStrategy({ privateKey: input.privateKey, account, network });\n console.log(` Signing via ${colors.cyan(describeSigningStrategy(strategy))}`);\n } catch (error) {\n return fail(error instanceof Error ? error.message : \"Unknown error\");\n }\n }\n\n // CDN deploy credentials (ADR 0020) — resolved before the build train so a\n // missing bundle origin or BOS_STORAGE_API_KEY fails fast instead of after\n // the full build. Config-only publishes ship the committed config verbatim;\n // nothing is uploaded, so no deploy origins are required.\n const session = readSessionHandle(configDir);\n let cdnDeploy: CdnDeployInputs = {\n cdnOrigin: undefined,\n storageOrigin: \"\",\n apiKey: undefined,\n };\n if (input.build) {\n const unpublished = await findUnpublishedFrameworkPackages(configDir);\n if (unpublished.length > 0) {\n const listing = unpublished.map((pkg) => `${pkg.name}@${pkg.version}`).join(\", \");\n return fail(\n `Framework package(s) ${listing} are not published to npm yet — deploys must not ship ` +\n \"bundles ahead of the registry (child scaffolds and update checks read these versions). \" +\n \"Re-run the Release workflow (or `pnpm run release`) first.\",\n );\n }\n\n cdnDeploy = resolveCdnDeployInputs({\n env: process.env as Record<string, string | undefined>,\n bosConfig,\n session: session?.credential ?? null,\n account,\n gateway,\n uploadsPlanned: input.build,\n });\n if (cdnDeploy.error) {\n return fail(cdnDeploy.error);\n }\n if (cdnDeploy.warning) {\n console.log(colors.yellow(` ! ${cdnDeploy.warning}`));\n }\n const cdnOrigin = cdnDeploy.cdnOrigin;\n if (!cdnOrigin) {\n return fail(\"CDN deploy resolved no bundle origin\");\n }\n const probeError = await probeStorageOrigin(cdnDeploy.storageOrigin);\n if (probeError) {\n return fail(\n `The bundle upload origin ${cdnDeploy.storageOrigin} is not running the platform API — ` +\n `${probeError}. Check BOS_STORAGE_ORIGIN / the bos login session, then re-run.`,\n );\n }\n }\n\n // Registry reachability + published-state capture: one FastKV read. A\n // missing config is fine for a first publish — an early signal, not a hard\n // gate. The captured config is the merge base for a config-only publish on\n // a TS-form project (authored hand-edits win; live pipeline state carries).\n let publishedConfig: Record<string, unknown> | null = null;\n let publishedConfigState: PublishedConfigState = \"missing\";\n try {\n publishedConfig = await fetchBosConfigFromFastKv<Record<string, unknown>>(\n registryUrl,\n input.registry,\n );\n publishedConfigState = \"fetched\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.startsWith(\"No config found\")) {\n console.log(colors.dim(\" Note: no published config found yet (first publish) — continuing\"));\n } else {\n publishedConfigState = \"unreachable\";\n console.log(colors.dim(\" Note: registry read failed — continuing\"));\n }\n }\n\n return {\n kind: \"ready\",\n plan: {\n isStaging,\n account,\n gateway,\n network,\n registryUrl,\n registryNamespace: getRegistryNamespaceForNetwork(network, input.registry),\n targets: selectWorkspaceTargets(input.packages, bosConfig),\n useWallet,\n strategy,\n cdnOrigin: cdnDeploy.cdnOrigin,\n storageOrigin: cdnDeploy.storageOrigin,\n storageApiKey: cdnDeploy.apiKey,\n publishedConfig,\n publishedConfigState,\n },\n };\n}\n\n/**\n * The deploy-train publish core (ADR 0020, as amended): preflight\n * (storage/CDN creds + signing) fails fast before the build, then build →\n * upload → version-manifest pin → config write-back → FastKV publish +\n * read-back. Scoped to one plugin via `packages`, a single-plugin redeploy\n * ships real bytes to the storage origin — same as the full train, nothing\n * image-native left.\n */\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const preflight = await preflightPublish(input);\n if (preflight.kind === \"error\") {\n return { status: \"error\", registryUrl: preflight.registryUrl, error: preflight.error };\n }\n if (preflight.kind === \"dry-run\") {\n return { status: \"dry-run\", registryUrl: preflight.registryUrl };\n }\n const plan = preflight.plan;\n const {\n isStaging,\n account,\n gateway,\n network,\n registryUrl,\n registryNamespace,\n targets,\n useWallet,\n strategy,\n } = plan;\n const storageOrigin = plan.storageOrigin;\n const storageApiKey = plan.storageApiKey;\n\n const { configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n let refreshedRawConfig: BosConfigInput | null = null;\n\n if (input.build) {\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await openResolution({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload the config after build\",\n };\n }\n\n bosConfig = refreshed.config;\n refreshedRawConfig = refreshed.rawConfig;\n }\n\n const authoredPath = findConfigPath(configDir);\n const tsForm = authoredPath !== null && isAppDescriptorPath(authoredPath);\n let rawConfig: BosConfigInput;\n if (refreshedRawConfig) {\n rawConfig = refreshedRawConfig;\n } else {\n const opened = await openResolution({ cwd: configDir });\n if (!opened?.rawConfig) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to load the authored config for publish\",\n };\n }\n rawConfig = opened.rawConfig;\n }\n if (tsForm && !input.build && plan.publishedConfigState === \"unreachable\") {\n // A config-only TS-form publish derives its pipeline state from the live\n // published config — publishing without it would wipe bundle URLs.\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error:\n \"Cannot read the currently published config from the registry — a config-only publish would overwrite live bundle URLs. Retry when the registry is reachable, or run a full deploy.\",\n };\n }\n let publishPayload: BosConfigInput =\n tsForm && !input.build\n ? // Config-only publish on a TS-form project: the authored config owns\n // composition (hand-edits win) while live pipeline state (bundle\n // URLs, integrity) carries over from the published config.\n mergeAuthoredOverPublished((plan.publishedConfig ?? {}) as BosConfigInput, rawConfig)\n : rawConfig;\n\n const urlOrigin = plan.cdnOrigin ?? `https://${gateway}`;\n const deployTargets = (built ?? []).filter((key) => targets.includes(key));\n const platformEntries: DeployResultEntry[] = [];\n const fullUpload = input.fullUpload === true || process.env.BOS_FULL_UPLOAD === \"1\";\n // Previous per-workspace pins for the diff upload: the local pointer wins\n // (written after every confirmed publish), the published config is the\n // fallback. Neither → full upload.\n const prevPins: Record<string, PreviousPin> = fullUpload\n ? {}\n : {\n ...pinsFromPublishedConfig(\n (plan.publishedConfig ?? {}) as BosConfigInput,\n account,\n gateway,\n ),\n ...pinsFromDeployState(configDir, account, gateway),\n };\n\n console.log();\n console.log(` CDN deploy — uploading workspace dists to ${storageOrigin}...`);\n for (const key of deployTargets) {\n const ws = resolveWorkspaceTarget(key, bosConfig, runtimeConfig, configDir);\n if (!ws) continue;\n\n const distFiles = await collectDistFiles(join(ws.path, \"dist\"));\n const workspaceBase = `${urlOrigin}/bundles/${account}/${gateway}/${key}/`;\n const startedAt = Date.now();\n // an upload failure aborts the train as a structured error — the\n // previously published version stays fully live (ticket 05)\n let outcome: DiffUploadOutcome;\n try {\n outcome = await diffUploadWorkspace({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: key,\n files: distFiles,\n base: workspaceBase,\n previousPin: prevPins[key],\n });\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: error instanceof Error ? error.message : `[publish] bundle upload for ${key} failed`,\n };\n }\n const report = readBuildReport(join(ws.path, \"dist\"));\n const ssrReport = readBuildReport(join(ws.path, \"dist\", \"ssr\"));\n // the entry SRI keyed by the build report's hashed name\n const integrity = report ? outcome.fileIntegrity[report.entry] : undefined;\n const ssrIntegrity = ssrReport?.entry\n ? outcome.fileIntegrity[`ssr/${ssrReport.entry}`]\n : undefined;\n\n const manifestPointer = await pinWorkspaceVersionManifest({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: key,\n report,\n ssrReport,\n integrityMap: outcome.fileIntegrity,\n files: outcome.fileIntegrity,\n });\n if (!manifestPointer) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `bundle upload for ${key}: version manifest missing — the dist predates hashed entry names (rebuild required; atomic-deploys hard break)`,\n };\n }\n\n if (outcome.result.storage === \"memory\" || manifestPointer.storage === \"memory\") {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error:\n \"The receiving instance is serving bundle storage from memory (BOS_STORAGE_* R2 credentials are not configured there) — uploaded bytes would be lost on restart. Aborting before publish.\",\n };\n }\n\n console.log(\n ` ${colors.green(icons.ok)} ${padRight(key, 28)} → ${urlOrigin}/bundles/${account}/${gateway}/${key}/ (${outcome.uploaded} uploaded, ${outcome.skipped} skipped, ${formatDuration(Date.now() - startedAt)})`,\n );\n\n platformEntries.push(\n ...platformUrlDeployEntries({\n origin: urlOrigin,\n account,\n gateway,\n key,\n kind: ws.kind,\n integrity,\n ssrIntegrity,\n pin: manifestPointer,\n }),\n );\n\n // Folder-form plugin ui: the workspace build also produces <plugin>/ui/dist\n // (web remoteEntry + ssr container) — upload it as its own bundle key and\n // pin <slot>.<key>.ui.* so the host can compose the ui surface in production.\n if (hasFolderFormUi(ws.path)) {\n const uiDistDir = join(ws.path, \"ui\", \"dist\");\n const uiSlot = ws.kind === \"app\" ? \"app\" : \"plugins\";\n const rawSlot = (uiSlot === \"app\" ? rawConfig.app : rawConfig.plugins) as\n | Record<string, Record<string, unknown> | undefined>\n | undefined;\n const rawUi = rawSlot?.[key]?.ui as Record<string, unknown> | undefined;\n const uiName = resolveUiRuntimeName(rawUi, join(ws.path, \"ui\"), key);\n let uiIntegrity: string | undefined;\n let uiSsrIntegrity: string | undefined;\n let uiManifestPointer: VersionManifestPin | undefined;\n if (existsSync(uiDistDir)) {\n const uiDistFiles = await collectDistFiles(uiDistDir);\n const uiStartedAt = Date.now();\n const uiOutcome = await diffUploadWorkspace({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: `${key}-ui`,\n files: uiDistFiles,\n base: `${urlOrigin}/bundles/${account}/${gateway}/${key}-ui/`,\n previousPin: prevPins[`${key}-ui`],\n });\n const uiReport = readBuildReport(uiDistDir);\n const uiSsrReport = readBuildReport(join(uiDistDir, \"ssr\"));\n uiIntegrity = uiReport ? uiOutcome.fileIntegrity[uiReport.entry] : undefined;\n uiSsrIntegrity = uiSsrReport?.entry\n ? uiOutcome.fileIntegrity[`ssr/${uiSsrReport.entry}`]\n : undefined;\n\n uiManifestPointer = await pinWorkspaceVersionManifest({\n origin: storageOrigin,\n apiKey: storageApiKey,\n account,\n gateway,\n workspace: `${key}-ui`,\n report: uiReport,\n ssrReport: uiSsrReport,\n integrityMap: uiOutcome.fileIntegrity,\n files: uiOutcome.fileIntegrity,\n });\n if (!uiManifestPointer) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `bundle upload for ${key}-ui: version manifest missing — the dist predates hashed entry names (rebuild required; atomic-deploys hard break)`,\n };\n }\n\n if (uiOutcome.result.storage === \"memory\" || uiManifestPointer.storage === \"memory\") {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error:\n \"The receiving instance is serving bundle storage from memory (BOS_STORAGE_* R2 credentials are not configured there) — uploaded bytes would be lost on restart. Aborting before publish.\",\n };\n }\n\n console.log(\n ` ${colors.green(icons.ok)} ${padRight(`${key}-ui`, 28)} → ${urlOrigin}/bundles/${account}/${gateway}/${key}-ui/ (${uiOutcome.uploaded} uploaded, ${uiOutcome.skipped} skipped, ${formatDuration(Date.now() - uiStartedAt)})`,\n );\n } else {\n console.log(\n ` ${colors.green(icons.ok)} ${padRight(`${key}-ui`, 28)} → ${urlOrigin}/bundles/${account}/${gateway}/${key}-ui/`,\n );\n }\n\n platformEntries.push(\n ...pluginUiUrlDeployEntries({\n origin: urlOrigin,\n account,\n gateway,\n key,\n kind: ws.kind,\n integrity: uiIntegrity,\n ssrIntegrity: uiSsrIntegrity,\n name: uiName,\n pin: uiManifestPointer,\n }),\n );\n }\n }\n\n if (platformEntries.length > 0) {\n const merged = applyDeployResults(rawConfig as Record<string, unknown>, platformEntries);\n if (!tsForm) {\n // Legacy JSON-form children keep their local write-back; TS-form keeps\n // pipeline state in FastKV only — a write-back would shadow the\n // authored bos.app.ts descriptor.\n try {\n writeFileSync(join(configDir, \"bos.config.json\"), `${JSON.stringify(merged, null, 2)}\\n`);\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `Failed to write bundle URLs to bos.config.json: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n publishPayload = merged as BosConfigInput;\n }\n if (isStaging) {\n publishPayload = { ...publishPayload, domain: gateway };\n }\n\n const pinVerification = await verifyRollbackSnapshot(publishPayload);\n if (pinVerification.verifiable && !pinVerification.ok) {\n const failures = pinVerification.slots\n .filter((check) => !check.ok)\n .map((check) => ` ${check.slot}: ${check.reason}`)\n .join(\"\\n\");\n console.error(\n ` ${colors.error(icons.err)} Publish blocked — a pinned slot's bytes do not serve at its production URL:\\n${failures}`,\n );\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `Publish blocked — pinned slot bytes missing or SRI mismatched:\\n${failures}`,\n };\n }\n\n const registryKey = `apps/${account}/${gateway}/bos.config.json`;\n const publishedAt = new Date().toISOString();\n // version identity printed + returned for every deploy (atomic-deploys 12)\n const fingerprint = pointerFingerprint(publishPayload as never);\n const publishSlotPins = slotPins(publishPayload as never);\n const registryEntries: Record<string, string> = {\n [registryKey]: JSON.stringify(publishPayload),\n };\n const manifestKey = `apps/${account}/${gateway}/manifests/${publishedAt.replace(/[:.]/g, \"-\")}.json`;\n registryEntries[manifestKey] = JSON.stringify({\n account,\n gateway,\n network,\n publishedAt,\n registryUrl,\n });\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n console.log(` ${colors.dim(\"Fingerprint:\")} ${fingerprint}`);\n for (const [slot, pin] of Object.entries(publishSlotPins)) {\n console.log(` ${colors.dim(`${slot}:`)}`);\n console.log(` ${pin}`);\n }\n console.log(\n ` ${colors.dim(`+ per-deploy manifest ${manifestKey.split(\"/\").pop()} (audit trail)`)}`,\n );\n\n // Record the live pins for the next deploy's diff upload — only after the\n // config is confirmed published, so the pointer never claims undeployed state.\n const persistDeployState = () => {\n try {\n const pins = pinsFromPublishedConfig(publishPayload as BosConfigInput, account, gateway);\n if (Object.keys(pins).length > 0) {\n upsertDeployStatePins(configDir, account, gateway, pins);\n }\n } catch (error) {\n console.log(\n colors.dim(\n ` Note: could not update .bos/deploy-state.json — ${error instanceof Error ? error.message : String(error)}`,\n ),\n );\n }\n };\n\n try {\n const alreadyPublished = await isConfigAlreadyPublished({\n account,\n gateway,\n publishConfig: publishPayload,\n registry: input.registry,\n });\n if (alreadyPublished) {\n console.log(\" Already up to date — skipping transaction\");\n persistDeployState();\n return {\n status: \"published\",\n registryUrl,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n }\n\n console.log(` Submitting transaction on ${network}...`);\n\n let result: { success: boolean; txHash?: string };\n if (useWallet) {\n const session = readSessionHandle(configDir);\n const credential = session?.credential;\n if (!credential || credential.accountId !== account) {\n return {\n status: \"error\",\n registryUrl,\n error: `--wallet requires a CLI session under ${account}. Run bos login first.`,\n };\n }\n const record = await ensureDelegateKey({\n configDir,\n account,\n contract: registryNamespace,\n network,\n siteUrl: credential.siteUrl,\n });\n result = await submitRegistryWriteDelegated({\n account,\n contract: registryNamespace,\n network,\n args: registryEntries,\n delegatePrivateKey: record.privateKey,\n relayEndpoint: `${credential.siteUrl}/api/auth/near/relay`,\n apiKey: credential.apiKey,\n });\n } else {\n if (!strategy) {\n return {\n status: \"error\",\n registryUrl,\n error: \"non-wallet publish requires a resolved signing strategy\",\n };\n }\n result = await submitRegistryWrite(\n {\n account,\n contract: registryNamespace,\n method: \"__fastdata_kv\",\n args: registryEntries,\n network,\n privateKey: input.privateKey,\n },\n strategy,\n );\n }\n\n if (result.txHash) {\n console.log(` Transaction submitted: ${colors.dim(result.txHash)}`);\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n registry: input.registry,\n });\n persistDeployState();\n\n return {\n status: \"published\",\n registryUrl,\n txHash: result.txHash,\n fingerprint,\n slotPins: publishSlotPins,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"does not have enough allowance\")) {\n return (\n \"The publish access key has insufficient allowance to cover this transaction.\\n\" +\n \" Regenerate your key with a higher allowance:\\n\" +\n \" bos key generate\\n\" +\n ` Original: ${message}`\n );\n }\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,SAAS,MAAM,IAA2B;CACxC,OAAO,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAqBA,eAAe,4BAA4B,OAWC;CAC1C,IAAI,CAAC,MAAM,QAAQ,OAAO;CAC1B,MAAM,kBAAkB,gCAAgC;EACtD,QAAQ,MAAM;EACd,WAAW,MAAM;EACjB,cAAc,MAAM;EACpB,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;CAC9C,CAAC;CACD,IAAI,CAAC,iBAAiB,OAAO;CAE7B,MAAM,eAAe,YAAY,gBAAgB,QAAQ;CACzD,MAAM,iBAAiB,MAAM,aAAa;EACxC,QAAQ,MAAM;EACd,QAAQ,MAAM;EACd,SAAS,MAAM;EACf,SAAS,MAAM;EACf,WAAW,MAAM;EACjB,OAAO,CACL;GACE,MAAM;GACN,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,GAAG,KAAK,UAAU,iBAAiB,MAAM,CAAC,EAAE,GAAG;EACjF,CACF;CACF,CAAC;CACD,MAAM,oBAAoB,eAAe,UAAU;CACnD,IAAI,CAAC,mBAAmB,OAAO;CAC/B,QAAQ,IACN,OAAO,OAAO,IAAI,GAAG,SAAS,IAAI,EAAE,EAAE,oBAAoB,aAAa,cAAc,GACvF;CACA,OAAO;EAAE,MAAM;EAAc,WAAW;EAAmB,SAAS,eAAe;CAAQ;AAC7F;;;;;;;AAsBA,eAAe,oBAAoB,OASJ;CAC7B,MAAM,WAAW,YAAY,MAAM,KAAK;CACxC,IAAI,cAAc,MAAM;CACxB,IAAI;CACJ,IAAI,MAAM,aACR,IAAI;EACF,MAAM,WAAW,MAAM,mBAAmB;GAAE,MAAM,MAAM;GAAM,KAAK,MAAM;EAAY,CAAC;EACtF,IAAI,SAAS,OAAO;GAClB,MAAM,OAAO,mBAAmB,MAAM,OAAO,UAAU,SAAS,KAAK;GACrE,YAAY,SAAS;GACrB,cAAc,KAAK;GACnB,IAAI,KAAK,UAAU,GACjB,QAAQ,IACN,OAAO,OAAO,IAAI,GAAG,SAAS,MAAM,WAAW,EAAE,EAAE,GAAG,KAAK,QAAQ,8CAA8C,GACnH;EAEJ;CACF,QAAQ;EACN,QAAQ,IACN,OAAO,OAAO,IAAI,GAAG,SAAS,MAAM,WAAW,EAAE,EAAE,mDAAmD,GACxG;CACF;CAGF,QAAQ,IACN,OAAO,SAAS,MAAM,WAAW,EAAE,EAAE,aAAa,YAAY,OAAO,MAAM,MAAM,MAAM,OAAO,UAAU,eAAe,WAAW,EAAE,MAAM,MAAM,MAClJ;CACA,MAAM,SACJ,YAAY,SAAS,IACjB,MAAM,oBAAoB;EACxB,QAAQ,MAAM;EACd,QAAQ,MAAM;EACd,SAAS,MAAM;EACf,SAAS,MAAM;EACf,WAAW,MAAM;EACjB,OAAO;CACT,CAAC,IACD;EAAE,QAAQ;EAAG,YAAY;EAAG,WAAW,CAAC;EAAG,SAAS;CAAU;CACpE,OAAO;EACL;EACA,eAAe,oBAAoB,MAAM,OAAO,OAAO,WAAW,SAAS;EAC3E,UAAU,OAAO;EACjB,SAAS,MAAM,MAAM,SAAS,YAAY;EAC1C,OAAO,MAAM,MAAM;CACrB;AACF;AAEA,SAAS,eAAe,OAA6C;CAEnE,OAAO,IADO,MAAM,QAAQ,KAAK,SAAS,MAAM,KAAK,MAAM,YAAY,CACxD,IAAI,OAAO,KAAI,CAAE,QAAQ,CAAC,EAAE;AAC7C;AAEA,eAAsB,uBAAuB,MAO3B;CAChB,MAAM,eAAe,OAAO,QAAQ,IAAI,mCAAmC;CAC3E,MAAM,gBAAgB,OAAO,QAAQ,IAAI,oCAAoC;CAC7E,MAAM,YACJ,KAAK,cAAc,OAAO,SAAS,YAAY,IAAI,eAAe,WAAc;CAClF,MAAM,aACJ,KAAK,eAAe,OAAO,SAAS,aAAa,IAAI,gBAAgB,WAAc;CACrF,MAAM,YAAY,KAAK,IAAI;CAC3B,IAAI;CAEJ,OAAO,KAAK,IAAI,IAAI,YAAY,WAAW;EACzC,IAAI;GACF,MAAM,iBAAiB,MAAM,yBAC3B,SAAS,KAAK,QAAQ,GAAG,KAAK,WAC9B,KAAK,QACP;GAEA,IAAI,KAAK,UAAU,cAAc,MAAM,KAAK,UAAU,KAAK,aAAa,GACtE;EAEJ,SAAS,OAAO;GACd,YAAY;EACd;EAEA,MAAM,MAAM,UAAU;CACxB;CAEA,MAAM,SAAS,qBAAqB,QAAQ,gBAAgB,UAAU,YAAY;CAClF,MAAM,IAAI,MACR,uDAAuD,KAAK,QAAQ,GAAG,KAAK,QAAQ,GAAG,QACzF;AACF;AAEA,eAAsB,yBAAyB,MAK1B;CACnB,IAAI;EACF,MAAM,UAAU,MAAM,yBACpB,SAAS,KAAK,QAAQ,GAAG,KAAK,WAC9B,KAAK,QACP;EACA,OAAO,KAAK,UAAU,OAAO,MAAM,KAAK,UAAU,KAAK,aAAa;CACtE,QAAQ;EACN,OAAO;CACT;AACF;AA0DA,MAAM,0BAA0B;CAAC;CAAoB;CAAgB;AAAgB;;;;;;AAOrF,eAAsB,oBAAoB,MAAc,SAA0C;CAChG,IAAI;EACF,MAAM,MAAM,MAAM,cAAc,8BAA8B,KAAK,GAAG,WAAW,EAC/E,SAAS,EAAE,QAAQ,mBAAmB,EACxC,CAAC;EACD,IAAI,IAAI,WAAW,KAAK,OAAO;EAC/B,IAAI,IAAI,WAAW,KAAK,OAAO;EAC/B,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;AAUA,eAAsB,iCACpB,WACmD;CACnD,MAAM,cAAwD,CAAC;CAC/D,KAAK,MAAM,QAAQ,yBAAyB;EAC1C,MAAM,eAAe,KAAK,WAAW,YAAY,MAAM,cAAc;EACrE,IAAI,CAAC,WAAW,YAAY,GAAG;EAC/B,MAAM,UAAW,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC,CAAC,CAC7D;EACH,IAAI,CAAC,SAAS;EACd,MAAM,YAAY,MAAM,oBAAoB,MAAM,OAAO;EACzD,IAAI,cAAc,OAChB,YAAY,KAAK;GAAE;GAAM;EAAQ,CAAC;OAC7B,IAAI,cAAc,MACvB,QAAQ,IACN,OAAO,OACL,wBAAwB,KAAK,GAAG,QAAQ,4CAC1C,CACF;CAEJ;CACA,OAAO;AACT;AAKA,eAAsB,iBAAiB,OAAwD;CAC7F,MAAM,EAAE,cAAc;CACtB,MAAM,YAAY,MAAM;CAExB,MAAM,YAAY,MAAM,QAAQ;CAChC,MAAM,UAAU,YAAa,UAAU,SAAS,WAAW,UAAU,UAAW,UAAU;CAC1F,MAAM,UAAU,YAAa,UAAU,SAAS,UAAU,UAAU,SAAU,UAAU;CACxF,IAAI,CAAC,SACH,OAAO;EACL,MAAM;EACN,aAAa;EACb,OAAO;CACT;CAGF,MAAM,UAAqB,MAAM,WAAW,uBAAuB,OAAO;CAC1E,MAAM,cAAc,iCAAiC,SAAS,SAAS,SAAS,MAAM,QAAQ;CAC9F,MAAM,QAAQ,WAAqC;EAAE,MAAM;EAAS;EAAa;CAAM;CAEvF,MAAM,cAAqC,UAAU,SAAS;CAE9D,KAD8B,gBAAgB,aAAa,MAAM,WAAW,CAAC,MAAM,YACzD;EACxB,MAAM,UAAU,kBAAkB,SAAS;EAC3C,IAAI,CAAC,SAAS,YACZ,OAAO,MACJ,MAAM,SACH,sBACA,8DACF,mFACJ;EAEF,IAAI,QAAQ,WAAW,aAAa,QAAQ,WAAW,cAAc,SACnE,OAAO,KACL,mCAAmC,QAAQ,WAAW,UAAU,kCAChD,QAAQ,mIAE1B;CAEJ;CACA,IAAI,eAAe,CAAC,MAAM,YACxB;MAAI,gBAAgB,WAClB,OAAO,KACL,wIACF;CACF;CAGF,IAAI,MAAM,QACR,OAAO;EAAE,MAAM;EAAW;CAAY;CAGxC,MAAM,YAAY,MAAM,WAAW;CACnC,IAAI;CACJ,IAAI,WACF,QAAQ,IACN,iBAAiB,OAAO,KAAK,mEAAmE,GAClG;MAEA,IAAI;EACF,WAAW,MAAM,uBAAuB;GAAE,YAAY,MAAM;GAAY;GAAS;EAAQ,CAAC;EAC1F,QAAQ,IAAI,iBAAiB,OAAO,KAAK,wBAAwB,QAAQ,CAAC,GAAG;CAC/E,SAAS,OAAO;EACd,OAAO,KAAK,iBAAiB,QAAQ,MAAM,UAAU,eAAe;CACtE;CAOF,MAAM,UAAU,kBAAkB,SAAS;CAC3C,IAAI,YAA6B;EAC/B,WAAW;EACX,eAAe;EACf,QAAQ;CACV;CACA,IAAI,MAAM,OAAO;EACf,MAAM,cAAc,MAAM,iCAAiC,SAAS;EACpE,IAAI,YAAY,SAAS,GAEvB,OAAO,KACL,wBAFc,YAAY,KAAK,QAAQ,GAAG,IAAI,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,KAAK,IAE5C,EAAE,0MAGlC;EAGF,YAAY,uBAAuB;GACjC,KAAK,QAAQ;GACb;GACA,SAAS,SAAS,cAAc;GAChC;GACA;GACA,gBAAgB,MAAM;EACxB,CAAC;EACD,IAAI,UAAU,OACZ,OAAO,KAAK,UAAU,KAAK;EAE7B,IAAI,UAAU,SACZ,QAAQ,IAAI,OAAO,OAAO,OAAO,UAAU,SAAS,CAAC;EAGvD,IAAI,CADc,UAAU,WAE1B,OAAO,KAAK,sCAAsC;EAEpD,MAAM,aAAa,MAAM,mBAAmB,UAAU,aAAa;EACnE,IAAI,YACF,OAAO,KACL,4BAA4B,UAAU,cAAc,qCAC/C,WAAW,iEAClB;CAEJ;CAMA,IAAI,kBAAkD;CACtD,IAAI,uBAA6C;CACjD,IAAI;EACF,kBAAkB,MAAM,yBACtB,aACA,MAAM,QACR;EACA,uBAAuB;CACzB,SAAS,OAAO;EAEd,KADgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAC1D,CAAC,WAAW,iBAAiB,GACtC,QAAQ,IAAI,OAAO,IAAI,oEAAoE,CAAC;OACvF;GACL,uBAAuB;GACvB,QAAQ,IAAI,OAAO,IAAI,2CAA2C,CAAC;EACrE;CACF;CAEA,OAAO;EACL,MAAM;EACN,MAAM;GACJ;GACA;GACA;GACA;GACA;GACA,mBAAmB,+BAA+B,SAAS,MAAM,QAAQ;GACzE,SAAS,uBAAuB,MAAM,UAAU,SAAS;GACzD;GACA;GACA,WAAW,UAAU;GACrB,eAAe,UAAU;GACzB,eAAe,UAAU;GACzB;GACA;EACF;CACF;AACF;;;;;;;;;AAUA,eAAsB,gBAAgB,OAA6D;CACjG,MAAM,YAAY,MAAM,iBAAiB,KAAK;CAC9C,IAAI,UAAU,SAAS,SACrB,OAAO;EAAE,QAAQ;EAAS,aAAa,UAAU;EAAa,OAAO,UAAU;CAAM;CAEvF,IAAI,UAAU,SAAS,WACrB,OAAO;EAAE,QAAQ;EAAW,aAAa,UAAU;CAAY;CAEjE,MAAM,OAAO,UAAU;CACvB,MAAM,EACJ,WACA,SACA,SACA,SACA,aACA,mBACA,SACA,WACA,aACE;CACJ,MAAM,gBAAgB,KAAK;CAC3B,MAAM,gBAAgB,KAAK;CAE3B,MAAM,EAAE,cAAc;CACtB,IAAI,YAAY,MAAM;CACtB,MAAM,gBAAgB,MAAM;CAC5B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,qBAA4C;CAEhD,IAAI,MAAM,OAAO;EACf,MAAM,sBAAsB,WAAW,WAAW;GAChD,KAAK;GACL,eAAe,iBAAiB;EAClC,CAAC;EAED,MAAM,SAAS,MAAM,sBAAsB;GACzC;GACA;GACA;GACA;GACA,QAAQ;GACR,SAAS,MAAM;EACjB,CAAC;EACD,QAAQ,OAAO;EACf,UAAU,OAAO;EACjB,gBAAgB,OAAO;EAEvB,IAAI,eAAe;GACjB,MAAM,WAAW,cAAc,QAAQ,MAAM,CAAC,EAAE,OAAO;GACvD,IAAI,SAAS,SAAS,GAAG;IACvB,MAAM,QAAQ,cAAc;IAC5B,QAAQ,IAAI;IACZ,QAAQ,IACN,OAAO,MACL,KAAK,MAAM,IAAI,mBAAmB,SAAS,OAAO,MAAM,MAAM,YAAY,QAAQ,IAAI,MAAM,GAAG,QACjG,CACF;IACA,QAAQ,IAAI;IACZ,KAAK,MAAM,KAAK,UAAU;KACxB,MAAM,aAAa,EAAE,SAAS,SAAQ,CAAE,MAAM,IAAI,CAAC,CAAC;KACpD,QAAQ,IAAI,OAAO,OAAO,MAAM,MAAM,GAAG,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,EAAE,GAAG,WAAW;IAClF;IACA,QAAQ,IAAI;IACZ,IAAI,CAAC,MAAM,SAAS;KAClB,QAAQ,IAAI,OAAO,IAAI,6CAA6C,CAAC;KACrE,QAAQ,IAAI;IACd;IACA,OAAO;KACL,QAAQ;KACR;KACA;KACA;KACA;KACA,OAAO,GAAG,SAAS,OAAO,MAAM,MAAM;IACxC;GACF;EACF;EAEA,MAAM,YAAY,MAAM,eAAe,EAAE,KAAK,UAAU,CAAC;EACzD,IAAI,CAAC,WAAW,QACd,OAAO;GACL,QAAQ;GACR;GACA;GACA;GACA;GACA,OAAO;EACT;EAGF,YAAY,UAAU;EACtB,qBAAqB,UAAU;CACjC;CAEA,MAAM,eAAe,eAAe,SAAS;CAC7C,MAAM,SAAS,iBAAiB,QAAQ,oBAAoB,YAAY;CACxE,IAAI;CACJ,IAAI,oBACF,YAAY;MACP;EACL,MAAM,SAAS,MAAM,eAAe,EAAE,KAAK,UAAU,CAAC;EACtD,IAAI,CAAC,QAAQ,WACX,OAAO;GACL,QAAQ;GACR;GACA;GACA;GACA;GACA,OAAO;EACT;EAEF,YAAY,OAAO;CACrB;CACA,IAAI,UAAU,CAAC,MAAM,SAAS,KAAK,yBAAyB,eAG1D,OAAO;EACL,QAAQ;EACR;EACA;EACA;EACA;EACA,OACE;CACJ;CAEF,IAAI,iBACF,UAAU,CAAC,MAAM,QAIb,2BAA4B,KAAK,mBAAmB,CAAC,GAAsB,SAAS,IACpF;CAEN,MAAM,YAAY,KAAK,aAAa,WAAW;CAC/C,MAAM,iBAAiB,SAAS,CAAC,EAAC,CAAE,QAAQ,QAAQ,QAAQ,SAAS,GAAG,CAAC;CACzE,MAAM,kBAAuC,CAAC;CAK9C,MAAM,WAJa,MAAM,eAAe,QAAQ,QAAQ,IAAI,oBAAoB,MAK5E,CAAC,IACD;EACE,GAAG,wBACA,KAAK,mBAAmB,CAAC,GAC1B,SACA,OACF;EACA,GAAG,oBAAoB,WAAW,SAAS,OAAO;CACpD;CAEJ,QAAQ,IAAI;CACZ,QAAQ,IAAI,+CAA+C,cAAc,IAAI;CAC7E,KAAK,MAAM,OAAO,eAAe;EAC/B,MAAM,KAAK,uBAAuB,KAAK,WAAW,eAAe,SAAS;EAC1E,IAAI,CAAC,IAAI;EAET,MAAM,YAAY,MAAM,iBAAiB,KAAK,GAAG,MAAM,MAAM,CAAC;EAC9D,MAAM,gBAAgB,GAAG,UAAU,WAAW,QAAQ,GAAG,QAAQ,GAAG,IAAI;EACxE,MAAM,YAAY,KAAK,IAAI;EAG3B,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,oBAAoB;IAClC,QAAQ;IACR,QAAQ;IACR;IACA;IACA,WAAW;IACX,OAAO;IACP,MAAM;IACN,aAAa,SAAS;GACxB,CAAC;EACH,SAAS,OAAO;GACd,OAAO;IACL,QAAQ;IACR;IACA;IACA;IACA;IACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,+BAA+B,IAAI;GACrF;EACF;EACA,MAAM,SAAS,gBAAgB,KAAK,GAAG,MAAM,MAAM,CAAC;EACpD,MAAM,YAAY,gBAAgB,KAAK,GAAG,MAAM,QAAQ,KAAK,CAAC;EAE9D,MAAM,YAAY,SAAS,QAAQ,cAAc,OAAO,SAAS;EACjE,MAAM,eAAe,WAAW,QAC5B,QAAQ,cAAc,OAAO,UAAU,WACvC;EAEJ,MAAM,kBAAkB,MAAM,4BAA4B;GACxD,QAAQ;GACR,QAAQ;GACR;GACA;GACA,WAAW;GACX;GACA;GACA,cAAc,QAAQ;GACtB,OAAO,QAAQ;EACjB,CAAC;EACD,IAAI,CAAC,iBACH,OAAO;GACL,QAAQ;GACR;GACA;GACA;GACA;GACA,OAAO,qBAAqB,IAAI;EAClC;EAGF,IAAI,QAAQ,OAAO,YAAY,YAAY,gBAAgB,YAAY,UACrE,OAAO;GACL,QAAQ;GACR;GACA;GACA;GACA;GACA,OACE;EACJ;EAGF,QAAQ,IACN,OAAO,OAAO,MAAM,MAAM,EAAE,EAAE,GAAG,SAAS,KAAK,EAAE,EAAE,KAAK,UAAU,WAAW,QAAQ,GAAG,QAAQ,GAAG,IAAI,KAAK,QAAQ,SAAS,aAAa,QAAQ,QAAQ,YAAY,eAAe,KAAK,IAAI,IAAI,SAAS,EAAE,EAC/M;EAEA,gBAAgB,KACd,GAAG,yBAAyB;GAC1B,QAAQ;GACR;GACA;GACA;GACA,MAAM,GAAG;GACT;GACA;GACA,KAAK;EACP,CAAC,CACH;EAKA,IAAI,gBAAgB,GAAG,IAAI,GAAG;GAC5B,MAAM,YAAY,KAAK,GAAG,MAAM,MAAM,MAAM;GAK5C,MAAM,UAJS,GAAG,SAAS,QAAQ,QAAQ,eACf,QAAQ,UAAU,MAAM,UAAU,QAGzC,GAAG,IAAI,EAAE;GAC9B,MAAM,SAAS,qBAAqB,OAAO,KAAK,GAAG,MAAM,IAAI,GAAG,GAAG;GACnE,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI,WAAW,SAAS,GAAG;IACzB,MAAM,cAAc,MAAM,iBAAiB,SAAS;IACpD,MAAM,cAAc,KAAK,IAAI;IAC7B,MAAM,YAAY,MAAM,oBAAoB;KAC1C,QAAQ;KACR,QAAQ;KACR;KACA;KACA,WAAW,GAAG,IAAI;KAClB,OAAO;KACP,MAAM,GAAG,UAAU,WAAW,QAAQ,GAAG,QAAQ,GAAG,IAAI;KACxD,aAAa,SAAS,GAAG,IAAI;IAC/B,CAAC;IACD,MAAM,WAAW,gBAAgB,SAAS;IAC1C,MAAM,cAAc,gBAAgB,KAAK,WAAW,KAAK,CAAC;IAC1D,cAAc,WAAW,UAAU,cAAc,SAAS,SAAS;IACnE,iBAAiB,aAAa,QAC1B,UAAU,cAAc,OAAO,YAAY,WAC3C;IAEJ,oBAAoB,MAAM,4BAA4B;KACpD,QAAQ;KACR,QAAQ;KACR;KACA;KACA,WAAW,GAAG,IAAI;KAClB,QAAQ;KACR,WAAW;KACX,cAAc,UAAU;KACxB,OAAO,UAAU;IACnB,CAAC;IACD,IAAI,CAAC,mBACH,OAAO;KACL,QAAQ;KACR;KACA;KACA;KACA;KACA,OAAO,qBAAqB,IAAI;IAClC;IAGF,IAAI,UAAU,OAAO,YAAY,YAAY,kBAAkB,YAAY,UACzE,OAAO;KACL,QAAQ;KACR;KACA;KACA;KACA;KACA,OACE;IACJ;IAGF,QAAQ,IACN,OAAO,OAAO,MAAM,MAAM,EAAE,EAAE,GAAG,SAAS,GAAG,IAAI,MAAM,EAAE,EAAE,KAAK,UAAU,WAAW,QAAQ,GAAG,QAAQ,GAAG,IAAI,QAAQ,UAAU,SAAS,aAAa,UAAU,QAAQ,YAAY,eAAe,KAAK,IAAI,IAAI,WAAW,EAAE,EAChO;GACF,OACE,QAAQ,IACN,OAAO,OAAO,MAAM,MAAM,EAAE,EAAE,GAAG,SAAS,GAAG,IAAI,MAAM,EAAE,EAAE,KAAK,UAAU,WAAW,QAAQ,GAAG,QAAQ,GAAG,IAAI,KACjH;GAGF,gBAAgB,KACd,GAAG,yBAAyB;IAC1B,QAAQ;IACR;IACA;IACA;IACA,MAAM,GAAG;IACT,WAAW;IACX,cAAc;IACd,MAAM;IACN,KAAK;GACP,CAAC,CACH;EACF;CACF;CAEA,IAAI,gBAAgB,SAAS,GAAG;EAC9B,MAAM,SAAS,mBAAmB,WAAsC,eAAe;EACvF,IAAI,CAAC,QAIH,IAAI;GACF,cAAc,KAAK,WAAW,iBAAiB,GAAG,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;EAC1F,SAAS,OAAO;GACd,OAAO;IACL,QAAQ;IACR;IACA;IACA;IACA;IACA,OAAO,mDAAmD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GACjH;EACF;EAEF,iBAAiB;CACnB;CACA,IAAI,WACF,iBAAiB;EAAE,GAAG;EAAgB,QAAQ;CAAQ;CAGxD,MAAM,kBAAkB,MAAM,uBAAuB,cAAc;CACnE,IAAI,gBAAgB,cAAc,CAAC,gBAAgB,IAAI;EACrD,MAAM,WAAW,gBAAgB,MAC9B,QAAQ,UAAU,CAAC,MAAM,EAAE,CAAC,CAC5B,KAAK,UAAU,OAAO,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC,CACpD,KAAK,IAAI;EACZ,QAAQ,MACN,KAAK,OAAO,MAAM,MAAM,GAAG,EAAE,gFAAgF,UAC/G;EACA,OAAO;GACL,QAAQ;GACR;GACA;GACA;GACA;GACA,OAAO,mEAAmE;EAC5E;CACF;CAEA,MAAM,cAAc,QAAQ,QAAQ,GAAG,QAAQ;CAC/C,MAAM,+BAAc,IAAI,KAAK,EAAC,CAAC,YAAY;CAE3C,MAAM,cAAc,mBAAmB,cAAuB;CAC9D,MAAM,kBAAkB,SAAS,cAAuB;CACxD,MAAM,kBAA0C,GAC7C,cAAc,KAAK,UAAU,cAAc,EAC9C;CACA,MAAM,cAAc,QAAQ,QAAQ,GAAG,QAAQ,aAAa,YAAY,QAAQ,SAAS,GAAG,EAAE;CAC9F,gBAAgB,eAAe,KAAK,UAAU;EAC5C;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,QAAQ,IAAI;CACZ,QAAQ,IAAI,kBAAkB;CAC9B,QAAQ,IAAI,OAAO,OAAO,KAAK,WAAW,GAAG;CAC7C,QAAQ,IAAI,OAAO,OAAO,IAAI,cAAc,EAAE,GAAG,aAAa;CAC9D,KAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,eAAe,GAAG;EACzD,QAAQ,IAAI,OAAO,OAAO,IAAI,GAAG,KAAK,EAAE,GAAG;EAC3C,QAAQ,IAAI,SAAS,KAAK;CAC5B;CACA,QAAQ,IACN,OAAO,OAAO,IAAI,yBAAyB,YAAY,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,eAAe,GACzF;CAIA,MAAM,2BAA2B;EAC/B,IAAI;GACF,MAAM,OAAO,wBAAwB,gBAAkC,SAAS,OAAO;GACvF,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS,GAC7B,sBAAsB,WAAW,SAAS,SAAS,IAAI;EAE3D,SAAS,OAAO;GACd,QAAQ,IACN,OAAO,IACL,qDAAqD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC5G,CACF;EACF;CACF;CAEA,IAAI;EAOF,IAAI,MAN2B,yBAAyB;GACtD;GACA;GACA,eAAe;GACf,UAAU,MAAM;EAClB,CAAC,GACqB;GACpB,QAAQ,IAAI,6CAA6C;GACzD,mBAAmB;GACnB,OAAO;IACL,QAAQ;IACR;IACA;IACA;IACA;IACA,eAAe;GACjB;EACF;EAEA,QAAQ,IAAI,+BAA+B,QAAQ,IAAI;EAEvD,IAAI;EACJ,IAAI,WAAW;GAEb,MAAM,aADU,kBAAkB,SACT,CAAC,EAAE;GAC5B,IAAI,CAAC,cAAc,WAAW,cAAc,SAC1C,OAAO;IACL,QAAQ;IACR;IACA,OAAO,yCAAyC,QAAQ;GAC1D;GAEF,MAAM,SAAS,MAAM,kBAAkB;IACrC;IACA;IACA,UAAU;IACV;IACA,SAAS,WAAW;GACtB,CAAC;GACD,SAAS,MAAM,6BAA6B;IAC1C;IACA,UAAU;IACV;IACA,MAAM;IACN,oBAAoB,OAAO;IAC3B,eAAe,GAAG,WAAW,QAAQ;IACrC,QAAQ,WAAW;GACrB,CAAC;EACH,OAAO;GACL,IAAI,CAAC,UACH,OAAO;IACL,QAAQ;IACR;IACA,OAAO;GACT;GAEF,SAAS,MAAM,oBACb;IACE;IACA,UAAU;IACV,QAAQ;IACR,MAAM;IACN;IACA,YAAY,MAAM;GACpB,GACA,QACF;EACF;EAEA,IAAI,OAAO,QACT,QAAQ,IAAI,4BAA4B,OAAO,IAAI,OAAO,MAAM,GAAG;EAGrE,QAAQ,IAAI,uCAAuC;EACnD,MAAM,uBAAuB;GAC3B;GACA;GACA,eAAe;GACf,UAAU,MAAM;EAClB,CAAC;EACD,mBAAmB;EAEnB,OAAO;GACL,QAAQ;GACR;GACA,QAAQ,OAAO;GACf;GACA,UAAU;GACV;GACA;GACA;GACA,eAAe;EACjB;CACF,SAAS,OAAO;EACd,OAAO;GACL,QAAQ;GACR;GACA,OAAO,gBAAgB,KAAK;GAC5B;GACA;GACA;EACF;CACF;AACF;AAEA,SAAS,gBAAgB,OAAwB;CAC/C,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CAErE,IAAI,QAAQ,SAAS,gCAAgC,GACnD,OACE;;;cAGe;CAInB,IAAI,QAAQ,SAAS,cAAc,KAAK,QAAQ,SAAS,kBAAkB,GACzE,OAAO,gDAAgD;CAGzD,IAAI,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,SAAS,GAC3D,OAAO,kEAAkE;CAG3E,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.cjs","names":["pathToFileURL","fetchBosConfigFromFastKv","existsSync","readFileSync","isAbsolute","resolve","isAppDescriptorPath","loadAppDescriptorConfig","parseAppDescriptorModule","ConfigLoadError","CircularExtendsError","parseBosRef","resolveSourceDir","dirname","resolveExtendsRef","parseExtendsTarget","getConfigBaseDir","mergeBosConfigWithExtends","ConfigExtendsError","findConfigPath","defaultConfigEnv","ConfigNotfoundError","runWithConfigWarningSink","buildRuntimeConfig","readWorkspaceCatalog","join","DEV_OVERLAY_FILENAME","parseDevOverlayModule","applyDevOverlay","resolveConfigComposableEntries","BosConfigSchema","buildRuntimePluginsForConfig"],"sources":["../../src/resolution/session.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { readWorkspaceCatalog, resolveSourceDir } from \"../cli/init\";\nimport { parseBosRef } from \"../cli/utils/helpers\";\nimport {\n BosConfigSchema,\n type BosEnv,\n buildRuntimeConfig,\n buildRuntimePluginsForConfig,\n CircularExtendsError,\n ConfigExtendsError,\n ConfigLoadError,\n ConfigNotfoundError,\n DEV_OVERLAY_FILENAME,\n defaultConfigEnv,\n findConfigPath,\n getConfigBaseDir,\n isAppDescriptorPath,\n loadAppDescriptorConfig,\n parseAppDescriptorModule,\n parseDevOverlayModule,\n parseExtendsTarget,\n resolveConfigComposableEntries,\n runWithConfigWarningSink,\n} from \"../config\";\nimport { applyDevOverlay } from \"../descriptor/resolve\";\nimport { fetchBosConfigFromFastKv } from \"../fastkv\";\nimport { mergeBosConfigWithExtends, resolveExtendsRef } from \"../merge\";\nimport type {\n BosConfig,\n BosConfigInput,\n ExtendsConfig,\n RuntimeConfig,\n RuntimePluginConfig,\n} from \"../types\";\n\nexport interface ResolutionRequest {\n cwd?: string;\n path?: string;\n bosUrl?: string;\n account?: string;\n gateway?: string;\n registry?: string;\n sourceDir?: string;\n env?: BosEnv;\n remotePlugins?: string[];\n collectCatalogs?: boolean;\n}\n\nexport interface ResolutionIo {\n fetchBosConfig?(bosUrl: string, registry?: string): Promise<unknown>;\n readFileOrNull?(path: string): Promise<string | null>;\n importModule?(path: string): Promise<Record<string, unknown>>;\n}\n\nexport interface RuntimeSources {\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n authSource?: \"local\" | \"remote\";\n hostSource?: \"local\" | \"remote\";\n env?: \"development\" | \"production\";\n plugins?: Record<string, unknown>;\n}\n\nexport interface WalkLink {\n ref: string;\n config: BosConfigInput;\n baseDir: string;\n sourceDir?: string;\n isLeaf: boolean;\n}\n\ninterface ResolvedIo {\n fetchBosConfig: (bosUrl: string, registry?: string) => Promise<unknown>;\n readFileOrNull: (path: string) => Promise<string | null>;\n importModule: (path: string) => Promise<Record<string, unknown>>;\n}\n\ninterface EntryDispatch {\n entry: string;\n baseDir: string;\n root: string;\n path: string | null;\n remote: boolean;\n}\n\ninterface WalkOptions {\n env: BosEnv;\n registry?: string;\n io: ResolvedIo;\n collectCatalogs: boolean;\n visit?: (link: WalkLink) => Promise<void>;\n registerCleanup?: (fn: () => Promise<void>) => void;\n}\n\ninterface SessionParts {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n path: string | null;\n chain: string[];\n rawConfig: BosConfigInput | null;\n catalog: Record<string, string> | null;\n repository: string | undefined;\n env: BosEnv;\n warnings: string[];\n}\n\nasync function defaultImportModule(path: string): Promise<Record<string, unknown>> {\n return import(/* webpackIgnore: true */ pathToFileURL(path).href);\n}\n\nfunction resolveIo(io?: ResolutionIo): ResolvedIo {\n return {\n fetchBosConfig:\n io?.fetchBosConfig ??\n (async (bosUrl, registry) => fetchBosConfigFromFastKv(bosUrl, registry)),\n readFileOrNull:\n io?.readFileOrNull ??\n (async (path) => (existsSync(path) ? readFileSync(path, \"utf-8\") : null)),\n importModule: io?.importModule ?? defaultImportModule,\n };\n}\n\nasync function loadNodeConfig(\n ref: string,\n baseDir: string,\n io: ResolvedIo,\n registry?: string,\n): Promise<BosConfigInput> {\n if (ref.startsWith(\"bos://\")) {\n return (await io.fetchBosConfig(ref, registry)) as BosConfigInput;\n }\n\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n if (isAppDescriptorPath(resolvedPath)) {\n return io.importModule === defaultImportModule\n ? loadAppDescriptorConfig(resolvedPath)\n : parseAppDescriptorModule(await io.importModule(resolvedPath), resolvedPath);\n }\n\n const content = await io.readFileOrNull(resolvedPath);\n if (content === null) {\n throw new ConfigLoadError({\n path: resolvedPath,\n message: `Config file not found: ${resolvedPath}`,\n });\n }\n return JSON.parse(content) as BosConfigInput;\n}\n\nasync function walkExtends(\n ref: string,\n baseDir: string,\n visited: Set<string>,\n chain: string[],\n options: WalkOptions,\n): Promise<BosConfigInput> {\n if (visited.has(ref)) {\n throw new CircularExtendsError({\n chain: [...visited, ref],\n message: `Circular extends detected: ${[...visited, ref].join(\" -> \")}`,\n });\n }\n\n let config: BosConfigInput;\n let nodeBaseDir = baseDir;\n let sourceDir: string | undefined;\n\n if (ref.startsWith(\"bos://\") && options.collectCatalogs) {\n const parsed = parseBosRef(ref);\n if (!parsed) {\n throw new ConfigLoadError({ path: ref, message: `Invalid bos ref: ${ref}` });\n }\n const sourceResult = await resolveSourceDir({\n extendsAccount: parsed.account,\n extendsGateway: parsed.gateway,\n });\n config = sourceResult.parentConfig as BosConfigInput;\n sourceDir = sourceResult.sourceDir || undefined;\n options.registerCleanup?.(sourceResult.cleanup);\n nodeBaseDir = sourceDir ?? baseDir;\n } else if (ref.startsWith(\"bos://\")) {\n config = await loadNodeConfig(ref, baseDir, options.io, options.registry);\n } else {\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n nodeBaseDir = dirname(resolvedPath);\n config = await loadNodeConfig(ref, nodeBaseDir, options.io, options.registry);\n }\n\n chain.push(ref);\n\n const extendsRef = config.extends\n ? resolveExtendsRef(config.extends as string | ExtendsConfig, options.env)\n : undefined;\n\n if (!extendsRef) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const parsedParentRef = parseExtendsTarget(extendsRef);\n const parentBaseDir = getConfigBaseDir(parsedParentRef.configPath, nodeBaseDir);\n\n if (\n options.collectCatalogs &&\n !canResolveExtendsRef(parsedParentRef.configPath, sourceDir ?? nodeBaseDir)\n ) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const nextVisited = new Set(visited);\n nextVisited.add(ref);\n const parent = await walkExtends(\n parsedParentRef.configPath,\n parentBaseDir,\n nextVisited,\n chain,\n options,\n );\n\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: false });\n return mergeBosConfigWithExtends(parent, config);\n}\n\nfunction canResolveExtendsRef(parentRef: string, baseDir: string | undefined): boolean {\n if (parentRef.startsWith(\"bos://\")) {\n return parseBosRef(parentRef) !== null;\n }\n if (!baseDir) {\n return false;\n }\n return existsSync(resolve(baseDir, parentRef));\n}\n\nfunction dispatchEntry(request: ResolutionRequest | undefined, cwd: string): EntryDispatch | null {\n if (request?.path) {\n const configPath = request.path;\n if (configPath.startsWith(\"bos://\")) {\n return { entry: configPath, baseDir: cwd, root: cwd, path: configPath, remote: true };\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n }\n\n if (request?.bosUrl) {\n return { entry: request.bosUrl, baseDir: cwd, root: cwd, path: null, remote: true };\n }\n\n if (request?.account) {\n if (!request.gateway) {\n throw new ConfigExtendsError({\n message: `Remote account \"${request.account}\" requires a gateway`,\n });\n }\n return {\n entry: `bos://${request.account}/${request.gateway}`,\n baseDir: cwd,\n root: cwd,\n path: null,\n remote: true,\n };\n }\n\n if (request?.sourceDir) {\n const sourceRoot = resolve(request.sourceDir);\n const configPath = findConfigPath(sourceRoot);\n if (!configPath) return null;\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: sourceRoot, path: configPath, remote: false };\n }\n\n const configPath = findConfigPath(cwd);\n if (!configPath) {\n return null;\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n}\n\nfunction isConfigNotFound(error: unknown): boolean {\n return error instanceof Error && error.message.startsWith(\"No config found for \");\n}\n\nexport class ResolutionSession {\n readonly config: BosConfig | null;\n readonly runtime: RuntimeConfig | null;\n readonly root: string;\n readonly path: string | null;\n readonly chain: readonly string[];\n readonly rawConfig: BosConfigInput | null;\n readonly catalog: Record<string, string> | null;\n readonly repository: string | undefined;\n\n #env: BosEnv;\n #warnings: string[];\n\n constructor(parts: SessionParts) {\n this.config = parts.config;\n this.runtime = parts.runtime;\n this.root = parts.root;\n this.path = parts.path;\n this.chain = parts.chain;\n this.rawConfig = parts.rawConfig;\n this.catalog = parts.catalog;\n this.repository = parts.repository;\n this.#env = parts.env;\n this.#warnings = parts.warnings;\n }\n\n static fromParts(parts: {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n source?: { path?: string; extended?: string[]; remote?: boolean };\n warnings?: string[];\n }): ResolutionSession {\n return new ResolutionSession({\n config: parts.config,\n runtime: parts.runtime,\n root: parts.root,\n path: parts.source?.path ?? null,\n chain: parts.source?.extended ?? [],\n rawConfig: null,\n catalog: null,\n repository: undefined,\n env: defaultConfigEnv(),\n warnings: [...(parts.warnings ?? [])],\n });\n }\n\n get warnings(): readonly string[] {\n const drained = [...this.#warnings];\n this.#warnings.length = 0;\n return drained;\n }\n\n async buildRuntime(sources?: RuntimeSources): Promise<RuntimeConfig> {\n if (!this.config) {\n throw new ConfigNotfoundError({\n message: \"No config loaded in this resolution session\",\n });\n }\n const config = this.config;\n const env = sources?.env ?? this.#env;\n return runWithConfigWarningSink(this.#warnings, () =>\n buildRuntimeConfig(config, this.root, env, {\n plugins: (sources?.plugins ?? {}) as Record<string, RuntimePluginConfig>,\n uiSource: sources?.uiSource,\n apiSource: sources?.apiSource,\n authSource: sources?.authSource,\n hostSource: sources?.hostSource,\n }),\n );\n }\n}\n\n/**\n * Opens a resolution session for the requested config source. In development,\n * a local leaf's `bos.dev.ts` overlay (beside the discovered entry config) is\n * merged child-wins over the extended input before parsing; overlays are never\n * read for `bos://` entries or in production/staging.\n */\nexport async function openResolution(\n request?: ResolutionRequest,\n io?: ResolutionIo,\n): Promise<ResolutionSession | null> {\n const resolvedIo = resolveIo(io);\n const env = request?.env ?? defaultConfigEnv();\n const runtimeEnv: BosEnv = env === \"staging\" ? \"production\" : env;\n const cwd = request?.cwd ?? process.cwd();\n const collectCatalogs = request?.collectCatalogs === true;\n\n const warnings: string[] = [];\n const cleanups: Array<() => Promise<void>> = [];\n\n try {\n const parts = await runWithConfigWarningSink(warnings, async () => {\n const dispatch = dispatchEntry(request, cwd);\n if (!dispatch) return null;\n\n const chain: string[] = [];\n const catalogs: Record<string, string>[] = [];\n let repository: string | undefined;\n let rawConfig: BosConfigInput | undefined;\n\n try {\n const mergedRaw = await walkExtends(dispatch.entry, dispatch.baseDir, new Set(), chain, {\n env,\n registry: request?.registry,\n io: resolvedIo,\n collectCatalogs,\n registerCleanup: (fn) => cleanups.push(fn),\n visit: async (link) => {\n if (link.ref === dispatch.entry) {\n rawConfig = link.config;\n }\n if (!collectCatalogs) return;\n catalogs.push(link.sourceDir ? readWorkspaceCatalog(link.sourceDir) : {});\n const repositoryValue = (link.config as Record<string, unknown>).repository;\n if (typeof repositoryValue === \"string\") {\n repository = repositoryValue;\n }\n },\n });\n\n let overlayMerged = mergedRaw;\n if (env === \"development\" && !dispatch.remote) {\n const overlayPath = join(dirname(dispatch.entry), DEV_OVERLAY_FILENAME);\n if ((await resolvedIo.readFileOrNull(overlayPath)) !== null) {\n const overlay = parseDevOverlayModule(\n await resolvedIo.importModule(overlayPath),\n overlayPath,\n );\n overlayMerged = applyDevOverlay(mergedRaw, overlay);\n }\n }\n\n const config = await resolveConfigComposableEntries(\n BosConfigSchema.parse(overlayMerged),\n dispatch.baseDir,\n runtimeEnv,\n );\n const pluginRuntime =\n (await buildRuntimePluginsForConfig(\n config,\n dispatch.baseDir,\n runtimeEnv,\n request?.remotePlugins,\n )) ?? {};\n const runtime = await buildRuntimeConfig(config, dispatch.baseDir, runtimeEnv, {\n plugins: pluginRuntime,\n });\n\n return {\n config,\n runtime,\n root: dispatch.root,\n path: dispatch.path,\n chain,\n rawConfig: rawConfig ?? null,\n catalog: collectCatalogs ? Object.assign({}, ...[...catalogs].reverse()) : null,\n repository,\n } satisfies Omit<SessionParts, \"env\" | \"warnings\">;\n } catch (error) {\n if (dispatch.remote && isConfigNotFound(error)) {\n return null;\n }\n throw error;\n }\n });\n\n if (!parts) return null;\n\n return new ResolutionSession({\n ...parts,\n env: runtimeEnv,\n warnings,\n });\n } finally {\n for (const cleanup of [...cleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\nexport async function walkExtendsChain(\n entry: string,\n options: {\n env?: BosEnv;\n io?: ResolutionIo;\n registry?: string;\n collectCatalogs?: boolean;\n visit(link: WalkLink): Promise<void>;\n registerCleanup?(fn: () => Promise<void>): void;\n },\n): Promise<{ chain: string[]; config: BosConfigInput }> {\n const baseDir = entry.startsWith(\"bos://\") ? process.cwd() : dirname(entry);\n const chain: string[] = [];\n const ownedCleanups: Array<() => Promise<void>> = [];\n try {\n const config = await walkExtends(entry, baseDir, new Set(), chain, {\n env: options.env ?? \"development\",\n registry: options.registry,\n io: resolveIo(options.io),\n collectCatalogs: options.collectCatalogs === true,\n visit: options.visit,\n registerCleanup: options.registerCleanup ?? ((fn) => ownedCleanups.push(fn)),\n });\n return { chain, config };\n } finally {\n for (const cleanup of [...ownedCleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\n/**\n * @internal — resolves the fully merged (parent-merged, un-parsed)\n * `BosConfigInput` for a config entry. Used by config.ts's\n * `resolveComposableReference` for plugin-entry extends resolution.\n */\nexport async function resolveMergedConfigInput(\n entry: string,\n options?: { baseDir?: string; env?: BosEnv; io?: ResolutionIo; registry?: string },\n): Promise<BosConfigInput> {\n const baseDir = options?.baseDir ?? process.cwd();\n return walkExtends(entry, baseDir, new Set(), [], {\n env: options?.env ?? \"development\",\n registry: options?.registry,\n io: resolveIo(options?.io),\n collectCatalogs: false,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"session.cjs","names":["pathToFileURL","fetchBosConfigFromFastKv","existsSync","readFileSync","isAbsolute","resolve","isAppDescriptorPath","loadAppDescriptorConfig","parseAppDescriptorModule","ConfigLoadError","CircularExtendsError","parseBosRef","resolveSourceDir","dirname","resolveExtendsRef","parseExtendsTarget","getConfigBaseDir","mergeBosConfigWithExtends","ConfigExtendsError","findConfigPath","defaultConfigEnv","ConfigNotfoundError","runWithConfigWarningSink","buildRuntimeConfig","readWorkspaceCatalog","join","DEV_OVERLAY_FILENAME","parseDevOverlayModule","applyDevOverlay","resolveConfigComposableEntries","BosConfigSchema","buildRuntimePluginsForConfig"],"sources":["../../src/resolution/session.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { readWorkspaceCatalog, resolveSourceDir } from \"../cli/init\";\nimport { parseBosRef } from \"../cli/utils/helpers\";\nimport {\n BosConfigSchema,\n type BosEnv,\n buildRuntimeConfig,\n buildRuntimePluginsForConfig,\n CircularExtendsError,\n ConfigExtendsError,\n ConfigLoadError,\n ConfigNotfoundError,\n DEV_OVERLAY_FILENAME,\n defaultConfigEnv,\n findConfigPath,\n getConfigBaseDir,\n isAppDescriptorPath,\n loadAppDescriptorConfig,\n parseAppDescriptorModule,\n parseDevOverlayModule,\n parseExtendsTarget,\n resolveConfigComposableEntries,\n runWithConfigWarningSink,\n} from \"../config\";\nimport { applyDevOverlay } from \"../descriptor/resolve\";\nimport { fetchBosConfigFromFastKv } from \"../fastkv\";\nimport { mergeBosConfigWithExtends, resolveExtendsRef } from \"../merge\";\nimport type {\n BosConfig,\n BosConfigInput,\n ExtendsConfig,\n RuntimeConfig,\n RuntimePluginConfig,\n} from \"../types\";\n\nexport interface ResolutionRequest {\n cwd?: string;\n path?: string;\n bosUrl?: string;\n account?: string;\n gateway?: string;\n registry?: string;\n sourceDir?: string;\n env?: BosEnv;\n remotePlugins?: string[];\n collectCatalogs?: boolean;\n}\n\nexport interface ResolutionIo {\n fetchBosConfig?: (bosUrl: string, registry?: string) => Promise<unknown>;\n readFileOrNull?: (path: string) => Promise<string | null>;\n importModule?: (path: string) => Promise<Record<string, unknown>>;\n}\n\nexport interface RuntimeSources {\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n authSource?: \"local\" | \"remote\";\n hostSource?: \"local\" | \"remote\";\n env?: \"development\" | \"production\";\n plugins?: Record<string, unknown>;\n}\n\nexport interface WalkLink {\n ref: string;\n config: BosConfigInput;\n baseDir: string;\n sourceDir?: string;\n isLeaf: boolean;\n}\n\ninterface ResolvedIo {\n fetchBosConfig: (bosUrl: string, registry?: string) => Promise<unknown>;\n readFileOrNull: (path: string) => Promise<string | null>;\n importModule: (path: string) => Promise<Record<string, unknown>>;\n}\n\ninterface EntryDispatch {\n entry: string;\n baseDir: string;\n root: string;\n path: string | null;\n remote: boolean;\n}\n\ninterface WalkOptions {\n env: BosEnv;\n registry?: string;\n io: ResolvedIo;\n collectCatalogs: boolean;\n visit?: (link: WalkLink) => Promise<void>;\n registerCleanup?: (fn: () => Promise<void>) => void;\n}\n\ninterface SessionParts {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n path: string | null;\n chain: string[];\n rawConfig: BosConfigInput | null;\n catalog: Record<string, string> | null;\n repository: string | undefined;\n env: BosEnv;\n warnings: string[];\n}\n\nasync function defaultImportModule(path: string): Promise<Record<string, unknown>> {\n return import(/* webpackIgnore: true */ pathToFileURL(path).href);\n}\n\nfunction resolveIo(io?: ResolutionIo): ResolvedIo {\n return {\n fetchBosConfig:\n io?.fetchBosConfig ??\n (async (bosUrl, registry) => fetchBosConfigFromFastKv(bosUrl, registry)),\n readFileOrNull:\n io?.readFileOrNull ??\n (async (path) => (existsSync(path) ? readFileSync(path, \"utf-8\") : null)),\n importModule: io?.importModule ?? defaultImportModule,\n };\n}\n\nasync function loadNodeConfig(\n ref: string,\n baseDir: string,\n io: ResolvedIo,\n registry?: string,\n): Promise<BosConfigInput> {\n if (ref.startsWith(\"bos://\")) {\n return (await io.fetchBosConfig(ref, registry)) as BosConfigInput;\n }\n\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n if (isAppDescriptorPath(resolvedPath)) {\n return io.importModule === defaultImportModule\n ? loadAppDescriptorConfig(resolvedPath)\n : parseAppDescriptorModule(await io.importModule(resolvedPath), resolvedPath);\n }\n\n const content = await io.readFileOrNull(resolvedPath);\n if (content === null) {\n throw new ConfigLoadError({\n path: resolvedPath,\n message: `Config file not found: ${resolvedPath}`,\n });\n }\n return JSON.parse(content) as BosConfigInput;\n}\n\nasync function walkExtends(\n ref: string,\n baseDir: string,\n visited: Set<string>,\n chain: string[],\n options: WalkOptions,\n): Promise<BosConfigInput> {\n if (visited.has(ref)) {\n throw new CircularExtendsError({\n chain: [...visited, ref],\n message: `Circular extends detected: ${[...visited, ref].join(\" -> \")}`,\n });\n }\n\n let config: BosConfigInput;\n let nodeBaseDir = baseDir;\n let sourceDir: string | undefined;\n\n if (ref.startsWith(\"bos://\") && options.collectCatalogs) {\n const parsed = parseBosRef(ref);\n if (!parsed) {\n throw new ConfigLoadError({ path: ref, message: `Invalid bos ref: ${ref}` });\n }\n const sourceResult = await resolveSourceDir({\n extendsAccount: parsed.account,\n extendsGateway: parsed.gateway,\n });\n config = sourceResult.parentConfig as BosConfigInput;\n sourceDir = sourceResult.sourceDir || undefined;\n options.registerCleanup?.(sourceResult.cleanup);\n nodeBaseDir = sourceDir ?? baseDir;\n } else if (ref.startsWith(\"bos://\")) {\n config = await loadNodeConfig(ref, baseDir, options.io, options.registry);\n } else {\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n nodeBaseDir = dirname(resolvedPath);\n config = await loadNodeConfig(ref, nodeBaseDir, options.io, options.registry);\n }\n\n chain.push(ref);\n\n const extendsRef = config.extends\n ? resolveExtendsRef(config.extends as string | ExtendsConfig, options.env)\n : undefined;\n\n if (!extendsRef) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const parsedParentRef = parseExtendsTarget(extendsRef);\n const parentBaseDir = getConfigBaseDir(parsedParentRef.configPath, nodeBaseDir);\n\n if (\n options.collectCatalogs &&\n !canResolveExtendsRef(parsedParentRef.configPath, sourceDir ?? nodeBaseDir)\n ) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const nextVisited = new Set(visited);\n nextVisited.add(ref);\n const parent = await walkExtends(\n parsedParentRef.configPath,\n parentBaseDir,\n nextVisited,\n chain,\n options,\n );\n\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: false });\n return mergeBosConfigWithExtends(parent, config);\n}\n\nfunction canResolveExtendsRef(parentRef: string, baseDir: string | undefined): boolean {\n if (parentRef.startsWith(\"bos://\")) {\n return parseBosRef(parentRef) !== null;\n }\n if (!baseDir) {\n return false;\n }\n return existsSync(resolve(baseDir, parentRef));\n}\n\nfunction dispatchEntry(request: ResolutionRequest | undefined, cwd: string): EntryDispatch | null {\n if (request?.path) {\n const configPath = request.path;\n if (configPath.startsWith(\"bos://\")) {\n return { entry: configPath, baseDir: cwd, root: cwd, path: configPath, remote: true };\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n }\n\n if (request?.bosUrl) {\n return { entry: request.bosUrl, baseDir: cwd, root: cwd, path: null, remote: true };\n }\n\n if (request?.account) {\n if (!request.gateway) {\n throw new ConfigExtendsError({\n message: `Remote account \"${request.account}\" requires a gateway`,\n });\n }\n return {\n entry: `bos://${request.account}/${request.gateway}`,\n baseDir: cwd,\n root: cwd,\n path: null,\n remote: true,\n };\n }\n\n if (request?.sourceDir) {\n const sourceRoot = resolve(request.sourceDir);\n const configPath = findConfigPath(sourceRoot);\n if (!configPath) return null;\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: sourceRoot, path: configPath, remote: false };\n }\n\n const configPath = findConfigPath(cwd);\n if (!configPath) {\n return null;\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n}\n\nfunction isConfigNotFound(error: unknown): boolean {\n return error instanceof Error && error.message.startsWith(\"No config found for \");\n}\n\nexport class ResolutionSession {\n readonly config: BosConfig | null;\n readonly runtime: RuntimeConfig | null;\n readonly root: string;\n readonly path: string | null;\n readonly chain: readonly string[];\n readonly rawConfig: BosConfigInput | null;\n readonly catalog: Record<string, string> | null;\n readonly repository: string | undefined;\n\n #env: BosEnv;\n #warnings: string[];\n\n constructor(parts: SessionParts) {\n this.config = parts.config;\n this.runtime = parts.runtime;\n this.root = parts.root;\n this.path = parts.path;\n this.chain = parts.chain;\n this.rawConfig = parts.rawConfig;\n this.catalog = parts.catalog;\n this.repository = parts.repository;\n this.#env = parts.env;\n this.#warnings = parts.warnings;\n }\n\n static fromParts(parts: {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n source?: { path?: string; extended?: string[]; remote?: boolean };\n warnings?: string[];\n }): ResolutionSession {\n return new ResolutionSession({\n config: parts.config,\n runtime: parts.runtime,\n root: parts.root,\n path: parts.source?.path ?? null,\n chain: parts.source?.extended ?? [],\n rawConfig: null,\n catalog: null,\n repository: undefined,\n env: defaultConfigEnv(),\n warnings: [...(parts.warnings ?? [])],\n });\n }\n\n get warnings(): readonly string[] {\n const drained = [...this.#warnings];\n this.#warnings.length = 0;\n return drained;\n }\n\n async buildRuntime(sources?: RuntimeSources): Promise<RuntimeConfig> {\n if (!this.config) {\n throw new ConfigNotfoundError({\n message: \"No config loaded in this resolution session\",\n });\n }\n const config = this.config;\n const env = sources?.env ?? this.#env;\n return runWithConfigWarningSink(this.#warnings, () =>\n buildRuntimeConfig(config, this.root, env, {\n plugins: (sources?.plugins ?? {}) as Record<string, RuntimePluginConfig>,\n uiSource: sources?.uiSource,\n apiSource: sources?.apiSource,\n authSource: sources?.authSource,\n hostSource: sources?.hostSource,\n }),\n );\n }\n}\n\n/**\n * Opens a resolution session for the requested config source. In development,\n * a local leaf's `bos.dev.ts` overlay (beside the discovered entry config) is\n * merged child-wins over the extended input before parsing; overlays are never\n * read for `bos://` entries or in production/staging.\n */\nexport async function openResolution(\n request?: ResolutionRequest,\n io?: ResolutionIo,\n): Promise<ResolutionSession | null> {\n const resolvedIo = resolveIo(io);\n const env = request?.env ?? defaultConfigEnv();\n const runtimeEnv: BosEnv = env === \"staging\" ? \"production\" : env;\n const cwd = request?.cwd ?? process.cwd();\n const collectCatalogs = request?.collectCatalogs === true;\n\n const warnings: string[] = [];\n const cleanups: Array<() => Promise<void>> = [];\n\n try {\n const parts = await runWithConfigWarningSink(warnings, async () => {\n const dispatch = dispatchEntry(request, cwd);\n if (!dispatch) return null;\n\n const chain: string[] = [];\n const catalogs: Record<string, string>[] = [];\n let repository: string | undefined;\n let rawConfig: BosConfigInput | undefined;\n\n try {\n const mergedRaw = await walkExtends(dispatch.entry, dispatch.baseDir, new Set(), chain, {\n env,\n registry: request?.registry,\n io: resolvedIo,\n collectCatalogs,\n registerCleanup: (fn) => cleanups.push(fn),\n visit: async (link) => {\n if (link.ref === dispatch.entry) {\n rawConfig = link.config;\n }\n if (!collectCatalogs) return;\n catalogs.push(link.sourceDir ? readWorkspaceCatalog(link.sourceDir) : {});\n const repositoryValue = (link.config as Record<string, unknown>).repository;\n if (typeof repositoryValue === \"string\") {\n repository = repositoryValue;\n }\n },\n });\n\n let overlayMerged = mergedRaw;\n if (env === \"development\" && !dispatch.remote) {\n const overlayPath = join(dirname(dispatch.entry), DEV_OVERLAY_FILENAME);\n if ((await resolvedIo.readFileOrNull(overlayPath)) !== null) {\n const overlay = parseDevOverlayModule(\n await resolvedIo.importModule(overlayPath),\n overlayPath,\n );\n overlayMerged = applyDevOverlay(mergedRaw, overlay);\n }\n }\n\n const config = await resolveConfigComposableEntries(\n BosConfigSchema.parse(overlayMerged),\n dispatch.baseDir,\n runtimeEnv,\n );\n const pluginRuntime =\n (await buildRuntimePluginsForConfig(\n config,\n dispatch.baseDir,\n runtimeEnv,\n request?.remotePlugins,\n )) ?? {};\n const runtime = await buildRuntimeConfig(config, dispatch.baseDir, runtimeEnv, {\n plugins: pluginRuntime,\n });\n\n return {\n config,\n runtime,\n root: dispatch.root,\n path: dispatch.path,\n chain,\n rawConfig: rawConfig ?? null,\n catalog: collectCatalogs ? Object.assign({}, ...[...catalogs].reverse()) : null,\n repository,\n } satisfies Omit<SessionParts, \"env\" | \"warnings\">;\n } catch (error) {\n if (dispatch.remote && isConfigNotFound(error)) {\n return null;\n }\n throw error;\n }\n });\n\n if (!parts) return null;\n\n return new ResolutionSession({\n ...parts,\n env: runtimeEnv,\n warnings,\n });\n } finally {\n for (const cleanup of [...cleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\nexport async function walkExtendsChain(\n entry: string,\n options: {\n env?: BosEnv;\n io?: ResolutionIo;\n registry?: string;\n collectCatalogs?: boolean;\n visit: (link: WalkLink) => Promise<void>;\n registerCleanup?: (fn: () => Promise<void>) => void;\n },\n): Promise<{ chain: string[]; config: BosConfigInput }> {\n const baseDir = entry.startsWith(\"bos://\") ? process.cwd() : dirname(entry);\n const chain: string[] = [];\n const ownedCleanups: Array<() => Promise<void>> = [];\n try {\n const config = await walkExtends(entry, baseDir, new Set(), chain, {\n env: options.env ?? \"development\",\n registry: options.registry,\n io: resolveIo(options.io),\n collectCatalogs: options.collectCatalogs === true,\n visit: options.visit,\n registerCleanup: options.registerCleanup ?? ((fn) => ownedCleanups.push(fn)),\n });\n return { chain, config };\n } finally {\n for (const cleanup of [...ownedCleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\n/**\n * @internal — resolves the fully merged (parent-merged, un-parsed)\n * `BosConfigInput` for a config entry. Used by config.ts's\n * `resolveComposableReference` for plugin-entry extends resolution.\n */\nexport async function resolveMergedConfigInput(\n entry: string,\n options?: { baseDir?: string; env?: BosEnv; io?: ResolutionIo; registry?: string },\n): Promise<BosConfigInput> {\n const baseDir = options?.baseDir ?? process.cwd();\n return walkExtends(entry, baseDir, new Set(), [], {\n env: options?.env ?? \"development\",\n registry: options?.registry,\n io: resolveIo(options?.io),\n collectCatalogs: false,\n });\n}\n"],"mappings":";;;;;;;;;;;;;AA6GA,eAAe,oBAAoB,MAAgD;CACjF,OAAO;;MAAiCA,wBAAc,IAAI,CAAC,CAAC;;AAC9D;AAEA,SAAS,UAAU,IAA+B;CAChD,OAAO;EACL,gBACE,IAAI,mBACH,OAAO,QAAQ,aAAaC,wCAAyB,QAAQ,QAAQ;EACxE,gBACE,IAAI,mBACH,OAAO,aAAUC,oBAAW,IAAI,QAAIC,sBAAa,MAAM,OAAO,IAAI;EACrE,cAAc,IAAI,gBAAgB;CACpC;AACF;AAEA,eAAe,eACb,KACA,SACA,IACA,UACyB;CACzB,IAAI,IAAI,WAAW,QAAQ,GACzB,OAAQ,MAAM,GAAG,eAAe,KAAK,QAAQ;CAG/C,MAAM,mBAAeC,sBAAW,GAAG,IAAI,UAAMC,mBAAQ,SAAS,GAAG;CACjE,IAAIC,mCAAoB,YAAY,GAClC,OAAO,GAAG,iBAAiB,sBACvBC,uCAAwB,YAAY,IACpCC,wCAAyB,MAAM,GAAG,aAAa,YAAY,GAAG,YAAY;CAGhF,MAAM,UAAU,MAAM,GAAG,eAAe,YAAY;CACpD,IAAI,YAAY,MACd,MAAM,IAAIC,+BAAgB;EACxB,MAAM;EACN,SAAS,0BAA0B;CACrC,CAAC;CAEH,OAAO,KAAK,MAAM,OAAO;AAC3B;AAEA,eAAe,YACb,KACA,SACA,SACA,OACA,SACyB;CACzB,IAAI,QAAQ,IAAI,GAAG,GACjB,MAAM,IAAIC,oCAAqB;EAC7B,OAAO,CAAC,GAAG,SAAS,GAAG;EACvB,SAAS,8BAA8B,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,KAAK,MAAM;CACtE,CAAC;CAGH,IAAI;CACJ,IAAI,cAAc;CAClB,IAAI;CAEJ,IAAI,IAAI,WAAW,QAAQ,KAAK,QAAQ,iBAAiB;EACvD,MAAM,SAASC,4BAAY,GAAG;EAC9B,IAAI,CAAC,QACH,MAAM,IAAIF,+BAAgB;GAAE,MAAM;GAAK,SAAS,oBAAoB;EAAM,CAAC;EAE7E,MAAM,eAAe,MAAMG,kCAAiB;GAC1C,gBAAgB,OAAO;GACvB,gBAAgB,OAAO;EACzB,CAAC;EACD,SAAS,aAAa;EACtB,YAAY,aAAa,aAAa;EACtC,QAAQ,kBAAkB,aAAa,OAAO;EAC9C,cAAc,aAAa;CAC7B,OAAO,IAAI,IAAI,WAAW,QAAQ,GAChC,SAAS,MAAM,eAAe,KAAK,SAAS,QAAQ,IAAI,QAAQ,QAAQ;MACnE;EACL,MAAM,mBAAeR,sBAAW,GAAG,IAAI,UAAMC,mBAAQ,SAAS,GAAG;EACjE,kBAAcQ,mBAAQ,YAAY;EAClC,SAAS,MAAM,eAAe,KAAK,aAAa,QAAQ,IAAI,QAAQ,QAAQ;CAC9E;CAEA,MAAM,KAAK,GAAG;CAEd,MAAM,aAAa,OAAO,UACtBC,gCAAkB,OAAO,SAAmC,QAAQ,GAAG,IACvE;CAEJ,IAAI,CAAC,YAAY;EACf,MAAM,QAAQ,QAAQ;GAAE;GAAK;GAAQ,SAAS;GAAa;GAAW,QAAQ;EAAK,CAAC;EACpF,OAAO;CACT;CAEA,MAAM,kBAAkBC,kCAAmB,UAAU;CACrD,MAAM,gBAAgBC,gCAAiB,gBAAgB,YAAY,WAAW;CAE9E,IACE,QAAQ,mBACR,CAAC,qBAAqB,gBAAgB,YAAY,aAAa,WAAW,GAC1E;EACA,MAAM,QAAQ,QAAQ;GAAE;GAAK;GAAQ,SAAS;GAAa;GAAW,QAAQ;EAAK,CAAC;EACpF,OAAO;CACT;CAEA,MAAM,cAAc,IAAI,IAAI,OAAO;CACnC,YAAY,IAAI,GAAG;CACnB,MAAM,SAAS,MAAM,YACnB,gBAAgB,YAChB,eACA,aACA,OACA,OACF;CAEA,MAAM,QAAQ,QAAQ;EAAE;EAAK;EAAQ,SAAS;EAAa;EAAW,QAAQ;CAAM,CAAC;CACrF,OAAOC,wCAA0B,QAAQ,MAAM;AACjD;AAEA,SAAS,qBAAqB,WAAmB,SAAsC;CACrF,IAAI,UAAU,WAAW,QAAQ,GAC/B,OAAON,4BAAY,SAAS,MAAM;CAEpC,IAAI,CAAC,SACH,OAAO;CAET,WAAOT,wBAAWG,mBAAQ,SAAS,SAAS,CAAC;AAC/C;AAEA,SAAS,cAAc,SAAwC,KAAmC;CAChG,IAAI,SAAS,MAAM;EACjB,MAAM,aAAa,QAAQ;EAC3B,IAAI,WAAW,WAAW,QAAQ,GAChC,OAAO;GAAE,OAAO;GAAY,SAAS;GAAK,MAAM;GAAK,MAAM;GAAY,QAAQ;EAAK;EAEtF,MAAM,cAAUQ,mBAAQ,UAAU;EAClC,OAAO;GAAE,OAAO;GAAY;GAAS,MAAM;GAAS,MAAM;GAAY,QAAQ;EAAM;CACtF;CAEA,IAAI,SAAS,QACX,OAAO;EAAE,OAAO,QAAQ;EAAQ,SAAS;EAAK,MAAM;EAAK,MAAM;EAAM,QAAQ;CAAK;CAGpF,IAAI,SAAS,SAAS;EACpB,IAAI,CAAC,QAAQ,SACX,MAAM,IAAIK,kCAAmB,EAC3B,SAAS,mBAAmB,QAAQ,QAAQ,sBAC9C,CAAC;EAEH,OAAO;GACL,OAAO,SAAS,QAAQ,QAAQ,GAAG,QAAQ;GAC3C,SAAS;GACT,MAAM;GACN,MAAM;GACN,QAAQ;EACV;CACF;CAEA,IAAI,SAAS,WAAW;EACtB,MAAM,iBAAab,mBAAQ,QAAQ,SAAS;EAC5C,MAAM,aAAac,8BAAe,UAAU;EAC5C,IAAI,CAAC,YAAY,OAAO;EAExB,OAAO;GAAE,OAAO;GAAY,aADZN,mBAAQ,UACU;GAAG,MAAM;GAAY,MAAM;GAAY,QAAQ;EAAM;CACzF;CAEA,MAAM,aAAaM,8BAAe,GAAG;CACrC,IAAI,CAAC,YACH,OAAO;CAET,MAAM,cAAUN,mBAAQ,UAAU;CAClC,OAAO;EAAE,OAAO;EAAY;EAAS,MAAM;EAAS,MAAM;EAAY,QAAQ;CAAM;AACtF;AAEA,SAAS,iBAAiB,OAAyB;CACjD,OAAO,iBAAiB,SAAS,MAAM,QAAQ,WAAW,sBAAsB;AAClF;AAEA,IAAa,oBAAb,MAAa,kBAAkB;CAC7B,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CAET;CACA;CAEA,YAAY,OAAqB;EAC/B,KAAK,SAAS,MAAM;EACpB,KAAK,UAAU,MAAM;EACrB,KAAK,OAAO,MAAM;EAClB,KAAK,OAAO,MAAM;EAClB,KAAK,QAAQ,MAAM;EACnB,KAAK,YAAY,MAAM;EACvB,KAAK,UAAU,MAAM;EACrB,KAAK,aAAa,MAAM;EACxB,KAAK,OAAO,MAAM;EAClB,KAAK,YAAY,MAAM;CACzB;CAEA,OAAO,UAAU,OAMK;EACpB,OAAO,IAAI,kBAAkB;GAC3B,QAAQ,MAAM;GACd,SAAS,MAAM;GACf,MAAM,MAAM;GACZ,MAAM,MAAM,QAAQ,QAAQ;GAC5B,OAAO,MAAM,QAAQ,YAAY,CAAC;GAClC,WAAW;GACX,SAAS;GACT,YAAY;GACZ,KAAKO,gCAAiB;GACtB,UAAU,CAAC,GAAI,MAAM,YAAY,CAAC,CAAE;EACtC,CAAC;CACH;CAEA,IAAI,WAA8B;EAChC,MAAM,UAAU,CAAC,GAAG,KAAK,SAAS;EAClC,KAAK,UAAU,SAAS;EACxB,OAAO;CACT;CAEA,MAAM,aAAa,SAAkD;EACnE,IAAI,CAAC,KAAK,QACR,MAAM,IAAIC,mCAAoB,EAC5B,SAAS,8CACX,CAAC;EAEH,MAAM,SAAS,KAAK;EACpB,MAAM,MAAM,SAAS,OAAO,KAAK;EACjC,OAAOC,wCAAyB,KAAK,iBACnCC,kCAAmB,QAAQ,KAAK,MAAM,KAAK;GACzC,SAAU,SAAS,WAAW,CAAC;GAC/B,UAAU,SAAS;GACnB,WAAW,SAAS;GACpB,YAAY,SAAS;GACrB,YAAY,SAAS;EACvB,CAAC,CACH;CACF;AACF;;;;;;;AAQA,eAAsB,eACpB,SACA,IACmC;CACnC,MAAM,aAAa,UAAU,EAAE;CAC/B,MAAM,MAAM,SAAS,OAAOH,gCAAiB;CAC7C,MAAM,aAAqB,QAAQ,YAAY,eAAe;CAC9D,MAAM,MAAM,SAAS,OAAO,QAAQ,IAAI;CACxC,MAAM,kBAAkB,SAAS,oBAAoB;CAErD,MAAM,WAAqB,CAAC;CAC5B,MAAM,WAAuC,CAAC;CAE9C,IAAI;EACF,MAAM,QAAQ,MAAME,wCAAyB,UAAU,YAAY;GACjE,MAAM,WAAW,cAAc,SAAS,GAAG;GAC3C,IAAI,CAAC,UAAU,OAAO;GAEtB,MAAM,QAAkB,CAAC;GACzB,MAAM,WAAqC,CAAC;GAC5C,IAAI;GACJ,IAAI;GAEJ,IAAI;IACF,MAAM,YAAY,MAAM,YAAY,SAAS,OAAO,SAAS,yBAAS,IAAI,IAAI,GAAG,OAAO;KACtF;KACA,UAAU,SAAS;KACnB,IAAI;KACJ;KACA,kBAAkB,OAAO,SAAS,KAAK,EAAE;KACzC,OAAO,OAAO,SAAS;MACrB,IAAI,KAAK,QAAQ,SAAS,OACxB,YAAY,KAAK;MAEnB,IAAI,CAAC,iBAAiB;MACtB,SAAS,KAAK,KAAK,YAAYE,sCAAqB,KAAK,SAAS,IAAI,CAAC,CAAC;MACxE,MAAM,kBAAmB,KAAK,OAAmC;MACjE,IAAI,OAAO,oBAAoB,UAC7B,aAAa;KAEjB;IACF,CAAC;IAED,IAAI,gBAAgB;IACpB,IAAI,QAAQ,iBAAiB,CAAC,SAAS,QAAQ;KAC7C,MAAM,kBAAcC,oBAAKZ,mBAAQ,SAAS,KAAK,GAAGa,mCAAoB;KACtE,IAAK,MAAM,WAAW,eAAe,WAAW,MAAO,MAAM;MAC3D,MAAM,UAAUC,qCACd,MAAM,WAAW,aAAa,WAAW,GACzC,WACF;MACA,gBAAgBC,gCAAgB,WAAW,OAAO;KACpD;IACF;IAEA,MAAM,SAAS,MAAMC,8CACnBC,8BAAgB,MAAM,aAAa,GACnC,SAAS,SACT,UACF;IACA,MAAM,gBACH,MAAMC,4CACL,QACA,SAAS,SACT,YACA,SAAS,aACX,KAAM,CAAC;IAKT,OAAO;KACL;KACA,eANoBR,kCAAmB,QAAQ,SAAS,SAAS,YAAY,EAC7E,SAAS,cACX,CAAC;KAKC,MAAM,SAAS;KACf,MAAM,SAAS;KACf;KACA,WAAW,aAAa;KACxB,SAAS,kBAAkB,OAAO,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI;KAC3E;IACF;GACF,SAAS,OAAO;IACd,IAAI,SAAS,UAAU,iBAAiB,KAAK,GAC3C,OAAO;IAET,MAAM;GACR;EACF,CAAC;EAED,IAAI,CAAC,OAAO,OAAO;EAEnB,OAAO,IAAI,kBAAkB;GAC3B,GAAG;GACH,KAAK;GACL;EACF,CAAC;CACH,UAAU;EACR,KAAK,MAAM,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC,QAAQ,GAC1C,MAAM,QAAQ;CAElB;AACF;AAEA,eAAsB,iBACpB,OACA,SAQsD;CACtD,MAAM,UAAU,MAAM,WAAW,QAAQ,IAAI,QAAQ,IAAI,QAAIV,mBAAQ,KAAK;CAC1E,MAAM,QAAkB,CAAC;CACzB,MAAM,gBAA4C,CAAC;CACnD,IAAI;EASF,OAAO;GAAE;GAAO,cARK,YAAY,OAAO,yBAAS,IAAI,IAAI,GAAG,OAAO;IACjE,KAAK,QAAQ,OAAO;IACpB,UAAU,QAAQ;IAClB,IAAI,UAAU,QAAQ,EAAE;IACxB,iBAAiB,QAAQ,oBAAoB;IAC7C,OAAO,QAAQ;IACf,iBAAiB,QAAQ,qBAAqB,OAAO,cAAc,KAAK,EAAE;GAC5E,CAAC;EACsB;CACzB,UAAU;EACR,KAAK,MAAM,WAAW,CAAC,GAAG,aAAa,CAAC,CAAC,QAAQ,GAC/C,MAAM,QAAQ;CAElB;AACF;;;;;;AAOA,eAAsB,yBACpB,OACA,SACyB;CAEzB,OAAO,YAAY,OADH,SAAS,WAAW,QAAQ,IAAI,mBACb,IAAI,IAAI,GAAG,CAAC,GAAG;EAChD,KAAK,SAAS,OAAO;EACrB,UAAU,SAAS;EACnB,IAAI,UAAU,SAAS,EAAE;EACzB,iBAAiB;CACnB,CAAC;AACH"}
@@ -15,9 +15,9 @@ interface ResolutionRequest {
15
15
  collectCatalogs?: boolean;
16
16
  }
17
17
  interface ResolutionIo {
18
- fetchBosConfig?(bosUrl: string, registry?: string): Promise<unknown>;
19
- readFileOrNull?(path: string): Promise<string | null>;
20
- importModule?(path: string): Promise<Record<string, unknown>>;
18
+ fetchBosConfig?: (bosUrl: string, registry?: string) => Promise<unknown>;
19
+ readFileOrNull?: (path: string) => Promise<string | null>;
20
+ importModule?: (path: string) => Promise<Record<string, unknown>>;
21
21
  }
22
22
  interface RuntimeSources {
23
23
  uiSource?: "local" | "remote";
@@ -83,8 +83,8 @@ declare function walkExtendsChain(entry: string, options: {
83
83
  io?: ResolutionIo;
84
84
  registry?: string;
85
85
  collectCatalogs?: boolean;
86
- visit(link: WalkLink): Promise<void>;
87
- registerCleanup?(fn: () => Promise<void>): void;
86
+ visit: (link: WalkLink) => Promise<void>;
87
+ registerCleanup?: (fn: () => Promise<void>) => void;
88
88
  }): Promise<{
89
89
  chain: string[];
90
90
  config: BosConfigInput;
@@ -15,9 +15,9 @@ interface ResolutionRequest {
15
15
  collectCatalogs?: boolean;
16
16
  }
17
17
  interface ResolutionIo {
18
- fetchBosConfig?(bosUrl: string, registry?: string): Promise<unknown>;
19
- readFileOrNull?(path: string): Promise<string | null>;
20
- importModule?(path: string): Promise<Record<string, unknown>>;
18
+ fetchBosConfig?: (bosUrl: string, registry?: string) => Promise<unknown>;
19
+ readFileOrNull?: (path: string) => Promise<string | null>;
20
+ importModule?: (path: string) => Promise<Record<string, unknown>>;
21
21
  }
22
22
  interface RuntimeSources {
23
23
  uiSource?: "local" | "remote";
@@ -83,8 +83,8 @@ declare function walkExtendsChain(entry: string, options: {
83
83
  io?: ResolutionIo;
84
84
  registry?: string;
85
85
  collectCatalogs?: boolean;
86
- visit(link: WalkLink): Promise<void>;
87
- registerCleanup?(fn: () => Promise<void>): void;
86
+ visit: (link: WalkLink) => Promise<void>;
87
+ registerCleanup?: (fn: () => Promise<void>) => void;
88
88
  }): Promise<{
89
89
  chain: string[];
90
90
  config: BosConfigInput;
@@ -1 +1 @@
1
- {"version":3,"file":"session.mjs","names":[],"sources":["../../src/resolution/session.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { readWorkspaceCatalog, resolveSourceDir } from \"../cli/init\";\nimport { parseBosRef } from \"../cli/utils/helpers\";\nimport {\n BosConfigSchema,\n type BosEnv,\n buildRuntimeConfig,\n buildRuntimePluginsForConfig,\n CircularExtendsError,\n ConfigExtendsError,\n ConfigLoadError,\n ConfigNotfoundError,\n DEV_OVERLAY_FILENAME,\n defaultConfigEnv,\n findConfigPath,\n getConfigBaseDir,\n isAppDescriptorPath,\n loadAppDescriptorConfig,\n parseAppDescriptorModule,\n parseDevOverlayModule,\n parseExtendsTarget,\n resolveConfigComposableEntries,\n runWithConfigWarningSink,\n} from \"../config\";\nimport { applyDevOverlay } from \"../descriptor/resolve\";\nimport { fetchBosConfigFromFastKv } from \"../fastkv\";\nimport { mergeBosConfigWithExtends, resolveExtendsRef } from \"../merge\";\nimport type {\n BosConfig,\n BosConfigInput,\n ExtendsConfig,\n RuntimeConfig,\n RuntimePluginConfig,\n} from \"../types\";\n\nexport interface ResolutionRequest {\n cwd?: string;\n path?: string;\n bosUrl?: string;\n account?: string;\n gateway?: string;\n registry?: string;\n sourceDir?: string;\n env?: BosEnv;\n remotePlugins?: string[];\n collectCatalogs?: boolean;\n}\n\nexport interface ResolutionIo {\n fetchBosConfig?(bosUrl: string, registry?: string): Promise<unknown>;\n readFileOrNull?(path: string): Promise<string | null>;\n importModule?(path: string): Promise<Record<string, unknown>>;\n}\n\nexport interface RuntimeSources {\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n authSource?: \"local\" | \"remote\";\n hostSource?: \"local\" | \"remote\";\n env?: \"development\" | \"production\";\n plugins?: Record<string, unknown>;\n}\n\nexport interface WalkLink {\n ref: string;\n config: BosConfigInput;\n baseDir: string;\n sourceDir?: string;\n isLeaf: boolean;\n}\n\ninterface ResolvedIo {\n fetchBosConfig: (bosUrl: string, registry?: string) => Promise<unknown>;\n readFileOrNull: (path: string) => Promise<string | null>;\n importModule: (path: string) => Promise<Record<string, unknown>>;\n}\n\ninterface EntryDispatch {\n entry: string;\n baseDir: string;\n root: string;\n path: string | null;\n remote: boolean;\n}\n\ninterface WalkOptions {\n env: BosEnv;\n registry?: string;\n io: ResolvedIo;\n collectCatalogs: boolean;\n visit?: (link: WalkLink) => Promise<void>;\n registerCleanup?: (fn: () => Promise<void>) => void;\n}\n\ninterface SessionParts {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n path: string | null;\n chain: string[];\n rawConfig: BosConfigInput | null;\n catalog: Record<string, string> | null;\n repository: string | undefined;\n env: BosEnv;\n warnings: string[];\n}\n\nasync function defaultImportModule(path: string): Promise<Record<string, unknown>> {\n return import(/* webpackIgnore: true */ pathToFileURL(path).href);\n}\n\nfunction resolveIo(io?: ResolutionIo): ResolvedIo {\n return {\n fetchBosConfig:\n io?.fetchBosConfig ??\n (async (bosUrl, registry) => fetchBosConfigFromFastKv(bosUrl, registry)),\n readFileOrNull:\n io?.readFileOrNull ??\n (async (path) => (existsSync(path) ? readFileSync(path, \"utf-8\") : null)),\n importModule: io?.importModule ?? defaultImportModule,\n };\n}\n\nasync function loadNodeConfig(\n ref: string,\n baseDir: string,\n io: ResolvedIo,\n registry?: string,\n): Promise<BosConfigInput> {\n if (ref.startsWith(\"bos://\")) {\n return (await io.fetchBosConfig(ref, registry)) as BosConfigInput;\n }\n\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n if (isAppDescriptorPath(resolvedPath)) {\n return io.importModule === defaultImportModule\n ? loadAppDescriptorConfig(resolvedPath)\n : parseAppDescriptorModule(await io.importModule(resolvedPath), resolvedPath);\n }\n\n const content = await io.readFileOrNull(resolvedPath);\n if (content === null) {\n throw new ConfigLoadError({\n path: resolvedPath,\n message: `Config file not found: ${resolvedPath}`,\n });\n }\n return JSON.parse(content) as BosConfigInput;\n}\n\nasync function walkExtends(\n ref: string,\n baseDir: string,\n visited: Set<string>,\n chain: string[],\n options: WalkOptions,\n): Promise<BosConfigInput> {\n if (visited.has(ref)) {\n throw new CircularExtendsError({\n chain: [...visited, ref],\n message: `Circular extends detected: ${[...visited, ref].join(\" -> \")}`,\n });\n }\n\n let config: BosConfigInput;\n let nodeBaseDir = baseDir;\n let sourceDir: string | undefined;\n\n if (ref.startsWith(\"bos://\") && options.collectCatalogs) {\n const parsed = parseBosRef(ref);\n if (!parsed) {\n throw new ConfigLoadError({ path: ref, message: `Invalid bos ref: ${ref}` });\n }\n const sourceResult = await resolveSourceDir({\n extendsAccount: parsed.account,\n extendsGateway: parsed.gateway,\n });\n config = sourceResult.parentConfig as BosConfigInput;\n sourceDir = sourceResult.sourceDir || undefined;\n options.registerCleanup?.(sourceResult.cleanup);\n nodeBaseDir = sourceDir ?? baseDir;\n } else if (ref.startsWith(\"bos://\")) {\n config = await loadNodeConfig(ref, baseDir, options.io, options.registry);\n } else {\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n nodeBaseDir = dirname(resolvedPath);\n config = await loadNodeConfig(ref, nodeBaseDir, options.io, options.registry);\n }\n\n chain.push(ref);\n\n const extendsRef = config.extends\n ? resolveExtendsRef(config.extends as string | ExtendsConfig, options.env)\n : undefined;\n\n if (!extendsRef) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const parsedParentRef = parseExtendsTarget(extendsRef);\n const parentBaseDir = getConfigBaseDir(parsedParentRef.configPath, nodeBaseDir);\n\n if (\n options.collectCatalogs &&\n !canResolveExtendsRef(parsedParentRef.configPath, sourceDir ?? nodeBaseDir)\n ) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const nextVisited = new Set(visited);\n nextVisited.add(ref);\n const parent = await walkExtends(\n parsedParentRef.configPath,\n parentBaseDir,\n nextVisited,\n chain,\n options,\n );\n\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: false });\n return mergeBosConfigWithExtends(parent, config);\n}\n\nfunction canResolveExtendsRef(parentRef: string, baseDir: string | undefined): boolean {\n if (parentRef.startsWith(\"bos://\")) {\n return parseBosRef(parentRef) !== null;\n }\n if (!baseDir) {\n return false;\n }\n return existsSync(resolve(baseDir, parentRef));\n}\n\nfunction dispatchEntry(request: ResolutionRequest | undefined, cwd: string): EntryDispatch | null {\n if (request?.path) {\n const configPath = request.path;\n if (configPath.startsWith(\"bos://\")) {\n return { entry: configPath, baseDir: cwd, root: cwd, path: configPath, remote: true };\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n }\n\n if (request?.bosUrl) {\n return { entry: request.bosUrl, baseDir: cwd, root: cwd, path: null, remote: true };\n }\n\n if (request?.account) {\n if (!request.gateway) {\n throw new ConfigExtendsError({\n message: `Remote account \"${request.account}\" requires a gateway`,\n });\n }\n return {\n entry: `bos://${request.account}/${request.gateway}`,\n baseDir: cwd,\n root: cwd,\n path: null,\n remote: true,\n };\n }\n\n if (request?.sourceDir) {\n const sourceRoot = resolve(request.sourceDir);\n const configPath = findConfigPath(sourceRoot);\n if (!configPath) return null;\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: sourceRoot, path: configPath, remote: false };\n }\n\n const configPath = findConfigPath(cwd);\n if (!configPath) {\n return null;\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n}\n\nfunction isConfigNotFound(error: unknown): boolean {\n return error instanceof Error && error.message.startsWith(\"No config found for \");\n}\n\nexport class ResolutionSession {\n readonly config: BosConfig | null;\n readonly runtime: RuntimeConfig | null;\n readonly root: string;\n readonly path: string | null;\n readonly chain: readonly string[];\n readonly rawConfig: BosConfigInput | null;\n readonly catalog: Record<string, string> | null;\n readonly repository: string | undefined;\n\n #env: BosEnv;\n #warnings: string[];\n\n constructor(parts: SessionParts) {\n this.config = parts.config;\n this.runtime = parts.runtime;\n this.root = parts.root;\n this.path = parts.path;\n this.chain = parts.chain;\n this.rawConfig = parts.rawConfig;\n this.catalog = parts.catalog;\n this.repository = parts.repository;\n this.#env = parts.env;\n this.#warnings = parts.warnings;\n }\n\n static fromParts(parts: {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n source?: { path?: string; extended?: string[]; remote?: boolean };\n warnings?: string[];\n }): ResolutionSession {\n return new ResolutionSession({\n config: parts.config,\n runtime: parts.runtime,\n root: parts.root,\n path: parts.source?.path ?? null,\n chain: parts.source?.extended ?? [],\n rawConfig: null,\n catalog: null,\n repository: undefined,\n env: defaultConfigEnv(),\n warnings: [...(parts.warnings ?? [])],\n });\n }\n\n get warnings(): readonly string[] {\n const drained = [...this.#warnings];\n this.#warnings.length = 0;\n return drained;\n }\n\n async buildRuntime(sources?: RuntimeSources): Promise<RuntimeConfig> {\n if (!this.config) {\n throw new ConfigNotfoundError({\n message: \"No config loaded in this resolution session\",\n });\n }\n const config = this.config;\n const env = sources?.env ?? this.#env;\n return runWithConfigWarningSink(this.#warnings, () =>\n buildRuntimeConfig(config, this.root, env, {\n plugins: (sources?.plugins ?? {}) as Record<string, RuntimePluginConfig>,\n uiSource: sources?.uiSource,\n apiSource: sources?.apiSource,\n authSource: sources?.authSource,\n hostSource: sources?.hostSource,\n }),\n );\n }\n}\n\n/**\n * Opens a resolution session for the requested config source. In development,\n * a local leaf's `bos.dev.ts` overlay (beside the discovered entry config) is\n * merged child-wins over the extended input before parsing; overlays are never\n * read for `bos://` entries or in production/staging.\n */\nexport async function openResolution(\n request?: ResolutionRequest,\n io?: ResolutionIo,\n): Promise<ResolutionSession | null> {\n const resolvedIo = resolveIo(io);\n const env = request?.env ?? defaultConfigEnv();\n const runtimeEnv: BosEnv = env === \"staging\" ? \"production\" : env;\n const cwd = request?.cwd ?? process.cwd();\n const collectCatalogs = request?.collectCatalogs === true;\n\n const warnings: string[] = [];\n const cleanups: Array<() => Promise<void>> = [];\n\n try {\n const parts = await runWithConfigWarningSink(warnings, async () => {\n const dispatch = dispatchEntry(request, cwd);\n if (!dispatch) return null;\n\n const chain: string[] = [];\n const catalogs: Record<string, string>[] = [];\n let repository: string | undefined;\n let rawConfig: BosConfigInput | undefined;\n\n try {\n const mergedRaw = await walkExtends(dispatch.entry, dispatch.baseDir, new Set(), chain, {\n env,\n registry: request?.registry,\n io: resolvedIo,\n collectCatalogs,\n registerCleanup: (fn) => cleanups.push(fn),\n visit: async (link) => {\n if (link.ref === dispatch.entry) {\n rawConfig = link.config;\n }\n if (!collectCatalogs) return;\n catalogs.push(link.sourceDir ? readWorkspaceCatalog(link.sourceDir) : {});\n const repositoryValue = (link.config as Record<string, unknown>).repository;\n if (typeof repositoryValue === \"string\") {\n repository = repositoryValue;\n }\n },\n });\n\n let overlayMerged = mergedRaw;\n if (env === \"development\" && !dispatch.remote) {\n const overlayPath = join(dirname(dispatch.entry), DEV_OVERLAY_FILENAME);\n if ((await resolvedIo.readFileOrNull(overlayPath)) !== null) {\n const overlay = parseDevOverlayModule(\n await resolvedIo.importModule(overlayPath),\n overlayPath,\n );\n overlayMerged = applyDevOverlay(mergedRaw, overlay);\n }\n }\n\n const config = await resolveConfigComposableEntries(\n BosConfigSchema.parse(overlayMerged),\n dispatch.baseDir,\n runtimeEnv,\n );\n const pluginRuntime =\n (await buildRuntimePluginsForConfig(\n config,\n dispatch.baseDir,\n runtimeEnv,\n request?.remotePlugins,\n )) ?? {};\n const runtime = await buildRuntimeConfig(config, dispatch.baseDir, runtimeEnv, {\n plugins: pluginRuntime,\n });\n\n return {\n config,\n runtime,\n root: dispatch.root,\n path: dispatch.path,\n chain,\n rawConfig: rawConfig ?? null,\n catalog: collectCatalogs ? Object.assign({}, ...[...catalogs].reverse()) : null,\n repository,\n } satisfies Omit<SessionParts, \"env\" | \"warnings\">;\n } catch (error) {\n if (dispatch.remote && isConfigNotFound(error)) {\n return null;\n }\n throw error;\n }\n });\n\n if (!parts) return null;\n\n return new ResolutionSession({\n ...parts,\n env: runtimeEnv,\n warnings,\n });\n } finally {\n for (const cleanup of [...cleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\nexport async function walkExtendsChain(\n entry: string,\n options: {\n env?: BosEnv;\n io?: ResolutionIo;\n registry?: string;\n collectCatalogs?: boolean;\n visit(link: WalkLink): Promise<void>;\n registerCleanup?(fn: () => Promise<void>): void;\n },\n): Promise<{ chain: string[]; config: BosConfigInput }> {\n const baseDir = entry.startsWith(\"bos://\") ? process.cwd() : dirname(entry);\n const chain: string[] = [];\n const ownedCleanups: Array<() => Promise<void>> = [];\n try {\n const config = await walkExtends(entry, baseDir, new Set(), chain, {\n env: options.env ?? \"development\",\n registry: options.registry,\n io: resolveIo(options.io),\n collectCatalogs: options.collectCatalogs === true,\n visit: options.visit,\n registerCleanup: options.registerCleanup ?? ((fn) => ownedCleanups.push(fn)),\n });\n return { chain, config };\n } finally {\n for (const cleanup of [...ownedCleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\n/**\n * @internal — resolves the fully merged (parent-merged, un-parsed)\n * `BosConfigInput` for a config entry. Used by config.ts's\n * `resolveComposableReference` for plugin-entry extends resolution.\n */\nexport async function resolveMergedConfigInput(\n entry: string,\n options?: { baseDir?: string; env?: BosEnv; io?: ResolutionIo; registry?: string },\n): Promise<BosConfigInput> {\n const baseDir = options?.baseDir ?? process.cwd();\n return walkExtends(entry, baseDir, new Set(), [], {\n env: options?.env ?? \"development\",\n registry: options?.registry,\n io: resolveIo(options?.io),\n collectCatalogs: false,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"session.mjs","names":[],"sources":["../../src/resolution/session.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { readWorkspaceCatalog, resolveSourceDir } from \"../cli/init\";\nimport { parseBosRef } from \"../cli/utils/helpers\";\nimport {\n BosConfigSchema,\n type BosEnv,\n buildRuntimeConfig,\n buildRuntimePluginsForConfig,\n CircularExtendsError,\n ConfigExtendsError,\n ConfigLoadError,\n ConfigNotfoundError,\n DEV_OVERLAY_FILENAME,\n defaultConfigEnv,\n findConfigPath,\n getConfigBaseDir,\n isAppDescriptorPath,\n loadAppDescriptorConfig,\n parseAppDescriptorModule,\n parseDevOverlayModule,\n parseExtendsTarget,\n resolveConfigComposableEntries,\n runWithConfigWarningSink,\n} from \"../config\";\nimport { applyDevOverlay } from \"../descriptor/resolve\";\nimport { fetchBosConfigFromFastKv } from \"../fastkv\";\nimport { mergeBosConfigWithExtends, resolveExtendsRef } from \"../merge\";\nimport type {\n BosConfig,\n BosConfigInput,\n ExtendsConfig,\n RuntimeConfig,\n RuntimePluginConfig,\n} from \"../types\";\n\nexport interface ResolutionRequest {\n cwd?: string;\n path?: string;\n bosUrl?: string;\n account?: string;\n gateway?: string;\n registry?: string;\n sourceDir?: string;\n env?: BosEnv;\n remotePlugins?: string[];\n collectCatalogs?: boolean;\n}\n\nexport interface ResolutionIo {\n fetchBosConfig?: (bosUrl: string, registry?: string) => Promise<unknown>;\n readFileOrNull?: (path: string) => Promise<string | null>;\n importModule?: (path: string) => Promise<Record<string, unknown>>;\n}\n\nexport interface RuntimeSources {\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n authSource?: \"local\" | \"remote\";\n hostSource?: \"local\" | \"remote\";\n env?: \"development\" | \"production\";\n plugins?: Record<string, unknown>;\n}\n\nexport interface WalkLink {\n ref: string;\n config: BosConfigInput;\n baseDir: string;\n sourceDir?: string;\n isLeaf: boolean;\n}\n\ninterface ResolvedIo {\n fetchBosConfig: (bosUrl: string, registry?: string) => Promise<unknown>;\n readFileOrNull: (path: string) => Promise<string | null>;\n importModule: (path: string) => Promise<Record<string, unknown>>;\n}\n\ninterface EntryDispatch {\n entry: string;\n baseDir: string;\n root: string;\n path: string | null;\n remote: boolean;\n}\n\ninterface WalkOptions {\n env: BosEnv;\n registry?: string;\n io: ResolvedIo;\n collectCatalogs: boolean;\n visit?: (link: WalkLink) => Promise<void>;\n registerCleanup?: (fn: () => Promise<void>) => void;\n}\n\ninterface SessionParts {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n path: string | null;\n chain: string[];\n rawConfig: BosConfigInput | null;\n catalog: Record<string, string> | null;\n repository: string | undefined;\n env: BosEnv;\n warnings: string[];\n}\n\nasync function defaultImportModule(path: string): Promise<Record<string, unknown>> {\n return import(/* webpackIgnore: true */ pathToFileURL(path).href);\n}\n\nfunction resolveIo(io?: ResolutionIo): ResolvedIo {\n return {\n fetchBosConfig:\n io?.fetchBosConfig ??\n (async (bosUrl, registry) => fetchBosConfigFromFastKv(bosUrl, registry)),\n readFileOrNull:\n io?.readFileOrNull ??\n (async (path) => (existsSync(path) ? readFileSync(path, \"utf-8\") : null)),\n importModule: io?.importModule ?? defaultImportModule,\n };\n}\n\nasync function loadNodeConfig(\n ref: string,\n baseDir: string,\n io: ResolvedIo,\n registry?: string,\n): Promise<BosConfigInput> {\n if (ref.startsWith(\"bos://\")) {\n return (await io.fetchBosConfig(ref, registry)) as BosConfigInput;\n }\n\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n if (isAppDescriptorPath(resolvedPath)) {\n return io.importModule === defaultImportModule\n ? loadAppDescriptorConfig(resolvedPath)\n : parseAppDescriptorModule(await io.importModule(resolvedPath), resolvedPath);\n }\n\n const content = await io.readFileOrNull(resolvedPath);\n if (content === null) {\n throw new ConfigLoadError({\n path: resolvedPath,\n message: `Config file not found: ${resolvedPath}`,\n });\n }\n return JSON.parse(content) as BosConfigInput;\n}\n\nasync function walkExtends(\n ref: string,\n baseDir: string,\n visited: Set<string>,\n chain: string[],\n options: WalkOptions,\n): Promise<BosConfigInput> {\n if (visited.has(ref)) {\n throw new CircularExtendsError({\n chain: [...visited, ref],\n message: `Circular extends detected: ${[...visited, ref].join(\" -> \")}`,\n });\n }\n\n let config: BosConfigInput;\n let nodeBaseDir = baseDir;\n let sourceDir: string | undefined;\n\n if (ref.startsWith(\"bos://\") && options.collectCatalogs) {\n const parsed = parseBosRef(ref);\n if (!parsed) {\n throw new ConfigLoadError({ path: ref, message: `Invalid bos ref: ${ref}` });\n }\n const sourceResult = await resolveSourceDir({\n extendsAccount: parsed.account,\n extendsGateway: parsed.gateway,\n });\n config = sourceResult.parentConfig as BosConfigInput;\n sourceDir = sourceResult.sourceDir || undefined;\n options.registerCleanup?.(sourceResult.cleanup);\n nodeBaseDir = sourceDir ?? baseDir;\n } else if (ref.startsWith(\"bos://\")) {\n config = await loadNodeConfig(ref, baseDir, options.io, options.registry);\n } else {\n const resolvedPath = isAbsolute(ref) ? ref : resolve(baseDir, ref);\n nodeBaseDir = dirname(resolvedPath);\n config = await loadNodeConfig(ref, nodeBaseDir, options.io, options.registry);\n }\n\n chain.push(ref);\n\n const extendsRef = config.extends\n ? resolveExtendsRef(config.extends as string | ExtendsConfig, options.env)\n : undefined;\n\n if (!extendsRef) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const parsedParentRef = parseExtendsTarget(extendsRef);\n const parentBaseDir = getConfigBaseDir(parsedParentRef.configPath, nodeBaseDir);\n\n if (\n options.collectCatalogs &&\n !canResolveExtendsRef(parsedParentRef.configPath, sourceDir ?? nodeBaseDir)\n ) {\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: true });\n return config;\n }\n\n const nextVisited = new Set(visited);\n nextVisited.add(ref);\n const parent = await walkExtends(\n parsedParentRef.configPath,\n parentBaseDir,\n nextVisited,\n chain,\n options,\n );\n\n await options.visit?.({ ref, config, baseDir: nodeBaseDir, sourceDir, isLeaf: false });\n return mergeBosConfigWithExtends(parent, config);\n}\n\nfunction canResolveExtendsRef(parentRef: string, baseDir: string | undefined): boolean {\n if (parentRef.startsWith(\"bos://\")) {\n return parseBosRef(parentRef) !== null;\n }\n if (!baseDir) {\n return false;\n }\n return existsSync(resolve(baseDir, parentRef));\n}\n\nfunction dispatchEntry(request: ResolutionRequest | undefined, cwd: string): EntryDispatch | null {\n if (request?.path) {\n const configPath = request.path;\n if (configPath.startsWith(\"bos://\")) {\n return { entry: configPath, baseDir: cwd, root: cwd, path: configPath, remote: true };\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n }\n\n if (request?.bosUrl) {\n return { entry: request.bosUrl, baseDir: cwd, root: cwd, path: null, remote: true };\n }\n\n if (request?.account) {\n if (!request.gateway) {\n throw new ConfigExtendsError({\n message: `Remote account \"${request.account}\" requires a gateway`,\n });\n }\n return {\n entry: `bos://${request.account}/${request.gateway}`,\n baseDir: cwd,\n root: cwd,\n path: null,\n remote: true,\n };\n }\n\n if (request?.sourceDir) {\n const sourceRoot = resolve(request.sourceDir);\n const configPath = findConfigPath(sourceRoot);\n if (!configPath) return null;\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: sourceRoot, path: configPath, remote: false };\n }\n\n const configPath = findConfigPath(cwd);\n if (!configPath) {\n return null;\n }\n const baseDir = dirname(configPath);\n return { entry: configPath, baseDir, root: baseDir, path: configPath, remote: false };\n}\n\nfunction isConfigNotFound(error: unknown): boolean {\n return error instanceof Error && error.message.startsWith(\"No config found for \");\n}\n\nexport class ResolutionSession {\n readonly config: BosConfig | null;\n readonly runtime: RuntimeConfig | null;\n readonly root: string;\n readonly path: string | null;\n readonly chain: readonly string[];\n readonly rawConfig: BosConfigInput | null;\n readonly catalog: Record<string, string> | null;\n readonly repository: string | undefined;\n\n #env: BosEnv;\n #warnings: string[];\n\n constructor(parts: SessionParts) {\n this.config = parts.config;\n this.runtime = parts.runtime;\n this.root = parts.root;\n this.path = parts.path;\n this.chain = parts.chain;\n this.rawConfig = parts.rawConfig;\n this.catalog = parts.catalog;\n this.repository = parts.repository;\n this.#env = parts.env;\n this.#warnings = parts.warnings;\n }\n\n static fromParts(parts: {\n config: BosConfig;\n runtime: RuntimeConfig;\n root: string;\n source?: { path?: string; extended?: string[]; remote?: boolean };\n warnings?: string[];\n }): ResolutionSession {\n return new ResolutionSession({\n config: parts.config,\n runtime: parts.runtime,\n root: parts.root,\n path: parts.source?.path ?? null,\n chain: parts.source?.extended ?? [],\n rawConfig: null,\n catalog: null,\n repository: undefined,\n env: defaultConfigEnv(),\n warnings: [...(parts.warnings ?? [])],\n });\n }\n\n get warnings(): readonly string[] {\n const drained = [...this.#warnings];\n this.#warnings.length = 0;\n return drained;\n }\n\n async buildRuntime(sources?: RuntimeSources): Promise<RuntimeConfig> {\n if (!this.config) {\n throw new ConfigNotfoundError({\n message: \"No config loaded in this resolution session\",\n });\n }\n const config = this.config;\n const env = sources?.env ?? this.#env;\n return runWithConfigWarningSink(this.#warnings, () =>\n buildRuntimeConfig(config, this.root, env, {\n plugins: (sources?.plugins ?? {}) as Record<string, RuntimePluginConfig>,\n uiSource: sources?.uiSource,\n apiSource: sources?.apiSource,\n authSource: sources?.authSource,\n hostSource: sources?.hostSource,\n }),\n );\n }\n}\n\n/**\n * Opens a resolution session for the requested config source. In development,\n * a local leaf's `bos.dev.ts` overlay (beside the discovered entry config) is\n * merged child-wins over the extended input before parsing; overlays are never\n * read for `bos://` entries or in production/staging.\n */\nexport async function openResolution(\n request?: ResolutionRequest,\n io?: ResolutionIo,\n): Promise<ResolutionSession | null> {\n const resolvedIo = resolveIo(io);\n const env = request?.env ?? defaultConfigEnv();\n const runtimeEnv: BosEnv = env === \"staging\" ? \"production\" : env;\n const cwd = request?.cwd ?? process.cwd();\n const collectCatalogs = request?.collectCatalogs === true;\n\n const warnings: string[] = [];\n const cleanups: Array<() => Promise<void>> = [];\n\n try {\n const parts = await runWithConfigWarningSink(warnings, async () => {\n const dispatch = dispatchEntry(request, cwd);\n if (!dispatch) return null;\n\n const chain: string[] = [];\n const catalogs: Record<string, string>[] = [];\n let repository: string | undefined;\n let rawConfig: BosConfigInput | undefined;\n\n try {\n const mergedRaw = await walkExtends(dispatch.entry, dispatch.baseDir, new Set(), chain, {\n env,\n registry: request?.registry,\n io: resolvedIo,\n collectCatalogs,\n registerCleanup: (fn) => cleanups.push(fn),\n visit: async (link) => {\n if (link.ref === dispatch.entry) {\n rawConfig = link.config;\n }\n if (!collectCatalogs) return;\n catalogs.push(link.sourceDir ? readWorkspaceCatalog(link.sourceDir) : {});\n const repositoryValue = (link.config as Record<string, unknown>).repository;\n if (typeof repositoryValue === \"string\") {\n repository = repositoryValue;\n }\n },\n });\n\n let overlayMerged = mergedRaw;\n if (env === \"development\" && !dispatch.remote) {\n const overlayPath = join(dirname(dispatch.entry), DEV_OVERLAY_FILENAME);\n if ((await resolvedIo.readFileOrNull(overlayPath)) !== null) {\n const overlay = parseDevOverlayModule(\n await resolvedIo.importModule(overlayPath),\n overlayPath,\n );\n overlayMerged = applyDevOverlay(mergedRaw, overlay);\n }\n }\n\n const config = await resolveConfigComposableEntries(\n BosConfigSchema.parse(overlayMerged),\n dispatch.baseDir,\n runtimeEnv,\n );\n const pluginRuntime =\n (await buildRuntimePluginsForConfig(\n config,\n dispatch.baseDir,\n runtimeEnv,\n request?.remotePlugins,\n )) ?? {};\n const runtime = await buildRuntimeConfig(config, dispatch.baseDir, runtimeEnv, {\n plugins: pluginRuntime,\n });\n\n return {\n config,\n runtime,\n root: dispatch.root,\n path: dispatch.path,\n chain,\n rawConfig: rawConfig ?? null,\n catalog: collectCatalogs ? Object.assign({}, ...[...catalogs].reverse()) : null,\n repository,\n } satisfies Omit<SessionParts, \"env\" | \"warnings\">;\n } catch (error) {\n if (dispatch.remote && isConfigNotFound(error)) {\n return null;\n }\n throw error;\n }\n });\n\n if (!parts) return null;\n\n return new ResolutionSession({\n ...parts,\n env: runtimeEnv,\n warnings,\n });\n } finally {\n for (const cleanup of [...cleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\nexport async function walkExtendsChain(\n entry: string,\n options: {\n env?: BosEnv;\n io?: ResolutionIo;\n registry?: string;\n collectCatalogs?: boolean;\n visit: (link: WalkLink) => Promise<void>;\n registerCleanup?: (fn: () => Promise<void>) => void;\n },\n): Promise<{ chain: string[]; config: BosConfigInput }> {\n const baseDir = entry.startsWith(\"bos://\") ? process.cwd() : dirname(entry);\n const chain: string[] = [];\n const ownedCleanups: Array<() => Promise<void>> = [];\n try {\n const config = await walkExtends(entry, baseDir, new Set(), chain, {\n env: options.env ?? \"development\",\n registry: options.registry,\n io: resolveIo(options.io),\n collectCatalogs: options.collectCatalogs === true,\n visit: options.visit,\n registerCleanup: options.registerCleanup ?? ((fn) => ownedCleanups.push(fn)),\n });\n return { chain, config };\n } finally {\n for (const cleanup of [...ownedCleanups].reverse()) {\n await cleanup();\n }\n }\n}\n\n/**\n * @internal — resolves the fully merged (parent-merged, un-parsed)\n * `BosConfigInput` for a config entry. Used by config.ts's\n * `resolveComposableReference` for plugin-entry extends resolution.\n */\nexport async function resolveMergedConfigInput(\n entry: string,\n options?: { baseDir?: string; env?: BosEnv; io?: ResolutionIo; registry?: string },\n): Promise<BosConfigInput> {\n const baseDir = options?.baseDir ?? process.cwd();\n return walkExtends(entry, baseDir, new Set(), [], {\n env: options?.env ?? \"development\",\n registry: options?.registry,\n io: resolveIo(options?.io),\n collectCatalogs: false,\n });\n}\n"],"mappings":"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"}
package/dist/types.d.cts CHANGED
@@ -941,7 +941,37 @@ declare const ClientRuntimeConfigSchema: z$1.ZodObject<{
941
941
  entry: z$1.ZodString;
942
942
  integrity: z$1.ZodOptional<z$1.ZodString>;
943
943
  entryUrl: z$1.ZodOptional<z$1.ZodString>;
944
- compose: any;
944
+ compose: z$1.ZodOptional<z$1.ZodObject<{
945
+ digest: z$1.ZodString;
946
+ remotes: z$1.ZodArray<z$1.ZodObject<{
947
+ key: z$1.ZodString;
948
+ name: z$1.ZodString;
949
+ entry: z$1.ZodString;
950
+ manifestUrl: z$1.ZodOptional<z$1.ZodString>;
951
+ }, z$1.core.$strip>>;
952
+ manifests: z$1.ZodArray<z$1.ZodObject<{
953
+ name: z$1.ZodString;
954
+ manifestVersion: z$1.ZodNumber;
955
+ rootMeta: z$1.ZodOptional<z$1.ZodObject<{
956
+ hasHead: z$1.ZodOptional<z$1.ZodBoolean>;
957
+ hasStaticData: z$1.ZodOptional<z$1.ZodBoolean>;
958
+ }, z$1.core.$strip>>;
959
+ routes: z$1.ZodArray<z$1.ZodObject<{
960
+ id: z$1.ZodString;
961
+ type: z$1.ZodEnum<{
962
+ index: "index";
963
+ layout: "layout";
964
+ route: "route";
965
+ }>;
966
+ path: z$1.ZodOptional<z$1.ZodString>;
967
+ parentId: z$1.ZodOptional<z$1.ZodString>;
968
+ mount: z$1.ZodOptional<z$1.ZodEnum<{
969
+ [x: string]: string;
970
+ }>>;
971
+ file: z$1.ZodOptional<z$1.ZodString>;
972
+ }, z$1.core.$strip>>;
973
+ }, z$1.core.$strip>>;
974
+ }, z$1.core.$strip>>;
945
975
  }, z$1.core.$strip>>;
946
976
  api: z$1.ZodOptional<z$1.ZodObject<{
947
977
  name: z$1.ZodString;
package/dist/types.d.mts CHANGED
@@ -941,7 +941,37 @@ declare const ClientRuntimeConfigSchema: z$1.ZodObject<{
941
941
  entry: z$1.ZodString;
942
942
  integrity: z$1.ZodOptional<z$1.ZodString>;
943
943
  entryUrl: z$1.ZodOptional<z$1.ZodString>;
944
- compose: any;
944
+ compose: z$1.ZodOptional<z$1.ZodObject<{
945
+ digest: z$1.ZodString;
946
+ remotes: z$1.ZodArray<z$1.ZodObject<{
947
+ key: z$1.ZodString;
948
+ name: z$1.ZodString;
949
+ entry: z$1.ZodString;
950
+ manifestUrl: z$1.ZodOptional<z$1.ZodString>;
951
+ }, z$1.core.$strip>>;
952
+ manifests: z$1.ZodArray<z$1.ZodObject<{
953
+ name: z$1.ZodString;
954
+ manifestVersion: z$1.ZodNumber;
955
+ rootMeta: z$1.ZodOptional<z$1.ZodObject<{
956
+ hasHead: z$1.ZodOptional<z$1.ZodBoolean>;
957
+ hasStaticData: z$1.ZodOptional<z$1.ZodBoolean>;
958
+ }, z$1.core.$strip>>;
959
+ routes: z$1.ZodArray<z$1.ZodObject<{
960
+ id: z$1.ZodString;
961
+ type: z$1.ZodEnum<{
962
+ index: "index";
963
+ layout: "layout";
964
+ route: "route";
965
+ }>;
966
+ path: z$1.ZodOptional<z$1.ZodString>;
967
+ parentId: z$1.ZodOptional<z$1.ZodString>;
968
+ mount: z$1.ZodOptional<z$1.ZodEnum<{
969
+ [x: string]: string;
970
+ }>>;
971
+ file: z$1.ZodOptional<z$1.ZodString>;
972
+ }, z$1.core.$strip>>;
973
+ }, z$1.core.$strip>>;
974
+ }, z$1.core.$strip>>;
945
975
  }, z$1.core.$strip>>;
946
976
  api: z$1.ZodOptional<z$1.ZodObject<{
947
977
  name: z$1.ZodString;