UNPKG

everything-dev

Version:

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

199 lines (197 loc) • 7.76 kB
const require_runtime = require('../_virtual/_rolldown/runtime.cjs'); const require_fastkv = require('../fastkv.cjs'); const require_config = require('../config.cjs'); const require_resolution_session = require('../resolution/session.cjs'); const require_fingerprint = require('../fingerprint.cjs'); const require_version_status = require('../version-status.cjs'); const require_shared = require('./shared.cjs'); const require_process_registry = require('../process-registry.cjs'); const require_app = require('../app.cjs'); const require_infra = require('../cli/infra.cjs'); const require_port_ownership = require('../infra/port-ownership.cjs'); const require_status = require('../cli/status.cjs'); const require_dev_logs = require('../dev-logs.cjs'); const require_process_kill = require('../process-kill.cjs'); let node_path = require("node:path"); let effect = require("effect"); let node_process = require("node:process"); node_process = require_runtime.__toESM(node_process, 1); //#region src/commands/ops.ts function registerOps(builder) { return { status: builder.status.handler(async ({ context }) => { try { const deps = effect.Context.get(context["effect/context"], require_shared.BosDepsTag); const configPath = require_config.findConfigPath(); if (!configPath) return { status: "error", packages: [], envFile: "missing", error: `${require_config.MISSING_CONFIG_MESSAGE} in current directory` }; const projectDir = (0, node_path.resolve)((0, node_path.dirname)(configPath)); return { ...await require_status.getStatus(projectDir), deployedVersion: await deployedVersionStatus(deps) }; } catch (error) { return { status: "error", packages: [], envFile: "missing", error: error instanceof Error ? error.message : "Unknown error" }; } }), logs: builder.logs.handler(async ({ input, context }) => { try { const configDir = effect.Context.get(context["effect/context"], require_shared.BosDepsTag).session?.root ?? node_process.default.cwd(); const text = await require_dev_logs.readDevLatestLog(configDir, { tail: input.tail }); const service = input.service; const lines = text.split("\n").filter((line) => line.length > 0).filter((line) => { if (!service) return true; const match = /\] \[([^\]]+)\] \[(?:OUT|ERR)\] /.exec(line); return match?.[1] === service || match?.[1] === `plugin:${service}`; }); return { logFile: require_dev_logs.resolveDevLatestFile(configDir), lines }; } catch (error) { return { logFile: "unknown", lines: [error instanceof Error ? `Failed to read logs: ${error.message}` : "Failed to read logs"] }; } }), ps: builder.ps.handler(async () => { try { return { status: "ok", entries: await effect.Effect.runPromise(require_process_registry.pruneDeadEffect(require_process_registry.readRegistry())) }; } catch (error) { return { status: "error", entries: [], error: error instanceof Error ? error.message : "Unknown error" }; } }), kill: builder.kill.handler(async ({ input }) => { try { const configPath = require_config.findConfigPath(); const targetConfigDir = input.all ? void 0 : input.configDir ?? (configPath ? (0, node_path.resolve)((0, node_path.dirname)(configPath)) : void 0); const targets = targetConfigDir ? require_process_registry.readRegistry().filter((entry) => entry.configDir === targetConfigDir) : require_process_registry.readRegistry(); const killed = []; const skipped = []; for (const entry of targets) { const wasAlive = require_process_registry.isPidAlive(entry.pid); if (wasAlive) await effect.Effect.runPromise(require_process_kill.killProcessGroupEscalating(entry.pid, { terminateMs: 5e3, signal: input.signal === "SIGKILL" ? "SIGKILL" : "SIGTERM" })); const reapedChildren = []; for (const childPid of entry.childPids ?? []) if (require_process_registry.isPidAlive(childPid)) { require_process_kill.reapGroup(childPid); reapedChildren.push(childPid); } const ports = Object.values(entry.ports ?? {}).filter((port) => Number.isFinite(port) && port > 0); const stillBound = []; for (const port of ports) { let bindable = false; for (let attempt = 0; attempt < 4; attempt++) { bindable = await effect.Effect.runPromise(require_app.probePortBindable(port)); if (bindable) break; await new Promise((resolve) => setTimeout(resolve, 500)); } if (!bindable) stillBound.push(port); } if (stillBound.length > 0) { const owner = await effect.Effect.runPromise(require_port_ownership.ownerOfPort(stillBound[0])); skipped.push({ pid: entry.pid, reason: `ports still bound after kill: ${stillBound.join(", ")}${owner ? ` — held by pid ${owner.pid} (${owner.command})` : " — owner unknown"}` }); continue; } require_process_registry.unregisterPid(entry.pid); killed.push({ pid: entry.pid, configDir: entry.configDir }); if (!wasAlive && reapedChildren.length > 0) skipped.push({ pid: entry.pid, reason: `process already exited; reaped orphaned children ${reapedChildren.join(", ")}` }); } return { status: "killed", killed, skipped }; } catch (error) { return { status: "error", killed: [], skipped: [], error: error instanceof Error ? error.message : "Unknown error" }; } }), infraExport: builder.infraExport.handler(async ({ input, context }) => { const deps = effect.Context.get(context["effect/context"], require_shared.BosDepsTag); const configDir = input.configDir ?? deps.session?.root ?? node_process.default.cwd(); const ci = deps.session?.runtime ? require_infra.buildCiInfraPlan(deps.session.runtime) : null; if (!ci) { const refreshed = await require_resolution_session.openResolution({ cwd: configDir }); if (!refreshed?.runtime) throw new Error("No resolved runtime config available for infra export"); return require_infra.buildCiInfraPlan(refreshed.runtime); } return { ...ci, account: deps.session?.config?.account ?? ci.account, gateway: ci.gateway ?? deps.session?.config?.domain ?? deps.session?.config?.account ?? ci.account }; }) }; } async function deployedVersionStatus(deps) { const config = deps.session?.config; if (!config?.account || !config.domain) return void 0; const { account, domain } = config; let publishedFingerprint; try { const published = await require_fastkv.fetchBosConfigFromFastKv(`bos://${account}/${domain}`); publishedFingerprint = require_fingerprint.pointerFingerprint(published); } catch { return; } const hostUrl = deps.session?.runtime?.host?.url; if (!hostUrl) return require_version_status.computeDeployedVersionStatus({ publishedFingerprint, servedFingerprint: null }); try { const response = await fetch(new URL("/.well-known/version", hostUrl)); if (!response.ok) return require_version_status.computeDeployedVersionStatus({ publishedFingerprint, servedFingerprint: null, servedError: `version endpoint returned ${response.status}` }); const body = await response.json(); return require_version_status.computeDeployedVersionStatus({ publishedFingerprint, servedFingerprint: body.fingerprint ?? null }); } catch (error) { return require_version_status.computeDeployedVersionStatus({ publishedFingerprint, servedFingerprint: null, servedError: error instanceof Error ? error.message : String(error) }); } } //#endregion exports.registerOps = registerOps; //# sourceMappingURL=ops.cjs.map