@amritk/mjst 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -4
- package/dist/cli-config.d.ts +21 -3
- package/dist/cli.js +345 -176
- package/dist/combine-files.d.ts +13 -0
- package/dist/parse-cli-args.d.ts +4 -2
- package/package.json +4 -4
- package/src/cli-config.ts +21 -3
- package/src/cli.ts +256 -67
- package/src/combine-files.test.ts +49 -0
- package/src/combine-files.ts +43 -0
- package/src/load-config.test.ts +9 -0
- package/src/load-config.ts +3 -0
- package/src/parse-cli-args.test.ts +48 -0
- package/src/parse-cli-args.ts +118 -94
package/src/parse-cli-args.ts
CHANGED
|
@@ -4,123 +4,147 @@ import type { CliConfig } from './cli-config'
|
|
|
4
4
|
|
|
5
5
|
const SOURCE_FORMATS: readonly SourceFormat[] = ['json', 'typebox', 'zod', 'valibot', 'effect']
|
|
6
6
|
|
|
7
|
+
// Mutable shape used while building, returned as Partial<CliConfig>.
|
|
8
|
+
type MutableConfig = {
|
|
9
|
+
schema?: string
|
|
10
|
+
schemaDir?: string
|
|
11
|
+
outDir?: string
|
|
12
|
+
outFile?: string
|
|
13
|
+
input?: SourceFormat
|
|
14
|
+
export?: string
|
|
15
|
+
typesOnly?: boolean
|
|
16
|
+
build?: boolean
|
|
17
|
+
logWarnings?: boolean
|
|
18
|
+
strict?: boolean
|
|
19
|
+
readonly?: boolean
|
|
20
|
+
helpers?: 'package' | 'embedded'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Boolean flags toggle on by presence and accept `--flag=false` to opt out.
|
|
24
|
+
const BOOLEAN_KEYS = new Set<keyof MutableConfig>(['typesOnly', 'build', 'logWarnings', 'strict', 'readonly'])
|
|
25
|
+
// Value flags consume the following argument (or `--flag=value`).
|
|
26
|
+
const VALUE_KEYS = new Set<keyof MutableConfig>([
|
|
27
|
+
'schema',
|
|
28
|
+
'schemaDir',
|
|
29
|
+
'outDir',
|
|
30
|
+
'outFile',
|
|
31
|
+
'input',
|
|
32
|
+
'export',
|
|
33
|
+
'helpers',
|
|
34
|
+
])
|
|
35
|
+
|
|
36
|
+
/** Normalizes a CLI flag name to its camelCase config key so both `--out-dir` and `--outDir` map to `outDir`. */
|
|
37
|
+
const toCamelCase = (key: string): string => key.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())
|
|
38
|
+
|
|
39
|
+
const parseHelpersValue = (value: string): 'package' | 'embedded' | undefined => {
|
|
40
|
+
if (value === 'package' || value === 'embedded') return value
|
|
41
|
+
return undefined
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const parseInputValue = (value: string): SourceFormat | undefined =>
|
|
45
|
+
(SOURCE_FORMATS as readonly string[]).includes(value) ? (value as SourceFormat) : undefined
|
|
46
|
+
|
|
47
|
+
/** Assigns a value-flag onto the config. Returns false for unknown keys. */
|
|
48
|
+
const assignValue = (config: MutableConfig, key: string, value: string): boolean => {
|
|
49
|
+
switch (key) {
|
|
50
|
+
case 'schema':
|
|
51
|
+
config.schema = value
|
|
52
|
+
return true
|
|
53
|
+
case 'schemaDir':
|
|
54
|
+
config.schemaDir = value
|
|
55
|
+
return true
|
|
56
|
+
case 'outDir':
|
|
57
|
+
config.outDir = value
|
|
58
|
+
return true
|
|
59
|
+
case 'outFile':
|
|
60
|
+
config.outFile = value
|
|
61
|
+
return true
|
|
62
|
+
case 'export':
|
|
63
|
+
config.export = value
|
|
64
|
+
return true
|
|
65
|
+
case 'input': {
|
|
66
|
+
const parsed = parseInputValue(value)
|
|
67
|
+
if (parsed) config.input = parsed
|
|
68
|
+
return true
|
|
69
|
+
}
|
|
70
|
+
case 'helpers': {
|
|
71
|
+
const parsed = parseHelpersValue(value)
|
|
72
|
+
if (parsed) config.helpers = parsed
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
default:
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Assigns a boolean flag onto the config. Returns false for unknown keys. */
|
|
81
|
+
const assignBoolean = (config: MutableConfig, key: string, value: boolean): boolean => {
|
|
82
|
+
switch (key) {
|
|
83
|
+
case 'typesOnly':
|
|
84
|
+
config.typesOnly = value
|
|
85
|
+
return true
|
|
86
|
+
case 'build':
|
|
87
|
+
config.build = value
|
|
88
|
+
return true
|
|
89
|
+
case 'logWarnings':
|
|
90
|
+
config.logWarnings = value
|
|
91
|
+
return true
|
|
92
|
+
case 'strict':
|
|
93
|
+
config.strict = value
|
|
94
|
+
return true
|
|
95
|
+
case 'readonly':
|
|
96
|
+
config.readonly = value
|
|
97
|
+
return true
|
|
98
|
+
default:
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
7
103
|
/**
|
|
8
104
|
* Parses command-line arguments into a partial CLI config.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
105
|
+
* Every flag accepts both kebab-case and camelCase (e.g. `--out-dir` and `--outDir`)
|
|
106
|
+
* and supports either `--flag value` or `--flag=value` syntax. Boolean flags toggle
|
|
107
|
+
* on by presence and accept `--flag=false` to opt out. Only flags that were explicitly
|
|
108
|
+
* provided are returned so they can be layered on top of config file values.
|
|
11
109
|
*/
|
|
12
110
|
export const parseCliArgs = (args: readonly string[]): Partial<CliConfig> => {
|
|
13
|
-
|
|
14
|
-
const config: {
|
|
15
|
-
schema?: string
|
|
16
|
-
outDir?: string
|
|
17
|
-
input?: SourceFormat
|
|
18
|
-
export?: string
|
|
19
|
-
typesOnly?: boolean
|
|
20
|
-
build?: boolean
|
|
21
|
-
logWarnings?: boolean
|
|
22
|
-
strict?: boolean
|
|
23
|
-
helpers?: 'package' | 'embedded'
|
|
24
|
-
} = {}
|
|
25
|
-
|
|
26
|
-
const parseHelpersValue = (value: string): 'package' | 'embedded' | undefined => {
|
|
27
|
-
if (value === 'package' || value === 'embedded') return value
|
|
28
|
-
return undefined
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const parseInputValue = (value: string): SourceFormat | undefined =>
|
|
32
|
-
(SOURCE_FORMATS as readonly string[]).includes(value) ? (value as SourceFormat) : undefined
|
|
111
|
+
const config: MutableConfig = {}
|
|
33
112
|
|
|
34
113
|
for (let i = 0; i < args.length; i++) {
|
|
35
114
|
const arg = args[i]
|
|
36
115
|
|
|
37
|
-
if (!arg) {
|
|
116
|
+
if (!arg || !arg.startsWith('--')) {
|
|
38
117
|
continue
|
|
39
118
|
}
|
|
40
119
|
|
|
41
120
|
// Handle --flag=value syntax
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const key = arg.slice(2, equalsIndex)
|
|
121
|
+
const equalsIndex = arg.indexOf('=')
|
|
122
|
+
if (equalsIndex !== -1) {
|
|
123
|
+
const key = toCamelCase(arg.slice(2, equalsIndex))
|
|
45
124
|
const value = arg.slice(equalsIndex + 1)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
config.outDir = value
|
|
51
|
-
} else if (key === 'input') {
|
|
52
|
-
const parsed = parseInputValue(value)
|
|
53
|
-
if (parsed) config.input = parsed
|
|
54
|
-
} else if (key === 'export') {
|
|
55
|
-
config.export = value
|
|
56
|
-
} else if (key === 'types-only') {
|
|
57
|
-
// Accept --types-only=false to explicitly opt out, otherwise treat as true
|
|
58
|
-
config.typesOnly = value !== 'false'
|
|
59
|
-
} else if (key === 'build') {
|
|
60
|
-
config.build = value !== 'false'
|
|
61
|
-
} else if (key === 'log-warnings') {
|
|
62
|
-
config.logWarnings = value !== 'false'
|
|
63
|
-
} else if (key === 'strict') {
|
|
64
|
-
config.strict = value !== 'false'
|
|
65
|
-
} else if (key === 'helpers') {
|
|
66
|
-
const parsed = parseHelpersValue(value)
|
|
67
|
-
if (parsed) config.helpers = parsed
|
|
125
|
+
if (BOOLEAN_KEYS.has(key as keyof MutableConfig)) {
|
|
126
|
+
assignBoolean(config, key, value !== 'false')
|
|
127
|
+
} else {
|
|
128
|
+
assignValue(config, key, value)
|
|
68
129
|
}
|
|
69
|
-
|
|
70
130
|
continue
|
|
71
131
|
}
|
|
72
132
|
|
|
73
|
-
|
|
74
|
-
if (arg === '--schema') {
|
|
75
|
-
const value = args[i + 1]
|
|
133
|
+
const key = toCamelCase(arg.slice(2))
|
|
76
134
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
const value = args[i + 1]
|
|
83
|
-
|
|
84
|
-
if (value && !value.startsWith('--')) {
|
|
85
|
-
config.outDir = value
|
|
86
|
-
i++
|
|
87
|
-
}
|
|
88
|
-
} else if (arg === '--input') {
|
|
89
|
-
const value = args[i + 1]
|
|
135
|
+
// Boolean flag: presence alone enables it, no value needed
|
|
136
|
+
if (BOOLEAN_KEYS.has(key as keyof MutableConfig)) {
|
|
137
|
+
assignBoolean(config, key, true)
|
|
138
|
+
continue
|
|
139
|
+
}
|
|
90
140
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (parsed) {
|
|
94
|
-
config.input = parsed
|
|
95
|
-
i++
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} else if (arg === '--export') {
|
|
141
|
+
// Value flag: consume the next argument when it is not another flag
|
|
142
|
+
if (VALUE_KEYS.has(key as keyof MutableConfig)) {
|
|
99
143
|
const value = args[i + 1]
|
|
100
|
-
|
|
101
144
|
if (value && !value.startsWith('--')) {
|
|
102
|
-
config
|
|
145
|
+
assignValue(config, key, value)
|
|
103
146
|
i++
|
|
104
147
|
}
|
|
105
|
-
} else if (arg === '--types-only') {
|
|
106
|
-
// Boolean flag: presence alone enables it, no value needed
|
|
107
|
-
config.typesOnly = true
|
|
108
|
-
} else if (arg === '--build') {
|
|
109
|
-
config.build = true
|
|
110
|
-
} else if (arg === '--log-warnings') {
|
|
111
|
-
config.logWarnings = true
|
|
112
|
-
} else if (arg === '--strict') {
|
|
113
|
-
config.strict = true
|
|
114
|
-
} else if (arg === '--helpers') {
|
|
115
|
-
const value = args[i + 1]
|
|
116
|
-
|
|
117
|
-
if (value && !value.startsWith('--')) {
|
|
118
|
-
const parsed = parseHelpersValue(value)
|
|
119
|
-
if (parsed) {
|
|
120
|
-
config.helpers = parsed
|
|
121
|
-
i++
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
148
|
}
|
|
125
149
|
}
|
|
126
150
|
|