UNPKG

everything-dev

Version:

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

1 lines • 12.1 kB
{"version":3,"file":"apply-manifest.cjs","names":["Effect","readText","writeText","OBSOLETE_FILES","fileExists","removePath","listFiles"],"sources":["../../../../../src/services/scaffold/upgrade-audit/steps/apply-manifest.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport type { ImportRewrite } from \"../domain\";\nimport { fileExists, listFiles, readText, removePath, writeText } from \"../fs\";\nimport { OBSOLETE_FILES } from \"../obsolete-files\";\nimport type { StepResult } from \"./author-config\";\n\nconst applyRewrites = (\n projectDir: string,\n rewrites: readonly ImportRewrite[],\n dryRun: boolean,\n): Effect.Effect<string[], Error> =>\n Effect.gen(function* () {\n const touched: string[] = [];\n for (const rewrite of rewrites) {\n for (const file of rewrite.files) {\n const source = yield* readText(projectDir, file);\n const next = source.replaceAll(rewrite.from, rewrite.to);\n if (next !== source) {\n touched.push(file);\n if (!dryRun) yield* writeText(projectDir, file, next);\n }\n }\n }\n return touched;\n });\n\nconst applyDeletions = (projectDir: string, dryRun: boolean): Effect.Effect<string[], Error> =>\n Effect.gen(function* () {\n const removed: string[] = [];\n for (const path of OBSOLETE_FILES) {\n if (yield* fileExists(projectDir, path)) {\n removed.push(path);\n if (!dryRun) yield* removePath(projectDir, path);\n }\n }\n return removed;\n });\n\ninterface PluginDepsResult {\n readonly added: readonly string[];\n readonly unresolved: readonly string[];\n}\n\nconst bareSpecifiers = (source: string): string[] => {\n const specifiers: string[] = [];\n const importRe =\n /(?:import|export)[^\"'`]*?from\\s*[\"']([^\"']+)[\"']|import\\s*\\(\\s*[\"']([^\"']+)[\"']\\s*\\)|require\\s*\\(\\s*[\"']([^\"']+)[\"']\\s*\\)/g;\n for (const match of source.matchAll(importRe)) {\n const spec = match[1] ?? match[2] ?? match[3];\n if (spec && !spec.startsWith(\".\") && !spec.startsWith(\"/\")) specifiers.push(spec);\n }\n return specifiers;\n};\n\nconst packageNameOf = (specifier: string): string => {\n if (specifier.startsWith(\"@\")) {\n const [, scope, name] = specifier.split(\"/\");\n return scope && name ? `${scope}/${name}` : specifier;\n }\n return specifier.split(\"/\")[0];\n};\n\nconst isProtocolSpecifier = (specifier: string): boolean => /^[^/]+:/.test(specifier);\n\nconst memberPackageNames = (projectDir: string): Effect.Effect<Set<string>, Error> =>\n Effect.gen(function* () {\n const pkgPaths = yield* listFiles(\n projectDir,\n \"{package.json,ui/package.json,api/package.json,plugins/*/package.json}\",\n );\n const names = new Set<string>();\n for (const pkgPath of pkgPaths) {\n if (pkgPath === \"package.json\") continue;\n const pkg = JSON.parse(yield* readText(projectDir, pkgPath)) as { name?: string };\n if (typeof pkg.name === \"string\") names.add(pkg.name);\n }\n return names;\n });\n\nconst declarePluginDeps = (\n projectDir: string,\n dryRun: boolean,\n): Effect.Effect<PluginDepsResult, Error> =>\n Effect.gen(function* () {\n const rootCatalog = JSON.parse(yield* readText(projectDir, \"package.json\")) as {\n workspaces?: { catalog?: Record<string, string> };\n };\n const catalog = rootCatalog.workspaces?.catalog ?? {};\n const members = yield* memberPackageNames(projectDir);\n\n const pluginPkgs = yield* listFiles(projectDir, \"plugins/*/package.json\");\n const added: string[] = [];\n const unresolved: string[] = [];\n\n for (const pkgPath of pluginPkgs) {\n const pluginDir = pkgPath.slice(0, pkgPath.lastIndexOf(\"/\"));\n const declared = new Set<string>();\n const pkg = JSON.parse(yield* readText(projectDir, pkgPath)) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n for (const name of [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ]) {\n declared.add(name);\n }\n\n const sources = yield* listFiles(projectDir, `${pluginDir}/src/**/*.{ts,tsx}`);\n const needed = new Set<string>();\n for (const source of sources) {\n const text = yield* readText(projectDir, source);\n for (const specifier of bareSpecifiers(text)) {\n if (isProtocolSpecifier(specifier)) continue;\n needed.add(packageNameOf(specifier));\n }\n }\n\n const nextDeps = { ...(pkg.dependencies ?? {}) };\n let modified = false;\n for (const name of needed) {\n if (declared.has(name) || name === pluginDir.split(\"/\")[1]) continue;\n // In-repo packages get workspace:* — the catalog holds external deps.\n if (members.has(name)) {\n added.push(`${pluginDir}: ${name} (workspace:*)`);\n nextDeps[name] = \"workspace:*\";\n modified = true;\n continue;\n }\n if (!(name in catalog)) {\n unresolved.push(`${pluginDir}: ${name} (not in catalog — declare manually)`);\n continue;\n }\n added.push(`${pluginDir}: ${name}`);\n nextDeps[name] = \"catalog:\";\n modified = true;\n }\n\n if (modified && !dryRun) {\n yield* writeText(\n projectDir,\n pkgPath,\n `${JSON.stringify({ ...pkg, dependencies: nextDeps }, null, 2)}\\n`,\n );\n }\n }\n return { added, unresolved };\n });\n\nexport const consumerizeRefs = (\n projectDir: string,\n dryRun: boolean,\n): Effect.Effect<string[], Error> =>\n Effect.gen(function* () {\n const pkgPaths = yield* listFiles(\n projectDir,\n \"{package.json,ui/package.json,api/package.json,plugins/*/package.json}\",\n );\n // Refs to in-repo packages stay `workspace:*` — pnpm resolves member\n // packages locally, and the catalog only holds external deps. Only\n // external `workspace:`/`file:` refs (bun-workspace leftovers pointing\n // outside the tree) are consumerized to `catalog:`.\n const memberNames = new Set<string>();\n for (const pkgPath of pkgPaths) {\n if (pkgPath === \"package.json\") continue;\n const pkg = JSON.parse(yield* readText(projectDir, pkgPath)) as { name?: string };\n if (typeof pkg.name === \"string\") memberNames.add(pkg.name);\n }\n const fixed: string[] = [];\n for (const pkgPath of pkgPaths) {\n const pkg = JSON.parse(yield* readText(projectDir, pkgPath)) as Record<string, unknown>;\n let modified = false;\n for (const field of [\"dependencies\", \"devDependencies\", \"peerDependencies\"]) {\n const deps = pkg[field];\n if (deps === null || typeof deps !== \"object\") continue;\n const record = deps as Record<string, string>;\n for (const [name, ref] of Object.entries(record)) {\n if (\n typeof ref === \"string\" &&\n (ref.startsWith(\"workspace:\") || ref.startsWith(\"file:\")) &&\n !memberNames.has(name)\n ) {\n record[name] = \"catalog:\";\n modified = true;\n }\n }\n }\n if (modified) {\n fixed.push(pkgPath);\n if (!dryRun) {\n yield* writeText(projectDir, pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n }\n }\n }\n return fixed;\n });\n\nexport const applyManifest = (\n projectDir: string,\n rewrites: readonly ImportRewrite[],\n dryRun: boolean,\n): Effect.Effect<StepResult, Error> =>\n Effect.gen(function* () {\n const rewritten = yield* applyRewrites(projectDir, rewrites, dryRun);\n const deleted = yield* applyDeletions(projectDir, dryRun);\n const deps = yield* declarePluginDeps(projectDir, dryRun);\n const refs = yield* consumerizeRefs(projectDir, dryRun);\n return {\n writes: rewritten,\n deletes: deleted,\n notes: [\n ...(refs.length > 0 ? [`workspace:/file: refs → catalog: in ${refs.join(\", \")}`] : []),\n ...(deps.added.length > 0 ? [`plugin deps added: ${deps.added.join(\", \")}`] : []),\n ...deps.unresolved,\n ],\n };\n });\n"],"mappings":"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"}