UNPKG

@senchou/cli

Version:

Generate TypeScript for Kubernetes resources.

328 lines (287 loc) 10.3 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); import arg from "arg"; import littlelog from "@littlethings/log"; import kleur from "kleur"; import fs from "fs"; import path from "path"; import mkdirp from "mkdirp"; import core from "@senchou/core"; const rootArgs = { "--help": Boolean, "-h": "--help", "--verbose": arg.COUNT, "-v": "--verbose" }; const args = arg(rootArgs, { permissive: true }); if (args["--verbose"]) { switch (args["--verbose"]) { default: case 0: break; case 1: littlelog.setVerbosity("INFO"); break; case 2: littlelog.setVerbosity("DEBUG"); break; case 3: littlelog.setVerbosity("TRACE"); break; } if (args["--verbose"] > 3) { littlelog.setVerbosity("TRACE"); } } else { littlelog.setVerbosity("INFO"); } var log = littlelog.create("@senchou/cli"); const help$2 = () => { const message = ` ${kleur.bold(`DESCRIPTION`)} Manage Kubernetes manifests with TypeScript. ${kleur.bold(`USAGE`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou`)} <command> [options] ${kleur.bold(`COMMANDS`)} k8s Import types for a Kubernetes release crd Import types for a CustomResourceDefinition ${kleur.bold(`OPTIONS`)} --help, -h Show this help message --verbose, -v Set logging verbosity ${kleur.bold(`EXAMPLE`)} ${kleur.dim(`$ # Get help for commands.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou k8s`)} --help ${kleur.dim(`$`)} ${kleur.bold(`senchou crd`)} --help ${kleur.dim(`$ # Run Senchou with verbose logging.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou`)} -v ${kleur.dim(`$`)} ${kleur.bold(`senchou`)} -vv ${kleur.dim(`$`)} ${kleur.bold(`senchou`)} -vvv ${kleur.dim(`$ # Run Senchou with no logging.`)} ${kleur.dim(`$`)} LOG_LEVEL=SILENT ${kleur.bold(`senchou`)} ${kleur.dim(`$ # Run Senchou with timestamps.`)} ${kleur.dim(`$`)} LOG_TIMESTAMP=TRUE ${kleur.bold(`senchou`)} ${kleur.dim(`$ # Filter logs from Senchou (based on log prefix).`)} ${kleur.dim(`$`)} DEBUG="^some-regex$" ${kleur.bold(`senchou`)} `; console.log(message); }; const help$1 = () => { const message = ` ${kleur.bold(`DESCRIPTION`)} Import types for a Kubernetes release. ${kleur.bold(`USAGE`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou k8s [version]`)} ${kleur.bold(`OPTIONS`)} --help, -h Show this help message --output, -o Set the output directory (default: ./senchou) --force, -f Remove any conflicting files before writing ${kleur.bold(`EXAMPLE`)} ${kleur.dim(`$ # Import the default Kubernetes release's types.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou k8s`)} ${kleur.dim(`$ # Import a specific Kubernetes release's types.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou k8s`)} 1.20.0 ${kleur.dim(`$ # Import to a custom directory.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou k8s`)} --output ./my-code ${kleur.dim(`$ # Overwrite an existing "k8s.ts" file.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou k8s`)} --force `; console.log(message); }; const getArgs$1 = () => { return arg(__spreadProps(__spreadValues({}, rootArgs), { "--output": String, "-o": "--output", "--force": Boolean, "-f": "--force" })); }; const resolveRelativePath = (relativePath) => { if (path.isAbsolute(relativePath)) { return relativePath; } else { return path.resolve(process.cwd(), relativePath); } }; const command$1 = async () => { const args2 = getArgs$1(); if (args2["--help"]) { help$1(); process.exit(0); } const output = args2["--output"] ? resolveRelativePath(args2["--output"]) : resolveRelativePath("senchou"); const version = args2._[1]; log.debug(`Creating directory "${output}".`); await mkdirp(output); const file = path.resolve(output, "k8s.ts"); if (fs.existsSync(file)) { if (args2["--force"]) { fs.rmSync(file); } else { log.fatal(`File already exists at path "${file}".`); log.fatal(`Remove the file and try again or use the "--force" option.`); process.exit(1); } } const specifier = `k8s${version ? `@${version}` : ""}`; log.trace(`Importing schema for "${specifier}".`); const schema = await core.import.kubernetes(specifier); log.trace(`Generating code for schema.`); const code = await core.generate.kubernetes(schema); log.debug(`Writing code to file "${file}".`); fs.writeFileSync(file, code); }; const help = () => { const message = ` ${kleur.bold(`DESCRIPTION`)} Import types for a CustomResourceDefinition. ${kleur.bold(`USAGE`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd <protocol>:<specifier>`)} ${kleur.bold(`OPTIONS`)} --help, -h Show this help message --output, -o Set the output directory (default: ./senchou) --force, -f Remove any conflicting files before writing --name, -n Set the name of the output file (appended with ".ts") ${kleur.bold(`PROTOCOLS`)} ${kleur.bold("github")} CRDs can be imported from GitHub using the "github" protocol. To fetch from GitHub, you must supply an owner and repository name like the following. ${kleur.dim(`$ # github:owner/repo`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd github:traefik/traefik-helm-chart`)} Tags can also be used to fetch CRDs from a specific release. ${kleur.dim(`$ # github:owner/repo@tag`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd github:traefik/traefik-helm-chart@v10.14.0`)} ${kleur.bold(`EXAMPLE`)} ${kleur.dim(`$ # Import types for Traefik from GitHub.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd`)} github:traefik/traefik-helm-chart ${kleur.dim(`$ # Import a specific version's types.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd`)} github:traefik/traefik-helm-chart@v10.14.0 ${kleur.dim(`$ # Import to a custom directory.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd`)} github:traefik/traefik-helm-chart --output ./my-code ${kleur.dim(`$ # Name the output file.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd`)} github:traefik/traefik-helm-chart --name traefik ${kleur.dim(`$ # Overwrite an existing file.`)} ${kleur.dim(`$`)} ${kleur.bold(`senchou crd`)} github:traefik/traefik-helm-chart --force `; console.log(message); }; const getArgs = () => { return arg(__spreadProps(__spreadValues({}, rootArgs), { "--output": String, "-o": "--output", "--force": Boolean, "-f": "--force", "--name": String, "-n": "--name" })); }; const specifierToFileName = (specifier) => { if (specifier.startsWith("github:")) { const suffix = specifier.split("github:")[1]; const path2 = suffix.split("@")[0]; const repo = path2.split("/")[1]; return repo; } else { return specifier.replace(/[^A-Za-z0-9]/g, "-"); } }; const importCRD = async (specifier) => { if (specifier.startsWith("github:")) { return core.import.github(specifier.substring("github:".length)); } else { log.fatal(`Unknown protocol "${specifier}" for CRD.`); process.exit(1); } }; const command = async () => { const args2 = getArgs(); if (args2["--help"]) { help(); process.exit(0); } if (!args2._[1]) { log.fatal("No specifier entered."); help(); process.exit(1); } const specifier = args2._[1]; const output = args2["--output"] ? resolveRelativePath(args2["--output"]) : resolveRelativePath("senchou"); const name = args2["--name"] ? args2["--name"] : specifierToFileName(specifier); log.trace(`Using name "${name}" for resource.`); log.debug(`Creating directory "${output}".`); await mkdirp(output); const file = path.resolve(output, `${name}.ts`); if (fs.existsSync(file)) { if (args2["--force"]) { fs.rmSync(file); } else { log.fatal(`File already exists at path "${file}".`); log.fatal(`Remove the file and try again or use the "--force" option.`); process.exit(1); } } log.trace(`Importing definitions for "${specifier}".`); const definitions = await importCRD(specifier); log.trace(`Generating code for definitions.`); const code = await core.generate.crd(definitions); log.debug(`Writing code to file "${file}".`); fs.writeFileSync(file, code); }; const commands = { k8s: command$1, crd: command }; const main = async () => { var _a; log.trace("Init."); log.trace("Parsing root arguments."); const args2 = arg(rootArgs, { permissive: true }); if (args2["--help"] && args2._.length === 0) { log.trace("Printing root help message."); help$2(); process.exit(0); } if (args2._.length === 0) { log.fatal("No command specified."); log.trace("Printing root help message due to error."); help$2(); process.exit(1); } const command2 = (_a = args2._) == null ? void 0 : _a[0]; if (command2 && command2 in commands) { log.trace(`Executing command "${command2}".`); await commands[command2](); } else { log.fatal(`Unknown command "${command2}".`); process.exit(1); } }; main().catch((error) => { var _a, _b, _c; log.fatal(error.message || error); for (const line of (_c = (_b = (_a = error.stack) == null ? void 0 : _a.split("\n")) == null ? void 0 : _b.slice(1)) != null ? _c : []) { log.fatal(`${line}`); } });