@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.
@@ -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
- * Supports --schema, --outDir, and --types-only flags with either `--flag value` or `--flag=value` syntax.
10
- * Only returns the flags that were explicitly provided so we can layer them on top of config file values.
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
- // Use a mutable local type for building, then return as Partial<CliConfig>
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
- if (arg.startsWith('--') && arg.includes('=')) {
43
- const equalsIndex = arg.indexOf('=')
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
- if (key === 'schema') {
48
- config.schema = value
49
- } else if (key === 'outDir') {
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
- // Handle --flag value syntax
74
- if (arg === '--schema') {
75
- const value = args[i + 1]
133
+ const key = toCamelCase(arg.slice(2))
76
134
 
77
- if (value && !value.startsWith('--')) {
78
- config.schema = value
79
- i++
80
- }
81
- } else if (arg === '--outDir') {
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
- if (value && !value.startsWith('--')) {
92
- const parsed = parseInputValue(value)
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.export = value
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