mdcontext 0.0.1 → 0.1.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/.changeset/README.md +28 -0
- package/.changeset/config.json +11 -0
- package/.github/workflows/ci.yml +83 -0
- package/.github/workflows/release.yml +113 -0
- package/.tldrignore +112 -0
- package/AGENTS.md +46 -0
- package/BACKLOG.md +338 -0
- package/README.md +231 -11
- package/biome.json +36 -0
- package/cspell.config.yaml +14 -0
- package/dist/chunk-KRYIFLQR.js +92 -0
- package/dist/chunk-S7E6TFX6.js +742 -0
- package/dist/chunk-VVTGZNBT.js +1519 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +2015 -0
- package/dist/index.d.ts +266 -0
- package/dist/index.js +86 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +376 -0
- package/docs/019-USAGE.md +586 -0
- package/docs/020-current-implementation.md +364 -0
- package/docs/021-DOGFOODING-FINDINGS.md +175 -0
- package/docs/BACKLOG.md +80 -0
- package/docs/DESIGN.md +439 -0
- package/docs/PROJECT.md +88 -0
- package/docs/ROADMAP.md +407 -0
- package/docs/test-links.md +9 -0
- package/package.json +69 -10
- package/pnpm-workspace.yaml +5 -0
- package/research/config-analysis/01-current-implementation.md +470 -0
- package/research/config-analysis/02-strategy-recommendation.md +428 -0
- package/research/config-analysis/03-task-candidates.md +715 -0
- package/research/config-analysis/033-research-configuration-management.md +828 -0
- package/research/config-analysis/034-research-effect-cli-config.md +1504 -0
- package/research/config-analysis/04-consolidated-task-candidates.md +277 -0
- package/research/dogfood/consolidated-tool-evaluation.md +373 -0
- package/research/dogfood/strategy-a/a-synthesis.md +184 -0
- package/research/dogfood/strategy-a/a1-docs.md +226 -0
- package/research/dogfood/strategy-a/a2-amorphic.md +156 -0
- package/research/dogfood/strategy-a/a3-llm.md +164 -0
- package/research/dogfood/strategy-b/b-synthesis.md +228 -0
- package/research/dogfood/strategy-b/b1-architecture.md +207 -0
- package/research/dogfood/strategy-b/b2-gaps.md +258 -0
- package/research/dogfood/strategy-b/b3-workflows.md +250 -0
- package/research/dogfood/strategy-c/c-synthesis.md +451 -0
- package/research/dogfood/strategy-c/c1-explorer.md +192 -0
- package/research/dogfood/strategy-c/c2-diver-memory.md +145 -0
- package/research/dogfood/strategy-c/c3-diver-control.md +148 -0
- package/research/dogfood/strategy-c/c4-diver-failure.md +151 -0
- package/research/dogfood/strategy-c/c5-diver-execution.md +221 -0
- package/research/dogfood/strategy-c/c6-diver-org.md +221 -0
- package/research/effect-cli-error-handling.md +845 -0
- package/research/effect-errors-as-values.md +943 -0
- package/research/errors-task-analysis/00-consolidated-tasks.md +207 -0
- package/research/errors-task-analysis/cli-commands-analysis.md +909 -0
- package/research/errors-task-analysis/embeddings-analysis.md +709 -0
- package/research/errors-task-analysis/index-search-analysis.md +812 -0
- package/research/mdcontext-error-analysis.md +521 -0
- package/research/npm_publish/011-npm-workflow-research-agent2.md +792 -0
- package/research/npm_publish/012-npm-workflow-research-agent1.md +530 -0
- package/research/npm_publish/013-npm-workflow-research-agent3.md +722 -0
- package/research/npm_publish/014-npm-workflow-synthesis.md +556 -0
- package/research/npm_publish/031-npm-workflow-task-analysis.md +134 -0
- package/research/semantic-search/002-research-embedding-models.md +490 -0
- package/research/semantic-search/003-research-rag-alternatives.md +523 -0
- package/research/semantic-search/004-research-vector-search.md +841 -0
- package/research/semantic-search/032-research-semantic-search.md +427 -0
- package/research/task-management-2026/00-synthesis-recommendations.md +295 -0
- package/research/task-management-2026/01-ai-workflow-tools.md +416 -0
- package/research/task-management-2026/02-agent-framework-patterns.md +476 -0
- package/research/task-management-2026/03-lightweight-file-based.md +567 -0
- package/research/task-management-2026/04-established-tools-ai-features.md +541 -0
- package/research/task-management-2026/linear/01-core-features-workflow.md +771 -0
- package/research/task-management-2026/linear/02-api-integrations.md +930 -0
- package/research/task-management-2026/linear/03-ai-features.md +368 -0
- package/research/task-management-2026/linear/04-pricing-setup.md +205 -0
- package/research/task-management-2026/linear/05-usage-patterns-best-practices.md +605 -0
- package/scripts/rebuild-hnswlib.js +63 -0
- package/src/cli/argv-preprocessor.test.ts +210 -0
- package/src/cli/argv-preprocessor.ts +202 -0
- package/src/cli/cli.test.ts +430 -0
- package/src/cli/commands/backlinks.ts +54 -0
- package/src/cli/commands/context.ts +197 -0
- package/src/cli/commands/index-cmd.ts +300 -0
- package/src/cli/commands/index.ts +13 -0
- package/src/cli/commands/links.ts +52 -0
- package/src/cli/commands/search.ts +451 -0
- package/src/cli/commands/stats.ts +146 -0
- package/src/cli/commands/tree.ts +107 -0
- package/src/cli/flag-schemas.ts +275 -0
- package/src/cli/help.ts +386 -0
- package/src/cli/index.ts +9 -0
- package/src/cli/main.ts +145 -0
- package/src/cli/options.ts +31 -0
- package/src/cli/typo-suggester.test.ts +105 -0
- package/src/cli/typo-suggester.ts +130 -0
- package/src/cli/utils.ts +126 -0
- package/src/core/index.ts +1 -0
- package/src/core/types.ts +140 -0
- package/src/embeddings/index.ts +8 -0
- package/src/embeddings/openai-provider.ts +165 -0
- package/src/embeddings/semantic-search.ts +583 -0
- package/src/embeddings/types.ts +82 -0
- package/src/embeddings/vector-store.ts +299 -0
- package/src/index/index.ts +4 -0
- package/src/index/indexer.ts +446 -0
- package/src/index/storage.ts +196 -0
- package/src/index/types.ts +109 -0
- package/src/index/watcher.ts +131 -0
- package/src/index.ts +8 -0
- package/src/mcp/server.ts +483 -0
- package/src/parser/index.ts +1 -0
- package/src/parser/parser.test.ts +291 -0
- package/src/parser/parser.ts +395 -0
- package/src/parser/section-filter.ts +270 -0
- package/src/search/query-parser.test.ts +260 -0
- package/src/search/query-parser.ts +319 -0
- package/src/search/searcher.test.ts +182 -0
- package/src/search/searcher.ts +602 -0
- package/src/summarize/budget-bugs.test.ts +620 -0
- package/src/summarize/formatters.ts +419 -0
- package/src/summarize/index.ts +20 -0
- package/src/summarize/summarizer.test.ts +275 -0
- package/src/summarize/summarizer.ts +528 -0
- package/src/summarize/verify-bugs.test.ts +238 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/tokens.test.ts +142 -0
- package/src/utils/tokens.ts +186 -0
- package/tests/fixtures/cli/.mdcontext/config.json +8 -0
- package/tests/fixtures/cli/.mdcontext/indexes/documents.json +33 -0
- package/tests/fixtures/cli/.mdcontext/indexes/links.json +12 -0
- package/tests/fixtures/cli/.mdcontext/indexes/sections.json +233 -0
- package/tests/fixtures/cli/.mdcontext/vectors.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/vectors.meta.json +1264 -0
- package/tests/fixtures/cli/README.md +9 -0
- package/tests/fixtures/cli/api-reference.md +11 -0
- package/tests/fixtures/cli/getting-started.md +11 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +21 -0
- package/vitest.setup.ts +12 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for argv-preprocessor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it } from 'vitest'
|
|
6
|
+
import { preprocessArgvWithValidation } from './argv-preprocessor.js'
|
|
7
|
+
|
|
8
|
+
describe('preprocessArgvWithValidation', () => {
|
|
9
|
+
const node = '/usr/bin/node'
|
|
10
|
+
const script = '/path/to/mdcontext'
|
|
11
|
+
|
|
12
|
+
describe('flag reordering', () => {
|
|
13
|
+
it('reorders flags before positional args', () => {
|
|
14
|
+
const result = preprocessArgvWithValidation([
|
|
15
|
+
node,
|
|
16
|
+
script,
|
|
17
|
+
'search',
|
|
18
|
+
'query',
|
|
19
|
+
'--limit',
|
|
20
|
+
'5',
|
|
21
|
+
'docs/',
|
|
22
|
+
])
|
|
23
|
+
expect(result.argv).toEqual([
|
|
24
|
+
node,
|
|
25
|
+
script,
|
|
26
|
+
'search',
|
|
27
|
+
'--limit',
|
|
28
|
+
'5',
|
|
29
|
+
'query',
|
|
30
|
+
'docs/',
|
|
31
|
+
])
|
|
32
|
+
expect(result.error).toBeUndefined()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('handles --flag=value syntax', () => {
|
|
36
|
+
const result = preprocessArgvWithValidation([
|
|
37
|
+
node,
|
|
38
|
+
script,
|
|
39
|
+
'search',
|
|
40
|
+
'query',
|
|
41
|
+
'--limit=5',
|
|
42
|
+
'docs/',
|
|
43
|
+
])
|
|
44
|
+
expect(result.argv).toEqual([
|
|
45
|
+
node,
|
|
46
|
+
script,
|
|
47
|
+
'search',
|
|
48
|
+
'--limit=5',
|
|
49
|
+
'query',
|
|
50
|
+
'docs/',
|
|
51
|
+
])
|
|
52
|
+
expect(result.error).toBeUndefined()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('handles boolean flags', () => {
|
|
56
|
+
const result = preprocessArgvWithValidation([
|
|
57
|
+
node,
|
|
58
|
+
script,
|
|
59
|
+
'context',
|
|
60
|
+
'file.md',
|
|
61
|
+
'--brief',
|
|
62
|
+
])
|
|
63
|
+
expect(result.argv).toEqual([
|
|
64
|
+
node,
|
|
65
|
+
script,
|
|
66
|
+
'context',
|
|
67
|
+
'--brief',
|
|
68
|
+
'file.md',
|
|
69
|
+
])
|
|
70
|
+
expect(result.error).toBeUndefined()
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('passes through --help flag', () => {
|
|
74
|
+
const result = preprocessArgvWithValidation([
|
|
75
|
+
node,
|
|
76
|
+
script,
|
|
77
|
+
'context',
|
|
78
|
+
'--help',
|
|
79
|
+
])
|
|
80
|
+
expect(result.argv).toEqual([node, script, 'context', '--help'])
|
|
81
|
+
expect(result.error).toBeUndefined()
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
describe('unknown flag detection', () => {
|
|
86
|
+
it('returns error for unknown flag', () => {
|
|
87
|
+
const result = preprocessArgvWithValidation([
|
|
88
|
+
node,
|
|
89
|
+
script,
|
|
90
|
+
'context',
|
|
91
|
+
'-x',
|
|
92
|
+
'file.md',
|
|
93
|
+
])
|
|
94
|
+
expect(result.error).toContain("Unknown option '-x'")
|
|
95
|
+
expect(result.error).toContain("'context'")
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('returns error for unknown long flag', () => {
|
|
99
|
+
const result = preprocessArgvWithValidation([
|
|
100
|
+
node,
|
|
101
|
+
script,
|
|
102
|
+
'search',
|
|
103
|
+
'--invalid',
|
|
104
|
+
'query',
|
|
105
|
+
])
|
|
106
|
+
expect(result.error).toContain("Unknown option '--invalid'")
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('returns error for unknown flag with value', () => {
|
|
110
|
+
const result = preprocessArgvWithValidation([
|
|
111
|
+
node,
|
|
112
|
+
script,
|
|
113
|
+
'context',
|
|
114
|
+
'--foo=bar',
|
|
115
|
+
'file.md',
|
|
116
|
+
])
|
|
117
|
+
expect(result.error).toContain("Unknown option '--foo'")
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
describe('typo suggestions', () => {
|
|
122
|
+
it('suggests --json for --jsno', () => {
|
|
123
|
+
const result = preprocessArgvWithValidation([
|
|
124
|
+
node,
|
|
125
|
+
script,
|
|
126
|
+
'context',
|
|
127
|
+
'--jsno',
|
|
128
|
+
'file.md',
|
|
129
|
+
])
|
|
130
|
+
expect(result.error).toContain("Did you mean '--json'")
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('suggests --limit for --limt', () => {
|
|
134
|
+
const result = preprocessArgvWithValidation([
|
|
135
|
+
node,
|
|
136
|
+
script,
|
|
137
|
+
'search',
|
|
138
|
+
'--limt',
|
|
139
|
+
'5',
|
|
140
|
+
'query',
|
|
141
|
+
])
|
|
142
|
+
expect(result.error).toContain("Did you mean '--limit'")
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('suggests --tokens for --toekns', () => {
|
|
146
|
+
const result = preprocessArgvWithValidation([
|
|
147
|
+
node,
|
|
148
|
+
script,
|
|
149
|
+
'context',
|
|
150
|
+
'--toekns',
|
|
151
|
+
'100',
|
|
152
|
+
'file.md',
|
|
153
|
+
])
|
|
154
|
+
expect(result.error).toContain("Did you mean '--tokens'")
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
describe('edge cases', () => {
|
|
159
|
+
it('passes through empty args', () => {
|
|
160
|
+
const result = preprocessArgvWithValidation([node, script])
|
|
161
|
+
expect(result.argv).toEqual([node, script])
|
|
162
|
+
expect(result.error).toBeUndefined()
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('passes through unknown subcommand', () => {
|
|
166
|
+
const result = preprocessArgvWithValidation([
|
|
167
|
+
node,
|
|
168
|
+
script,
|
|
169
|
+
'unknown',
|
|
170
|
+
'--flag',
|
|
171
|
+
])
|
|
172
|
+
// Unknown subcommand should pass through (no schema)
|
|
173
|
+
expect(result.argv).toEqual([node, script, 'unknown', '--flag'])
|
|
174
|
+
expect(result.error).toBeUndefined()
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('handles -- end of flags marker', () => {
|
|
178
|
+
const result = preprocessArgvWithValidation([
|
|
179
|
+
node,
|
|
180
|
+
script,
|
|
181
|
+
'context',
|
|
182
|
+
'--',
|
|
183
|
+
'--not-a-flag',
|
|
184
|
+
'file.md',
|
|
185
|
+
])
|
|
186
|
+
// After --, everything is positional
|
|
187
|
+
expect(result.argv).toEqual([
|
|
188
|
+
node,
|
|
189
|
+
script,
|
|
190
|
+
'context',
|
|
191
|
+
'--not-a-flag',
|
|
192
|
+
'file.md',
|
|
193
|
+
])
|
|
194
|
+
expect(result.error).toBeUndefined()
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it('validates alias flags', () => {
|
|
198
|
+
const result = preprocessArgvWithValidation([
|
|
199
|
+
node,
|
|
200
|
+
script,
|
|
201
|
+
'context',
|
|
202
|
+
'-t',
|
|
203
|
+
'100',
|
|
204
|
+
'file.md',
|
|
205
|
+
])
|
|
206
|
+
expect(result.error).toBeUndefined()
|
|
207
|
+
expect(result.argv).toContain('-t')
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
})
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argv Preprocessor - Enables flexible flag positioning
|
|
3
|
+
*
|
|
4
|
+
* Effect CLI requires flags before positional args, but users expect
|
|
5
|
+
* to be able to do either:
|
|
6
|
+
* mdcontext search "query" --limit 5
|
|
7
|
+
* mdcontext search --limit 5 "query"
|
|
8
|
+
*
|
|
9
|
+
* This preprocessor reorders argv so flags always come first for each
|
|
10
|
+
* subcommand, while preserving the user's intended positional arg order.
|
|
11
|
+
*
|
|
12
|
+
* It also validates flags against per-command schemas and provides
|
|
13
|
+
* helpful error messages for unknown flags with typo suggestions.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
type CommandSchema,
|
|
18
|
+
getCommandSchema,
|
|
19
|
+
getValidFlags,
|
|
20
|
+
flagTakesValue as schemaFlagTakesValue,
|
|
21
|
+
} from './flag-schemas.js'
|
|
22
|
+
import { formatValidFlags, suggestFlag } from './typo-suggester.js'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Result of preprocessing
|
|
26
|
+
*/
|
|
27
|
+
export interface PreprocessResult {
|
|
28
|
+
/** Processed argv (reordered) */
|
|
29
|
+
argv: string[]
|
|
30
|
+
/** Error if unknown flag detected */
|
|
31
|
+
error?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if an argument looks like a flag
|
|
36
|
+
*/
|
|
37
|
+
const isFlag = (arg: string): boolean => {
|
|
38
|
+
return arg.startsWith('-')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Extract the base flag name (handles --flag=value syntax)
|
|
43
|
+
*/
|
|
44
|
+
const extractFlagName = (arg: string): string => {
|
|
45
|
+
const eqIndex = arg.indexOf('=')
|
|
46
|
+
return eqIndex >= 0 ? arg.slice(0, eqIndex) : arg
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Validate a flag against a command schema
|
|
51
|
+
* Returns an error message if invalid, undefined if valid
|
|
52
|
+
*/
|
|
53
|
+
const validateFlag = (
|
|
54
|
+
flag: string,
|
|
55
|
+
schema: CommandSchema,
|
|
56
|
+
): string | undefined => {
|
|
57
|
+
const flagName = extractFlagName(flag)
|
|
58
|
+
const validFlags = getValidFlags(schema)
|
|
59
|
+
|
|
60
|
+
if (validFlags.has(flagName)) {
|
|
61
|
+
return undefined // Valid flag
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Unknown flag - build error message with suggestion
|
|
65
|
+
const suggestion = suggestFlag(flagName, schema)
|
|
66
|
+
|
|
67
|
+
let errorMsg = `Unknown option '${flagName}' for '${schema.name}'`
|
|
68
|
+
|
|
69
|
+
if (suggestion) {
|
|
70
|
+
errorMsg += `\nDid you mean '${suggestion.flag}'?`
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
errorMsg += `\n\nValid options for '${schema.name}':\n${formatValidFlags(schema)}`
|
|
74
|
+
|
|
75
|
+
return errorMsg
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Preprocess argv to put flags before positional arguments
|
|
80
|
+
*
|
|
81
|
+
* Transforms: ['search', 'query', '--limit', '5', 'path']
|
|
82
|
+
* Into: ['search', '--limit', '5', 'query', 'path']
|
|
83
|
+
*
|
|
84
|
+
* Also validates flags and returns error for unknown flags.
|
|
85
|
+
*/
|
|
86
|
+
export const preprocessArgv = (argv: string[]): string[] => {
|
|
87
|
+
const result = preprocessArgvWithValidation(argv)
|
|
88
|
+
|
|
89
|
+
if (result.error) {
|
|
90
|
+
// Print error and exit
|
|
91
|
+
console.error(`\nError: ${result.error}`)
|
|
92
|
+
console.error('\nRun "mdcontext <command> --help" for usage information.')
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return result.argv
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Preprocess argv with validation (for testing)
|
|
101
|
+
*/
|
|
102
|
+
export const preprocessArgvWithValidation = (
|
|
103
|
+
argv: string[],
|
|
104
|
+
): PreprocessResult => {
|
|
105
|
+
// argv[0] = node, argv[1] = script, rest = user args
|
|
106
|
+
const nodeAndScript = argv.slice(0, 2)
|
|
107
|
+
const userArgs = argv.slice(2)
|
|
108
|
+
|
|
109
|
+
if (userArgs.length === 0) {
|
|
110
|
+
return { argv }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Check if first arg is a subcommand (not a flag)
|
|
114
|
+
const firstArg = userArgs[0]
|
|
115
|
+
if (!firstArg || isFlag(firstArg)) {
|
|
116
|
+
// No subcommand, return as-is
|
|
117
|
+
return { argv }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const subcommand = firstArg
|
|
121
|
+
const restArgs = userArgs.slice(1)
|
|
122
|
+
|
|
123
|
+
// Get schema for this command
|
|
124
|
+
const schema = getCommandSchema(subcommand)
|
|
125
|
+
|
|
126
|
+
// If no schema, use legacy behavior (pass through)
|
|
127
|
+
if (!schema) {
|
|
128
|
+
return { argv }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Separate flags (with their values) from positional args
|
|
132
|
+
const flags: string[] = []
|
|
133
|
+
const positionals: string[] = []
|
|
134
|
+
|
|
135
|
+
let i = 0
|
|
136
|
+
while (i < restArgs.length) {
|
|
137
|
+
const arg = restArgs[i]
|
|
138
|
+
if (!arg) {
|
|
139
|
+
i++
|
|
140
|
+
continue
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (isFlag(arg)) {
|
|
144
|
+
// Skip --help/-h, let Effect CLI handle it
|
|
145
|
+
if (arg === '--help' || arg === '-h') {
|
|
146
|
+
flags.push(arg)
|
|
147
|
+
i++
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Skip -- (end of flags marker)
|
|
152
|
+
if (arg === '--') {
|
|
153
|
+
// Everything after -- is positional
|
|
154
|
+
i++
|
|
155
|
+
while (i < restArgs.length) {
|
|
156
|
+
const remaining = restArgs[i]
|
|
157
|
+
if (remaining) positionals.push(remaining)
|
|
158
|
+
i++
|
|
159
|
+
}
|
|
160
|
+
continue
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Validate the flag
|
|
164
|
+
const error = validateFlag(arg, schema)
|
|
165
|
+
if (error) {
|
|
166
|
+
return { argv, error }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// It's a valid flag
|
|
170
|
+
if (arg.includes('=')) {
|
|
171
|
+
// --flag=value syntax, keep as single arg
|
|
172
|
+
flags.push(arg)
|
|
173
|
+
i++
|
|
174
|
+
} else if (schemaFlagTakesValue(schema, arg)) {
|
|
175
|
+
// Flag with separate value
|
|
176
|
+
flags.push(arg)
|
|
177
|
+
i++
|
|
178
|
+
// Grab the value if it exists and isn't another flag
|
|
179
|
+
if (i < restArgs.length) {
|
|
180
|
+
const nextArg = restArgs[i]
|
|
181
|
+
if (nextArg && !isFlag(nextArg)) {
|
|
182
|
+
flags.push(nextArg)
|
|
183
|
+
i++
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
// Boolean flag
|
|
188
|
+
flags.push(arg)
|
|
189
|
+
i++
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
// Positional argument
|
|
193
|
+
positionals.push(arg)
|
|
194
|
+
i++
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Reconstruct: node, script, subcommand, flags, positionals
|
|
199
|
+
return {
|
|
200
|
+
argv: [...nodeAndScript, subcommand, ...flags, ...positionals],
|
|
201
|
+
}
|
|
202
|
+
}
|