#!/usr/bin/env node
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
    if (typeof path === "string" && /^\.\.?\//.test(path)) {
        return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
            return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
        });
    }
    return path;
};
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
import { dirname, isAbsolute, join, resolve } from "node:path";
import arg from "arg";
import { load } from "js-yaml";
import z from "zod/v4";
import { generatePages } from "../pages/generatePages.js";
import { DocusaurusSite } from "../renderers/docusaurus.js";
import { NextraSite } from "../renderers/nextra.js";
import { settingsSchema } from "../types/settings.js";
import { assertNever } from "../util/assertNever.js";
const CONFIG_FILE_NAMES = [
    "speakeasy.config.js",
    "speakeasy.config.mjs",
    "speakeasy.config.cjs",
    "speakeasy.config.ts",
    "speakeasy.config.mts",
    "speakeasy.config.cts",
];
const args = arg({
    "--help": Boolean,
    "--config": String,
    "--clean": Boolean,
    "-h": "--help",
    "-c": "--config",
    "-C": "--clean",
});
function printHelp() {
    console.log(`Usage: docsmd [options]

Options:
  --help, -h     Show this help message
  --config, -c   Path to config file
  --clean, -C    Clean the output directories before generating`);
}
if (args["--help"]) {
    printHelp();
    process.exit(0);
}
function reportError(msg) {
    console.error(msg + "\n");
    printHelp();
    process.exit(1);
}
async function getSettings() {
    // First, determine the config file path
    let configFilePath = args["--config"];
    if (!configFilePath) {
        // If it wasn't supplied, we'll look for a config file in the current directory
        const dirContents = readdirSync(process.cwd());
        for (const fileName of dirContents) {
            if (CONFIG_FILE_NAMES.includes(fileName)) {
                if (configFilePath) {
                    reportError("Multiple config files found in current directory");
                }
                configFilePath = resolve(join(process.cwd(), fileName));
            }
        }
    }
    // Sanity check the config file path
    if (!configFilePath) {
        reportError(`No config file found in ${process.cwd()}. Please supply a config file with the --config option`);
    }
    if (!existsSync(configFilePath)) {
        reportError(`Config file "${configFilePath}" does not exist`);
    }
    // Note: typing below is something of an abomination of casts, but that's ok
    // since we do runtime validation with Zod after we're done with these casts.
    // The Zod validation is what ensures the types are correct.
    // Read in the config file. We wrap in a try-catch in case there are syntax
    // errors in the config file, which we want to report with a more
    // user-friendly error message than the standard thrown exception
    let configFileImport;
    try {
        // TODO: this _probably_ doesn't work for CommonJS. Not sure we care though
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
        const importedConfig = (await import(__rewriteRelativeImportExtension(configFilePath))).default;
        if (typeof importedConfig !== "object" || importedConfig === null) {
            reportError(`The default export in the config file must be an object`);
        }
        configFileImport = importedConfig;
    }
    catch (e) {
        reportError(`Error importing config file "${configFilePath}": ${e.message}`);
    }
    if (!configFileImport.output) {
        configFileImport.output = {};
    }
    // Parse the settings using Zod to ensure accuracy
    const configFileContents = settingsSchema.safeParse(configFileImport);
    if (!configFileContents.success) {
        reportError(`Error parsing config file "${configFilePath}": ${z.prettifyError(configFileContents.error)}`);
    }
    // Validate and format various settings, as needed
    const configFileDirectory = dirname(configFilePath);
    if (!isAbsolute(configFileContents.data.spec)) {
        configFileContents.data.spec = resolve(configFileDirectory, configFileContents.data.spec);
    }
    if (!existsSync(configFileContents.data.spec)) {
        throw new Error(`OpenAPI spec file "${configFileContents.data.spec}" does not exist`);
    }
    if (!isAbsolute(configFileContents.data.output.pageOutDir)) {
        configFileContents.data.output.pageOutDir = resolve(configFileDirectory, configFileContents.data.output.pageOutDir);
    }
    if (!isAbsolute(configFileContents.data.output.componentOutDir)) {
        configFileContents.data.output.componentOutDir = resolve(configFileDirectory, configFileContents.data.output.componentOutDir);
    }
    return configFileContents.data;
}
const settings = await getSettings();
const specData = readFileSync(settings.spec, "utf-8");
const specContents = JSON.stringify(load(specData));
let site;
switch (settings.output.framework) {
    case "docusaurus": {
        site = new DocusaurusSite();
        break;
    }
    case "nextra": {
        site = new NextraSite();
        break;
    }
    default: {
        // We should never get here cause we validate the settings in the CLI
        assertNever(settings.output.framework);
    }
}
const pageContents = await generatePages({
    site,
    specContents,
    settings,
});
if (args["--clean"]) {
    rmSync(settings.output.pageOutDir, {
        recursive: true,
        force: true,
    });
    rmSync(settings.output.componentOutDir, {
        recursive: true,
        force: true,
    });
}
for (const [filename, contents] of Object.entries(pageContents)) {
    mkdirSync(dirname(filename), {
        recursive: true,
    });
    writeFileSync(filename, contents, {
        encoding: "utf-8",
    });
}
console.log("Success!");
//# sourceMappingURL=cli.js.map