UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

1 lines • 14.1 kB
{"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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"}