11import { z } from 'zod'
22import { isZodError , ParseError } from './error'
33import { toCamelCase } from './utils'
4+ import { ArgsObject } from './command'
45
5- export const OptionConfig = < T extends z . ZodType > ( type : T ) =>
6+ export const OptionConfig = < OptionType , Args extends ArgsObject = ArgsObject > (
7+ type : z . ZodType < OptionType > ,
8+ ) =>
69 z . object ( {
710 /** Name of the option */
811 name : z . string ( ) ,
@@ -16,7 +19,9 @@ export const OptionConfig = <T extends z.ZodType>(type: T) =>
1619 * Parse the value of the option. You can return any type here, or throw an error if the value
1720 * is invalid.
1821 */
19- parse : z . function ( ) . args ( z . string ( ) ) . returns ( type ) . optional ( ) ,
22+ parse : z . function ( ) . args ( z . string ( ) , z . any ( ) ) . returns ( type ) . optional ( ) as z . ZodOptional <
23+ z . ZodType < Parser < Args , OptionType > >
24+ > ,
2025 /**
2126 * Whether the option is an array.
2227 *
@@ -41,24 +46,33 @@ export const OptionConfig = <T extends z.ZodType>(type: T) =>
4146 /** Specify a custom name for the output, which will be used when parsing the args. */
4247 outputName : z . string ( ) . optional ( ) ,
4348 } )
44- export type OptionConfig < T = unknown > = z . infer < ReturnType < typeof OptionConfig < z . ZodType < T > > > >
49+ export type OptionConfig < T = unknown , Args extends ArgsObject = ArgsObject > = z . infer <
50+ ReturnType < typeof OptionConfig < T , Args > >
51+ >
52+
53+ export type Parser < Args extends ArgsObject = ArgsObject , OptionType extends any = any > = (
54+ x : string ,
55+ y : Args ,
56+ ) => OptionType
4557
46- export const TypedOptionConfig = < T extends z . ZodType > ( type : T ) =>
47- OptionConfig ( type ) . merge (
58+ export const TypedOptionConfig = < OptionType , Args extends ArgsObject = ArgsObject > (
59+ type : z . ZodType < OptionType > ,
60+ ) =>
61+ OptionConfig < OptionType , Args > ( type ) . merge (
4862 z . object ( {
4963 type : z . enum ( [ 'number' ] ) . optional ( ) ,
5064 } ) ,
5165 )
52- export type TypedOptionConfig < T = unknown > = z . infer <
53- ReturnType < typeof TypedOptionConfig < z . ZodType < T > > >
66+ export type TypedOptionConfig < T , A extends ArgsObject = ArgsObject > = z . infer <
67+ ReturnType < typeof TypedOptionConfig < T , A > >
5468>
5569
5670/**
5771 * @see OptionConfig
5872 * @see ArrayOptionConfig
5973 */
60- export const ArrayOptionConfig = < T extends z . ZodType > ( type : T ) =>
61- TypedOptionConfig ( z . array ( type ) ) . merge (
74+ export const ArrayOptionConfig = < T , A extends ArgsObject = ArgsObject > ( type : z . ZodType < T > ) =>
75+ TypedOptionConfig < T [ ] , A > ( z . array ( type ) ) . merge (
6276 // OptionConfig(z.array(type)).merge(
6377 z . object ( {
6478 defaultValue : z . array ( type ) . optional ( ) ,
@@ -105,29 +119,31 @@ export type ArgvValue<T> = { argv: string[]; value: T; key: string }
105119 * })
106120 * ```
107121 */
108- export class MassargOption < T = unknown > {
122+ export class MassargOption < OptionType extends any = unknown , Args extends ArgsObject = ArgsObject > {
109123 name : string
110124 description : string
111- defaultValue ?: T
125+ defaultValue ?: OptionType
112126 aliases : string [ ]
113- parse : ( value : string ) => T
127+ parse : Parser < Args , OptionType >
114128 isArray : boolean
115129 isDefault : boolean
116130 outputName ?: string
117131
118- constructor ( options : OptionConfig < T > ) {
132+ constructor ( options : OptionConfig < OptionType , Args > ) {
119133 OptionConfig ( z . any ( ) ) . parse ( options )
120134 this . name = options . name
121135 this . description = options . description
122136 this . defaultValue = options . defaultValue
123137 this . aliases = options . aliases
124- this . parse = options . parse ?? ( ( x ) => x as unknown as T )
138+ this . parse = options . parse ?? ( ( x : string ) => x as OptionType )
125139 this . isArray = options . array ?? false
126140 this . isDefault = options . isDefault ?? false
127141 this . outputName = options . outputName
128142 }
129143
130- static fromTypedConfig < T = unknown > ( config : TypedOptionConfig < T > ) : MassargOption < T > {
144+ static fromTypedConfig < T = unknown , A extends ArgsObject = ArgsObject > (
145+ config : TypedOptionConfig < T , A > ,
146+ ) : MassargOption < T > {
131147 switch ( config . type ) {
132148 case 'number' :
133149 return new MassargNumber ( config as OptionConfig < number > ) as MassargOption < T >
@@ -139,7 +155,7 @@ export class MassargOption<T = unknown> {
139155 return this . outputName || toCamelCase ( this . name )
140156 }
141157
142- _parseDetails ( argv : string [ ] ) : ArgvValue < T > {
158+ _parseDetails ( argv : string [ ] , options : ArgsObject ) : ArgvValue < OptionType > {
143159 // TODO: support --option=value
144160 let input = ''
145161 try {
@@ -153,7 +169,7 @@ export class MassargOption<T = unknown> {
153169 }
154170 argv . shift ( )
155171 input = argv . shift ( ) !
156- const value = this . parse ( input )
172+ const value = this . parse ( input , options as Args )
157173 return { key : this . getOutputName ( ) , value, argv }
158174 } catch ( e ) {
159175 if ( isZodError ( e ) ) {
@@ -243,13 +259,13 @@ export class MassargNumber extends MassargOption<number> {
243259 constructor ( options : Omit < OptionConfig < number > , 'parse' > ) {
244260 super ( {
245261 ...options ,
246- parse : ( value ) => Number ( value ) ,
262+ parse : ( value ) => Number ( value ) as any ,
247263 } )
248264 }
249265
250- _parseDetails ( argv : string [ ] ) : ArgvValue < number > {
266+ _parseDetails ( argv : string [ ] , options : ArgsObject ) : ArgvValue < number > {
251267 try {
252- const { argv : _argv , value } = super . _parseDetails ( argv )
268+ const { argv : _argv , value } = super . _parseDetails ( argv , options )
253269 if ( isNaN ( value ) ) {
254270 throw new ParseError ( {
255271 path : [ this . name ] ,
@@ -298,7 +314,7 @@ export class MassargFlag extends MassargOption<boolean> {
298314 constructor ( options : Omit < OptionConfig < boolean > , 'parse' > ) {
299315 super ( {
300316 ...options ,
301- parse : ( ) => true ,
317+ parse : ( ) => true as any ,
302318 } )
303319 }
304320
0 commit comments