UNPKG

everything-dev

Version:

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

1 lines • 8.42 kB
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/scaffold/upgrade-audit/index.ts"],"sourcesContent":["/**\n * v1 → v2 upgrade train (NEARBuilders/everything-dev#455).\n *\n * Audits an everything-dev v1 child app for upgrade readiness (hardline\n * mount-conformance gate, config surface, legacy imports) and applies the\n * deterministic v2 transforms (authored descriptor, bun→pnpm catalog\n * migration, consumerized refs, import rewrites, obsolete-file deletion,\n * plugin dep declarations). State-aware: a tree with an authored\n * `bos.app.ts` is already on the v2 train — the audit reads\n * `bos.config.json` and is for pre-upgrade trees only.\n */\nimport { existsSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { Effect } from \"effect\";\nimport { apply } from \"./apply\";\nimport { audit } from \"./audit\";\nimport {\n AUTH_FIXTURE_PATH,\n type ComposeProbe,\n composeFindings,\n probeComposeSeam,\n readEveryPluginVersion,\n} from \"./checks/compose-seam\";\nimport type { Manifest, RouterSeam, Finding as RuntimeFinding } from \"./domain\";\nimport { GateBlocked } from \"./domain\";\nimport type { StepResult } from \"./steps/author-config\";\nimport { migrateI18nSeam } from \"./steps/migrate-i18n-seam\";\nimport { migrateRouteMounts } from \"./steps/migrate-route-mounts\";\nimport { patchDbTopology } from \"./steps/patch-db-topology\";\nimport { portRouteGuards } from \"./steps/port-route-guards\";\nexport type UpgradeAuditStep =\n | \"port-route-guards\"\n | \"db-topology\"\n | \"i18n-seam\"\n | \"compose-seam\"\n | \"route-mounts\";\n\nexport type PlainFinding = {\n readonly check: string;\n readonly path: string;\n readonly severity: \"blocker\" | \"warn\";\n readonly message: string;\n};\n\nexport type AuditManifest = Manifest;\n\nexport type AuditOutcome = {\n readonly tier: \"A\" | \"B\";\n readonly gateBlocked: boolean;\n readonly findings: readonly PlainFinding[];\n readonly manifest: AuditManifest;\n};\n\nexport type ApplyOutcome = {\n readonly migrated: string[];\n readonly notes: string[];\n};\n\nconst toPlainFinding = (finding: RuntimeFinding): PlainFinding => ({\n check: finding.check,\n path: finding.path,\n severity: finding.severity,\n message: finding.message,\n});\n\nexport const isV2Tree = (projectDir: string): boolean => existsSync(join(projectDir, \"bos.app.ts\"));\n\nconst writeManifestFile = async (projectDir: string, manifest: Manifest): Promise<void> => {\n await mkdir(join(projectDir, \".bos\"), { recursive: true });\n await writeFile(\n join(projectDir, \".bos/v2-upgrade-manifest.json\"),\n `${JSON.stringify(manifest, null, 2)}\\n`,\n );\n};\n\n/** Run the v1 audit: gate findings, manifest emit, no tree writes. */\nexport const auditV1Tree = async (projectDir: string): Promise<AuditOutcome> => {\n const report = await Effect.runPromise(audit(projectDir));\n const findings = report.findings.map(toPlainFinding);\n await writeManifestFile(projectDir, report.manifest);\n return {\n tier: report.tier,\n gateBlocked: report.manifest.blockerCount > 0,\n findings,\n manifest: report.manifest,\n };\n};\n\n/** Apply the v2 transforms; the hardline gate must pass first. */\nexport const applyV1Tree = async (\n projectDir: string,\n dryRun: boolean,\n): Promise<\n { ok: true; outcome: ApplyOutcome } | { ok: false; blockers: readonly PlainFinding[] }\n> => {\n try {\n const logs = await Effect.runPromise(apply(projectDir, dryRun));\n const migrated: string[] = [];\n const notes: string[] = [];\n for (const log of logs) {\n for (const path of log.result.writes) migrated.push(`${log.name}: ${path}`);\n for (const path of log.result.deletes) migrated.push(`${log.name}: deleted ${path}`);\n for (const note of log.result.notes) notes.push(`${log.name}: ${note}`);\n }\n return { ok: true, outcome: { migrated, notes } };\n } catch (error) {\n if (error instanceof GateBlocked) {\n return { ok: false, blockers: error.findings.map(toPlainFinding) };\n }\n throw error;\n }\n};\n\n/** Re-run a post-upgrade maintenance step (regression guard after `bos sync`). */\nexport const maintainV1Tree = async (\n projectDir: string,\n step: UpgradeAuditStep,\n dryRun: boolean,\n): Promise<StepResult> => {\n switch (step) {\n case \"route-mounts\": {\n return await Effect.runPromise(migrateRouteMounts(projectDir, dryRun));\n }\n case \"port-route-guards\":\n return await Effect.runPromise(portRouteGuards(projectDir, dryRun));\n case \"db-topology\":\n return await Effect.runPromise(patchDbTopology(projectDir, dryRun));\n case \"i18n-seam\":\n return await Effect.runPromise(migrateI18nSeam(projectDir, dryRun));\n case \"compose-seam\": {\n const probe = await Effect.runPromise(probeComposeSeam(projectDir, { live: false }));\n const version = await Effect.runPromise(readEveryPluginVersion(projectDir));\n const findings = composeFindings(probe, version);\n return {\n writes: [],\n deletes: [],\n notes: [\n `every-plugin ${version}, auth manifest: ${AUTH_FIXTURE_PATH}`,\n `seam: ${describeComposeProbe(probe)}`,\n ...probe.composeLog,\n ...(probe.error ? [`error: ${probe.error}`] : []),\n ...findings.map((finding) => `[${finding.severity}] ${finding.message}`),\n ],\n };\n }\n }\n};\n\nexport const describeComposeProbe = (probe: ComposeProbe): string => {\n switch (probe.seam) {\n case \"ok\":\n return probe.composeLog.some((line) => line.includes(\"core ui wins\"))\n ? \"compose ok — core ui wins; shadowed auth routes skipped cleanly\"\n : \"compose ok — note: no /login shadow exercised (core ui no longer claims /login)\";\n case \"absent-ui-manifest\":\n return \"ui/src/manifest.gen.json absent — run `bos types gen` first\";\n case \"cascade-bug\":\n return 'KNOWN BUG — false \"unresolvable parentage\" for the /login shadow cascade';\n case \"path-collision\":\n return \"REGRESSION — the /login shadow is treated as a hard path collision\";\n case \"compose-failed\":\n return \"compose failed\";\n }\n};\n\nexport type { Manifest, RouterSeam, StepResult };\n"],"mappings":"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"}