{"version":3,"file":"build.cjs","names":["access","resolveLocalDevelopmentPath","run","padRight","colors","icons","formatDuration","syncResolvedSharedDeps","findWorkspaceRoot","process","ensureFreshDeps"],"sources":["../src/build.ts"],"sourcesContent":["import { access, readFile } from \"node:fs/promises\";\nimport process from \"node:process\";\nimport { formatDuration } from \"./cli/timing\";\nimport { resolveLocalDevelopmentPath } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport { syncResolvedSharedDeps } from \"./shared-deps\";\nimport type { BosConfig, BosPluginRef, RuntimeConfig } from \"./types\";\nimport { run } from \"./utils/run\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\nimport { ensureFreshDeps, findWorkspaceRoot } from \"./workspace\";\n\nconst buildCommands: Record<string, { cmd: string; args: string[] }> = {\n  host: { cmd: \"pnpm\", args: [\"run\", \"build\"] },\n  ui: { cmd: \"pnpm\", args: [\"run\", \"build\"] },\n  api: { cmd: \"pnpm\", args: [\"run\", \"build\"] },\n};\n\nexport type WorkspaceTarget = {\n  key: string;\n  kind: \"app\" | \"plugin\";\n  path: string;\n};\n\nexport function getPluginRef(entry: string | BosPluginRef | undefined | null): BosPluginRef | null {\n  if (!entry || typeof entry === \"string\") return null;\n  return entry;\n}\n\nexport async function fileExists(path: string): Promise<boolean> {\n  try {\n    await access(path);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nexport async function readJsonFile<T>(path: string): Promise<T> {\n  return JSON.parse(await readFile(path, \"utf8\")) as T;\n}\n\nexport function 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\nexport function 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  if (packages === \"local\") {\n    return allPackages.filter((k) => isLocalTarget(k, bosConfig));\n  }\n\n  return packages\n    .split(\",\")\n    .map((pkg) => pkg.trim())\n    .filter((pkg) => allPackages.includes(pkg));\n}\n\nfunction isLocalTarget(key: string, bosConfig: BosConfig | null): boolean {\n  const slot =\n    (bosConfig?.app as Record<string, { development?: string }> | undefined)?.[key] ??\n    bosConfig?.plugins?.[key];\n  const dev = (slot as { development?: unknown } | undefined)?.development;\n  return typeof dev === \"string\" && dev.startsWith(\"local:\");\n}\n\ninterface WorkspaceBuildOutcome {\n  key: string;\n  kind: \"app\" | \"plugin\";\n  success: boolean;\n  error?: string;\n  durationMs: number;\n}\n\nasync function buildOneWorkspace(\n  ws: WorkspaceTarget,\n  env: Record<string, string>,\n  opts: { verbose?: boolean },\n): Promise<WorkspaceBuildOutcome> {\n  const buildConfig = buildCommands[ws.key] ?? { cmd: \"pnpm\", args: [\"run\", \"build\"] };\n  const verbose = opts.verbose ?? false;\n  const startTime = Date.now();\n\n  const proc = await run(buildConfig.cmd, buildConfig.args, {\n    cwd: ws.path,\n    env,\n    capture: true,\n    onChunk: (stream, chunk) => {\n      if (stream === \"stderr\") {\n        process.stderr.write(chunk);\n      } else if (verbose) {\n        process.stdout.write(chunk);\n      }\n    },\n  });\n\n  const exitCode = proc?.exitCode ?? 0;\n  const durationMs = Date.now() - startTime;\n  const output = `${proc?.stdout ?? \"\"}\\n${proc?.stderr ?? \"\"}`;\n  const result: WorkspaceBuildOutcome = {\n    key: ws.key,\n    kind: ws.kind,\n    success: exitCode === 0,\n    ...(exitCode !== 0 && {\n      error: `Build failed (exit code ${exitCode})\\n${output.trim().split(\"\\n\").slice(-5).join(\"\\n\")}`,\n    }),\n    durationMs,\n  };\n\n  if (!verbose) {\n    const name = padRight(ws.key, 28);\n    if (result.success) {\n      console.log(`  ${colors.green(icons.ok)} ${name} ${colors.dim(formatDuration(durationMs))}`);\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\nexport async 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(\"pnpm\", [\"install\"], {\n      cwd: findWorkspaceRoot(opts.configDir)?.dir ?? opts.configDir,\n    });\n  }\n\n  // Prerequisite train: every target's local workspace deps get fresh dists\n  // before the target builds (runtime subpaths resolve from dist — ADR 0018;\n  // bundler-config factories resolve from src, so the config chain cannot go\n  // stale). Fresh members no-op; failures are loud. Deploy prerequisite\n  // builds run in the same build mode as the target builds below — one env\n  // contract for every deploy build child.\n  const env: Record<string, string> = {\n    ...process.env,\n    NODE_ENV: opts.deploy ? \"production\" : \"development\",\n  };\n  // Dist-first deploy builds (ADR 0018): a deploy build must never inherit a\n  // DEPLOY value from the operator's shell, and a dev build must never see one.\n  if (opts.deploy) env.DEPLOY = \"true\";\n  else delete env.DEPLOY;\n\n  const depsReport = await ensureFreshDeps(\n    opts.configDir,\n    existing.map((entry) => entry.path),\n    { force: opts.deploy, env },\n  );\n  if (depsReport.rebuilt.length > 0) {\n    console.log(\n      `  ${colors.dim(`prerequisites: rebuilt ${depsReport.rebuilt.map((member) => member.name).join(\", \")}`)}`,\n    );\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)),\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    for (const ws of sequentialGroup) {\n      const result = await buildOneWorkspace(ws, env, opts);\n      if (result.success) {\n        built.push(ws.key);\n      }\n      deployResults.push(result);\n    }\n\n    console.log();\n  } else {\n    for (const resolved of orderedExisting) {\n      const buildConfig = buildCommands[resolved.key] ?? {\n        cmd: \"pnpm\",\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"],"mappings":"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"}