everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 117 kB
Source Map (JSON)
{"version":3,"file":"plugin.cjs","names":["EventEmitter","resolveLocalDevelopmentPath","loadResolvedConfig","syncApiContractBridge","process","fetchBosConfigFromFastKv","run","resolveExtendsRef","parseBosUrl","mergeBosConfigWithExtends","resolveConfigComposableEntries","BosConfigSchema","readDeployResults","colors","icons","syncResolvedSharedDeps","readAllDeployResults","applyDeployResults","z","bosContract","Effect","getProjectRoot","loadLocalConfig","saveBosConfig","fetchRemotePluginManifest","computeSriHashForUrl","detectLocalPackages","getHostDevelopmentPort","buildRuntimeConfig","prepareDevelopmentRuntimeConfig","buildServiceDescriptorMap","buildDescription","buildRegistryConfigUrl","buildRuntimePluginsForConfig","findConfigPath","getNetworkIdForAccount","getRegistryNamespaceForAccount","ensureNearCli","addFunctionCallAccessKey","fetchParentConfig","detectGitRemoteUrl","resolveSourceDir","scaffoldMinimalProject","personalizeConfig","buildInitPatterns","copyFilteredFiles","writeInitSnapshot","personalizeAgentsMd","runBunInstall","runTypesGen","generateDatabaseMigrations","syncTemplate","upgradeTemplate","getStatus","buildRegistryConfigUrlForNetwork","resolveNearSigningMode","executeTransaction","getRegistryNamespaceForNetwork"],"sources":["../src/plugin.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { access, readFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { type ContractBridgeStatus, syncApiContractBridge } from \"./api-contract\";\nimport { buildRuntimeConfig, detectLocalPackages, prepareDevelopmentRuntimeConfig } from \"./app\";\nimport {\n ensureEnvFile,\n loadProjectEnv,\n syncGeneratedInfra,\n writeGeneratedInfra,\n} from \"./cli/infra\";\nimport {\n buildInitPatterns,\n copyFilteredFiles,\n detectGitRemoteUrl,\n fetchParentConfig,\n generateDatabaseMigrations,\n personalizeAgentsMd,\n personalizeConfig,\n removeInitLockfile,\n resolveSourceDir,\n runBunInstall,\n runTypesGen,\n scaffoldMinimalProject,\n stripOrphanedWorkspacesFromLockfile,\n writeInitSnapshot,\n} from \"./cli/init\";\nimport { getStatus } from \"./cli/status\";\nimport { syncTemplate } from \"./cli/sync\";\nimport { upgradeTemplate } from \"./cli/upgrade\";\nimport {\n buildRuntimePluginsForConfig,\n drainConfigWarnings,\n findConfigPath,\n getHostDevelopmentPort,\n getProjectRoot,\n loadLocalConfig,\n loadResolvedConfig,\n resolveConfigComposableEntries,\n resolveLocalDevelopmentPath,\n resumeWarnings,\n suppressWarnings,\n writeResolvedConfig,\n} from \"./config\";\nimport {\n type BosConfigResult,\n bosContract,\n type OverrideSection,\n type PhaseTiming,\n type PluginListResult,\n type WorkspaceDeployResult,\n} from \"./contract\";\nimport {\n buildRegistryConfigUrl,\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n fetchRemotePluginManifest,\n getRegistryNamespaceForAccount,\n getRegistryNamespaceForNetwork,\n type PluginManifest,\n parseBosUrl,\n} from \"./fastkv\";\nimport {\n applyDeployResults,\n cleanDeployResultDir,\n computeSriHashForUrl,\n readAllDeployResults,\n readDeployResults,\n} from \"./integrity\";\nimport { type BosEnv, mergeBosConfigWithExtends, resolveExtendsRef } from \"./merge\";\nimport {\n addFunctionCallAccessKey,\n ensureNearCli,\n executeTransaction,\n resolveNearSigningMode,\n} from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport { createPlugin, z } from \"./sdk\";\nimport {\n type AppOrchestrator,\n buildDescription,\n buildServiceDescriptorMap,\n type ServiceDescriptor,\n} from \"./service-descriptor\";\nimport { syncResolvedSharedDeps } from \"./shared-deps\";\nimport type {\n BosConfig,\n BosConfigInput,\n BosPluginRef,\n ExtendsConfig,\n RuntimeConfig,\n SourceMode,\n} from \"./types\";\nimport { BosConfigSchema } from \"./types\";\nimport { run } from \"./utils/run\";\nimport { saveBosConfig } from \"./utils/save-config\";\nimport { colors, icons } from \"./utils/theme\";\n\nexport interface DevSessionData {\n orchestrator: AppOrchestrator;\n services: Map<string, ServiceDescriptor>;\n runtimeConfig: RuntimeConfig;\n}\n\nexport interface StartSummary {\n configSource: string;\n configSourceHttp?: string;\n account: string;\n domain?: string;\n modules: { host?: string; ui?: string; api?: string; auth?: string };\n warnings: string[];\n}\n\nexport type ProgressEvent = {\n phase: string;\n status: \"running\" | \"done\" | \"error\";\n durationMs?: number;\n message?: string;\n};\n\nexport const pluginEvents = new EventEmitter();\n\nlet pendingSession: DevSessionData | null = null;\nlet pendingStartSummary: StartSummary | null = null;\n\nexport function consumeDevSession(): (DevSessionData & { summary?: StartSummary }) | null {\n const data = pendingSession;\n const summary = pendingStartSummary;\n pendingSession = null;\n pendingStartSummary = null;\n if (!data) return null;\n return summary ? { ...data, summary } : data;\n}\n\nasync function timePhase<T>(\n timings: PhaseTiming[],\n name: string,\n fn: () => Promise<T>,\n): Promise<T> {\n pluginEvents.emit(\"progress\", { phase: name, status: \"running\" } satisfies ProgressEvent);\n const startedAt = Date.now();\n try {\n const result = await fn();\n timings.push({ name, durationMs: Date.now() - startedAt });\n pluginEvents.emit(\"progress\", {\n phase: name,\n status: \"done\",\n durationMs: Date.now() - startedAt,\n } satisfies ProgressEvent);\n return result;\n } catch (error) {\n pluginEvents.emit(\"progress\", {\n phase: name,\n status: \"error\",\n durationMs: Date.now() - startedAt,\n } satisfies ProgressEvent);\n throw error;\n }\n}\n\nconst buildCommands: Record<string, { cmd: string; args: string[] }> = {\n host: { cmd: \"bun\", args: [\"run\", \"build\"] },\n ui: { cmd: \"bun\", args: [\"run\", \"build\"] },\n api: { cmd: \"bun\", args: [\"run\", \"build\"] },\n};\n\nconst PUBLISH_FUNCTION_NAMES = [\"__fastdata_kv\"];\n\ntype BosDeps = {\n bosConfig: BosConfig | null;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n};\n\ntype PluginAttachmentConfig = NonNullable<BosConfig[\"plugins\"]>[string];\n\nfunction getPluginRef(entry: string | BosPluginRef | undefined | null): BosPluginRef | null {\n if (!entry || typeof entry === \"string\") return null;\n return entry;\n}\n\nfunction parseSourceMode(value: string | undefined, defaultValue: SourceMode): SourceMode {\n if (value === \"local\" || value === \"remote\") return value;\n return defaultValue;\n}\n\nfunction buildConfigResult(\n bosConfig: BosConfigInput | BosConfig | null,\n full = false,\n): BosConfigResult {\n const packages =\n bosConfig?.app && typeof bosConfig.app === \"object\" ? Object.keys(bosConfig.app) : [];\n const remotes = packages.filter((name) => name !== \"host\");\n\n return {\n config: bosConfig ?? null,\n packages,\n remotes,\n full,\n };\n}\n\ntype WorkspaceTarget = {\n key: string;\n kind: \"app\" | \"plugin\";\n path: string;\n};\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJsonFile<T>(path: string): Promise<T> {\n return JSON.parse(await readFile(path, \"utf8\")) as T;\n}\n\nfunction resolveWorkspaceTarget(\n key: string,\n bosConfig: BosConfig | null,\n runtimeConfig: RuntimeConfig | null,\n configDir: string,\n): WorkspaceTarget | null {\n if (bosConfig?.app && key in bosConfig.app) {\n const appEntry = (bosConfig.app as Record<string, { development?: string }>)[key];\n const devPath = resolveLocalDevelopmentPath(appEntry?.development, configDir);\n if (devPath) {\n return {\n key,\n kind: \"app\",\n path: devPath,\n };\n }\n return {\n key,\n kind: \"app\",\n path: `${configDir}/${key}`,\n };\n }\n\n const runtimePlugin = runtimeConfig?.plugins?.[key];\n const pluginPath =\n runtimePlugin?.localPath ??\n resolveLocalDevelopmentPath(getPluginRef(bosConfig?.plugins?.[key])?.development, configDir);\n if (pluginPath) {\n return {\n key,\n kind: \"plugin\",\n path: pluginPath,\n };\n }\n\n return null;\n}\n\nfunction isValidProxyUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === \"http:\" || parsed.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nfunction resolveProxyUrl(bosConfig: BosConfig | null): string | null {\n if (!bosConfig) return null;\n const apiConfig = bosConfig.app.api;\n if (!apiConfig) return null;\n if (apiConfig.proxy && isValidProxyUrl(apiConfig.proxy)) return apiConfig.proxy;\n if (apiConfig.production && isValidProxyUrl(apiConfig.production)) return apiConfig.production;\n return null;\n}\n\nfunction sanitizePluginKey(value: string): string {\n return value\n .replace(/[^A-Za-z0-9/_-]/g, \"-\")\n .replace(/\\/+/g, \"/\")\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => segment.replace(/[^A-Za-z0-9_-]/g, \"-\"))\n .join(\"/\")\n .replace(/^\\/+|\\/+$/g, \"\");\n}\n\nfunction defaultPluginKey(source: string): string {\n const normalized = source.replace(/^local:/, \"\").replace(/\\/$/, \"\");\n if (source.startsWith(\"local:\")) {\n return sanitizePluginKey(basename(normalized)) || \"plugin\";\n }\n\n try {\n const url = new URL(source);\n return sanitizePluginKey(basename(url.pathname) || url.hostname) || \"plugin\";\n } catch {\n return sanitizePluginKey(source) || \"plugin\";\n }\n}\n\nfunction pluginLocalPath(configDir: string, attachment: PluginAttachmentConfig): string | null {\n const ref = getPluginRef(attachment);\n const source = ref?.development ?? ref?.production;\n if (!source?.startsWith(\"local:\")) {\n return null;\n }\n\n return join(configDir, source.slice(\"local:\".length));\n}\n\nfunction listPluginAttachments(config: BosConfig | null) {\n return (Object.entries(config?.plugins ?? {}) as Array<[string, PluginAttachmentConfig]>)\n .map(([key, attachment]) => {\n const ref = getPluginRef(attachment);\n return {\n key,\n development: ref?.development,\n production: ref?.production,\n localPath: ref?.development?.startsWith(\"local:\")\n ? ref.development.slice(\"local:\".length)\n : undefined,\n source: ref?.development?.startsWith(\"local:\") ? (\"local\" as const) : (\"remote\" as const),\n integrity: ref?.integrity,\n version: ref?.version,\n name: ref?.name,\n };\n })\n .sort((a, b) => a.key.localeCompare(b.key));\n}\n\ninterface GeneratedArtifacts {\n resolvedConfigPath?: string;\n contractBridgePath: string;\n}\n\nasync function generateCodeArtifacts(\n configDir: string,\n config: BosConfig,\n opts?: {\n env?: BosEnv;\n extendsChain?: string[];\n runtimeConfig?: RuntimeConfig;\n },\n): Promise<(GeneratedArtifacts & { contractStatus: ContractBridgeStatus[] }) | null> {\n if (opts?.env) {\n writeResolvedConfig(configDir, config, opts.env, opts.extendsChain);\n }\n\n const runtimeConfig =\n opts?.runtimeConfig ?? (await loadResolvedConfig({ cwd: configDir }))?.runtime;\n if (!runtimeConfig) return null;\n\n const bridge = await syncApiContractBridge({\n configDir,\n runtimeConfig,\n apiBaseUrl: runtimeConfig.api.url,\n });\n\n return {\n resolvedConfigPath: opts?.env ? join(configDir, \".bos/bos.resolved-config.json\") : undefined,\n contractBridgePath: bridge.bridgePath,\n contractStatus: bridge.status,\n };\n}\n\nfunction extractPublishedUrl(output: string): string | null {\n const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n if (!match || match.length === 0) return null;\n return match[match.length - 1] ?? null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\nasync function buildEveryPluginQuietly(cwd: string, force = false) {\n const packageDir = `${cwd}/packages/every-plugin`;\n const packageExists = await fileExists(`${packageDir}/package.json`);\n if (!packageExists) {\n return;\n }\n\n const distPath = `${cwd}/packages/every-plugin/dist/build/rspack/plugin.mjs`;\n const distExists = await fileExists(distPath);\n\n if (distExists && !force) {\n return;\n }\n\n const result = (await run(\"bun\", [\"run\", \"--cwd\", \"packages/every-plugin\", \"build\"], {\n cwd,\n capture: true,\n })) as { stdout: string; stderr: string; exitCode: number };\n\n if (result.exitCode === 0) {\n return;\n }\n\n if (result.stdout.trim()) {\n process.stdout.write(result.stdout);\n }\n\n if (result.stderr.trim()) {\n process.stderr.write(result.stderr);\n }\n\n throw new Error(\n `bun run --cwd packages/every-plugin build failed with exit code ${result.exitCode}`,\n );\n}\n\nasync function buildEverythingDevQuietly(cwd: string, force = false) {\n const packageDir = `${cwd}/packages/everything-dev`;\n const packageExists = await fileExists(`${packageDir}/package.json`);\n if (!packageExists) {\n return;\n }\n\n const distPath = `${cwd}/packages/everything-dev/dist/index.mjs`;\n const distExists = await fileExists(distPath);\n\n if (distExists && !force) {\n return;\n }\n\n const result = (await run(\"bun\", [\"run\", \"--cwd\", \"packages/everything-dev\", \"build\"], {\n cwd,\n capture: true,\n })) as { stdout: string; stderr: string; exitCode: number };\n\n if (result.exitCode === 0) {\n return;\n }\n\n if (result.stdout.trim()) {\n process.stdout.write(result.stdout);\n }\n\n if (result.stderr.trim()) {\n process.stderr.write(result.stderr);\n }\n\n throw new Error(\n `bun run --cwd packages/everything-dev build failed with exit code ${result.exitCode}`,\n );\n}\n\nexport async function resolveRemoteConfigChain(\n accountId: string,\n gatewayId: string,\n visited: Set<string>,\n): Promise<BosConfig> {\n const selfRef = `bos://${accountId}/${gatewayId}`;\n if (visited.has(selfRef)) {\n throw new Error(`Circular extends detected: ${selfRef}`);\n }\n\n const nextVisited = new Set(visited);\n nextVisited.add(selfRef);\n\n const config = await fetchBosConfigFromFastKv<BosConfigInput>(selfRef);\n const parentRef = config.extends\n ? resolveExtendsRef(config.extends as string | ExtendsConfig, \"production\")\n : undefined;\n\n let merged: BosConfigInput;\n if (!parentRef) {\n merged = config;\n } else {\n const { accountId: parentAccountId, gatewayId: parentGatewayId } = parseBosUrl(parentRef);\n const parentResolved = await resolveRemoteConfigChain(\n parentAccountId,\n parentGatewayId,\n nextVisited,\n );\n merged = mergeBosConfigWithExtends(parentResolved as BosConfigInput, config);\n }\n\n return resolveConfigComposableEntries(BosConfigSchema.parse(merged), process.cwd(), \"production\");\n}\n\nasync function fetchPublishedConfig(\n accountId: string,\n gatewayId: string,\n): Promise<BosConfig | null> {\n try {\n return await resolveRemoteConfigChain(accountId, gatewayId, new Set());\n } catch (error) {\n if (error instanceof Error && error.message.startsWith(\"No config found\")) {\n return null;\n }\n throw error;\n }\n}\n\nfunction selectWorkspaceTargets(packages: string, bosConfig: BosConfig | null): string[] {\n const allPackages = [\n ...Object.keys(bosConfig?.app ?? {}),\n ...Object.keys(bosConfig?.plugins ?? {}),\n ];\n if (packages === \"all\") {\n return allPackages;\n }\n\n return packages\n .split(\",\")\n .map((pkg) => pkg.trim())\n .filter((pkg) => allPackages.includes(pkg));\n}\n\nfunction padRight(str: string, len: number): string {\n return str.length >= len ? str : str + \" \".repeat(len - str.length);\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\ninterface BuildAttemptResult {\n success: boolean;\n url?: string;\n error?: string;\n exitCode: number;\n output: string;\n}\n\nasync function runBuildAttempt(\n cmd: string,\n args: string[],\n cwd: string,\n env: Record<string, string>,\n verbose: boolean,\n wsKey: string,\n resultBaseDir?: string,\n): Promise<BuildAttemptResult> {\n if (verbose) {\n try {\n await run(cmd, args, { cwd, env, capture: false });\n if (resultBaseDir) {\n const results = readDeployResults(join(resultBaseDir, wsKey));\n if (results.length > 0) {\n return { success: true, url: results[0]?.url, exitCode: 0, output: \"\" };\n }\n }\n return { success: true, exitCode: 0, output: \"\" };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n exitCode: 1,\n output: \"\",\n };\n }\n }\n\n const result = await run(cmd, args, { cwd, env, capture: true });\n const stdout = result?.stdout ?? \"\";\n const stderr = result?.stderr ?? \"\";\n const exitCode = result?.exitCode ?? 0;\n const output = `${stdout}\\n${stderr}`;\n\n if (exitCode !== 0) {\n const lastLines = output.trim().split(\"\\n\").slice(-5).join(\"\\n\");\n return {\n success: false,\n error: `Build failed (exit code ${exitCode})\\n${lastLines}`,\n exitCode,\n output,\n };\n }\n\n const zeMatch = output.match(/ZE\\d+/);\n if (zeMatch) {\n return {\n success: false,\n error: `Zephyr upload failed (${zeMatch[0]})`,\n exitCode: 0,\n output,\n };\n }\n\n if (resultBaseDir) {\n const results = readDeployResults(join(resultBaseDir, wsKey));\n if (results.length > 0) {\n return { success: true, url: results[0]?.url, exitCode: 0, output };\n }\n }\n\n const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n if (deployMatch) {\n return { success: true, url: deployMatch[1], exitCode: 0, output };\n }\n\n if (env.DEPLOY === \"true\") {\n return {\n success: false,\n error: \"No deploy URL found (Zephyr may have failed)\",\n exitCode: 0,\n output,\n };\n }\n return { success: true, exitCode: 0, output };\n}\n\nasync function buildOneWorkspace(\n ws: WorkspaceTarget,\n env: Record<string, string>,\n opts: { deploy: boolean; verbose?: boolean },\n resultBaseDir?: string,\n): Promise<WorkspaceDeployResult> {\n const pkgJson = await readJsonFile<{\n scripts?: Record<string, string>;\n }>(`${ws.path}/package.json`);\n const shouldDeployScript = opts.deploy && pkgJson.scripts?.deploy;\n const buildConfig = shouldDeployScript\n ? { cmd: \"bun\", args: [\"run\", \"deploy\"] }\n : (buildCommands[ws.key] ?? { cmd: \"bun\", args: [\"run\", \"build\"] });\n\n const wsEnv = { ...env };\n if (resultBaseDir) {\n wsEnv.BOS_DEPLOY_RESULT_DIR = join(resultBaseDir, ws.key);\n }\n\n const startTime = Date.now();\n let attempt = await runBuildAttempt(\n buildConfig.cmd,\n buildConfig.args,\n ws.path,\n wsEnv,\n opts.verbose ?? false,\n ws.key,\n resultBaseDir,\n );\n\n let retried = false;\n\n if (!attempt.success && attempt.exitCode === 0 && opts.deploy) {\n if (!opts.verbose) {\n console.log(` ${colors.yellow(\"↻\")} ${padRight(ws.key, 28)} retrying...`);\n }\n if (resultBaseDir) {\n const wsResultDir = join(resultBaseDir, ws.key);\n if (existsSync(wsResultDir)) {\n rmSync(wsResultDir, { recursive: true, force: true });\n }\n }\n retried = true;\n attempt = await runBuildAttempt(\n buildConfig.cmd,\n buildConfig.args,\n ws.path,\n wsEnv,\n opts.verbose ?? false,\n ws.key,\n resultBaseDir,\n );\n }\n\n const durationMs = Date.now() - startTime;\n const result: WorkspaceDeployResult = {\n key: ws.key,\n kind: ws.kind,\n success: attempt.success,\n url: attempt.url,\n error: attempt.error,\n durationMs,\n retried: retried ? true : undefined,\n };\n\n if (!opts.verbose) {\n const name = padRight(ws.key, 28);\n if (result.success) {\n const duration = formatDuration(durationMs);\n const retryTag = retried ? \" (retried)\" : \"\";\n console.log(` ${colors.green(icons.ok)} ${name} ${colors.dim(duration + retryTag)}`);\n } else {\n const errorLine = (result.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${name} ${errorLine}`);\n }\n }\n\n return result;\n}\n\nasync function buildWorkspaceTargets(opts: {\n configDir: string;\n bosConfig: BosConfig | null;\n runtimeConfig: RuntimeConfig | null;\n targets: string[];\n deploy: boolean;\n verbose?: boolean;\n}): Promise<{\n built: string[];\n skipped: string[];\n deployResults?: WorkspaceDeployResult[];\n}> {\n const existing: WorkspaceTarget[] = [];\n const skipped: string[] = [];\n\n for (const target of opts.targets) {\n const resolved = resolveWorkspaceTarget(\n target,\n opts.bosConfig,\n opts.runtimeConfig,\n opts.configDir,\n );\n if (!resolved) {\n skipped.push(target);\n continue;\n }\n\n const exists = await fileExists(`${resolved.path}/package.json`);\n if (exists) existing.push(resolved);\n else skipped.push(target);\n }\n\n if (existing.length === 0) {\n return { built: [], skipped };\n }\n\n const sharedSync = await syncResolvedSharedDeps({\n configDir: opts.configDir,\n hostMode: \"local\",\n bosConfig: opts.bosConfig ?? undefined,\n extendsChain: [],\n });\n if (sharedSync.catalogChanged) {\n await run(\"bun\", [\"install\"], { cwd: opts.configDir });\n }\n\n const shouldBuildPlugin = existing.some((entry) => entry.key === \"api\");\n\n const forceRebuild = opts.deploy;\n const buildTasks: Promise<void>[] = [buildEverythingDevQuietly(opts.configDir, forceRebuild)];\n if (shouldBuildPlugin) {\n buildTasks.push(buildEveryPluginQuietly(opts.configDir, forceRebuild));\n }\n await Promise.all(buildTasks);\n\n const env: Record<string, string> = {\n ...process.env,\n NODE_ENV: opts.deploy ? \"production\" : \"development\",\n };\n if (opts.deploy) {\n env.DEPLOY = \"true\";\n } else {\n delete env.DEPLOY;\n }\n\n const resultBaseDir = opts.deploy ? join(opts.configDir, \".bos\", \"deploy-results\") : undefined;\n if (resultBaseDir) {\n cleanDeployResultDir(resultBaseDir);\n }\n\n const bosConfigPath = join(opts.configDir, \"bos.config.json\");\n let configSnapshot: string | undefined;\n if (opts.deploy && existsSync(bosConfigPath)) {\n configSnapshot = readFileSync(bosConfigPath, \"utf-8\");\n }\n\n const orderedExisting = opts.deploy\n ? [\n ...existing.filter((entry) => entry.kind === \"app\" && entry.key !== \"host\"),\n ...existing.filter((entry) => entry.kind === \"plugin\"),\n ...existing.filter((entry) => entry.kind === \"app\" && entry.key === \"host\"),\n ]\n : existing;\n\n const parallelGroup = opts.deploy\n ? orderedExisting.filter((e) => e.key !== \"host\")\n : orderedExisting;\n const sequentialGroup = opts.deploy ? orderedExisting.filter((e) => e.key === \"host\") : [];\n\n const built: string[] = [];\n const deployResults: WorkspaceDeployResult[] = [];\n\n if (opts.deploy && parallelGroup.length > 0) {\n const total = parallelGroup.length + sequentialGroup.length;\n console.log();\n console.log(` Building ${total} workspace${total > 1 ? \"s\" : \"\"}...`);\n console.log();\n\n const results = await Promise.allSettled(\n parallelGroup.map((ws) => buildOneWorkspace(ws, env, opts, resultBaseDir)),\n );\n\n for (let i = 0; i < parallelGroup.length; i++) {\n const ws = parallelGroup[i];\n const result = results[i];\n if (result.status === \"fulfilled\") {\n if (result.value.success) {\n built.push(ws.key);\n }\n deployResults.push(result.value);\n } else {\n deployResults.push({\n key: ws.key,\n kind: ws.kind,\n success: false,\n error: result.reason?.message ?? \"Unknown error\",\n });\n }\n }\n\n if (resultBaseDir && configSnapshot) {\n const allResults = readAllDeployResults(resultBaseDir);\n if (allResults.length > 0) {\n const config = JSON.parse(configSnapshot) as Record<string, unknown>;\n const merged = applyDeployResults(config, allResults);\n writeFileSync(bosConfigPath, `${JSON.stringify(merged, null, 2)}\\n`);\n }\n }\n\n for (const ws of sequentialGroup) {\n const result = await buildOneWorkspace(ws, env, opts, resultBaseDir);\n if (result.success) {\n built.push(ws.key);\n }\n deployResults.push(result);\n }\n\n if (resultBaseDir && existsSync(bosConfigPath)) {\n const allResults = readAllDeployResults(resultBaseDir);\n const currentConfig = JSON.parse(readFileSync(bosConfigPath, \"utf-8\")) as Record<\n string,\n unknown\n >;\n const hostResults = allResults.filter((r) => r.urlField.startsWith(\"app.host\"));\n if (hostResults.length > 0) {\n const merged = applyDeployResults(currentConfig, hostResults);\n writeFileSync(bosConfigPath, `${JSON.stringify(merged, null, 2)}\\n`);\n }\n }\n\n console.log();\n } else {\n for (const resolved of orderedExisting) {\n const buildConfig = buildCommands[resolved.key] ?? {\n cmd: \"bun\",\n args: [\"run\", \"build\"],\n };\n\n await run(buildConfig.cmd, buildConfig.args, {\n cwd: resolved.path,\n env,\n });\n built.push(resolved.key);\n }\n }\n\n return { built, skipped, deployResults: opts.deploy ? deployResults : undefined };\n}\n\nexport default createPlugin({\n variables: z.object({\n configPath: z.string().optional(),\n }),\n secrets: z.object({}),\n contract: bosContract,\n initialize: (config) =>\n Effect.promise(async () => {\n const configResult = await loadResolvedConfig({ path: config.variables.configPath });\n return {\n bosConfig: configResult?.config ?? null,\n runtimeConfig: configResult?.runtime ?? null,\n configDir: getProjectRoot(),\n } satisfies BosDeps;\n }),\n shutdown: () => Effect.void,\n createRouter: (deps, builder) => ({\n config: builder.config.handler(async ({ input }) => {\n if (input.full) {\n return buildConfigResult(deps.bosConfig, true);\n }\n\n const localConfig = await loadLocalConfig({ cwd: deps.configDir });\n return buildConfigResult(localConfig?.config ?? null, false);\n }),\n\n pluginAdd: builder.pluginAdd.handler(async ({ input }) => {\n if (!deps.bosConfig) {\n return {\n status: \"error\" as const,\n key: \"\",\n error: \"No bos.config.json found\",\n };\n }\n\n const isBosRef = input.source.startsWith(\"bos://\");\n const isLocal = input.source.startsWith(\"local:\");\n const key = sanitizePluginKey(\n input.as ??\n (isBosRef ? (input.source.split(\"/\").pop() ?? \"plugin\") : defaultPluginKey(input.source)),\n );\n const existing = deps.bosConfig.plugins?.[key];\n const existingEntry = existing && typeof existing === \"object\" ? existing : {};\n const nextPlugins = { ...(deps.bosConfig.plugins ?? {}) };\n\n if (isBosRef) {\n nextPlugins[key] = {\n ...existingEntry,\n extends: input.source,\n };\n } else if (isLocal) {\n nextPlugins[key] = {\n ...existingEntry,\n development: input.source,\n ...(existingEntry.extends ? {} : {}),\n };\n } else {\n nextPlugins[key] = {\n ...existingEntry,\n production: input.production ?? input.source,\n };\n }\n\n deps.bosConfig = {\n ...deps.bosConfig,\n plugins: nextPlugins,\n };\n\n await saveBosConfig(deps.configDir, deps.bosConfig);\n await generateCodeArtifacts(deps.configDir, deps.bosConfig);\n\n const stored = deps.bosConfig.plugins?.[key];\n const storedObj = stored && typeof stored === \"object\" ? stored : {};\n\n return {\n status: \"added\" as const,\n key,\n development: storedObj.development,\n production: storedObj.production,\n integrity: storedObj.integrity,\n version: storedObj.version,\n };\n }),\n\n pluginRemove: builder.pluginRemove.handler(async ({ input }) => {\n if (!deps.bosConfig) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: \"No bos.config.json found\",\n };\n }\n\n if (!deps.bosConfig.plugins?.[input.key]) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const nextPlugins = { ...(deps.bosConfig.plugins ?? {}) };\n delete nextPlugins[input.key];\n deps.bosConfig = {\n ...deps.bosConfig,\n plugins: Object.keys(nextPlugins).length > 0 ? nextPlugins : undefined,\n };\n\n await saveBosConfig(deps.configDir, deps.bosConfig);\n await generateCodeArtifacts(deps.configDir, deps.bosConfig);\n\n return {\n status: \"removed\" as const,\n key: input.key,\n };\n }),\n\n pluginList: builder.pluginList.handler(async () => {\n const plugins: PluginListResult[\"plugins\"] = listPluginAttachments(deps.bosConfig);\n return {\n status: \"listed\" as const,\n plugins,\n };\n }),\n\n pluginPublish: builder.pluginPublish.handler(async ({ input }) => {\n if (!deps.bosConfig) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: \"No bos.config.json found\",\n };\n }\n\n const attachment = deps.bosConfig.plugins?.[input.key];\n if (!attachment) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const attachmentRef = getPluginRef(attachment);\n\n const localPath = pluginLocalPath(deps.configDir, attachment);\n if (!localPath) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' does not have a local development path`,\n };\n }\n\n const pkgPath = join(localPath, \"package.json\");\n if (!(await fileExists(pkgPath))) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Missing package.json at ${localPath}`,\n };\n }\n\n const pkgJson = await readJsonFile<{\n scripts?: Record<string, string>;\n name?: string;\n version?: string;\n }>(pkgPath);\n const script = pkgJson.scripts?.deploy ? \"deploy\" : \"build\";\n\n const { stdout, stderr, exitCode } = (await run(\"bun\", [\"run\", script], {\n cwd: localPath,\n capture: true,\n })) as { stdout: string; stderr: string; exitCode: number };\n\n if (exitCode !== 0) {\n if (stdout.trim()) process.stdout.write(stdout);\n if (stderr.trim()) process.stderr.write(stderr);\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Publish failed with exit code ${exitCode}`,\n };\n }\n\n if (stdout.trim()) process.stdout.write(stdout);\n if (stderr.trim()) process.stderr.write(stderr);\n\n let publishedUrl = extractPublishedUrl(`${stdout}\\n${stderr}`);\n\n let manifest: PluginManifest | null = null;\n if (publishedUrl) {\n manifest = await fetchRemotePluginManifest(publishedUrl);\n } else if (attachmentRef?.production) {\n manifest = await fetchRemotePluginManifest(attachmentRef.production);\n if (manifest) {\n publishedUrl = attachmentRef.production;\n }\n }\n\n const integrity = publishedUrl ? await computeSriHashForUrl(publishedUrl) : null;\n const version = manifest?.plugin.version ?? pkgJson.version;\n\n if (publishedUrl) {\n const rootConfigPath = join(deps.configDir, \"bos.config.json\");\n try {\n const rootConfig = JSON.parse(readFileSync(rootConfigPath, \"utf-8\")) as Record<\n string,\n unknown\n >;\n if (!rootConfig.plugins || typeof rootConfig.plugins !== \"object\") {\n rootConfig.plugins = {};\n }\n const plugins = rootConfig.plugins as Record<string, unknown>;\n if (!plugins[input.key] || typeof plugins[input.key] !== \"object\") {\n plugins[input.key] = {};\n }\n const entry = plugins[input.key] as Record<string, unknown>;\n entry.production = publishedUrl;\n if (integrity) {\n entry.integrity = integrity;\n } else {\n delete entry.integrity;\n }\n writeFileSync(rootConfigPath, `${JSON.stringify(rootConfig, null, 2)}\\n`);\n console.log(` ✅ Updated bos.config.json: plugins.${input.key}.production`);\n } catch (err) {\n console.error(\n ` ❌ Failed to update bos.config.json:`,\n err instanceof Error ? err.message : err,\n );\n }\n\n await generateCodeArtifacts(deps.configDir, deps.bosConfig);\n }\n\n return {\n status: \"published\" as const,\n key: input.key,\n path: localPath,\n script,\n production: publishedUrl ?? attachmentRef?.production,\n integrity: integrity ?? undefined,\n version: version ?? undefined,\n };\n }),\n\n dev: builder.dev.handler(async ({ input }) => {\n const devTimings: PhaseTiming[] = [];\n\n ensureEnvFile(deps.configDir);\n loadProjectEnv(deps.configDir);\n\n const localPackages = detectLocalPackages(\n deps.bosConfig ?? undefined,\n deps.runtimeConfig ?? undefined,\n );\n\n const hostSource: SourceMode = localPackages.includes(\"host\")\n ? parseSourceMode(input.host, \"local\")\n : \"remote\";\n const uiSource: SourceMode = localPackages.includes(\"ui\")\n ? parseSourceMode(input.ui, \"local\")\n : \"remote\";\n const apiSource: SourceMode = localPackages.includes(\"api\")\n ? parseSourceMode(input.api, \"local\")\n : \"remote\";\n const authSource: SourceMode = localPackages.includes(\"auth\")\n ? parseSourceMode(input.auth, \"local\")\n : \"remote\";\n const ssr = input.ssr ?? false;\n const proxy = input.proxy ?? false;\n\n const sharedSync = await timePhase(devTimings, \"shared deps\", () =>\n syncResolvedSharedDeps({\n configDir: deps.configDir,\n hostMode: hostSource,\n bosConfig: deps.bosConfig ?? undefined,\n extendsChain: [],\n }),\n );\n let configMayHaveChanged = false;\n if (sharedSync.catalogChanged) {\n await timePhase(devTimings, \"install\", () =>\n run(\"bun\", [\"install\"], { cwd: deps.configDir }),\n );\n configMayHaveChanged = true;\n }\n const shouldBuildPlugin =\n (apiSource === \"local\" && !proxy) || localPackages.some((pkg) => pkg.startsWith(\"plugin:\"));\n\n await timePhase(devTimings, \"build\", async () => {\n const buildTasks: Promise<void>[] = [buildEverythingDevQuietly(deps.configDir)];\n if (shouldBuildPlugin) {\n buildTasks.push(buildEveryPluginQuietly(deps.configDir));\n }\n await Promise.all(buildTasks);\n });\n\n let devExtendsChain: string[] | undefined;\n if (configMayHaveChanged || input.remotePlugins?.length) {\n const refreshed = await timePhase(devTimings, \"resolve config\", () =>\n loadResolvedConfig({\n cwd: deps.configDir,\n remotePlugins: input.remotePlugins,\n }),\n );\n deps.bosConfig = refreshed?.config ?? deps.bosConfig;\n deps.runtimeConfig = refreshed?.runtime ?? deps.runtimeConfig;\n devExtendsChain = refreshed?.source.extended;\n }\n\n if (!deps.bosConfig) {\n return {\n status: \"error\" as const,\n description: \"No bos.config.json found\",\n processes: [],\n timings: devTimings,\n };\n }\n\n if (proxy && !resolveProxyUrl(deps.bosConfig)) {\n return {\n status: \"error\" as const,\n description: \"No valid proxy URL configured in bos.config.json\",\n processes: [],\n timings: devTimings,\n };\n }\n\n const hostPort = input.port ?? getHostDevelopmentPort(deps.bosConfig.app.host.development);\n suppressWarnings();\n const developmentRuntime = buildRuntimeConfig(deps.bosConfig, {\n uiSource,\n apiSource,\n authSource,\n hostSource,\n env: \"development\",\n plugins: deps.runtimeConfig?.plugins,\n });\n drainConfigWarnings();\n resumeWarnings();\n const runtimeConfig = await timePhase(devTimings, \"ports\", () =>\n prepareDevelopmentRuntimeConfig(developmentRuntime, {\n hostPort,\n ssr,\n }),\n );\n\n syncGeneratedInfra(deps.configDir, runtimeConfig);\n ensureEnvFile(deps.configDir);\n loadProjectEnv(deps.configDir);\n\n await timePhase(devTimings, \"generate artifacts\", () =>\n generateCodeArtifacts(deps.configDir, deps.bosConfig!, {\n env: \"development\",\n extendsChain: devExtendsChain,\n runtimeConfig,\n }),\n );\n\n const services = buildServiceDescriptorMap(runtimeConfig, { ssr, proxy });\n const packages = [...services.keys()];\n if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") {\n console.error(\"[DEBUG dev] services keys:\", packages.join(\", \"));\n console.error(\n \"[DEBUG dev] services sources:\",\n packages.map((k) => `${k}=${services.get(k)?.source ?? \"?\"}`).join(\", \"),\n );\n console.error(\n \"[DEBUG dev] runtimeConfig.plugins keys:\",\n Object.keys(runtimeConfig.plugins ?? {}).join(\", \"),\n );\n console.error(\n \"[DEBUG dev] runtimeConfig.plugins sources:\",\n Object.entries(runtimeConfig.plugins ?? {})\n .map(([k, v]) => `${k}=${v.source}`)\n .join(\", \"),\n );\n }\n const displayEnv: Record<string, string> = {};\n const apiDescriptor = services.get(\"api\");\n if (apiDescriptor?.proxy) {\n const proxyUrl = resolveProxyUrl(deps.bosConfig);\n if (proxyUrl) displayEnv.API_PROXY = proxyUrl;\n }\n\n const orchestrator: AppOrchestrator = {\n packages,\n env: displayEnv,\n description: buildDescription(services),\n port: runtimeConfig.host.port,\n interactive: input.interactive,\n };\n\n pendingSession = { orchestrator, services, runtimeConfig };\n\n return {\n status: \"started\" as const,\n description: orchestrator.description,\n processes: packages,\n timings: devTimings,\n };\n }),\n\n start: builder.start.handler(async ({ input }) => {\n ensureEnvFile(deps.configDir);\n loadProjectEnv(deps.configDir);\n\n pluginEvents.emit(\"progress\", { phase: \"config\", status: \"running\" } satisfies ProgressEvent);\n\n const bosEnv = input.env ?? (process.env.BOS_ENV === \"staging\" ? \"staging\" : \"production\");\n const account = input.account ?? process.env.BOS_ACCOUNT;\n const domain = input.domain ?? process.env.BOS_GATEWAY;\n\n let config: BosConfig | null = null;\n let remoteConfig: BosConfig | null = null;\n\n if (account && domain) {\n try {\n remoteConfig = await fetchPublishedConfig(account, domain);\n if (remoteConfig) {\n config = remoteConfig;\n } else {\n return {\n status: \"error\" as const,\n url: \"\",\n error: `No config found at bos://${account}/${domain}. Verify the account and gateway are correct and the config has been published.\\nExpected URL: ${buildRegistryConfigUrl(account, domain)}`,\n };\n }\n } catch (error) {\n return {\n status: \"error\" as const,\n url: \"\",\n error: `Failed to fetch config for bos://${account}/${domain}: ${error instanceof Error ? error.message : \"Unknown error\"}\\nExpected URL: ${buildRegistryConfigUrl(account, domain)}`,\n };\n }\n } else {\n config = deps.bosConfig;\n }\n\n if (!config) {\n return {\n status: \"error\" as const,\n url: \"\",\n error:\n \"No configuration found. Provide --account and --gateway flags, or create a local bos.config.json.\",\n };\n }\n\n // Apply runtime overrides from CLI flags / env vars\n if (account) {\n config = { ...config, account };\n }\n if (domain) {\n config = { ...config, domain };\n }\n\n const port = input.port ?? getHostDevelopmentPort(config.app.host.development);\n const isStaging = bosEnv === \"staging\";\n const runtimePlugins = await buildRuntimePluginsForConfig(\n config,\n deps.configDir,\n \"production\",\n );\n suppressWarnings();\n const runtimeConfig = buildRuntimeConfig(config, {\n uiSource: \"remote\",\n apiSource: \"remote\",\n authSource: \"remote\",\n hostSource: \"remote\",\n env: \"production\",\n plugins: runtimePlugins,\n });\n drainConfigWarnings();\n resumeWarnings();\n\n if (isStaging && config.staging?.domain) {\n runtimeConfig.domain = config.staging.domain;\n }\n\n if (isStaging) {\n runtimeConfig.env = \"staging\";\n }\n\n syncGeneratedInfra(deps.configDir, runtimeConfig);\n ensureEnvFile(deps.configDir);\n loadProjectEnv(deps.configDir);\n\n pluginEvents.emit(\"progress\", {\n phase: \"generate artifacts\",\n status: \"running\",\n } satisfies ProgressEvent);\n await generateCodeArtifacts(deps.configDir, config, {\n env: \"production\",\n runtimeConfig,\n });\n pluginEvents.emit(\"progress\", {\n phase: \"generate artifacts\",\n status: \"done\",\n } satisfies ProgressEvent);\n\n // ── Production Readiness Validation ──\n const productionEnv: Record<string, string> = {};\n const warnings: string[] = [];\n\n // Default CORS_ORIGIN to the configured domain if not set\n if (!process.env.CORS_ORIGIN && config.domain) {\n const effectiveDomain = isStaging\n ? (config.staging?.domain ?? config.domain)\n : config.domain;\n const defaultOrigin = `https://${effectiveDomain}`;\n productionEnv.CORS_ORIGIN = defaultOrigin;\n warnings.push(`CORS_ORIGIN defaulting to ${defaultOrigin}`);\n }\n\n // Validate required secrets\n const requiredSecrets = new Set<string>();\n const missingSecrets: string[] = [];\n\n if (runtimeConfig.host.secrets) {\n for (const s of runtimeConfig.host.secrets) requiredSecrets.add(s);\n }\n if (runtimeConfig.auth?.secrets) {\n for (const s of runtimeConfig.auth.secrets) requiredSecrets.add(s);\n }\n if (runtimeConfig.api?.secrets) {\n for (const s of runtimeConfig.api.secrets) requiredSecrets.add(s);\n }\n for (const plugin of Object.values(runtimeConfig.plugins ?? {})) {\n if (plugin.secrets) {\n for (const s of plugin.secrets) requiredSecrets.add(s);\n }\n }\n\n for (const secret of requiredSecrets) {\n const value = process.env[secret];\n if (!value || value.length === 0) {\n missingSecrets.push(secret);\n }\n }\n\n if (missingSecrets.length > 0) {\n warnings.push(`Missing ${missingSecrets.length} secret(s): ${missingSecrets.join(\", \")}`);\n }\n\n const services = buildServiceDescriptorMap(runtimeConfig);\n\n const stagingEnvVars: Record<string, string> = isStaging\n ? { BOS_GATEWAY: config.staging?.domain ?? config.domain ?? \"\" }\n : {};\n\n const configSource = remoteConfig\n ? `bos://${account}/${domain}`\n : (findConfigPath() ?? \"bos.config.json\");\n\n const configSourceHttp =\n remoteConfig && account && domain ? buildRegistryConfigUrl(account, domain) : undefined;\n\n const summary: StartSummary = {\n configSource,\n configSourceHttp,\n account: config.account,\n domain: config.domain ?? undefined,\n modules: {\n host: runtimeConfig.host.remoteUrl ?? runtimeConfig.host.url ?? \"local\",\n ui: runtimeConfig.ui.url ?? \"local\",\n api: runtimeConfig.api.url ?? \"local\",\n auth: runtimeConfig.auth?.url ?? undefined,\n },\n warnings,\n };\n\n const orchestrator: AppOrchestrator = {\n packages: [\"host\"],\n env: {\n NODE_ENV: \"production\",\n ...productionEnv,\n ...stagingEnvVars,\n },\n description: `${isStaging ? \"Staging\" : \"Production\"} Mode (${config.account})`,\n port,\n interactive: input.interactive,\n noLogs: true,\n };\n\n pendingSession = { orchestrator, services, runtimeConfig };\n pendingStartSummary = summary;\n\n pluginEvents.emit(\"progress\", { phase: \"config\", status: \"done\" } satisfies ProgressEvent);\n\n return {\n status: \"running\" as const,\n url: `http://localhost:${port}`,\n };\n }),\n\n build: builder.build.handler(async ({ input }) => {\n if (!deps.bosConfig) {\n return {\n status: \"error\" as const,\n built: [],\n skipped: [],\n };\n }\n\n const buildEnv: BosEnv = input.deploy ? \"production\" : \"development\";\n\n const targets = selectWorkspaceTargets(input.packages, deps.bosConfig);\n if (targets.length === 0) {\n return {\n status: \"error\" as const,\n built: [],\n skipped: [],\n };\n }\n\n suppressWarnings();\n const runtimeConfig = buildRuntimeConfig(deps.bosConfig, {\n uiSource: deps.bosConfig.app.ui?.development ? \"local\" : \"remote\",\n apiSource: deps.bosConfig.app.api?.development ? \"local\" : \"remote\",\n authSource: deps.bosConfig.app.auth?.development ? \"local\" : \"remote\",\n hostSource: deps.bosConfig.app.host?.development ? \"local\" : \"remote\",\n env: buildEnv,\n plugins: deps.runtimeConfig?.plugins,\n });\n drainConfigWarnings();\n resumeWarnings();\n\n await generateCodeArtifacts(deps.configDir, deps.bosConfig, {\n env: buildEnv,\n runtimeConfig,\n });\n\n const { built, skipped } = await buildWorkspaceTargets({\n configDir: deps.configDir,\n bosConfig: deps.bosConfig,\n runtimeConfig: runtimeConfig,\n targets,\n deploy: input.deploy,\n });\n\n if (built.length === 0) {\n return {\n status: \"error\" as const,\n built: [],\n skipped,\n };\n }\n\n return {\n status: \"success\" as const,\n built,\n skipped,\n deployed: input.deploy,\n };\n }),\n\n publish: builder.publish.handler(async ({ input }) => {\n if (!deps.bosConfig) {\n return {\n status: \"error\" as const,\n registryUrl: \"\",\n error: \"No bos.config.json found\",\n };\n }\n\n const result = await publishToFastKv({\n bosConfig: deps.bosConfig,\n runtimeConfig: deps.runtimeConfig,\n configDir: deps.configDir