From 2069b1665636c478e1ca5180795ecca56ab77479 Mon Sep 17 00:00:00 2001 From: sukairo-02 Date: Fri, 5 Jul 2024 17:08:14 +0300 Subject: [PATCH] Added 'transform' (types to be fixed) --- package.json | 2 +- src/command-core.ts | 57 ++++++++++++++++++++++++++++++++++----------- src/index.ts | 1 + 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 8c2a97b..b1a5915 100755 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@drizzle-team/brocli", "type": "module", "author": "Drizzle Team", - "version": "0.4.0", + "version": "0.5.0", "description": "Typed CLI command runner", "license": "Apache-2.0", "sideEffects": false, diff --git a/src/command-core.ts b/src/command-core.ts index d416c84..308f36e 100755 --- a/src/command-core.ts +++ b/src/command-core.ts @@ -38,13 +38,18 @@ export type RawCommand< TOpts extends Record | undefined = | Record | undefined, -> = TOpts extends Record | undefined ? RawCommandWithSubcommands - : RawCommandWithPositionals; + TOptsData = TOpts extends Record ? TypeOf : undefined, + TTransformed = TOptsData, +> = TOpts extends Record | undefined + ? RawCommandWithSubcommands + : RawCommandWithPositionals; export type RawCommandWithPositionals< TOpts extends Record | undefined = | Record | undefined, + TOptsData = TOpts extends Record ? TypeOf : undefined, + TTransformed = TOptsData, > = { name?: string; aliases?: [string, ...string[]]; @@ -52,13 +57,16 @@ export type RawCommandWithPositionals< hidden?: boolean; options?: TOpts; help?: string | Function; - handler?: CommandHandler; + transform?: (options: TOptsData) => TTransformed; + handler?: (options: Awaited) => any; }; export type RawCommandWithSubcommands< TOpts extends Record | undefined = | Record | undefined, + TOptsData = TOpts extends Record ? TypeOf : undefined, + TTransformed = TOptsData, > = { name?: string; aliases?: [string, ...string[]]; @@ -66,7 +74,26 @@ export type RawCommandWithSubcommands< hidden?: boolean; options?: TOpts; help?: string | Function; - handler?: CommandHandler; + transform?: (options: TOptsData) => TTransformed; + handler?: (options: Awaited) => any; + subcommands?: [Command, ...Command[]]; +}; + +export type RawCommandUniversal< + TOpts extends Record | undefined = + | Record + | undefined, + TOptsData = TOpts extends Record ? TypeOf : undefined, + TTransformed = TOptsData, +> = { + name?: string; + aliases?: [string, ...string[]]; + description?: string; + hidden?: boolean; + options?: TOpts; + help?: string | Function; + transform?: (options: TOptsData) => TTransformed; + handler?: (options: Awaited) => any; subcommands?: [Command, ...Command[]]; }; @@ -81,7 +108,8 @@ export type AnyRawCommand< hidden?: boolean; options?: TOpts; help?: string | Function; - handler?: CommandHandler; + transform?: GenericCommandHandler; + handler?: GenericCommandHandler; subcommands?: [Command, ...Command[]]; }; @@ -92,6 +120,7 @@ export type Command = { hidden?: boolean; options?: ProcessedOptions; help?: string | Function; + transform?: GenericCommandHandler; handler: GenericCommandHandler; subcommands?: [Command, ...Command[]]; parent?: Command; @@ -125,7 +154,7 @@ const unknownSubcommand = (command: Command, caller: string) => { return new Error(msg); }; -const missingRequired = (command: RawCommand, missingOpts: [string[], ...string[][]]) => { +const missingRequired = (command: RawCommand, missingOpts: [string[], ...string[][]]) => { const msg = `Command '${command.name}' is missing following required options: ${ missingOpts.map((opt) => { const name = opt.shift()!; @@ -140,7 +169,7 @@ const missingRequired = (command: RawCommand, missingOpts: [string[], ...st return new Error(msg); }; -const unrecognizedOptions = (command: RawCommand, unrecognizedArgs: [string, ...string[]]) => { +const unrecognizedOptions = (command: RawCommand, unrecognizedArgs: [string, ...string[]]) => { const msg = `Unrecognized options for command '${command.name}': ${unrecognizedArgs.join(', ')}`; return new Error(msg); @@ -304,11 +333,15 @@ const validateOptions = | undefined, ->(command: RawCommand) => commandCheckBypass(command); + TOptsData = TOpts extends Record ? TypeOf : undefined, + TTransformed = TOptsData, +>(command: RawCommandUniversal) => commandCheckBypass(command); const commandCheckBypass = < TOpts extends Record | undefined, ->(command: RawCommand, ignoreReserved = true) => { + TOptsData = TOpts extends Record ? TypeOf : undefined, + TTransformed = TOptsData, +>(command: RawCommandUniversal, ignoreReserved = true) => { const allNames = command.aliases ? [command.name, ...command.aliases] : [command.name]; const processedOptions = command.options ? validateOptions(command.options) : undefined; @@ -725,7 +758,7 @@ export const rawCli = async (commands: Command[], config?: BroCliConfig) => { options = parseOptions(command, newArgs, omitKeysOfUndefinedOptions); cmd = command; - await cmd.handler(options); + await cmd.handler(command.transform ? await command.transform(options) : options); return undefined; }; @@ -740,9 +773,7 @@ export const runCli = async (commands: Command[], config?: BroCliConfig) => { try { await rawCli(commands, config); } catch (e) { - if (e instanceof BroCliError) throw e; - - console.log(typeof e === 'object' && e !== null && 'message' in e ? e.message : e); + console.error(typeof e === 'object' && e !== null && 'message' in e ? e.message : e); process.exit(1); } diff --git a/src/index.ts b/src/index.ts index 55264bf..db6fcb0 100755 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ export type { HelpHandler, InnerCommandParseRes, RawCommand, + RawCommandUniversal, RawCommandWithPositionals, RawCommandWithSubcommands, } from './command-core';