cli: align config aware commands options

This commit is contained in:
dswbx
2025-08-29 09:40:27 +02:00
parent 93019827b0
commit c04ad89a86
7 changed files with 49 additions and 45 deletions

View File

@@ -3,16 +3,14 @@ import type { CliCommand } from "../types";
import { makeAppFromEnv } from "cli/commands/run"; import { makeAppFromEnv } from "cli/commands/run";
import { writeFile } from "node:fs/promises"; import { writeFile } from "node:fs/promises";
import c from "picocolors"; import c from "picocolors";
import { withConfigOptions } from "cli/utils/options";
export const config: CliCommand = (program) => { export const config: CliCommand = (program) => {
program withConfigOptions(program.command("config"))
.command("config")
.description("get app config") .description("get app config")
.option("--pretty", "pretty print") .option("--pretty", "pretty print")
.option("--default", "use default config") .option("--default", "use default config")
.option("--secrets", "include secrets in output") .option("--secrets", "include secrets in output")
.option("--config <config>", "config file")
.option("--db-url <db>", "database url, can be any valid sqlite url")
.option("--out <file>", "output file") .option("--out <file>", "output file")
.action(async (options) => { .action(async (options) => {
let config: any = {}; let config: any = {};

View File

@@ -2,13 +2,11 @@ import type { CliCommand } from "cli/types";
import { makeAppFromEnv } from "../run"; import { makeAppFromEnv } from "../run";
import { getSystemMcp } from "modules/mcp/system-mcp"; import { getSystemMcp } from "modules/mcp/system-mcp";
import { $console, stdioTransport } from "bknd/utils"; import { $console, stdioTransport } from "bknd/utils";
import { withConfigOptions, type WithConfigOptions } from "cli/utils/options";
export const mcp: CliCommand = (program) => export const mcp: CliCommand = (program) =>
program withConfigOptions(program.command("mcp"))
.command("mcp")
.description("mcp server stdio transport") .description("mcp server stdio transport")
.option("--config <config>", "config file")
.option("--db-url <db>", "database url, can be any valid sqlite url")
.option( .option(
"--token <token>", "--token <token>",
"token to authenticate requests, if not provided, uses BEARER_TOKEN environment variable", "token to authenticate requests, if not provided, uses BEARER_TOKEN environment variable",
@@ -18,14 +16,14 @@ export const mcp: CliCommand = (program) =>
.option("--force", "force enable mcp") .option("--force", "force enable mcp")
.action(action); .action(action);
async function action(options: { async function action(
options: WithConfigOptions<{
verbose?: boolean; verbose?: boolean;
config?: string;
dbUrl?: string;
token?: string; token?: string;
logLevel?: string; logLevel?: string;
force?: boolean; force?: boolean;
}) { }>,
) {
const verbose = !!options.verbose; const verbose = !!options.verbose;
const __oldConsole = { ...console }; const __oldConsole = { ...console };

View File

@@ -17,6 +17,7 @@ import {
} from "./platform"; } from "./platform";
import { createRuntimeApp, makeConfig } from "bknd/adapter"; import { createRuntimeApp, makeConfig } from "bknd/adapter";
import { colorizeConsole, isBun } from "bknd/utils"; import { colorizeConsole, isBun } from "bknd/utils";
import { withConfigOptions, type WithConfigOptions } from "cli/utils/options";
const env_files = [".env", ".dev.vars"]; const env_files = [".env", ".dev.vars"];
dotenv.config({ dotenv.config({
@@ -25,8 +26,7 @@ dotenv.config({
const is_bun = isBun(); const is_bun = isBun();
export const run: CliCommand = (program) => { export const run: CliCommand = (program) => {
program withConfigOptions(program.command("run"))
.command("run")
.description("run an instance") .description("run an instance")
.addOption( .addOption(
new Option("-p, --port <port>", "port to run on") new Option("-p, --port <port>", "port to run on")
@@ -41,12 +41,6 @@ export const run: CliCommand = (program) => {
"db-token", "db-token",
]), ]),
) )
.addOption(new Option("-c, --config <config>", "config file"))
.addOption(
new Option("--db-url <db>", "database url, can be any valid sqlite url").conflicts(
"config",
),
)
.addOption( .addOption(
new Option("--server <server>", "server type") new Option("--server <server>", "server type")
.choices(PLATFORMS) .choices(PLATFORMS)
@@ -84,14 +78,14 @@ export async function makeConfigApp(_config: CliBkndConfig, platform?: Platform)
}); });
} }
type RunOptions = { type RunOptions = WithConfigOptions<{
port: number; port: number;
memory?: boolean; memory?: boolean;
config?: string; config?: string;
dbUrl?: string; dbUrl?: string;
server: Platform; server: Platform;
open?: boolean; open?: boolean;
}; }>;
export async function makeAppFromEnv(options: Partial<RunOptions> = {}) { export async function makeAppFromEnv(options: Partial<RunOptions> = {}) {
const configFilePath = await getConfigPath(options.config); const configFilePath = await getConfigPath(options.config);

View File

@@ -2,13 +2,11 @@ import type { CliCommand } from "../types";
import { makeAppFromEnv } from "cli/commands/run"; import { makeAppFromEnv } from "cli/commands/run";
import { writeFile } from "node:fs/promises"; import { writeFile } from "node:fs/promises";
import c from "picocolors"; import c from "picocolors";
import { withConfigOptions } from "cli/utils/options";
export const sync: CliCommand = (program) => { export const sync: CliCommand = (program) => {
program withConfigOptions(program.command("sync"))
.command("sync")
.description("sync database") .description("sync database")
.option("--config <config>", "config file")
.option("--db-url <db>", "database url, can be any valid sqlite url")
.option("--dump", "dump operations to console instead of executing them") .option("--dump", "dump operations to console instead of executing them")
.option("--drop", "include destructive DDL operations") .option("--drop", "include destructive DDL operations")
.option("--out <file>", "output file") .option("--out <file>", "output file")

View File

@@ -4,33 +4,35 @@ import { makeAppFromEnv } from "cli/commands/run";
import { EntityTypescript } from "data/entities/EntityTypescript"; import { EntityTypescript } from "data/entities/EntityTypescript";
import { writeFile } from "cli/utils/sys"; import { writeFile } from "cli/utils/sys";
import c from "picocolors"; import c from "picocolors";
import { withConfigOptions, type WithConfigOptions } from "cli/utils/options";
export const types: CliCommand = (program) => { export const types: CliCommand = (program) => {
program withConfigOptions(program.command("types"))
.command("types")
.description("generate types") .description("generate types")
.addOption(new Option("-o, --outfile <outfile>", "output file").default("bknd-types.d.ts")) .addOption(new Option("-o, --outfile <outfile>", "output file").default("bknd-types.d.ts"))
.addOption(new Option("--no-write", "do not write to file").default(true)) .addOption(new Option("--dump", "dump types to console instead of writing to file"))
.action(action); .action(action);
}; };
async function action({ async function action({
outfile, outfile,
write, dump,
}: { ...options
}: WithConfigOptions<{
outfile: string; outfile: string;
write: boolean; dump: boolean;
}) { }>) {
const app = await makeAppFromEnv({ const app = await makeAppFromEnv({
server: "node", server: "node",
...options,
}); });
const et = new EntityTypescript(app.em); const et = new EntityTypescript(app.em);
if (write) { if (dump) {
console.info(et.toString());
} else {
await writeFile(outfile, et.toString()); await writeFile(outfile, et.toString());
console.info(`\nTypes written to ${c.cyan(outfile)}`); console.info(`\nTypes written to ${c.cyan(outfile)}`);
} else {
console.info(et.toString());
} }
} }

View File

@@ -11,20 +11,18 @@ import type { CliCommand } from "cli/types";
import { Argument } from "commander"; import { Argument } from "commander";
import { $console, isBun } from "bknd/utils"; import { $console, isBun } from "bknd/utils";
import c from "picocolors"; import c from "picocolors";
import { withConfigOptions, type WithConfigOptions } from "cli/utils/options";
export const user: CliCommand = (program) => { export const user: CliCommand = (program) => {
program withConfigOptions(program.command("user"))
.command("user")
.description("create/update users, or generate a token (auth)") .description("create/update users, or generate a token (auth)")
.addArgument( .addArgument(
new Argument("<action>", "action to perform").choices(["create", "update", "token"]), new Argument("<action>", "action to perform").choices(["create", "update", "token"]),
) )
.option("--config <config>", "config file")
.option("--db-url <db>", "database url, can be any valid sqlite url")
.action(action); .action(action);
}; };
async function action(action: "create" | "update" | "token", options: any) { async function action(action: "create" | "update" | "token", options: WithConfigOptions) {
const app = await makeAppFromEnv({ const app = await makeAppFromEnv({
config: options.config, config: options.config,
dbUrl: options.dbUrl, dbUrl: options.dbUrl,

View File

@@ -0,0 +1,16 @@
import { type Command, Option } from "commander";
export function withConfigOptions(program: Command) {
return program
.addOption(new Option("-c, --config <config>", "config file"))
.addOption(
new Option("--db-url <db>", "database url, can be any valid sqlite url").conflicts(
"config",
),
);
}
export type WithConfigOptions<CustomOptions = {}> = {
config?: string;
dbUrl?: string;
} & CustomOptions;