1- import chalk from "chalk"
2- import { CommandDef , ExampleDef , HelpDef , MainDef , OptionDef } from "./options"
3- import { asArray } from "./utils"
1+ import { CommandDef , ExampleDef , HelpDef , MainDef , Named , OptionDef } from "./options"
2+ import { ArrayOr , asArray } from "./utils"
43
5- export function assert ( condition : any , message ?: string ) : void {
4+ // prettier-ignore
5+ export const colorList = [
6+ "reset" , "bold" , "dim" , "italic" , "underline" , "inverse" , "hidden" , "strikethrough" , "black" , "red" , "green" ,
7+ "yellow" , "blue" , "magenta" , "cyan" , "white" , "gray" , "bgBlack" , "bgRed" , "bgGreen" , "bgYellow" , "bgBlue" ,
8+ "bgMagenta" , "bgCyan" , "bgWhite" ,
9+ ]
10+
11+ function assert ( condition : any , message ?: string ) : void {
612 if ( ! condition ) {
713 throw new Error ( message )
814 }
@@ -12,146 +18,93 @@ function nullOr(condition: any, condition2: any): boolean {
1218 return [ null , undefined ] . includes ( condition ) || condition2
1319}
1420
15- export const colorList = [
16- "reset" ,
17- "bold" ,
18- "dim" ,
19- "italic" ,
20- "underline" ,
21- "inverse" ,
22- "hidden" ,
23- "strikethrough" ,
24- "black" ,
25- "red" ,
26- "green" ,
27- "yellow" ,
28- "blue" ,
29- "magenta" ,
30- "cyan" ,
31- "white" ,
32- "gray" ,
33- "bgBlack" ,
34- "bgRed" ,
35- "bgGreen" ,
36- "bgYellow" ,
37- "bgBlue" ,
38- "bgMagenta" ,
39- "bgCyan" ,
40- "bgWhite" ,
41- ]
21+ function assertType ( obj : any , prefix : string , name : string , options : { type : string ; required ?: boolean } ) : void {
22+ if ( options . required ) {
23+ assert ( ! [ undefined , null ] . includes ( obj ) , `${ prefix } : ${ name } must be provided` )
24+ } else if ( [ null , undefined ] . includes ( obj ) ) {
25+ return
26+ }
4227
43- export function assertHelp ( help : HelpDef ) {
44- assert ( nullOr ( help . binName , typeof help . binName === "string" ) , "Help: Binary Name must be string" )
45- assert (
46- nullOr (
47- help . normalColors ,
48- asArray ( help . normalColors ) . every ( ( c ) => colorList . includes ( c ! ) )
49- ) ,
50- "Help: Normal colors must be string or array of strings. Accepted values: " + colorList . join ( ", " )
51- )
52- assert (
53- nullOr (
54- help . bodyColors ,
55- asArray ( help . bodyColors ) . every ( ( c ) => colorList . includes ( c ! ) )
56- ) ,
57- "Help: Body colors must be string or array of strings. Accepted values: " + colorList . join ( ", " )
58- )
59- assert (
60- nullOr (
61- help . titleColors ,
62- asArray ( help . titleColors ) . every ( ( c ) => colorList . includes ( c ! ) )
63- ) ,
64- "Help: Title colors must be string or array of strings. Accepted values: " + colorList . join ( ", " )
65- )
66- assert (
67- nullOr (
68- help . subtitleColors ,
69- asArray ( help . subtitleColors ) . every ( ( c ) => colorList . includes ( c ! ) )
70- ) ,
71- "Help: Subtitle colors must be string or array of strings. Accepted values: " + colorList . join ( ", " )
72- )
28+ assert ( typeof obj === options . type , `${ prefix } : ${ name } must be ${ options . type } ` )
29+ }
30+
31+ function assertNumber (
32+ obj : number | null | undefined ,
33+ prefix : string ,
34+ name : string ,
35+ options : { min ?: number ; max ?: number ; required ?: boolean }
36+ ) : void {
37+ assertType ( obj , prefix , name , { required : options . required , type : "number" } )
38+
39+ if ( ! options . required && [ null , undefined ] . includes ( obj as any ) ) {
40+ return
41+ }
42+
43+ if ( typeof options . max === "number" ) {
44+ assert ( obj ! <= options . max , `${ prefix } : ${ name } must be ≤ ${ options . max } ` )
45+ }
46+ if ( typeof options . min === "number" ) {
47+ assert ( obj ! >= options . min , `${ prefix } : ${ name } must be ≥ ${ options . min } ` )
48+ }
49+ }
50+
51+ function assertColor ( color : ArrayOr < string > | undefined , prefix : string , name : string ) {
7352 assert (
7453 nullOr (
75- help . highlightColors ,
76- asArray ( help . highlightColors ) . every ( ( c ) => colorList . includes ( c ! ) )
54+ color ,
55+ asArray ( color ) . every ( ( c ) => colorList . includes ( c ! ) )
7756 ) ,
78- "Help: Highlight colors must be string or array of strings. Accepted values: " + colorList . join ( ", " )
79- )
80- assert ( nullOr ( help . footer , typeof help . footer === "string" ) , "Help: Footer must be string" )
81- assert ( nullOr ( help . header , typeof help . header === "string" ) , "Help: Header must be string" )
82- assert (
83- nullOr ( help . optionNameSeparator , typeof help . optionNameSeparator === "string" ) ,
84- "Help: Option Name Separator must be string"
85- )
86- assert (
87- nullOr ( help . commandNameSeparator , typeof help . commandNameSeparator === "string" ) ,
88- "Help: Command Name Separator must be string"
89- )
90- assert (
91- nullOr ( help . printWidth , typeof help . printWidth === "number" && help . printWidth >= 0 ) ,
92- "Help: Print Width must be a number ≥ 0"
93- )
94- assert (
95- nullOr ( help . exampleInputPrefix , typeof help . exampleInputPrefix === "string" ) ,
96- "Help: Example Input Prefix must be string"
97- )
98- assert (
99- nullOr ( help . exampleOutputPrefix , typeof help . exampleOutputPrefix === "string" ) ,
100- "Help: Example Output Prefix must be string"
101- )
102- assert ( nullOr ( help . usageExample , typeof help . usageExample === "string" ) , "Help: Usage Example must be string" )
103- assert (
104- nullOr ( help . useGlobalColumns , typeof help . useGlobalColumns === "boolean" ) ,
105- "Help: Use Global Columns must be boolean"
57+ `${ prefix } : ${ name } must be string or array of strings. Accepted values: ` + colorList . join ( ", " )
10658 )
59+ }
60+
61+ function assertAliases ( def : Named , allDefs : Named [ ] , prefix : string ) {
10762 assert (
108- nullOr ( help . includeDefaults , typeof help . includeDefaults === "boolean" ) ,
109- "Help: Include Defaults must be boolean"
63+ ! def . aliases || def . aliases . every ( ( a ) => ! allDefs . find ( ( opt ) => [ opt . name , ... ( opt . aliases ?? [ ] ) ] . includes ( a ) ) ) ,
64+ ` ${ prefix } : Aliases must be unique`
11065 )
111- assert ( nullOr ( help . useColors , typeof help . useColors === "boolean" ) , "Help: Use Colors must be boolean" )
66+ }
67+
68+ export function assertHelp ( help : HelpDef ) {
69+ assertType ( help . binName , "Help" , "Binary Name" , { type : "string" } )
70+ assertColor ( help . normalColors , "Help" , "Normal colors" )
71+ assertColor ( help . bodyColors , "Help" , "Body colors" )
72+ assertColor ( help . titleColors , "Help" , "Title colors" )
73+ assertColor ( help . subtitleColors , "Help" , "Subtitle colors" )
74+ assertColor ( help . highlightColors , "Help" , "Highlight colors" )
75+ assertType ( help . footer , "Help" , "Footer" , { type : "string" } )
76+ assertType ( help . header , "Help" , "Header" , { type : "string" } )
77+ assertType ( help . optionNameSeparator , "Help" , "Option Name Separator" , { type : "string" } )
78+ assertType ( help . commandNameSeparator , "Help" , "Command Name Separator" , { type : "string" } )
79+ assertNumber ( help . printWidth , "Help" , "Print Width" , { min : 0 } )
80+ assertType ( help . exampleInputPrefix , "Help" , "Example Input Prefix" , { type : "string" } )
81+ assertType ( help . exampleOutputPrefix , "Help" , "Example Output Prefix" , { type : "string" } )
82+ assertType ( help . usageExample , "Help" , "Usage Example" , { type : "string" } )
83+ assertType ( help . useGlobalColumns , "Help" , "Use Global Columns" , { type : "boolean" } )
84+ assertType ( help . includeDefaults , "Help" , "Include Defaults" , { type : "boolean" } )
85+ assertType ( help . useColors , "Help" , "Use Colors" , { type : "boolean" } )
11286}
11387
11488export function assertCommand ( command : CommandDef < any > , allCommands : CommandDef < any > [ ] ) : void {
115- assert ( command . name , "Command: Name must be provided" )
116- assert ( typeof command . name === "string" , "Command: Name must be string" )
117- assert (
118- ! command . aliases ||
119- command . aliases . every ( ( a ) => ! allCommands . find ( ( cmd ) => cmd . name === a || cmd . aliases ?. includes ( a ) ) ) ,
120- "Command: Aliases must be unique"
121- )
122- assert ( command . run , "Command: Run function must be provided" )
123- assert ( typeof command . run === "function" , "Command: Run must be a function" )
89+ assertType ( command . name , "Command" , "Name" , { required : true , type : "string" } )
90+ assertAliases ( command , allCommands , "Command" )
91+ assertType ( command . run , "Command" , "Run" , { required : true , type : "function" } )
12492}
12593
12694export function assertOption ( option : OptionDef < any , any > , allOptions : OptionDef < any , any > [ ] ) : void {
12795 assert ( option . name , "Option: Name must be provided" )
12896 assert ( typeof option . name === "string" , "Option: Name must be string" )
129-
130- assert (
131- nullOr (
132- option . aliases ,
133- option . aliases ?. every ( ( a ) => typeof a === "string" )
134- ) ,
135- "Option: Aliases must an array of strings"
136- )
137- assert (
138- nullOr (
139- option . aliases ,
140- option . aliases ?. every ( ( a ) => ! allOptions . find ( ( opt ) => opt . name === a || opt . aliases ?. includes ( a ) ) )
141- ) ,
142- "Option: Aliases must be unique"
143- )
144- assert ( nullOr ( option . boolean , typeof [ "undefined" , "boolean" ] . includes ( typeof option . defaultValue ) ) )
145-
146- assert ( typeof option . parse === "function" , "Option: Parse must be a function" )
97+ assertAliases ( option , allOptions , "Option" )
98+ assertType ( option . boolean , "Option" , "Default Value" , { type : "boolean" } )
99+ assertType ( option . parse , "Option" , "Parse" , { type : "function" } )
147100}
148101
149102export function assertExample ( example : ExampleDef ) {
150- assert ( example . input , "Example: Input must be provided" )
151- assert ( typeof example . output === "string" , 'Example: Output must be provided. To signify empty output, use ""' )
103+ assertType ( example . input , "Example" , "Input" , { required : true , type : "string" } )
104+ assertType ( example . output , "Example" , "Output" , { required : true , type : "string" } )
105+ assertType ( example . description , "Example" , "Description" , { type : "string" } )
152106}
153107
154108export function assertMain ( run : MainDef < any > ) {
155- assert ( run , "Main: Main function must be provided" )
156- assert ( typeof run === "function" , "Main: Main must be a function" )
109+ assertType ( run , "Main" , "Main" , { required : true , type : "function" } )
157110}
0 commit comments