@spongex/docbuilder
Version:
Run document generators for multiple projects
190 lines (184 loc) • 5.76 kB
JavaScript
// src/docbuilder.ts
import fs from "fs";
import path from "path";
import { exec } from "child_process";
import { red, green, yellow, cyan, dim } from "kolorist";
import { __locale } from "@spongex/system-locale";
import { AsyncResolver } from "@spongex/async-resolver";
import { scriptError } from "@spongex/script-error";
var constants = {
SETTINGS_FILE: `.docbuilder.config.json`,
LOG_FILE: `.docbuilder.log`,
OUTPUT_FOLDER: "docs"
};
var loadSettings = () => {
try {
const settings2 = fs.readFileSync(path.join(process.cwd(), constants.SETTINGS_FILE));
return JSON.parse(settings2.toString());
} catch (error) {
scriptError(`Can't find a local '${constants.SETTINGS_FILE}' configuration file.`);
}
};
var writeLog = (message) => {
try {
fs.appendFileSync(path.normalize(path.join(process.cwd(), constants.LOG_FILE)), message);
} catch (error) {
scriptError(error.message);
}
};
var verifyFolder = (folder) => {
try {
fs.accessSync(path.normalize(folder));
} catch (error) {
try {
fs.mkdirSync(folder);
} catch (error2) {
scriptError(error2.message);
}
}
};
var deleteFolder = (folder) => {
if (fs.existsSync(folder)) {
try {
fs.rmSync(folder, { recursive: true, force: true });
} catch (error) {
}
}
};
var jobRunner = async (jobs, command, splicer, callback) => {
splicer = splicer || (() => {
return command;
});
callback = callback || (() => {
});
const runningJobs = [];
jobs.forEach((job) => {
runningJobs.push(new AsyncResolver());
const jobIDX = runningJobs.length - 1;
const run_command = splicer(job, command);
exec(run_command, { cwd: path.normalize(job.path) }, (error, stdout, stderr) => {
let cmdRes;
if (error) {
cmdRes = {
name: job.name,
command: run_command,
code: error.code,
stdout,
stderr
};
runningJobs[jobIDX].reject(cmdRes);
} else {
cmdRes = {
name: job.name,
command: run_command,
code: 0,
stdout,
stderr
};
const jobOut = job.out || "docs";
try {
fs.cpSync(
path.join(job.path, jobOut),
path.join(process.cwd(), constants.OUTPUT_FOLDER),
{ recursive: true }
);
} catch (error2) {
deleteFolder(path.join(job.path, jobOut));
cmdRes.stderr = error2.message;
runningJobs[jobIDX].reject(cmdRes);
}
if (job.hasOwnProperty("removeold") && job.removeold)
deleteFolder(path.join(job.path, jobOut));
runningJobs[jobIDX].resolve(cmdRes);
}
callback(error, cmdRes);
});
});
let jobPromises = [];
runningJobs.forEach((job) => {
jobPromises.push(job.promise);
});
return await Promise.allSettled(jobPromises);
};
console.log(cyan(`Documentation Generation Script
`));
var settings = loadSettings();
if (!settings.hasOwnProperty("generators"))
scriptError("Must define documentation generators to run.");
settings["jobs"].forEach((job) => {
if (!job.hasOwnProperty("name") || !job.hasOwnProperty("generator") || !job.hasOwnProperty("path"))
scriptError(`Invalid job format.`);
});
if (settings.hasOwnProperty("log_file"))
constants.LOG_FILE = settings["log_file"];
if (settings.hasOwnProperty("output_folder"))
constants.OUTPUT_FOLDER = settings["output_folder"];
if (!settings["nologging"]) {
console.log(dim(yellow(`Logging output to '${constants.LOG_FILE}'...`)));
if (fs.existsSync(path.join(process.cwd(), constants.LOG_FILE))) {
try {
fs.unlinkSync(path.join(process.cwd(), constants.LOG_FILE));
} catch (error) {
scriptError(`Unable to remove old log file! Verify you have write access`);
}
}
writeLog(`Documentation Generation Script Log File
`);
}
if (fs.existsSync(path.join(process.cwd(), constants.OUTPUT_FOLDER))) {
try {
fs.rmSync(
path.join(process.cwd(), constants.OUTPUT_FOLDER),
{ recursive: true, force: true }
);
} catch (error) {
scriptError(`Unable to remove old documentation folder! Verify you have write access`);
}
}
verifyFolder(path.join(process.cwd(), constants.OUTPUT_FOLDER));
var logRes = "";
console.log(`Running jobs, please wait...`);
await jobRunner(
settings["jobs"],
"",
(job) => {
if (job.checkfolder)
verifyFolder(path.join(process.cwd(), constants.OUTPUT_FOLDER, job.name));
let runCmd = settings["generators"][job.generator];
runCmd = runCmd.replaceAll("$PROJECT_LOCATION", job.path);
runCmd = runCmd.replaceAll("$PROJECT", job.name);
runCmd = runCmd.replaceAll("$OUTPUT_FOLDER", constants.OUTPUT_FOLDER);
return runCmd;
},
(error, cmdRes) => {
logRes += `--------------------------------------------------
Job: ${cmdRes.name}
--------------------------------------------------
Command: ${cmdRes.command}
Return code: ${cmdRes.code}
Output:
${cmdRes.stdout}
Errors:
${cmdRes.stderr}
`;
if (error)
console.log(red(`
WARNING: Problems running job '${cmdRes.name}' see log for details...`));
}
).then((jobResults) => {
let goodRes = jobResults.length;
jobResults.forEach((job) => {
if (job.status === "rejected") goodRes--;
});
if (!settings["nologging"]) {
writeLog(logRes + `--------------------------------------------------
`);
writeLog(`${goodRes} of ${jobResults.length} jobs completed successfully at ${(/* @__PURE__ */ new Date()).toLocaleString(__locale)}`);
}
console.log(`
${goodRes} of ${jobResults.length} jobs completed successfully at ${(/* @__PURE__ */ new Date()).toLocaleString(__locale)}`);
console.log(green(`Done!
`));
});
process.exit(0);