idioma-cli
Version:
CLI for Idioma - Internationalization engine with smart defaults
97 lines (94 loc) • 11.7 kB
JavaScript
// src/cli/background.ts
import { spawn as nodeSpawn } from "node:child_process";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
var __dirname = "/Users/ryanwaits/Code/projects/idioma/packages/cli/src/cli";
var STATUS_DIR = path.join(os.tmpdir(), "idioma-translations");
var STATUS_FILE = path.join(STATUS_DIR, "status.json");
var PID_FILE = path.join(STATUS_DIR, "process.pid");
async function startBackgroundTranslation(args) {
await fs.mkdir(STATUS_DIR, { recursive: true });
const isRunning = await isTranslationRunning();
if (isRunning) {
console.log("❌ A translation is already running in the background.");
console.log('Run "idioma status" to check progress or "idioma stop" to cancel it.');
return;
}
const isBun = typeof Bun !== "undefined";
const runtime = isBun ? "bun" : "node";
const scriptPath = path.join(__dirname, "worker.js");
const proc = nodeSpawn(runtime, [scriptPath, ...args], {
cwd: process.cwd(),
env: process.env,
detached: true,
stdio: "ignore"
});
proc.unref();
await fs.writeFile(PID_FILE, proc.pid.toString());
const initialStatus = {
status: "running",
startTime: new Date().toISOString(),
totalFiles: 0,
processedFiles: 0,
errors: [],
pid: proc.pid
};
await fs.writeFile(STATUS_FILE, JSON.stringify(initialStatus, null, 2));
console.log(`✅ Translation started in background (PID: ${proc.pid})`);
console.log('Run "idioma status" to check progress.');
}
async function getTranslationStatus() {
try {
const statusData = await fs.readFile(STATUS_FILE, "utf-8");
return JSON.parse(statusData);
} catch {
return null;
}
}
async function stopBackgroundTranslation() {
try {
const pidData = await fs.readFile(PID_FILE, "utf-8");
const pid = parseInt(pidData, 10);
process.kill(pid, "SIGTERM");
await fs.unlink(PID_FILE).catch(() => {});
await fs.unlink(STATUS_FILE).catch(() => {});
console.log("✅ Background translation stopped.");
return true;
} catch (_error) {
console.log("❌ No background translation running.");
return false;
}
}
async function isTranslationRunning() {
try {
const pidData = await fs.readFile(PID_FILE, "utf-8");
const pid = parseInt(pidData, 10);
try {
process.kill(pid, 0);
return true;
} catch {
await fs.unlink(PID_FILE).catch(() => {});
return false;
}
} catch {
return false;
}
}
async function updateStatus(updates) {
const current = await getTranslationStatus() || {
status: "running",
startTime: new Date().toISOString(),
totalFiles: 0,
processedFiles: 0,
errors: []
};
const updated = { ...current, ...updates };
if (updates.errors && Array.isArray(updates.errors)) {
updated.errors = [...current.errors || [], ...updates.errors];
}
await fs.writeFile(STATUS_FILE, JSON.stringify(updated, null, 2));
}
export { startBackgroundTranslation, getTranslationStatus, stopBackgroundTranslation, updateStatus };
//# debugId=E20AC452E3FF854464756E2164756E21
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NsaS9iYWNrZ3JvdW5kLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWwogICAgImltcG9ydCB7IHNwYXduIGFzIG5vZGVTcGF3biB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgZnMgZnJvbSAnbm9kZTpmcy9wcm9taXNlcyc7XG5pbXBvcnQgb3MgZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xuXG5jb25zdCBTVEFUVVNfRElSID0gcGF0aC5qb2luKG9zLnRtcGRpcigpLCAnaWRpb21hLXRyYW5zbGF0aW9ucycpO1xuY29uc3QgU1RBVFVTX0ZJTEUgPSBwYXRoLmpvaW4oU1RBVFVTX0RJUiwgJ3N0YXR1cy5qc29uJyk7XG5jb25zdCBQSURfRklMRSA9IHBhdGguam9pbihTVEFUVVNfRElSLCAncHJvY2Vzcy5waWQnKTtcblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2xhdGlvblN0YXR1cyB7XG4gIHN0YXR1czogJ3J1bm5pbmcnIHwgJ2NvbXBsZXRlZCcgfCAnZmFpbGVkJztcbiAgc3RhcnRUaW1lOiBzdHJpbmc7XG4gIGVuZFRpbWU/OiBzdHJpbmc7XG4gIHRvdGFsRmlsZXM6IG51bWJlcjtcbiAgcHJvY2Vzc2VkRmlsZXM6IG51bWJlcjtcbiAgY3VycmVudEZpbGU/OiBzdHJpbmc7XG4gIGVycm9yczogc3RyaW5nW107XG4gIHBpZD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0QmFja2dyb3VuZFRyYW5zbGF0aW9uKGFyZ3M6IHN0cmluZ1tdKTogUHJvbWlzZTx2b2lkPiB7XG4gIC8vIEVuc3VyZSBzdGF0dXMgZGlyZWN0b3J5IGV4aXN0c1xuICBhd2FpdCBmcy5ta2RpcihTVEFUVVNfRElSLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAvLyBDaGVjayBpZiB0cmFuc2xhdGlvbiBpcyBhbHJlYWR5IHJ1bm5pbmdcbiAgY29uc3QgaXNSdW5uaW5nID0gYXdhaXQgaXNUcmFuc2xhdGlvblJ1bm5pbmcoKTtcbiAgaWYgKGlzUnVubmluZykge1xuICAgIGNvbnNvbGUubG9nKCfinYwgQSB0cmFuc2xhdGlvbiBpcyBhbHJlYWR5IHJ1bm5pbmcgaW4gdGhlIGJhY2tncm91bmQuJyk7XG4gICAgY29uc29sZS5sb2coJ1J1biBcImlkaW9tYSBzdGF0dXNcIiB0byBjaGVjayBwcm9ncmVzcyBvciBcImlkaW9tYSBzdG9wXCIgdG8gY2FuY2VsIGl0LicpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFByZXBhcmUgdGhlIGNvbW1hbmQgLSBkZXRlY3QgcnVudGltZVxuICBjb25zdCBpc0J1biA9IHR5cGVvZiBCdW4gIT09ICd1bmRlZmluZWQnO1xuICBjb25zdCBydW50aW1lID0gaXNCdW4gPyAnYnVuJyA6ICdub2RlJztcbiAgY29uc3Qgc2NyaXB0UGF0aCA9IHBhdGguam9pbihfX2Rpcm5hbWUsICd3b3JrZXIuanMnKTsgLy8gVXNlIC5qcyBmb3IgY29tcGF0aWJpbGl0eVxuXG4gIC8vIFNwYXduIHRoZSBiYWNrZ3JvdW5kIHByb2Nlc3MgdXNpbmcgTm9kZSdzIGNoaWxkX3Byb2Nlc3NcbiAgY29uc3QgcHJvYyA9IG5vZGVTcGF3bihydW50aW1lLCBbc2NyaXB0UGF0aCwgLi4uYXJnc10sIHtcbiAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgZW52OiBwcm9jZXNzLmVudixcbiAgICBkZXRhY2hlZDogdHJ1ZSxcbiAgICBzdGRpbzogJ2lnbm9yZScsXG4gIH0pO1xuXG4gIC8vIERldGFjaCB0aGUgcHJvY2VzcyBzbyBpdCBydW5zIGluZGVwZW5kZW50bHlcbiAgcHJvYy51bnJlZigpO1xuXG4gIC8vIFNhdmUgdGhlIFBJRFxuICBhd2FpdCBmcy53cml0ZUZpbGUoUElEX0ZJTEUsIHByb2MucGlkLnRvU3RyaW5nKCkpO1xuXG4gIC8vIEluaXRpYWxpemUgc3RhdHVzIGZpbGVcbiAgY29uc3QgaW5pdGlhbFN0YXR1czogVHJhbnNsYXRpb25TdGF0dXMgPSB7XG4gICAgc3RhdHVzOiAncnVubmluZycsXG4gICAgc3RhcnRUaW1lOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgdG90YWxGaWxlczogMCxcbiAgICBwcm9jZXNzZWRGaWxlczogMCxcbiAgICBlcnJvcnM6IFtdLFxuICAgIHBpZDogcHJvYy5waWQsXG4gIH07XG4gIGF3YWl0IGZzLndyaXRlRmlsZShTVEFUVVNfRklMRSwgSlNPTi5zdHJpbmdpZnkoaW5pdGlhbFN0YXR1cywgbnVsbCwgMikpO1xuXG4gIGNvbnNvbGUubG9nKGDinIUgVHJhbnNsYXRpb24gc3RhcnRlZCBpbiBiYWNrZ3JvdW5kIChQSUQ6ICR7cHJvYy5waWR9KWApO1xuICBjb25zb2xlLmxvZygnUnVuIFwiaWRpb21hIHN0YXR1c1wiIHRvIGNoZWNrIHByb2dyZXNzLicpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0VHJhbnNsYXRpb25TdGF0dXMoKTogUHJvbWlzZTxUcmFuc2xhdGlvblN0YXR1cyB8IG51bGw+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBzdGF0dXNEYXRhID0gYXdhaXQgZnMucmVhZEZpbGUoU1RBVFVTX0ZJTEUsICd1dGYtOCcpO1xuICAgIHJldHVybiBKU09OLnBhcnNlKHN0YXR1c0RhdGEpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RvcEJhY2tncm91bmRUcmFuc2xhdGlvbigpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwaWREYXRhID0gYXdhaXQgZnMucmVhZEZpbGUoUElEX0ZJTEUsICd1dGYtOCcpO1xuICAgIGNvbnN0IHBpZCA9IHBhcnNlSW50KHBpZERhdGEsIDEwKTtcblxuICAgIC8vIEtpbGwgdGhlIHByb2Nlc3NcbiAgICBwcm9jZXNzLmtpbGwocGlkLCAnU0lHVEVSTScpO1xuXG4gICAgLy8gQ2xlYW4gdXAgZmlsZXNcbiAgICBhd2FpdCBmcy51bmxpbmsoUElEX0ZJTEUpLmNhdGNoKCgpID0+IHt9KTtcbiAgICBhd2FpdCBmcy51bmxpbmsoU1RBVFVTX0ZJTEUpLmNhdGNoKCgpID0+IHt9KTtcblxuICAgIGNvbnNvbGUubG9nKCfinIUgQmFja2dyb3VuZCB0cmFuc2xhdGlvbiBzdG9wcGVkLicpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChfZXJyb3IpIHtcbiAgICBjb25zb2xlLmxvZygn4p2MIE5vIGJhY2tncm91bmQgdHJhbnNsYXRpb24gcnVubmluZy4nKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGlzVHJhbnNsYXRpb25SdW5uaW5nKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICB0cnkge1xuICAgIGNvbnN0IHBpZERhdGEgPSBhd2FpdCBmcy5yZWFkRmlsZShQSURfRklMRSwgJ3V0Zi04Jyk7XG4gICAgY29uc3QgcGlkID0gcGFyc2VJbnQocGlkRGF0YSwgMTApO1xuXG4gICAgLy8gQ2hlY2sgaWYgcHJvY2VzcyBpcyBzdGlsbCBydW5uaW5nXG4gICAgdHJ5IHtcbiAgICAgIHByb2Nlc3Mua2lsbChwaWQsIDApOyAvLyBTaWduYWwgMCBjaGVja3MgaWYgcHJvY2VzcyBleGlzdHNcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gUHJvY2VzcyBkb2Vzbid0IGV4aXN0LCBjbGVhbiB1cCBzdGFsZSBmaWxlc1xuICAgICAgYXdhaXQgZnMudW5saW5rKFBJRF9GSUxFKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVN0YXR1cyh1cGRhdGVzOiBQYXJ0aWFsPFRyYW5zbGF0aW9uU3RhdHVzPik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjdXJyZW50ID0gKGF3YWl0IGdldFRyYW5zbGF0aW9uU3RhdHVzKCkpIHx8IHtcbiAgICBzdGF0dXM6ICdydW5uaW5nJyxcbiAgICBzdGFydFRpbWU6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICB0b3RhbEZpbGVzOiAwLFxuICAgIHByb2Nlc3NlZEZpbGVzOiAwLFxuICAgIGVycm9yczogW10sXG4gIH07XG5cbiAgY29uc3QgdXBkYXRlZCA9IHsgLi4uY3VycmVudCwgLi4udXBkYXRlcyB9O1xuXG4gIC8vIEhhbmRsZSBlcnJvcnMgYXJyYXkgc3BlY2lhbGx5IC0gYXBwZW5kIGluc3RlYWQgb2YgcmVwbGFjZVxuICBpZiAodXBkYXRlcy5lcnJvcnMgJiYgQXJyYXkuaXNBcnJheSh1cGRhdGVzLmVycm9ycykpIHtcbiAgICB1cGRhdGVkLmVycm9ycyA9IFsuLi4oY3VycmVudC5lcnJvcnMgfHwgW10pLCAuLi51cGRhdGVzLmVycm9yc107XG4gIH1cblxuICBhd2FpdCBmcy53cml0ZUZpbGUoU1RBVFVTX0ZJTEUsIEpTT04uc3RyaW5naWZ5KHVwZGF0ZWQsIG51bGwsIDIpKTtcbn1cbiIKICBdLAogICJtYXBwaW5ncyI6ICI7QUFBQSxrQkFBUztBQUNUO0FBQ0E7QUFDQTtBQUFBO0FBRUEsSUFBTSxhQUFhLEtBQUssS0FBSyxHQUFHLE9BQU8sR0FBRyxxQkFBcUI7QUFDL0QsSUFBTSxjQUFjLEtBQUssS0FBSyxZQUFZLGFBQWE7QUFDdkQsSUFBTSxXQUFXLEtBQUssS0FBSyxZQUFZLGFBQWE7QUFhcEQsZUFBc0IsMEJBQTBCLENBQUMsTUFBK0I7QUFBQSxFQUU5RSxNQUFNLEdBQUcsTUFBTSxZQUFZLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFBQSxFQUc5QyxNQUFNLFlBQVksTUFBTSxxQkFBcUI7QUFBQSxFQUM3QyxJQUFJLFdBQVc7QUFBQSxJQUNiLFFBQVEsSUFBSSx1REFBc0Q7QUFBQSxJQUNsRSxRQUFRLElBQUksc0VBQXNFO0FBQUEsSUFDbEY7QUFBQSxFQUNGO0FBQUEsRUFHQSxNQUFNLFFBQVEsT0FBTyxRQUFRO0FBQUEsRUFD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