everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 21.8 kB
Source Map (JSON)
{"version":3,"file":"build-train.cjs","names":["access","resolveLocalDevelopmentPath","run","syncResolvedSharedDeps","findWorkspaceRoot","process","readInstalledFrameworkVersion","ensureFreshDeps","contentHashStalenessOracle","os","Context","Layer","Effect","Option"],"sources":["../../../src/services/workspace/build-train.ts"],"sourcesContent":["import { access, readFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport process from \"node:process\";\nimport { Context, Effect, Layer, Option } from \"effect\";\nimport { resolveLocalDevelopmentPath } from \"../../config\";\nimport type { WorkspaceDeployResult } from \"../../contract\";\nimport type { BosConfig, BosPluginRef, RuntimeConfig } from \"../../types\";\nimport { run } from \"../../utils/run\";\nimport { readInstalledFrameworkVersion } from \"../framework-version\";\nimport { syncResolvedSharedDeps } from \"./shared-deps\";\nimport { contentHashStalenessOracle, 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\nexport type WorkspaceBuildOutcome = {\n key: string;\n kind: \"app\" | \"plugin\";\n success: boolean;\n error?: string;\n durationMs: number;\n stderr: string;\n /** Warning segments extracted from the build's own output — attributed to\n * this workspace and rendered in the Build section, never interleaved raw. */\n warnings: string[];\n};\n\n/** Render events the build train emits (#424) — the ✓/✗ table, the deploy\n * banner, and the prerequisite line are presentation: the service only\n * decides WHEN, `cli/render/workspace-build` decides HOW. */\nexport interface WorkspaceBuildRender {\n banner?(total: number): void;\n prerequisites?(names: readonly string[]): void;\n outcome?(outcome: WorkspaceBuildOutcome): void;\n end?(): void;\n}\n\nexport interface BuildTargetsInput {\n configDir: string;\n bosConfig: BosConfig | null;\n runtimeConfig: RuntimeConfig | null;\n targets: string[];\n deploy: boolean;\n verbose?: boolean;\n /** Parallel-build cap (#430) — defaults to ~os.cpus(). Unbounded parallelism\n * oversubscribes 2-4 core CI runners. */\n concurrency?: number;\n /** Escape hatch for the content-hash oracle (#430): force every prerequisite\n * rebuild (the pre-#430 deploy behavior). */\n forceBuild?: boolean;\n}\n\nexport interface BuildTargetsDeps {\n runChild?: typeof run;\n freshDeps?: typeof ensureFreshDeps;\n fileExists?: typeof fileExists;\n render?: WorkspaceBuildRender;\n /** Fired as each workspace's build SUCCEEDS (#430) — the deploy train\n * pipelines that workspace's upload while the rest of the train builds. */\n onWorkspaceBuilt?: (key: string) => void;\n}\n\nexport interface BuildTargetsResult {\n built: string[];\n skipped: string[];\n deployResults?: WorkspaceDeployResult[];\n}\n\n/** Pulls warning segments out of a build's stderr: a WARNING/⚠ line opens a\n * segment that runs to the next blank line; `$ ` command echoes never count. */\nexport function extractBuildWarnings(stderr: string): string[] {\n const warnings: string[] = [];\n let current: string[] | null = null;\n for (const line of stderr.split(\"\\n\")) {\n if (current === null) {\n if (!/^\\$\\s/.test(line.trim()) && /WARNING|⚠|\\bwarning\\b/i.test(line)) {\n current = [line];\n }\n } else if (line.trim() === \"\") {\n if (current.some((l) => l.trim().length > 0)) warnings.push(current.join(\"\\n\"));\n current = null;\n } else {\n current.push(line);\n }\n }\n if (current?.some((l) => l.trim().length > 0)) warnings.push(current.join(\"\\n\"));\n return warnings;\n}\n\nasync function buildOneWorkspace(\n ws: WorkspaceTarget,\n env: Record<string, string>,\n opts: { verbose?: boolean },\n deps: BuildTargetsDeps,\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 const stderrBuffer: string[] = [];\n\n const proc = await (deps.runChild ?? run)(buildConfig.cmd, buildConfig.args, {\n cwd: ws.path,\n env,\n capture: true,\n onChunk: (stream, chunk) => {\n if (stream === \"stderr\") {\n // Raw streaming is verbose-only; by default stderr is buffered and\n // surfaced attributed — as warnings in the Build section (#431).\n if (verbose) process.stderr.write(chunk);\n stderrBuffer.push(chunk.toString());\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 stderr: proc?.stderr ?? \"\",\n warnings: extractBuildWarnings(stderrBuffer.join(\"\")),\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) deps.render?.outcome?.(result);\n if (result.success) deps.onWorkspaceBuilt?.(ws.key);\n\n return result;\n}\n\nexport async function buildWorkspaceTargets(\n input: BuildTargetsInput,\n deps: BuildTargetsDeps = {},\n): Promise<BuildTargetsResult> {\n const render = deps.render;\n const existing: WorkspaceTarget[] = [];\n const skipped: string[] = [];\n\n for (const target of input.targets) {\n const resolved = resolveWorkspaceTarget(\n target,\n input.bosConfig,\n input.runtimeConfig,\n input.configDir,\n );\n if (!resolved) {\n skipped.push(target);\n continue;\n }\n\n const exists = await (deps.fileExists ?? 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: input.configDir,\n hostMode: \"local\",\n bosConfig: input.bosConfig ?? undefined,\n extendsChain: [],\n });\n if (sharedSync.catalogChanged) {\n await run(\"pnpm\", [\"install\"], {\n cwd: findWorkspaceRoot(input.configDir)?.dir ?? input.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: input.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 (input.deploy) env.DEPLOY = \"true\";\n else delete env.DEPLOY;\n // MF_BUILD_VERSION (#546): the toolchain's buildInfo.buildVersion otherwise\n // stamps the building workspace's own package.json version — an unrelated\n // number that made deployed bundles advertise a stale platform identity.\n // Deploy builds stamp the installed everything-dev version instead, so a\n // bundle's manifest names the platform release it was built against.\n if (input.deploy) {\n const frameworkVersion = readInstalledFrameworkVersion(input.configDir, \"everything-dev\");\n if (frameworkVersion) env.MF_BUILD_VERSION = frameworkVersion;\n else delete env.MF_BUILD_VERSION;\n }\n\n const root = findWorkspaceRoot(input.configDir);\n // Deploy prerequisite freshness (#430): the content-hash oracle replaces the\n // blanket force-rebuild — unknown hash or missing dist errs toward building.\n // The force flag (input or BOS_FORCE_BUILD=1) keeps the old behavior as an\n // escape hatch: a forced build never judges.\n const force = input.deploy && (input.forceBuild === true || process.env.BOS_FORCE_BUILD === \"1\");\n const depsReport = await (deps.freshDeps ?? ensureFreshDeps)(\n input.configDir,\n existing.map((entry) => entry.path),\n {\n force,\n env,\n ...(input.deploy && root && !force\n ? { oracle: contentHashStalenessOracle(root.dir, root.members) }\n : {}),\n },\n );\n if (depsReport.rebuilt.length > 0) {\n render?.prerequisites?.(depsReport.rebuilt.map((member) => member.name));\n }\n\n const orderedExisting = input.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 = input.deploy\n ? orderedExisting.filter((e) => e.key !== \"host\")\n : orderedExisting;\n const sequentialGroup = input.deploy ? orderedExisting.filter((e) => e.key === \"host\") : [];\n\n const built: string[] = [];\n const deployResults: WorkspaceDeployResult[] = [];\n\n if (input.deploy && parallelGroup.length > 0) {\n const total = parallelGroup.length + sequentialGroup.length;\n render?.banner?.(total);\n\n const results = await mapWithConcurrency(\n parallelGroup,\n (ws) => buildOneWorkspace(ws, env, input, deps),\n buildConcurrencyCap(input.concurrency),\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 warnings: [],\n });\n }\n }\n\n for (const ws of sequentialGroup) {\n const result = await buildOneWorkspace(ws, env, input, deps);\n if (result.success) {\n built.push(ws.key);\n }\n deployResults.push(result);\n }\n\n render?.end?.();\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 (deps.runChild ?? 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: input.deploy ? deployResults : undefined };\n}\n\nexport function buildConcurrencyCap(requested?: number): number {\n const cpus = os.cpus().length;\n const cap = Math.max(1, Math.min(requested ?? cpus, cpus));\n return cap;\n}\n\n/** Runs `fn` over `items` with at most `limit` in flight; results keep input\n * order. Rejections propagate after all in-flight work settles. */\nexport async function mapWithConcurrency<T, R>(\n items: readonly T[],\n fn: (item: T, index: number) => Promise<R>,\n limit: number,\n): Promise<PromiseSettledResult<R>[]> {\n const results: PromiseSettledResult<R>[] = new Array(items.length);\n let next = 0;\n const workers = Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, async () => {\n while (true) {\n const index = next++;\n if (index >= items.length) return;\n try {\n results[index] = { status: \"fulfilled\", value: await fn(items[index], index) };\n } catch (reason) {\n results[index] = { status: \"rejected\", reason };\n }\n }\n });\n await Promise.all(workers);\n return results;\n}\n\n/** Presentation seam the composition root wires to `cli/render` (#424). */\nexport class WorkspaceBuildRenderService extends Context.Service<\n WorkspaceBuildRenderService,\n WorkspaceBuildRender\n>()(\"everything-dev/workspace/build-render\") {}\n\n/**\n * The build train as a Context.Service (ticket #424): parallel/sequential\n * group logic and the prerequisite train behind one tag; the ✓ table renders\n * through the composition root's render, never the service.\n */\nexport class BuildTrainService extends Context.Service<\n BuildTrainService,\n {\n buildTargets: (\n input: BuildTargetsInput,\n deps?: BuildTargetsDeps,\n ) => Promise<BuildTargetsResult>;\n }\n>()(\"everything-dev/workspace/build-train\") {\n static readonly Live = Layer.effect(\n this,\n Effect.gen(function* () {\n const renderOption = yield* Effect.serviceOption(WorkspaceBuildRenderService);\n return BuildTrainService.of({\n buildTargets: (input, deps) =>\n buildWorkspaceTargets(input, {\n ...deps,\n render: deps?.render ?? Option.getOrUndefined(renderOption),\n }),\n });\n }),\n );\n}\n"],"mappings":"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"}