UNPKG

everything-dev

Version:

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

1 lines • 18.9 kB
{"version":3,"file":"workspace.mjs","names":[],"sources":["../src/workspace.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { Data } from \"effect\";\nimport { parse } from \"yaml\";\nimport { run } from \"./utils/run\";\n\nexport interface WorkspaceMember {\n readonly name: string;\n readonly dir: string;\n readonly localDeps: readonly string[];\n}\n\nexport interface WorkspaceRoot {\n readonly dir: string;\n readonly members: readonly WorkspaceMember[];\n}\n\nexport interface DepsReport {\n readonly rebuilt: readonly WorkspaceMember[];\n readonly fresh: readonly WorkspaceMember[];\n}\n\nexport interface DepsBuildFailureEntry {\n readonly member: WorkspaceMember;\n readonly exitCode: number;\n readonly output: string;\n}\n\nexport class DepsBuildFailure extends Data.TaggedError(\"DepsBuildFailure\")<{\n readonly failures: readonly DepsBuildFailureEntry[];\n}> {\n override get message() {\n const detail = this.failures\n .map(\n (failure) =>\n `${failure.member.name} (exit ${failure.exitCode})\\n${outputTail(failure.output)}`,\n )\n .join(\"\\n\\n\");\n return `workspace dependency builds failed:\\n${detail}`;\n }\n}\n\nconst workspaceRootCache = new Map<string, WorkspaceRoot | null>();\n\nexport function clearWorkspaceRootCache(): void {\n workspaceRootCache.clear();\n}\n\nexport function findWorkspaceRoot(startDir: string): WorkspaceRoot | null {\n const key = resolve(startDir);\n const cached = workspaceRootCache.get(key);\n if (cached !== undefined) return cached;\n const found = discoverWorkspaceRoot(key);\n workspaceRootCache.set(key, found);\n return found;\n}\n\nfunction discoverWorkspaceRoot(dir: string): WorkspaceRoot | null {\n let current = dir;\n while (true) {\n const root = readWorkspaceRootAt(current);\n if (root) return root;\n const parent = dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction readWorkspaceRootAt(dir: string): WorkspaceRoot | null {\n // v2 (ADR 0026): workspace globs live in pnpm-workspace.yaml. Pre-v2\n // runtimes keep the package.json workspaces fallback.\n const yamlPath = join(dir, \"pnpm-workspace.yaml\");\n if (existsSync(yamlPath)) {\n const doc = parse(readFileSync(yamlPath, \"utf8\")) as { packages?: unknown } | null;\n const globs = workspaceGlobsFromYaml(doc?.packages);\n if (globs) return readWorkspaceMembers(dir, globs);\n }\n\n const manifestPath = join(dir, \"package.json\");\n if (!existsSync(manifestPath)) return null;\n const manifest = readManifest(manifestPath);\n if (!manifest) return null;\n const globs = workspaceGlobs(manifest.workspaces);\n if (!globs) return null;\n\n return readWorkspaceMembers(dir, globs);\n}\n\nfunction workspaceGlobsFromYaml(packages: unknown): string[] | null {\n if (!Array.isArray(packages)) return null;\n const globs = packages.filter((glob): glob is string => typeof glob === \"string\");\n return globs.length > 0 ? globs : null;\n}\n\nfunction readWorkspaceMembers(dir: string, globs: readonly string[]): WorkspaceRoot {\n const memberDirs = matchMemberDirs(dir, globs);\n const drafts: { name: string; dir: string; manifest: Record<string, unknown> }[] = [];\n for (const memberDir of memberDirs) {\n const memberManifest = readManifest(join(memberDir, \"package.json\"));\n if (!memberManifest || typeof memberManifest.name !== \"string\") continue;\n drafts.push({ name: memberManifest.name, dir: memberDir, manifest: memberManifest });\n }\n\n const names = new Set(drafts.map((draft) => draft.name));\n const members = drafts\n .map((draft) => ({\n name: draft.name,\n dir: draft.dir,\n localDeps: declaredDepNames(draft.manifest).filter((dep) => names.has(dep)),\n }))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n return { dir, members };\n}\n\nfunction workspaceGlobs(workspaces: unknown): string[] | null {\n if (Array.isArray(workspaces)) {\n return workspaces.filter((glob): glob is string => typeof glob === \"string\");\n }\n if (workspaces && typeof workspaces === \"object\") {\n const packages = (workspaces as { packages?: unknown }).packages;\n if (Array.isArray(packages)) {\n return packages.filter((glob): glob is string => typeof glob === \"string\");\n }\n }\n return null;\n}\n\nfunction matchMemberDirs(rootDir: string, globs: readonly string[]): string[] {\n const found = new Set<string>();\n for (const glob of globs) {\n collectMemberDirs(rootDir, glob.split(\"/\"), found);\n }\n return [...found].sort();\n}\n\nfunction collectMemberDirs(dir: string, segments: readonly string[], out: Set<string>): void {\n const [head, ...rest] = segments;\n if (!head) return;\n let entries: readonly { name: string; isDirectory(): boolean }[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (head !== \"*\" && head !== entry.name) continue;\n const child = join(dir, entry.name);\n if (rest.length === 0) out.add(child);\n else collectMemberDirs(child, rest, out);\n }\n}\n\nfunction readManifest(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction declaredDepNames(manifest: Record<string, unknown>): string[] {\n const names: string[] = [];\n for (const field of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = manifest[field];\n if (deps && typeof deps === \"object\") {\n names.push(...Object.keys(deps as Record<string, unknown>));\n }\n }\n return names;\n}\n\nexport function localDepsOf(\n root: WorkspaceRoot,\n targetDirs: readonly string[],\n): readonly WorkspaceMember[] {\n const byName = new Map(root.members.map((member) => [member.name, member]));\n const byDir = new Map(root.members.map((member) => [member.dir, member]));\n const ordered: WorkspaceMember[] = [];\n const seen = new Set<string>();\n\n const visit = (member: WorkspaceMember): void => {\n if (seen.has(member.name)) return;\n seen.add(member.name);\n for (const dep of member.localDeps) {\n const depMember = byName.get(dep);\n if (depMember) visit(depMember);\n }\n ordered.push(member);\n };\n\n for (const targetDir of targetDirs) {\n const target = byDir.get(resolve(targetDir));\n if (!target) continue;\n for (const dep of target.localDeps) {\n const depMember = byName.get(dep);\n if (depMember) visit(depMember);\n }\n }\n\n return ordered;\n}\n\nexport async function ensureFreshDeps(\n startDir: string,\n targetDirs: readonly string[],\n opts?: {\n readonly force?: boolean;\n /** Build-mode contract for prerequisite children (ADR 0018): deploy\n * builds run dist-first, so every build child — prerequisite or target —\n * must receive the same env; a bundler-config workspace in the closure\n * resolves differently without it. Callers that pass nothing keep the\n * ambient env (dev-time staleness rebuilds). */\n readonly env?: Record<string, string>;\n },\n): Promise<DepsReport> {\n const root = findWorkspaceRoot(startDir);\n if (!root) return { rebuilt: [], fresh: [] };\n\n const closure = localDepsOf(root, targetDirs);\n const force = opts?.force ?? false;\n const judgements = await Promise.all(\n closure.map(async (member) => force || (await isStaleMember(member))),\n );\n const rebuilt = closure.filter((_, index) => judgements[index]);\n const fresh = closure.filter((_, index) => !judgements[index]);\n\n const failures: DepsBuildFailureEntry[] = [];\n // Layered order: a member's dist must exist before its dependents build —\n // dts emit resolves types through dependency dists, so building the whole\n // stale closure in parallel races (everything-dev dts collapsing to `any`\n // when its deps were still writing dists was shipped this way in rc.1).\n for (const layer of buildLayers(rebuilt)) {\n const results = await Promise.allSettled(\n layer.map((member) =>\n run(\"pnpm\", [\"run\", \"build\"], {\n cwd: member.dir,\n capture: true,\n env: opts?.env,\n }),\n ),\n );\n failures.push(\n ...results.flatMap((result, index) => {\n const value = result.status === \"fulfilled\" ? result.value : undefined;\n if (value && value.exitCode === 0) return [];\n const output = value\n ? `${value.stdout}\\n${value.stderr}`\n : result.status === \"rejected\"\n ? String(result.reason)\n : \"\";\n return [\n {\n member: layer[index],\n exitCode: value ? (value.exitCode ?? 1) : 1,\n output,\n },\n ];\n }),\n );\n if (failures.length > 0) break;\n }\n if (failures.length > 0) throw new DepsBuildFailure({ failures });\n\n return { rebuilt, fresh };\n}\n\nexport function buildLayers(members: readonly WorkspaceMember[]): readonly WorkspaceMember[][] {\n const byName = new Map(members.map((member) => [member.name, member]));\n const remaining = new Set(members.map((member) => member.name));\n const layers: WorkspaceMember[][] = [];\n while (remaining.size > 0) {\n const layer = members.filter(\n (member) =>\n remaining.has(member.name) &&\n member.localDeps.every((dep) => !byName.has(dep) || !remaining.has(dep)),\n );\n if (layer.length === 0) {\n throw new Error(`dependency cycle in workspace closure: ${[...remaining].join(\", \")}`);\n }\n for (const member of layer) remaining.delete(member.name);\n layers.push(layer);\n }\n return layers;\n}\n\nasync function isStaleMember(member: WorkspaceMember): Promise<boolean> {\n const oracle = distOracle(member.dir);\n if (!oracle) return false;\n return isWorkspaceDistStale(member.dir, oracle);\n}\n\nfunction distOracle(memberDir: string): string | null {\n const manifest = readManifest(join(memberDir, \"package.json\"));\n if (!manifest) return null;\n\n const entry =\n manifest.exports && typeof manifest.exports === \"object\"\n ? (manifest.exports as Record<string, unknown>)[\".\"]\n : undefined;\n if (entry && typeof entry === \"object\") {\n for (const key of [\"import\", \"default\", \"require\", \"types\"] as const) {\n const value = (entry as Record<string, unknown>)[key];\n if (typeof value === \"string\" && !value.startsWith(\"./src\")) return value;\n }\n }\n if (typeof manifest.module === \"string\" && !manifest.module.startsWith(\"./src\")) {\n return manifest.module;\n }\n if (typeof manifest.main === \"string\" && !manifest.main.startsWith(\"./src\")) {\n return manifest.main;\n }\n\n const reportPath = join(memberDir, \"dist\", \"build-report.json\");\n if (existsSync(reportPath)) {\n const report = readManifest(reportPath);\n if (report && typeof report.entry === \"string\" && report.entry) {\n return join(\"dist\", report.entry);\n }\n }\n return null;\n}\n\nasync function newestSourceMtimeMs(dir: string): Promise<number> {\n let newest = 0;\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name === \"node_modules\" || entry.name === \"dist\") continue;\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n newest = Math.max(newest, await newestSourceMtimeMs(fullPath));\n } else {\n newest = Math.max(newest, (await stat(fullPath)).mtimeMs);\n }\n }\n return newest;\n}\n\nexport async function isWorkspaceDistStale(\n packageDir: string,\n distEntry: string,\n): Promise<boolean> {\n const distPath = join(packageDir, distEntry);\n if (!existsSync(distPath)) return true;\n const [distMtime, srcMtime, pkgMtime] = await Promise.all([\n stat(distPath).then((s) => s.mtimeMs),\n newestSourceMtimeMs(join(packageDir, \"src\")),\n stat(join(packageDir, \"package.json\")).then((s) => s.mtimeMs),\n ]);\n return Math.max(srcMtime, pkgMtime) > distMtime;\n}\n\nfunction outputTail(output: string): string {\n const lines = output.trim().split(\"\\n\");\n return lines.slice(-10).join(\"\\n\");\n}\n"],"mappings":"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"}