151 lines
3.5 KiB
TypeScript
151 lines
3.5 KiB
TypeScript
import { parseArgs } from "node:util";
|
|
import {
|
|
serializePlaybill,
|
|
ValidatedPlaybillSchema,
|
|
} from "@proscenium/playbill";
|
|
import chalk from "chalk";
|
|
import { loadFromBinding, resolveBindingPath } from "./binding";
|
|
import { usage } from "./usage";
|
|
import { CLIError, MuseError } from "./errors";
|
|
import { renderAsHTML } from "./renderers/html";
|
|
|
|
enum ExitCode {
|
|
Success = 0,
|
|
Error = 1,
|
|
}
|
|
|
|
async function main(): Promise<number> {
|
|
// -- ARGUMENT PARSING -- //
|
|
const { values: options, positionals: args } = parseArgs({
|
|
args: Bun.argv.slice(2),
|
|
options: {
|
|
write: {
|
|
short: "w",
|
|
type: "boolean",
|
|
default: false,
|
|
},
|
|
check: {
|
|
short: "c",
|
|
type: "boolean",
|
|
default: false,
|
|
},
|
|
outfile: {
|
|
short: "o",
|
|
type: "string",
|
|
default: "playbill.json",
|
|
},
|
|
help: {
|
|
short: "h",
|
|
default: false,
|
|
type: "boolean",
|
|
},
|
|
verbose: {
|
|
short: "v",
|
|
default: false,
|
|
type: "boolean",
|
|
},
|
|
minify: {
|
|
short: "m",
|
|
default: false,
|
|
type: "boolean",
|
|
},
|
|
renderer: {
|
|
short: "r",
|
|
default: "json",
|
|
type: "string",
|
|
},
|
|
},
|
|
strict: true,
|
|
allowPositionals: true,
|
|
});
|
|
|
|
// -- HELP TEXT -- //
|
|
if (options.help) {
|
|
console.log(usage);
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
// -- ARG VALIDATION -- //
|
|
if (options.check && options.write) {
|
|
throw new CLIError("Cannot use --check and --write together");
|
|
}
|
|
|
|
const VERBOSE = options.verbose;
|
|
|
|
/**
|
|
* Log a message if the vervose flag has been set
|
|
* @param msg - The message to log
|
|
*/
|
|
function verboseLog(msg: string) {
|
|
if (VERBOSE) {
|
|
console.log(chalk.dim(msg));
|
|
}
|
|
}
|
|
|
|
// -- BINDING FILE -- //
|
|
const bindingPathInput = args[0] ?? "./binding.yaml";
|
|
const bindingPath = await resolveBindingPath(bindingPathInput);
|
|
|
|
verboseLog(`Building Playbill with binding: ${bindingPath}`);
|
|
|
|
const binding = await loadFromBinding(bindingPath);
|
|
|
|
verboseLog(
|
|
`↳ Binding loaded with ${binding.includedFiles.length} associated resources`,
|
|
);
|
|
|
|
// -- VALDATE PLAYBILL -- //
|
|
verboseLog("Validating playbill");
|
|
const validatedPlaybill = ValidatedPlaybillSchema.safeParse(binding.playbill);
|
|
|
|
if (!validatedPlaybill.success) {
|
|
console.error("Error validating playbill");
|
|
console.error(validatedPlaybill.error.errors);
|
|
return ExitCode.Error;
|
|
}
|
|
|
|
verboseLog("Playbill validated");
|
|
|
|
// -- EXIT EARLY IF JUST CHECKING VALIDATION --//
|
|
if (options.check) {
|
|
console.log(chalk.green("Playbill validated successfully"));
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
// -- SERIALIZE USING RENDERER --//
|
|
let serializedPlaybill = "";
|
|
|
|
switch (options.renderer) {
|
|
case "json":
|
|
serializedPlaybill = serializePlaybill(validatedPlaybill.data);
|
|
break;
|
|
case "html":
|
|
serializedPlaybill = await renderAsHTML(validatedPlaybill.data, binding);
|
|
break;
|
|
default:
|
|
throw new CLIError(`Unknown renderer: ${options.renderer}`);
|
|
}
|
|
|
|
// -- WRITE TO DISK OR STDOUT --//
|
|
if (options.write) {
|
|
await Bun.write(options.outfile, serializedPlaybill);
|
|
return ExitCode.Success;
|
|
}
|
|
|
|
console.log(serializedPlaybill);
|
|
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);
|
|
}
|