everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
116 lines (114 loc) • 5.31 kB
JavaScript
const require_domain = require('./domain.cjs');
const require_audit = require('./audit.cjs');
const require_migrate_route_mounts = require('./steps/migrate-route-mounts.cjs');
const require_apply = require('./apply.cjs');
const require_compose_seam = require('./checks/compose-seam.cjs');
const require_migrate_i18n_seam = require('./steps/migrate-i18n-seam.cjs');
const require_patch_db_topology = require('./steps/patch-db-topology.cjs');
const require_port_route_guards = require('./steps/port-route-guards.cjs');
let node_fs = require("node:fs");
let node_path = require("node:path");
let effect = require("effect");
let node_fs_promises = require("node:fs/promises");
//#region src/services/scaffold/upgrade-audit/index.ts
/**
* v1 → v2 upgrade train (NEARBuilders/everything-dev#455).
*
* Audits an everything-dev v1 child app for upgrade readiness (hardline
* mount-conformance gate, config surface, legacy imports) and applies the
* deterministic v2 transforms (authored descriptor, bun→pnpm catalog
* migration, consumerized refs, import rewrites, obsolete-file deletion,
* plugin dep declarations). State-aware: a tree with an authored
* `bos.app.ts` is already on the v2 train — the audit reads
* `bos.config.json` and is for pre-upgrade trees only.
*/
const toPlainFinding = (finding) => ({
check: finding.check,
path: finding.path,
severity: finding.severity,
message: finding.message
});
const isV2Tree = (projectDir) => (0, node_fs.existsSync)((0, node_path.join)(projectDir, "bos.app.ts"));
const writeManifestFile = async (projectDir, manifest) => {
await (0, node_fs_promises.mkdir)((0, node_path.join)(projectDir, ".bos"), { recursive: true });
await (0, node_fs_promises.writeFile)((0, node_path.join)(projectDir, ".bos/v2-upgrade-manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`);
};
/** Run the v1 audit: gate findings, manifest emit, no tree writes. */
const auditV1Tree = async (projectDir) => {
const report = await effect.Effect.runPromise(require_audit.audit(projectDir));
const findings = report.findings.map(toPlainFinding);
await writeManifestFile(projectDir, report.manifest);
return {
tier: report.tier,
gateBlocked: report.manifest.blockerCount > 0,
findings,
manifest: report.manifest
};
};
/** Apply the v2 transforms; the hardline gate must pass first. */
const applyV1Tree = async (projectDir, dryRun) => {
try {
const logs = await effect.Effect.runPromise(require_apply.apply(projectDir, dryRun));
const migrated = [];
const notes = [];
for (const log of logs) {
for (const path of log.result.writes) migrated.push(`${log.name}: ${path}`);
for (const path of log.result.deletes) migrated.push(`${log.name}: deleted ${path}`);
for (const note of log.result.notes) notes.push(`${log.name}: ${note}`);
}
return {
ok: true,
outcome: {
migrated,
notes
}
};
} catch (error) {
if (error instanceof require_domain.GateBlocked) return {
ok: false,
blockers: error.findings.map(toPlainFinding)
};
throw error;
}
};
/** Re-run a post-upgrade maintenance step (regression guard after `bos sync`). */
const maintainV1Tree = async (projectDir, step, dryRun) => {
switch (step) {
case "route-mounts": return await effect.Effect.runPromise(require_migrate_route_mounts.migrateRouteMounts(projectDir, dryRun));
case "port-route-guards": return await effect.Effect.runPromise(require_port_route_guards.portRouteGuards(projectDir, dryRun));
case "db-topology": return await effect.Effect.runPromise(require_patch_db_topology.patchDbTopology(projectDir, dryRun));
case "i18n-seam": return await effect.Effect.runPromise(require_migrate_i18n_seam.migrateI18nSeam(projectDir, dryRun));
case "compose-seam": {
const probe = await effect.Effect.runPromise(require_compose_seam.probeComposeSeam(projectDir, { live: false }));
const version = await effect.Effect.runPromise(require_compose_seam.readEveryPluginVersion(projectDir));
const findings = require_compose_seam.composeFindings(probe, version);
return {
writes: [],
deletes: [],
notes: [
`every-plugin ${version}, auth manifest: ${require_compose_seam.AUTH_FIXTURE_PATH}`,
`seam: ${describeComposeProbe(probe)}`,
...probe.composeLog,
...probe.error ? [`error: ${probe.error}`] : [],
...findings.map((finding) => `[${finding.severity}] ${finding.message}`)
]
};
}
}
};
const describeComposeProbe = (probe) => {
switch (probe.seam) {
case "ok": return probe.composeLog.some((line) => line.includes("core ui wins")) ? "compose ok — core ui wins; shadowed auth routes skipped cleanly" : "compose ok — note: no /login shadow exercised (core ui no longer claims /login)";
case "absent-ui-manifest": return "ui/src/manifest.gen.json absent — run `bos types gen` first";
case "cascade-bug": return "KNOWN BUG — false \"unresolvable parentage\" for the /login shadow cascade";
case "path-collision": return "REGRESSION — the /login shadow is treated as a hard path collision";
case "compose-failed": return "compose failed";
}
};
//#endregion
exports.applyV1Tree = applyV1Tree;
exports.auditV1Tree = auditV1Tree;
exports.describeComposeProbe = describeComposeProbe;
exports.isV2Tree = isV2Tree;
exports.maintainV1Tree = maintainV1Tree;
//# sourceMappingURL=index.cjs.map