everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
549 lines (547 loc) • 20.9 kB
JavaScript
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
const require_load = require('../services/resolution/load.cjs');
const require_theme = require('../utils/theme.cjs');
const require_catalog = require('../services/workspace/catalog.cjs');
const require_services_resolution_session = require('../services/resolution/session.cjs');
const require_services_federation_service = require('../services/federation/service.cjs');
const require_artifacts = require('../services/codegen/artifacts.cjs');
const require_workspace = require('../services/workspace/workspace.cjs');
const require_framework_version = require('../services/framework-version.cjs');
const require_build_train = require('../services/workspace/build-train.cjs');
const require_manifest = require('../services/platform/manifest.cjs');
const require_published = require('../services/registry/published.cjs');
const require_upgrade = require('../services/scaffold/upgrade.cjs');
const require_index = require('../services/scaffold/upgrade-audit/index.cjs');
let node_fs = require("node:fs");
let node_path = require("node:path");
let effect = require("effect");
let node_child_process = require("node:child_process");
let node_process = require("node:process");
node_process = require_runtime.__toESM(node_process, 1);
let every_plugin_ui_manifest_generator = require("every-plugin/ui/manifest-generator");
//#region src/handlers/upgrade.ts
function registerUpgrade(builder) {
return {
upgrade: builder.upgrade.effect(function* (_opts, input) {
return yield* effect.Effect.tryPromise({
try: async () => {
const configPath = require_load.findConfigPath();
if (!configPath) return {
status: "error",
packages: [],
error: `${require_load.MISSING_CONFIG_MESSAGE} in current directory`
};
const projectDir = (0, node_path.resolve)((0, node_path.dirname)(configPath));
if (input.from === "v1") {
if (require_index.isV2Tree(projectDir)) return {
status: "already-upgraded",
packages: [],
notes: ["bos.app.ts present — this tree is already on the v2 train; nothing to audit or apply"]
};
if (input.maintain && input.maintain.length > 0) {
const migrated = [];
const notes = [];
for (const step of input.maintain) {
const result = await require_index.maintainV1Tree(projectDir, step, input.dryRun);
for (const path of result.writes) migrated.push(`${step}: wrote ${path}`);
for (const path of result.deletes) migrated.push(`${step}: deleted ${path}`);
for (const note of result.notes) notes.push(`${step}: ${note}`);
}
return {
status: input.dryRun ? "dry-run" : "upgraded",
packages: [],
migrated,
notes
};
}
if (input.audit) {
const outcome = await require_index.auditV1Tree(projectDir);
const auditResult = {
tier: outcome.tier,
findings: outcome.findings,
manifest: outcome.manifest
};
return outcome.gateBlocked ? {
status: "gate-blocked",
packages: [],
audit: auditResult,
blockers: outcome.findings.filter((f) => f.severity === "blocker")
} : {
status: "audit",
packages: [],
audit: auditResult
};
}
const outcome = await require_index.applyV1Tree(projectDir, input.dryRun);
if (!outcome.ok) return {
status: "gate-blocked",
packages: [],
blockers: outcome.blockers
};
return {
status: input.dryRun ? "dry-run" : "upgraded",
packages: [],
migrated: outcome.outcome.migrated,
notes: outcome.outcome.notes
};
}
return await require_upgrade.upgradeTemplate(projectDir, input);
},
catch: (error) => ({
status: "error",
packages: [],
error: error instanceof Error ? error.message : "Unknown error"
})
});
}),
typesGen: builder.typesGen.effect(function* (_opts, input) {
return yield* effect.Effect.tryPromise({
try: async () => {
const configPath = require_load.findConfigPath();
if (!configPath) return {
status: "error",
generated: [],
fetched: [],
skipped: [],
failed: [],
error: `${require_load.MISSING_CONFIG_MESSAGE} in current directory`
};
const projectDir = (0, node_path.resolve)((0, node_path.dirname)(configPath));
const env = input.env ?? (node_process.default.env.NODE_ENV === "production" ? "production" : "development");
const refreshed = await require_services_resolution_session.openResolution({
cwd: projectDir,
env,
remotePlugins: input.remotePlugins
});
if (!refreshed?.config || !refreshed.runtime) return {
status: "error",
generated: [],
fetched: [],
skipped: [],
failed: [],
error: "Failed to load the authored config"
};
const runtime = refreshed.runtime;
const resolvedConfig = refreshed.config;
if (input.dryRun) {
const pluginEntries = Object.entries(runtime.plugins ?? {});
const fetched = [];
const skipped = [];
const hasLocalApiWorkspace = (0, node_fs.existsSync)((0, node_path.join)(projectDir, "api", "src"));
if (runtime.api.source !== "local") fetched.push(`api remote (${runtime.api.url})`);
else {
const path = runtime.api.localPath ? ` (${(0, node_path.relative)(projectDir, runtime.api.localPath)})` : "";
skipped.push(`api local${path}`);
}
if (runtime.auth) {
if (runtime.auth.source !== "local") fetched.push(`auth remote (${runtime.auth.url})`);
else {
const path = runtime.auth.localPath ? ` (${(0, node_path.relative)(projectDir, runtime.auth.localPath)})` : "";
skipped.push(`auth local${path}`);
}
}
for (const [key, plugin] of pluginEntries) if (plugin.url && plugin.source !== "local") fetched.push(`${key} remote (${plugin.url})`);
else if (plugin.localPath) skipped.push(`${key} local (${(0, node_path.relative)(projectDir, plugin.localPath)})`);
else skipped.push(`${key} no URL resolved`);
const generated = [
"ui/src/lib/api-types.gen.ts",
"ui/src/lib/auth-types.gen.ts",
".bos/bos.resolved-config.json"
];
if (hasLocalApiWorkspace) generated.push("api/src/lib/plugins-types.gen.ts", "api/src/lib/auth-types.gen.ts");
if ((0, node_fs.existsSync)((0, node_path.join)(projectDir, "host", "src"))) generated.push("host/src/lib/auth-types.gen.ts");
for (const [_key, plugin] of pluginEntries) {
const localPath = plugin.localPath;
if (!localPath) continue;
const pluginSrc = (0, node_path.join)(localPath, "src", "lib", "plugins-client.gen.ts");
if ((0, node_fs.existsSync)(pluginSrc)) generated.push((0, node_path.relative)(projectDir, pluginSrc));
}
if (runtime.auth?.localPath) {
const authSrc = (0, node_path.join)(runtime.auth.localPath, "src", "lib", "plugins-client.gen.ts");
if ((0, node_fs.existsSync)(authSrc)) generated.push((0, node_path.relative)(projectDir, authSrc));
}
return {
status: "success",
generated,
fetched,
skipped,
failed: []
};
}
const artifacts = await require_artifacts.generateCodeArtifacts(projectDir, resolvedConfig, {
env,
extendsChain: [...refreshed.chain],
runtimeConfig: runtime,
forceRouteTree: true
});
const hasLocalApiWorkspace = (0, node_fs.existsSync)((0, node_path.join)(projectDir, "api", "src"));
const generated = ["ui/src/lib/api-types.gen.ts"];
if (hasLocalApiWorkspace) generated.push("api/src/lib/plugins-types.gen.ts", "api/src/lib/auth-types.gen.ts");
if (runtime.auth && (runtime.auth.source !== "local" || runtime.auth.localPath)) generated.push("ui/src/lib/auth-types.gen.ts");
if ((0, node_fs.existsSync)((0, node_path.join)(projectDir, "host", "src"))) generated.push("host/src/lib/auth-types.gen.ts");
for (const [_key, plugin] of Object.entries(runtime.plugins ?? {})) {
const localPath = plugin.localPath;
if (!localPath) continue;
const pluginSrc = (0, node_path.join)(localPath, "src", "lib", "plugins-client.gen.ts");
if ((0, node_fs.existsSync)(pluginSrc)) generated.push((0, node_path.relative)(projectDir, pluginSrc));
}
if (runtime.auth?.localPath) {
const authSrc = (0, node_path.join)(runtime.auth.localPath, "src", "lib", "plugins-client.gen.ts");
if ((0, node_fs.existsSync)(authSrc)) generated.push((0, node_path.relative)(projectDir, authSrc));
}
const contractStatus = artifacts?.contractStatus ?? [];
const fetched = [];
const skipped = [];
const failed = [];
for (const entry of contractStatus) if (entry.source === "remote") fetched.push(entry.url ? `${entry.key} remote (${entry.url})` : entry.key);
else if (entry.source === "local") {
const path = entry.localPath ? ` (${(0, node_path.relative)(projectDir, entry.localPath)})` : "";
skipped.push(`${entry.key} local${path}`);
} else if (entry.source === "skipped") skipped.push(`${entry.key} no URL resolved`);
else if (entry.source === "failed") {
const detail = entry.error ? `: ${entry.error}` : "";
failed.push(`${entry.key}${detail}`);
}
return {
status: "success",
generated: [...generated, ".bos/bos.resolved-config.json"],
fetched,
skipped,
failed
};
},
catch: (error) => ({
status: "error",
generated: [],
fetched: [],
skipped: [],
failed: [],
error: error instanceof Error ? error.message : "Unknown error"
})
});
}),
typecheck: builder.typecheck.effect(function* (_opts, input) {
return yield* effect.Effect.tryPromise({
try: async () => {
const configPath = require_load.findConfigPath();
if (!configPath) return {
status: "error",
checked: [],
skipped: [],
results: [],
error: `${require_load.MISSING_CONFIG_MESSAGE} in current directory`
};
const projectDir = (0, node_path.resolve)((0, node_path.dirname)(configPath));
const refreshed = await require_services_resolution_session.openResolution({ cwd: projectDir });
if (!refreshed?.config || !refreshed.runtime) return {
status: "error",
checked: [],
skipped: [],
results: [],
error: "Failed to load the authored config"
};
const runtime = refreshed.runtime;
const resolvedConfig = refreshed.config;
await require_artifacts.generateCodeArtifacts(projectDir, resolvedConfig, {
env: node_process.default.env.NODE_ENV === "production" ? "production" : "development",
extendsChain: [...refreshed.chain],
runtimeConfig: runtime
});
const workspaceEntries = [];
const skipped = [];
const appTargets = [
{
key: "host",
label: "host",
target: runtime.host
},
{
key: "ui",
label: "ui",
target: runtime.ui
},
{
key: "api",
label: "api",
target: runtime.api
}
];
if (runtime.auth) appTargets.push({
key: "auth",
label: "auth",
target: runtime.auth
});
for (const entry of appTargets) if (entry.target?.source === "local" && entry.target.localPath && (0, node_fs.existsSync)((0, node_path.join)(entry.target.localPath, "tsconfig.json"))) workspaceEntries.push({
key: entry.key,
label: entry.label,
dir: entry.target.localPath
});
else skipped.push({
key: entry.key,
label: entry.label
});
for (const [key, plugin] of Object.entries(runtime.plugins ?? {})) {
const label = `plugins/${key}`;
const localPath = plugin.source === "local" ? plugin.localPath : void 0;
if (localPath && (0, node_fs.existsSync)((0, node_path.join)(localPath, "tsconfig.json"))) workspaceEntries.push({
key,
label,
dir: localPath
});
else skipped.push({
key,
label
});
if (localPath && (0, node_fs.existsSync)((0, node_path.join)(localPath, "ui", "tsconfig.json"))) workspaceEntries.push({
key,
label: `${label}/ui`,
dir: localPath,
ui: true
});
}
const selected = require_build_train.selectWorkspaceTargets(input.packages, resolvedConfig);
const targets = input.packages === "all" ? workspaceEntries : workspaceEntries.filter((entry) => selected.includes(entry.key));
const skippedEntries = input.packages === "all" ? skipped : skipped.filter((entry) => selected.includes(entry.key));
const checked = [];
const results = [];
for (const entry of targets) {
if (entry.ui && !(0, node_fs.existsSync)((0, node_path.join)(entry.dir, "ui", "src", "routeTree.gen.ts"))) try {
await (0, every_plugin_ui_manifest_generator.generateUiManifest)({
workspaceRoot: (0, node_path.join)(entry.dir, "ui"),
pluginName: entry.key,
emitRouteTree: true
});
} catch (error) {
checked.push(entry.label);
results.push({
workspace: entry.label,
passed: false,
error: `routeTree materialization failed: ${error instanceof Error ? error.message : String(error)}`
});
continue;
}
const packageJsonPath = (0, node_path.join)(entry.dir, "package.json");
let args = entry.ui ? [
"exec",
"tsc",
"--noEmit",
"-p",
"ui/tsconfig.json"
] : [
"exec",
"tsc",
"--noEmit"
];
if ((0, node_fs.existsSync)(packageJsonPath)) try {
const pkg = JSON.parse((0, node_fs.readFileSync)(packageJsonPath, "utf-8"));
const scriptName = entry.ui ? "typecheck:ui" : "typecheck";
if (pkg.scripts?.[scriptName]) args = ["run", scriptName];
} catch {}
console.log(`\n ${require_theme.colors.dim("Checking")} ${require_theme.colors.cyan(entry.label)}`);
const child = (0, node_child_process.spawnSync)("pnpm", args, {
cwd: entry.dir,
stdio: "inherit"
});
const passed = child.status === 0;
checked.push(entry.label);
results.push({
workspace: entry.label,
passed,
error: passed ? void 0 : `typecheck failed (exit code ${child.status ?? "n/a"})`
});
}
return {
status: "success",
checked,
skipped: skippedEntries.map((entry) => entry.label),
results
};
},
catch: (error) => ({
status: "error",
checked: [],
skipped: [],
results: [],
error: error instanceof Error ? error.message : "Unknown error"
})
});
}),
mfCheck: builder.mfCheck.effect(function* (_opts, input) {
const platformManifest = yield* require_manifest.PlatformManifestService;
return yield* effect.Effect.promise(async () => {
let authored = null;
try {
authored = await require_load.readAuthoredConfigInput();
} catch (e) {
return {
status: "fail",
hostVersion: null,
hostReachable: false,
hostReason: e instanceof Error ? e.message : String(e),
remotes: []
};
}
if (!authored) {
const account = node_process.default.env.BOS_ACCOUNT;
const gateway = node_process.default.env.BOS_GATEWAY;
if (!account || !gateway) return {
status: "fail",
hostVersion: null,
hostReachable: false,
hostReason: require_load.MISSING_CONFIG_MESSAGE,
remotes: []
};
try {
authored = await require_published.resolvePublishedConfig(account, gateway);
} catch (e) {
return {
status: "fail",
hostVersion: null,
hostReachable: false,
hostReason: e instanceof Error ? e.message : String(e),
remotes: []
};
}
if (!authored) return {
status: "fail",
hostVersion: null,
hostReachable: false,
hostReason: `No config found at bos://${account}/${gateway} — verify BOS_ACCOUNT/BOS_GATEWAY and that the config has been published.`,
remotes: []
};
}
const report = await require_services_federation_service.checkFederationCompat(authored, { timeoutMs: input.timeoutMs });
const ui = await require_services_federation_service.checkUiCompositionCompat(authored, { timeoutMs: input.timeoutMs });
let platform;
try {
const configPath = require_load.findConfigPath();
if (configPath) {
const projectDir = (0, node_path.resolve)((0, node_path.dirname)(configPath));
const resolved = await platformManifest.resolvePlatformManifest({
configDir: projectDir,
localConfig: authored
});
if (resolved) {
const root = require_workspace.findWorkspaceRoot(projectDir)?.dir ?? projectDir;
const violations = platformManifest.checkPlatformCompat(resolved.manifest, {
platformVersion: require_framework_version.readInstalledFrameworkVersion(projectDir, "everything-dev"),
catalog: require_catalog.readWorkspaceCatalog(root)
});
platform = {
ok: violations.length === 0,
violations
};
}
}
} catch (e) {
platform = {
ok: false,
violations: [{
kind: "minChild",
message: `platform manifest resolution failed: ${e instanceof Error ? e.message : String(e)}`
}]
};
}
return {
status: report.ok && (platform?.ok ?? true) ? "ok" : "fail",
hostVersion: report.hostVersion,
hostReachable: report.hostReachable,
hostReason: report.hostReason,
remotes: report.remotes,
...ui.slots.length > 0 ? { ui: {
ok: ui.ok,
slots: ui.slots
} } : {},
...platform ? { platform } : {}
};
});
}),
platformManifest: builder.platformManifest.effect(function* (_opts, input) {
const platformManifest = yield* require_manifest.PlatformManifestService;
return yield* effect.Effect.promise(async () => {
const inImage = platformManifest.readInImagePlatformManifest();
if (inImage) return {
status: "ok",
version: inImage.frameworkVersion,
source: "in-image",
...input.check ? { compat: {
ok: true,
violations: []
} } : {}
};
const configPath = require_load.findConfigPath();
if (!configPath) return {
status: "absent",
version: null,
error: `${require_load.MISSING_CONFIG_MESSAGE} — and the in-image platform manifest is absent (non-framework image)`
};
const projectDir = (0, node_path.resolve)((0, node_path.dirname)(configPath));
try {
const authoredConfig = await require_load.readAuthoredConfigInput() ?? {};
let resolved;
let drift;
try {
resolved = await platformManifest.resolvePlatformManifest({
configDir: projectDir,
localConfig: authoredConfig
});
} catch (pinError) {
const latest = await platformManifest.resolvePlatformManifest({
configDir: projectDir,
localConfig: {
...authoredConfig,
platform: void 0
}
});
if (!latest) throw pinError;
resolved = latest;
const pinned = typeof authoredConfig.platform === "string" ? authoredConfig.platform : void 0;
drift = pinned ? {
pinned,
published: latest.manifest.frameworkVersion
} : void 0;
}
if (!resolved) return {
status: "absent",
version: null
};
if (drift) return {
status: "fail",
version: drift.published,
source: `bos://${resolved.source.account}/${resolved.source.gateway}`,
drift,
error: `parent platform is ${drift.published} (published at bos://${resolved.source.account}/${resolved.source.gateway}), you pinned ${drift.pinned} — run \`bos upgrade\` to realign`
};
const base = {
status: "ok",
version: resolved.manifest.frameworkVersion,
source: `bos://${resolved.source.account}/${resolved.source.gateway}`,
fromCache: resolved.fromCache
};
if (!input.check) return base;
const root = require_workspace.findWorkspaceRoot(projectDir)?.dir ?? projectDir;
const violations = platformManifest.checkPlatformCompat(resolved.manifest, {
platformVersion: require_framework_version.readInstalledFrameworkVersion(projectDir, "everything-dev"),
catalog: require_catalog.readWorkspaceCatalog(root)
});
return {
...base,
compat: {
ok: violations.length === 0,
violations
}
};
} catch (e) {
return {
status: "fail",
version: null,
error: e instanceof Error ? e.message : String(e)
};
}
});
})
};
}
//#endregion
exports.registerUpgrade = registerUpgrade;
//# sourceMappingURL=upgrade.cjs.map