@lunora/cli
Version:
The Lunora CLI: init, dev, deploy, codegen, run, reset, and migrate commands
117 lines (114 loc) • 3.94 kB
JavaScript
import { mkdtempSync, rmSync, existsSync, readdirSync, statSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, relative } from 'node:path';
import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-v4hHpQd0.mjs';
import { defaultSpawner } from '../packem_shared/createRecordingSpawner-WuSn20kb.mjs';
const walk = (root) => {
const entries = [];
const recurse = (directory) => {
for (const name of readdirSync(directory)) {
const full = join(directory, name);
const info = statSync(full);
if (info.isDirectory()) {
recurse(full);
} else if (info.isFile()) {
entries.push({ path: relative(root, full), sizeBytes: info.size });
}
}
};
recurse(root);
return entries;
};
const formatBytes = (bytes) => {
if (bytes < 1024) {
return `${String(bytes)} B`;
}
if (bytes < 1024 * 1024) {
return `${(bytes / 1024).toFixed(1)} KiB`;
}
return `${(bytes / (1024 * 1024)).toFixed(2)} MiB`;
};
const buildReport = (outdir) => {
const all = walk(outdir);
const sorted = all.toSorted((a, b) => b.sizeBytes - a.sizeBytes);
const totalBytes = all.reduce((sum, entry) => sum + entry.sizeBytes, 0);
const generatedFiles = all.filter((entry) => entry.path.includes("_generated"));
return {
generatedFiles,
outdir,
topModules: sorted.slice(0, 10),
totalBytes,
totalFiles: all.length
};
};
const renderText = (report, logger) => {
logger.info(`outdir: ${report.outdir}`);
logger.info(`total: ${String(report.totalFiles)} files, ${formatBytes(report.totalBytes)}`);
if (report.topModules.length > 0) {
logger.info("");
logger.info("top modules by size:");
for (const entry of report.topModules) {
logger.info(` ${formatBytes(entry.sizeBytes).padStart(10, " ")} ${entry.path}`);
}
}
if (report.generatedFiles.length > 0) {
logger.info("");
logger.info(`_generated/ files: ${String(report.generatedFiles.length)}`);
for (const entry of report.generatedFiles) {
logger.info(` ${formatBytes(entry.sizeBytes).padStart(10, " ")} ${entry.path}`);
}
}
};
const runAnalyzeCommand = async (options) => {
const cwd = options.cwd ?? process.cwd();
const { logger } = options;
let outdir;
let descriptor;
let temporary = false;
if (options.inspectOnly) {
outdir = options.inspectOnly;
} else {
outdir = mkdtempSync(join(tmpdir(), "lunora-analyze-"));
temporary = true;
const exec = execArgsFor(detectPackageManager(cwd), "wrangler", ["deploy", "--dry-run", "--outdir", outdir]);
descriptor = {
args: exec.args,
command: exec.command,
cwd
};
logger.info(`analyze: building via ${descriptor.command} ${descriptor.args.join(" ")}`);
const spawner = options.spawner ?? defaultSpawner;
const spawned = await spawner(descriptor);
if (spawned.code !== 0) {
logger.error(`analyze: wrangler dry-run failed (exit ${String(spawned.code)})`);
rmSync(outdir, { force: true, recursive: true });
return { code: spawned.code, descriptor, report: void 0 };
}
}
try {
if (!existsSync(outdir)) {
logger.error(`analyze: outdir not found at ${outdir}`);
return { code: 1, descriptor, report: void 0 };
}
const report = buildReport(outdir);
if (options.json) {
process.stdout.write(`${JSON.stringify(report, void 0, 2)}
`);
} else {
renderText(report, logger);
}
return { code: 0, descriptor, report };
} finally {
if (temporary && existsSync(outdir)) {
try {
rmSync(outdir, { force: true, recursive: true });
} catch {
}
}
}
};
const execute = defineHandler(
({ cwd, logger, options }) => runAnalyzeCommand({ cwd, json: options.json === true, logger })
);
export { execute, runAnalyzeCommand };