@amritk/mjst 0.7.5 → 0.7.7

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.
@@ -1,174 +0,0 @@
1
- import type { SourceFormat } from '@amritk/adapters/source-format'
2
-
3
- import type { CliConfig } from './cli-config'
4
-
5
- const SOURCE_FORMATS: readonly SourceFormat[] = ['json', 'typebox', 'zod', 'valibot', 'effect']
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
- typeSuffix?: string
22
- banner?: boolean | string
23
- }
24
-
25
- // Boolean flags toggle on by presence and accept `--flag=false` to opt out.
26
- const BOOLEAN_KEYS = new Set<keyof MutableConfig>(['typesOnly', 'build', 'logWarnings', 'strict', 'readonly'])
27
- // Value flags consume the following argument (or `--flag=value`).
28
- const VALUE_KEYS = new Set<keyof MutableConfig>([
29
- 'schema',
30
- 'schemaDir',
31
- 'outDir',
32
- 'outFile',
33
- 'input',
34
- 'export',
35
- 'helpers',
36
- 'typeSuffix',
37
- ])
38
-
39
- /** Normalizes a CLI flag name to its camelCase config key so both `--out-dir` and `--outDir` map to `outDir`. */
40
- const toCamelCase = (key: string): string => key.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())
41
-
42
- const parseHelpersValue = (value: string): 'package' | 'embedded' | undefined => {
43
- if (value === 'package' || value === 'embedded') return value
44
- return undefined
45
- }
46
-
47
- const parseInputValue = (value: string): SourceFormat | undefined =>
48
- (SOURCE_FORMATS as readonly string[]).includes(value) ? (value as SourceFormat) : undefined
49
-
50
- /** Assigns a value-flag onto the config. Returns false for unknown keys. */
51
- const assignValue = (config: MutableConfig, key: string, value: string): boolean => {
52
- switch (key) {
53
- case 'schema':
54
- config.schema = value
55
- return true
56
- case 'schemaDir':
57
- config.schemaDir = value
58
- return true
59
- case 'outDir':
60
- config.outDir = value
61
- return true
62
- case 'outFile':
63
- config.outFile = value
64
- return true
65
- case 'export':
66
- config.export = value
67
- return true
68
- case 'typeSuffix':
69
- config.typeSuffix = value
70
- return true
71
- case 'input': {
72
- const parsed = parseInputValue(value)
73
- if (parsed) config.input = parsed
74
- return true
75
- }
76
- case 'helpers': {
77
- const parsed = parseHelpersValue(value)
78
- if (parsed) config.helpers = parsed
79
- return true
80
- }
81
- default:
82
- return false
83
- }
84
- }
85
-
86
- /** Assigns a boolean flag onto the config. Returns false for unknown keys. */
87
- const assignBoolean = (config: MutableConfig, key: string, value: boolean): boolean => {
88
- switch (key) {
89
- case 'typesOnly':
90
- config.typesOnly = value
91
- return true
92
- case 'build':
93
- config.build = value
94
- return true
95
- case 'logWarnings':
96
- config.logWarnings = value
97
- return true
98
- case 'strict':
99
- config.strict = value
100
- return true
101
- case 'readonly':
102
- config.readonly = value
103
- return true
104
- default:
105
- return false
106
- }
107
- }
108
-
109
- /**
110
- * Parses command-line arguments into a partial CLI config.
111
- * Every flag accepts both kebab-case and camelCase (e.g. `--out-dir` and `--outDir`)
112
- * and supports either `--flag value` or `--flag=value` syntax. Boolean flags toggle
113
- * on by presence and accept `--flag=false` to opt out. Only flags that were explicitly
114
- * provided are returned so they can be layered on top of config file values.
115
- */
116
- export const parseCliArgs = (args: readonly string[]): Partial<CliConfig> => {
117
- const config: MutableConfig = {}
118
-
119
- for (let i = 0; i < args.length; i++) {
120
- const arg = args[i]
121
-
122
- if (!arg || !arg.startsWith('--')) {
123
- continue
124
- }
125
-
126
- // Handle --flag=value syntax
127
- const equalsIndex = arg.indexOf('=')
128
- if (equalsIndex !== -1) {
129
- const key = toCamelCase(arg.slice(2, equalsIndex))
130
- const value = arg.slice(equalsIndex + 1)
131
- if (key === 'banner') {
132
- // --banner=false → false, --banner=true → true, --banner=<text> → custom string
133
- config.banner = value === 'false' ? false : value === 'true' ? true : value
134
- } else if (BOOLEAN_KEYS.has(key as keyof MutableConfig)) {
135
- assignBoolean(config, key, value !== 'false')
136
- } else {
137
- assignValue(config, key, value)
138
- }
139
- continue
140
- }
141
-
142
- const key = toCamelCase(arg.slice(2))
143
-
144
- // --banner: presence alone enables the default message; an immediately
145
- // following non-flag argument is treated as a custom message string.
146
- if (key === 'banner') {
147
- const nextArg = args[i + 1]
148
- if (nextArg && !nextArg.startsWith('--')) {
149
- config.banner = nextArg
150
- i++
151
- } else {
152
- config.banner = true
153
- }
154
- continue
155
- }
156
-
157
- // Boolean flag: presence alone enables it, no value needed
158
- if (BOOLEAN_KEYS.has(key as keyof MutableConfig)) {
159
- assignBoolean(config, key, true)
160
- continue
161
- }
162
-
163
- // Value flag: consume the next argument when it is not another flag
164
- if (VALUE_KEYS.has(key as keyof MutableConfig)) {
165
- const value = args[i + 1]
166
- if (value && !value.startsWith('--')) {
167
- assignValue(config, key, value)
168
- i++
169
- }
170
- }
171
- }
172
-
173
- return config
174
- }
@@ -1,18 +0,0 @@
1
- import { readFile } from 'node:fs/promises'
2
- import { describe, expect, it } from 'vitest'
3
-
4
- import { readVersion } from './read-version'
5
-
6
- describe('read-version', () => {
7
- it('returns the version declared in the package.json', async () => {
8
- const pkg = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf-8')) as {
9
- version: string
10
- }
11
-
12
- expect(await readVersion()).toBe(pkg.version)
13
- })
14
-
15
- it('returns a semver-shaped string', async () => {
16
- expect(await readVersion()).toMatch(/^\d+\.\d+\.\d+/)
17
- })
18
- })
@@ -1,14 +0,0 @@
1
- import { readFile } from 'node:fs/promises'
2
-
3
- /**
4
- * Reads the CLI's own version from its `package.json`.
5
- *
6
- * Resolved relative to this module so it works whether the code runs from
7
- * `src/` (dev) or the bundled `dist/cli.js` (published) — `package.json`
8
- * sits one directory above both.
9
- */
10
- export const readVersion = async (): Promise<string> => {
11
- const pkgUrl = new URL('../package.json', import.meta.url)
12
- const pkg = JSON.parse(await readFile(pkgUrl, 'utf-8')) as { version?: string }
13
- return pkg.version ?? '0.0.0'
14
- }