178 lines
4.9 KiB
TypeScript
178 lines
4.9 KiB
TypeScript
#!/usr/bin/env -S deno run -A
|
|
/** Non-interactive entry: validate | generate | deploy */
|
|
|
|
import { parseArgs } from "@std/cli/parse-args";
|
|
import { join } from "@std/path";
|
|
|
|
import {
|
|
DEFAULT_BS_MANAGER_CAMPAIGNS,
|
|
DEFAULT_DIST_DIR,
|
|
DEFAULT_INVENTORY_PATH,
|
|
} from "./lib/paths.ts";
|
|
import { generateCampaignToDist } from "./lib/generate.ts";
|
|
import {
|
|
defaultInventoryTemplate,
|
|
readCampaignInventory,
|
|
writeCampaignInventory,
|
|
} from "./lib/inventory.ts";
|
|
import { deployCampaignFolder } from "./lib/deploy.ts";
|
|
import {
|
|
formatIssues,
|
|
validateGeneratedFolder,
|
|
validateInventory,
|
|
} from "./lib/validate.ts";
|
|
|
|
function usage(): string {
|
|
return `
|
|
ost-campaign tools (Deno)
|
|
|
|
Usage:
|
|
deno task validate [--inventory <path>] [--dist <campaignDir>]
|
|
deno task generate [--inventory <path>] [--dist-dir <distRoot>]
|
|
deno task deploy [--dist <campaignDir>] [--to <CustomCampaignsDir>] [--dry-run] [--name <folderName>]
|
|
|
|
Defaults:
|
|
inventory: ${DEFAULT_INVENTORY_PATH}
|
|
dist-root: ${DEFAULT_DIST_DIR}
|
|
deploy to: ${DEFAULT_BS_MANAGER_CAMPAIGNS}
|
|
|
|
Environment:
|
|
BS_MANAGER_CUSTOM_CAMPAIGNS Overrides default BSManager CustomCampaigns path
|
|
`.trim();
|
|
}
|
|
|
|
async function cmdValidate(invPath: string, distDir?: string): Promise<number> {
|
|
const inv = await readCampaignInventory(invPath);
|
|
const invIssues = validateInventory(inv);
|
|
console.log(invIssues.length ? formatIssues(invIssues) : "(inventory OK)");
|
|
let code = invIssues.some((x) => x.level === "error") ? 1 : 0;
|
|
if (distDir) {
|
|
try {
|
|
await Deno.stat(distDir);
|
|
} catch {
|
|
console.error(`Missing dist folder: ${distDir}`);
|
|
return 1;
|
|
}
|
|
const disk = await validateGeneratedFolder(inv, distDir);
|
|
if (disk.length) {
|
|
console.log("--- generated folder ---");
|
|
console.log(formatIssues(disk));
|
|
}
|
|
if (disk.some((x) => x.level === "error")) code = 1;
|
|
}
|
|
return code;
|
|
}
|
|
|
|
async function cmdGenerate(invPath: string, distRoot: string): Promise<number> {
|
|
const inv = await readCampaignInventory(invPath);
|
|
const invIssues = validateInventory(inv);
|
|
const errors = invIssues.filter((x) => x.level === "error");
|
|
if (errors.length) {
|
|
console.error(formatIssues(errors));
|
|
console.error("(fix inventory errors before generating)");
|
|
return 1;
|
|
}
|
|
const { outDir, missionCount } = await generateCampaignToDist(inv, distRoot);
|
|
console.log(`Wrote ${missionCount} missions to ${outDir}`);
|
|
return 0;
|
|
}
|
|
|
|
async function cmdDeploy(
|
|
distCampaignDir: string,
|
|
destParent: string,
|
|
dryRun: boolean,
|
|
folderName?: string,
|
|
): Promise<number> {
|
|
const { destDir, files } = await deployCampaignFolder({
|
|
srcDir: distCampaignDir,
|
|
destParentDir: destParent,
|
|
folderName,
|
|
dryRun,
|
|
});
|
|
if (dryRun) {
|
|
console.log(`Dry run: would copy ${files} files to ${destDir}`);
|
|
} else {
|
|
console.log(`Copied ${files} files -> ${destDir}`);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
async function seedInventoryIfMissing(path: string): Promise<void> {
|
|
try {
|
|
await Deno.stat(path);
|
|
} catch {
|
|
const tmpl = defaultInventoryTemplate();
|
|
await writeCampaignInventory(path, tmpl);
|
|
console.log(`Created starter inventory at ${path}`);
|
|
}
|
|
}
|
|
|
|
const parsed = parseArgs(Deno.args, {
|
|
alias: {
|
|
i: "inventory",
|
|
I: "inventory",
|
|
h: "help",
|
|
},
|
|
boolean: ["help", "dry-run"],
|
|
string: ["inventory", "dist", "dist-dir", "to", "name"],
|
|
});
|
|
|
|
if (parsed.help || parsed._.length === 0) {
|
|
console.log(usage());
|
|
Deno.exit(parsed.help ? 0 : 1);
|
|
}
|
|
|
|
const cmd = String(parsed._[0]);
|
|
|
|
(async () => {
|
|
const invPath = parsed.inventory ?? DEFAULT_INVENTORY_PATH;
|
|
|
|
if (cmd === "validate") {
|
|
try {
|
|
await Deno.stat(invPath);
|
|
} catch {
|
|
console.error(`Inventory not found: ${invPath}`);
|
|
Deno.exit(1);
|
|
}
|
|
let distDir: string | undefined = parsed.dist;
|
|
if (!distDir) {
|
|
try {
|
|
const inv = await readCampaignInventory(invPath);
|
|
const candidate = join(DEFAULT_DIST_DIR, inv.outputFolderName);
|
|
try {
|
|
await Deno.stat(candidate);
|
|
distDir = candidate;
|
|
} catch {
|
|
distDir = undefined;
|
|
}
|
|
} catch {
|
|
distDir = undefined;
|
|
}
|
|
}
|
|
Deno.exit(await cmdValidate(invPath, distDir));
|
|
}
|
|
|
|
if (cmd === "generate") {
|
|
await seedInventoryIfMissing(invPath);
|
|
const distRoot = parsed["dist-dir"] ?? DEFAULT_DIST_DIR;
|
|
Deno.exit(await cmdGenerate(invPath, distRoot));
|
|
}
|
|
|
|
if (cmd === "deploy") {
|
|
let distCampaignDir = parsed.dist;
|
|
const folderName = parsed.name;
|
|
await seedInventoryIfMissing(invPath);
|
|
if (!distCampaignDir) {
|
|
const inv = await readCampaignInventory(invPath);
|
|
distCampaignDir = join(DEFAULT_DIST_DIR, inv.outputFolderName);
|
|
}
|
|
const dry = parsed["dry-run"] === true;
|
|
const dest = parsed.to ?? DEFAULT_BS_MANAGER_CAMPAIGNS;
|
|
Deno.exit(await cmdDeploy(distCampaignDir, dest, dry, folderName));
|
|
}
|
|
|
|
console.error(`Unknown command: ${cmd}`);
|
|
console.log(usage());
|
|
Deno.exit(1);
|
|
})();
|