everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
255 lines (253 loc) • 12.9 kB
JavaScript
const require_load = require('../../services/resolution/load.cjs');
const require_theme = require('../../utils/theme.cjs');
const require_status = require('../../services/status.cjs');
const require_exit_codes = require('../exit-codes.cjs');
const require_config = require('../render/config.cjs');
const require_logs = require('../render/logs.cjs');
const require_processes = require('../render/processes.cjs');
let node_fs = require("node:fs");
let node_path = require("node:path");
let node_fs_promises = require("node:fs/promises");
//#region src/cli/commands/inspect.ts
const inspectRenderers = {
config: async (result, _ctx) => {
if (!result.config) {
console.error(require_load.MISSING_CONFIG_MESSAGE);
process.exit(1);
}
require_config.printConfigView(result.config);
process.stdout.write(`${JSON.stringify(result.config, null, 2)}\n`);
},
status: async (result, _ctx) => {
console.log();
if (require_exit_codes.exitCodeFor(result) === 1) {
console.error(`[CLI] ${result.error || "Unknown error"}`);
process.exit(1);
}
console.log(require_theme.colors.cyan(require_theme.frames.top(52)));
console.log(` ${require_theme.icons.app} ${require_theme.gradients.cyber("STATUS")}`);
console.log(require_theme.colors.cyan(require_theme.frames.bottom(52)));
console.log();
if (result.extends) console.log(` ${require_theme.colors.dim("Extends:")} ${result.extends}`);
if (result.account) console.log(` ${require_theme.colors.dim("Account:")} ${result.account}`);
if (result.domain) console.log(` ${require_theme.colors.dim("Domain:")} ${result.domain}`);
console.log();
console.log(` ${require_theme.colors.dim("Packages:")}`);
for (const pkg of result.packages) {
const hasUpdate = pkg.installed && pkg.latest && require_status.compareSemver(pkg.installed, pkg.latest) < 0;
const versionStr = hasUpdate ? `${pkg.installed} → ${pkg.latest}` : pkg.installed || "not installed";
const label = hasUpdate ? require_theme.colors.yellow(versionStr) : require_theme.colors.dim(versionStr);
console.log(` ${require_theme.colors.dim(`${pkg.name}`)} ${label}`);
}
console.log();
if (result.lastSync) {
const ago = require_logs.formatTimeAgo(result.lastSync);
console.log(` ${require_theme.colors.dim("Last sync:")} ${ago}`);
} else console.log(` ${require_theme.colors.dim("Last sync:")} never`);
const envLabel = result.envFile === "found" ? require_theme.colors.green("found") : result.envFile === "example-only" ? require_theme.colors.yellow("missing (only .env.example found)") : require_theme.colors.error("missing");
console.log(` ${require_theme.colors.dim(".env:")} ${envLabel}`);
if (result.parentReachable !== void 0) {
const parentLabel = result.parentReachable ? require_theme.colors.green("reachable") : require_theme.colors.error("unreachable");
console.log(` ${require_theme.colors.dim("Parent:")} ${parentLabel}`);
}
if (result.packages.some((p) => p.installed && p.latest && require_status.compareSemver(p.installed, p.latest) < 0)) {
console.log();
console.log(require_theme.colors.dim(` Run ${require_theme.colors.cyan("bos upgrade")} to update packages and sync template files.`));
}
console.log();
},
ps: async (result, _ctx) => {
require_processes.renderPs(result);
},
logs: async (result, ctx) => {
const input = ctx.input;
const logsResult = result;
const opts = input;
for (const line of logsResult.lines) console.log(line);
if (logsResult.lines.length === 0) console.log(require_theme.colors.dim(` No matching log lines in ${logsResult.logFile}.`));
if (opts.follow) {
if (logsResult.logFile === "unknown" || !(0, node_fs.existsSync)(logsResult.logFile)) console.log(require_theme.colors.dim(" No log file to follow — nothing was found on disk."));
else {
const filter = opts.service;
let byteOffset = 0;
for (const line of logsResult.lines) byteOffset += Buffer.byteLength(line, "utf8") + 1;
const followMatch = (line) => {
if (!filter) return true;
const source = /\] \[([^\]]+)\] \[(?:OUT|ERR)\] /.exec(line)?.[1];
return source === filter || source === `plugin:${filter}`;
};
const watcher = (0, node_fs.watch)(logsResult.logFile, (event) => {
if (event !== "change") return;
(0, node_fs_promises.readFile)(logsResult.logFile, "utf8").then((text) => {
const newLines = text.slice(byteOffset).split("\n").filter((line) => line.length > 0 && followMatch(line));
byteOffset = Buffer.byteLength(text, "utf8");
for (const line of newLines) console.log(line);
}).catch(() => {
watcher.close();
});
});
console.log(require_theme.colors.dim(" Following — Ctrl+C to stop."));
process.on("SIGINT", () => {
watcher.close();
process.exit(0);
});
}
}
},
kill: async (result, ctx) => {
const input = ctx.input;
const killResult = result;
console.log();
if (killResult.status === "error") {
console.error(`[CLI] ${killResult.error || "Unknown error"}`);
process.exit(1);
}
if (killResult.killed.length > 0) {
console.log(require_theme.colors.green(`${require_theme.icons.ok} Sent ${killResult.killed.length} kill signal(s)`));
for (const k of killResult.killed) console.log(` ${require_theme.colors.dim("pid")} ${k.pid} ${require_theme.colors.dim(k.configDir)}`);
}
if (killResult.skipped.length > 0) {
console.log(require_theme.colors.yellow(`${require_theme.icons.err} ${killResult.skipped.length} skipped`));
for (const s of killResult.skipped) console.log(` ${require_theme.colors.dim("pid")} ${s.pid} ${require_theme.colors.dim(s.reason)}`);
}
if (killResult.killed.length === 0 && killResult.skipped.length === 0) {
const opts = input;
if (opts.all) console.log(require_theme.colors.dim(" No tracked processes to kill."));
else {
const configPath = require_load.findConfigPath();
const dir = opts.configDir ?? (configPath ? (0, node_path.resolve)((0, node_path.dirname)(configPath)) : process.cwd());
console.log(require_theme.colors.dim(` No tracked processes for ${dir}`));
console.log(require_theme.colors.dim(` Use ${require_theme.colors.cyan("--all")} to kill across all directories.`));
}
}
console.log();
},
typesGen: async (result, _ctx) => {
console.log();
if (require_exit_codes.exitCodeFor(result) === 1) {
console.error(`[CLI] ${result.error || "Unknown error"}`);
process.exit(1);
}
console.log(require_theme.colors.green(`${require_theme.icons.ok} Types generated`));
if (result.generated.length > 0) {
console.log(` ${require_theme.colors.dim("Written:")}`);
for (const f of result.generated) console.log(` ${require_theme.colors.dim(f)}`);
}
if (result.fetched.length > 0 || result.skipped.length > 0 || result.failed.length > 0) {
console.log(` ${require_theme.colors.dim("Contract sources:")}`);
for (const entry of result.fetched) {
const space = entry.indexOf(" ");
const key = space !== -1 ? entry.slice(0, space) : entry;
const rest = space !== -1 ? entry.slice(space + 1) : "";
const restSpace = rest.indexOf(" ");
const detail = restSpace !== -1 ? rest.slice(restSpace + 1) : "";
console.log(` ${key} ${require_theme.colors.cyan("remote")}${detail ? ` ${require_theme.colors.dim(detail)}` : ""}`);
}
for (const entry of result.skipped) {
const space = entry.indexOf(" ");
const key = space !== -1 ? entry.slice(0, space) : entry;
const rest = space !== -1 ? entry.slice(space + 1) : "";
if (rest === "no URL resolved") {
console.log(` ${key} ${require_theme.colors.dim("no URL resolved")}`);
continue;
}
const restSpace = rest.indexOf(" ");
const detail = restSpace !== -1 ? rest.slice(restSpace + 1) : "";
console.log(` ${key} ${require_theme.colors.dim("local")}${detail ? ` ${require_theme.colors.dim(detail)}` : ""}`);
}
}
if (result.failed.length > 0) {
console.log(` ${require_theme.colors.yellow("Failed:")}`);
for (const f of result.failed) {
const colon = f.indexOf(": ");
if (colon !== -1) console.log(` ${require_theme.colors.error(f.slice(0, colon))}${require_theme.colors.dim(f.slice(colon))}`);
else console.log(` ${require_theme.colors.error(f)}`);
}
}
console.log();
},
typecheck: async (result, _ctx) => {
console.log();
if (require_exit_codes.exitCodeFor(result) === 1) {
console.error(`[CLI] ${result.error || "Unknown error"}`);
process.exit(1);
}
const failed = result.results.filter((r) => !r.passed);
const passed = result.results.filter((r) => r.passed);
console.log(require_theme.colors.cyan(require_theme.frames.top(52)));
console.log(` ${require_theme.icons.app} ${require_theme.gradients.cyber("TYPECHECK")}`);
console.log(require_theme.colors.cyan(require_theme.frames.bottom(52)));
console.log();
for (const r of result.results) {
const icon = r.passed ? require_theme.colors.green("✓") : require_theme.colors.error("✗");
console.log(` ${icon} ${r.workspace}`);
}
if (result.skipped.length > 0) console.log(` ${require_theme.colors.dim(`Skipped: ${result.skipped.join(", ")}`)}`);
console.log();
if (failed.length > 0) {
console.log(` ${require_theme.colors.error(`${failed.length} failed`)}`);
for (const f of failed) if (f.error) console.log(` ${require_theme.colors.dim(f.error)}`);
console.log();
process.exit(1);
}
console.log(` ${require_theme.colors.green(`${passed.length} passed`)}`);
console.log();
},
mfCheck: async (result, _ctx) => {
console.log();
console.log(` ${require_theme.colors.dim("Host")} ${result.hostReachable ? require_theme.colors.green("OK ") : require_theme.colors.error("FAIL")} ${result.hostVersion ?? "unreachable"}${result.hostReason ? ` (${result.hostReason})` : ""}`);
for (const r of result.remotes) {
const tag = r.ok ? require_theme.colors.green("OK ") : require_theme.colors.error("FAIL");
console.log(` ${require_theme.colors.dim(r.role.padEnd(10))} ${tag} ${r.url} pluginVersion=${r.pluginVersion ?? "?"}${r.reason ? ` ↳ ${r.reason}` : ""}`);
}
if (result.ui) for (const slot of result.ui.slots) {
const tag = slot.ok ? require_theme.colors.green("OK ") : require_theme.colors.error("FAIL");
console.log(` ${require_theme.colors.dim(`ui:${slot.slot}`.padEnd(10))} ${tag} ${slot.url}${slot.reason ? ` ↳ ${slot.reason}` : ""}`);
}
if (result.platform) {
for (const v of result.platform.violations) console.log(` ${require_theme.colors.dim("platform".padEnd(10))} ${require_theme.colors.error("FAIL")} ${v.message}`);
if (result.platform.ok) console.log(` ${require_theme.colors.dim("platform".padEnd(10))} ${require_theme.colors.green("OK ")} release contract satisfied`);
}
console.log();
if (result.status !== "ok") {
console.log(require_theme.colors.error(" mf-compat: ✗ federation manifests NOT compatible — redeploy affected plugin(s) so pluginVersion and shared versions match host"));
console.log();
process.exit(1);
}
console.log(require_theme.colors.green(" mf-compat: ✓ all federation manifests compatible"));
console.log();
},
platformManifest: async (result, _ctx) => {
console.log();
if (result.status === "fail") {
console.error(`[CLI] ${result.error || "platform manifest resolution failed"}`);
if (result.drift) {
console.log();
console.log(require_theme.colors.error(` parent platform is ${result.drift.published} (published), you pinned ${result.drift.pinned} — run \`bos upgrade\` to realign`));
}
console.log();
process.exit(1);
}
if (result.status === "absent") {
console.log(require_theme.colors.yellow(` ${require_theme.icons.err} No platform release manifest resolves${result.error ? ` — ${result.error}` : ""}.`));
console.log(require_theme.colors.dim(" Children fall back to the parent-repo tarball walk (ADR 0034 pt 7)."));
console.log();
return;
}
console.log(` ${require_theme.colors.dim("Platform")} ${require_theme.colors.green(result.version ?? "?")} ${require_theme.colors.dim(`(${result.source}${result.fromCache ? ", cached" : ""})`)}`);
if (result.compat) {
for (const v of result.compat.violations) console.log(` ${require_theme.colors.error("FAIL")} ${v.message}`);
console.log();
if (!result.compat.ok) {
console.log(require_theme.colors.error(" platform-compat: ✗ the workspace does not satisfy this release's compat contract — bump the framework or clear the pin"));
console.log();
process.exit(1);
}
console.log(require_theme.colors.green(" platform-compat: ✓ workspace satisfies the release contract"));
}
console.log();
}
};
//#endregion
exports.inspectRenderers = inspectRenderers;
//# sourceMappingURL=inspect.cjs.map