102 lines
3.6 KiB
TypeScript
102 lines
3.6 KiB
TypeScript
import { defineCommand } from "citty";
|
|
import { wrapCommandErrors } from "../lib/error";
|
|
|
|
function lazyCommand<T extends object>(
|
|
load: () => Promise<T>,
|
|
): () => Promise<T> {
|
|
let pending: Promise<T> | undefined;
|
|
return () =>
|
|
(pending ??= load()
|
|
.then((command) => {
|
|
// Keep the exported command objects pristine: tests and callers may
|
|
// import them directly while the CLI needs wrapped handlers.
|
|
const cliCommand = cloneCommand(command);
|
|
wrapCommandErrors(cliCommand);
|
|
return cliCommand;
|
|
})
|
|
.catch((error) => {
|
|
pending = undefined;
|
|
throw error;
|
|
}));
|
|
}
|
|
|
|
function cloneCommand<T extends object>(command: T): T {
|
|
const clone = { ...command } as T & { subCommands?: unknown };
|
|
const subCommands = clone.subCommands;
|
|
if (subCommands && typeof subCommands === "object") {
|
|
clone.subCommands = Object.fromEntries(
|
|
Object.entries(subCommands).map(([name, child]) => [
|
|
name,
|
|
child && typeof child === "object" ? cloneCommand(child) : child,
|
|
]),
|
|
);
|
|
}
|
|
return clone;
|
|
}
|
|
|
|
export const main = defineCommand({
|
|
meta: {
|
|
name: "kuber",
|
|
version: "2.6.1-rc5",
|
|
description: "Docker Compose -> K8s translation layer",
|
|
},
|
|
args: {
|
|
config: {
|
|
type: "string",
|
|
description: "Path to a kuber configuration file",
|
|
},
|
|
},
|
|
subCommands: {
|
|
audit: lazyCommand(() => import("./audit").then((m) => m.audit)),
|
|
ci: lazyCommand(() => import("./ci").then((m) => m.ci)),
|
|
db: lazyCommand(() => import("./db").then((m) => m.db)),
|
|
down: lazyCommand(() => import("./down").then((m) => m.down)),
|
|
export: lazyCommand(() => import("./export").then((m) => m.exportCommand)),
|
|
exec: lazyCommand(() => import("./exec").then((m) => m.exec)),
|
|
logs: lazyCommand(() => import("./logs").then((m) => m.logs)),
|
|
maintenance: lazyCommand(() =>
|
|
import("./maintenance").then((m) => m.maintenance),
|
|
),
|
|
login: lazyCommand(() => import("./auth").then((m) => m.login)),
|
|
logout: lazyCommand(() => import("./auth").then((m) => m.logout)),
|
|
operations: lazyCommand(() =>
|
|
import("./operations").then((m) => m.operations),
|
|
),
|
|
ps: lazyCommand(() => import("./ps").then((m) => m.ps)),
|
|
restart: lazyCommand(() => import("./restart").then((m) => m.restart)),
|
|
rollback: lazyCommand(() => import("./rollback").then((m) => m.rollback)),
|
|
s3: lazyCommand(() => import("./s3").then((m) => m.s3)),
|
|
start: lazyCommand(() => import("./start").then((m) => m.start)),
|
|
stop: lazyCommand(() => import("./stop").then((m) => m.stop)),
|
|
up: lazyCommand(() => import("./up").then((m) => m.up)),
|
|
users: lazyCommand(() => import("./users").then((m) => m.users)),
|
|
trust: lazyCommand(() => import("./trust").then((m) => m.trust)),
|
|
whoami: lazyCommand(() => import("./auth").then((m) => m.whoami)),
|
|
},
|
|
});
|
|
|
|
type Completion = Awaited<
|
|
ReturnType<typeof import("@bomb.sh/tab/citty")["default"]>
|
|
>;
|
|
let completion: Promise<Completion> | undefined;
|
|
|
|
export function initializeCompletion() {
|
|
completion ??= (async () => {
|
|
// tab inspects command objects directly, unlike citty's lazy resolver.
|
|
const commands = main.subCommands;
|
|
if (commands && typeof commands !== "function") {
|
|
main.subCommands = Object.fromEntries(
|
|
await Promise.all(
|
|
Object.entries(commands).map(async ([name, command]) => [
|
|
name,
|
|
typeof command === "function" ? await command() : await command,
|
|
]),
|
|
),
|
|
);
|
|
}
|
|
const { default: tab } = await import("@bomb.sh/tab/citty");
|
|
return tab(main);
|
|
})();
|
|
return completion;
|
|
}
|