120 lines
2.8 KiB
TypeScript
120 lines
2.8 KiB
TypeScript
import { watch } from "node:fs/promises";
|
|
import chalk from "chalk";
|
|
import {
|
|
CLIError,
|
|
MuseError,
|
|
compileMarkdownInPlaybill,
|
|
loadFromBinding,
|
|
resolveBindingPath,
|
|
} from "#lib";
|
|
import { renderPlaybillToHTML } from "#render/html";
|
|
import {
|
|
type CLIArguments,
|
|
getAbsoluteDirname,
|
|
parseCLIArguments,
|
|
USAGE,
|
|
} from "#util";
|
|
|
|
enum ExitCode {
|
|
Success = 0,
|
|
Error = 1,
|
|
}
|
|
|
|
async function processBinding({ inputFilePath, options }: CLIArguments) {
|
|
// Load the binding
|
|
const bindingPath = await resolveBindingPath(inputFilePath);
|
|
const binding = await loadFromBinding(bindingPath);
|
|
|
|
// If --check is specified, exit early
|
|
if (options.check) {
|
|
console.log(chalk.green("Playbill validated successfully"));
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
if (options.markdown) {
|
|
await compileMarkdownInPlaybill(binding);
|
|
}
|
|
|
|
// Serialize (default: JSON)
|
|
let serializedPlaybill = "";
|
|
|
|
switch (options.renderer) {
|
|
case "json":
|
|
serializedPlaybill = binding.playbill.serialize();
|
|
break;
|
|
case "html":
|
|
serializedPlaybill = await renderPlaybillToHTML(binding);
|
|
break;
|
|
default:
|
|
throw new CLIError(`Unknown renderer: ${options.renderer}`);
|
|
}
|
|
|
|
// Write to disk if --outfile is specified
|
|
if (options.outfile !== "") {
|
|
await Bun.write(options.outfile, serializedPlaybill);
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
// Otherwise, write to stdout
|
|
console.log(serializedPlaybill);
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
async function main(): Promise<number> {
|
|
const cliArguments = parseCLIArguments(Bun.argv.slice(2));
|
|
const { options } = cliArguments;
|
|
|
|
// If --help is specified, print usage and exit
|
|
if (options.help) {
|
|
console.log(USAGE);
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
let lastProcessResult = await processBinding(cliArguments);
|
|
|
|
if (options.watch) {
|
|
const watchDir = getAbsoluteDirname(cliArguments.inputFilePath);
|
|
|
|
console.log(`Watching ${watchDir} for changes...`);
|
|
|
|
const watcher = watch(watchDir, {
|
|
recursive: true,
|
|
});
|
|
|
|
for await (const event of watcher) {
|
|
console.log(
|
|
`Detected ${event.eventType} on ${event.filename}. Reprocessing...`,
|
|
);
|
|
|
|
try {
|
|
lastProcessResult = await processBinding(cliArguments);
|
|
|
|
if (lastProcessResult === ExitCode.Error) {
|
|
console.error(`Error processing ${event.filename}`);
|
|
} else {
|
|
console.log("Reprocessed changes");
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error processing ${event.filename}`);
|
|
console.error(error);
|
|
}
|
|
}
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
try {
|
|
const exitCode = await main();
|
|
process.exit(exitCode);
|
|
} catch (error) {
|
|
if (error instanceof MuseError) {
|
|
console.error(chalk.red(error.fmt()));
|
|
} else {
|
|
console.error("An unexpected error occurred");
|
|
console.error(error);
|
|
}
|
|
|
|
process.exit(1);
|
|
}
|