goke 6.12.1 → 6.12.2

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.
@@ -1009,10 +1009,11 @@ describe('space-separated subcommands', () => {
1009
1009
  // Should show error message instead of root help
1010
1010
  expect(stripAnsi(errOutput)).toContain('Unknown command: foo');
1011
1011
  });
1012
- test('unknown command without prefix outputs error', async () => {
1012
+ test('unknown command without prefix outputs error and help', async () => {
1013
1013
  let errOutput = '';
1014
+ let stdOutput = '';
1014
1015
  const cli = goke('mycli', {
1015
- stdout: { write() { } },
1016
+ stdout: { write(data) { stdOutput += data; } },
1016
1017
  stderr: { write(data) { errOutput += data; } },
1017
1018
  exit: () => { },
1018
1019
  });
@@ -1023,7 +1024,10 @@ describe('space-separated subcommands', () => {
1023
1024
  await cli.parse(['node', 'bin', 'something'], { run: true });
1024
1025
  expect(cli.matchedCommand).toBeUndefined();
1025
1026
  expect(stripAnsi(errOutput)).toContain('Unknown command: something');
1026
- expect(stripAnsi(errOutput)).toContain('mycli --help');
1027
+ // Should output help so the user can see available commands
1028
+ expect(stripAnsi(stdOutput)).toContain('Usage:');
1029
+ expect(stripAnsi(stdOutput)).toContain('mcp login');
1030
+ expect(stripAnsi(stdOutput)).toContain('build');
1027
1031
  });
1028
1032
  test('no args without default command outputs root help', async () => {
1029
1033
  const stdout = createTestOutputStream();
@@ -1080,6 +1084,19 @@ describe('space-separated subcommands', () => {
1080
1084
  await cli.parse(['node', 'bin', 'deploy'], { run: true });
1081
1085
  expect(receivedScript).toBe('deploy');
1082
1086
  });
1087
+ test('default command WITH positional args alongside other commands', async () => {
1088
+ let defaultScript;
1089
+ let buildRan = false;
1090
+ const cli = gokeTestable('mycli');
1091
+ cli.command('[file]', 'Process a file').action(async (file) => {
1092
+ defaultScript = file;
1093
+ });
1094
+ cli.command('build', 'Build project').action(async () => { buildRan = true; });
1095
+ // Passing an arg that is NOT a known command should route to the default
1096
+ await cli.parse(['node', 'bin', 'readme.md'], { run: true });
1097
+ expect(defaultScript).toBe('readme.md');
1098
+ expect(buildRan).toBe(false);
1099
+ });
1083
1100
  test('default command rejects unknown nonexistent command', async () => {
1084
1101
  let defaultRan = false;
1085
1102
  let unknownFired = false;
@@ -2089,3 +2106,126 @@ describe('getAction()', () => {
2089
2106
  expect(() => cmd.getAction()).toThrow(/No action registered/);
2090
2107
  });
2091
2108
  });
2109
+ describe('command routing with conflicting enum options', () => {
2110
+ test('commands with same option name but different enums route correctly', async () => {
2111
+ const cli = gokeTestable('egaki');
2112
+ let matched = '';
2113
+ cli.command('image <prompt>', 'Generate images')
2114
+ .option('-m, --model [model]', z.enum(['imagen-4', 'dall-e-3']).describe('Image model'))
2115
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}`; });
2116
+ cli.command('video <prompt>', 'Generate videos')
2117
+ .option('-m, --model [model]', z.enum(['veo-3', 'grok-video']).describe('Video model'))
2118
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}`; });
2119
+ await cli.parse(['node', 'bin', 'video', 'test', '--model', 'grok-video']);
2120
+ expect(matched).toBe('video:test:grok-video');
2121
+ });
2122
+ test('first-defined command still works with its own enum values', async () => {
2123
+ const cli = gokeTestable('egaki');
2124
+ let matched = '';
2125
+ cli.command('image <prompt>', 'Generate images')
2126
+ .option('-m, --model [model]', z.enum(['imagen-4', 'dall-e-3']).describe('Image model'))
2127
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}`; });
2128
+ cli.command('video <prompt>', 'Generate videos')
2129
+ .option('-m, --model [model]', z.enum(['veo-3', 'grok-video']).describe('Video model'))
2130
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}`; });
2131
+ await cli.parse(['node', 'bin', 'image', 'sunset', '--model', 'dall-e-3']);
2132
+ expect(matched).toBe('image:sunset:dall-e-3');
2133
+ });
2134
+ test('parent child command matches before parent <arg>', async () => {
2135
+ const cli = gokeTestable('mycli');
2136
+ let matched = '';
2137
+ cli.command('parent <arg>', 'Parent with positional')
2138
+ .action((arg) => { matched = `parent:${arg}`; });
2139
+ cli.command('parent child', 'Parent child subcommand')
2140
+ .action(() => { matched = 'parent child'; });
2141
+ await cli.parse(['node', 'bin', 'parent', 'child']);
2142
+ expect(matched).toBe('parent child');
2143
+ });
2144
+ test('parent <arg> still works for non-subcommand args', async () => {
2145
+ const cli = gokeTestable('mycli');
2146
+ let matched = '';
2147
+ cli.command('parent <arg>', 'Parent with positional')
2148
+ .action((arg) => { matched = `parent:${arg}`; });
2149
+ cli.command('parent child', 'Parent child subcommand')
2150
+ .action(() => { matched = 'parent child'; });
2151
+ await cli.parse(['node', 'bin', 'parent', 'something']);
2152
+ expect(matched).toBe('parent:something');
2153
+ });
2154
+ test('multi-word commands with same first word and conflicting enums route correctly', async () => {
2155
+ const cli = gokeTestable('egaki');
2156
+ let matched = '';
2157
+ cli.command('image create <prompt>', 'Create image')
2158
+ .option('--model [model]', z.enum(['imagen']).describe('Create model'))
2159
+ .action((prompt, options) => { matched = `create:${prompt}:${options.model}`; });
2160
+ cli.command('image edit <prompt>', 'Edit image')
2161
+ .option('--model [model]', z.enum(['edit-model']).describe('Edit model'))
2162
+ .action((prompt, options) => { matched = `edit:${prompt}:${options.model}`; });
2163
+ await cli.parse(['node', 'bin', 'image', 'edit', 'test', '--model', 'edit-model']);
2164
+ expect(matched).toBe('edit:test:edit-model');
2165
+ });
2166
+ test('aliased command with conflicting enum routes correctly', async () => {
2167
+ const cli = gokeTestable('egaki');
2168
+ let matched = '';
2169
+ cli.command('image <prompt>', 'Generate images')
2170
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2171
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}`; });
2172
+ cli.command('video <prompt>', 'Generate videos')
2173
+ .alias('v')
2174
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2175
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}`; });
2176
+ await cli.parse(['node', 'bin', 'v', 'test', '--model', 'veo']);
2177
+ expect(matched).toBe('video:test:veo');
2178
+ });
2179
+ test('global boolean flag before command does not disable routing precheck', async () => {
2180
+ const cli = gokeTestable('egaki');
2181
+ let matched = '';
2182
+ cli.option('--verbose', 'Verbose output');
2183
+ cli.command('image <prompt>', 'Generate images')
2184
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2185
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}`; });
2186
+ cli.command('video <prompt>', 'Generate videos')
2187
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2188
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}`; });
2189
+ await cli.parse(['node', 'bin', '--verbose', 'video', 'test', '--model', 'veo']);
2190
+ expect(matched).toBe('video:test:veo');
2191
+ });
2192
+ test('global value option before command keeps routing precheck enabled', async () => {
2193
+ const cli = gokeTestable('egaki');
2194
+ let matched = '';
2195
+ cli.option('--config <path>', z.string().describe('Config path'));
2196
+ cli.command('image <prompt>', 'Generate images')
2197
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2198
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}`; });
2199
+ cli.command('video <prompt>', 'Generate videos')
2200
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2201
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}`; });
2202
+ await cli.parse(['node', 'bin', '--config', 'config.json', 'video', 'test', '--model', 'veo']);
2203
+ expect(matched).toBe('video:test:veo');
2204
+ });
2205
+ test('global value option with equals syntax keeps routing precheck enabled', async () => {
2206
+ const cli = gokeTestable('egaki');
2207
+ let matched = '';
2208
+ cli.option('--config <path>', z.string().describe('Config path'));
2209
+ cli.command('image <prompt>', 'Generate images')
2210
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2211
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}`; });
2212
+ cli.command('video <prompt>', 'Generate videos')
2213
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2214
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}`; });
2215
+ await cli.parse(['node', 'bin', '--config=config.json', 'video', 'test', '--model', 'veo']);
2216
+ expect(matched).toBe('video:test:veo');
2217
+ });
2218
+ test('global boolean flag with explicit equals value keeps routing precheck enabled', async () => {
2219
+ const cli = gokeTestable('egaki');
2220
+ let matched = '';
2221
+ cli.option('--verbose', 'Verbose output');
2222
+ cli.command('image <prompt>', 'Generate images')
2223
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2224
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}`; });
2225
+ cli.command('video <prompt>', 'Generate videos')
2226
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2227
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}`; });
2228
+ await cli.parse(['node', 'bin', '--verbose=false', 'video', 'test', '--model', 'veo']);
2229
+ expect(matched).toBe('video:test:veo');
2230
+ });
2231
+ });
@@ -291,6 +291,22 @@ describe('generateDocs', () => {
291
291
  const pages = generateDocs({ cli });
292
292
  expect(pages).toEqual([]);
293
293
  });
294
+ test('supports basePath option for links', async () => {
295
+ const cli = gokeTestable('mycli');
296
+ cli.command('deploy', 'Deploy the app');
297
+ cli.command('status', 'Show status');
298
+ const pages = generateDocs({ cli, basePath: '/docs/cli' });
299
+ const index = pages.find((p) => p.slug === 'index');
300
+ expect(index.content).toContain('[\`deploy\`](/docs/cli/deploy.md)');
301
+ expect(index.content).toContain('[\`status\`](/docs/cli/status.md)');
302
+ });
303
+ test('basePath with trailing slash is normalized', async () => {
304
+ const cli = gokeTestable('mycli');
305
+ cli.command('deploy', 'Deploy the app');
306
+ const pages = generateDocs({ cli, basePath: '/docs/cli/' });
307
+ const index = pages.find((p) => p.slug === 'index');
308
+ expect(index.content).toContain('[\`deploy\`](/docs/cli/deploy.md)');
309
+ });
294
310
  test('skips deprecated options', async () => {
295
311
  const cli = gokeTestable('mycli');
296
312
  cli
package/dist/goke.d.ts CHANGED
@@ -698,6 +698,8 @@ interface DocPage {
698
698
  interface GenerateDocsOptions {
699
699
  /** The Goke CLI instance to generate docs from. */
700
700
  cli: Goke<any>;
701
+ /** Base path prefix for links between pages (e.g. "/docs/cli"). Defaults to ".". */
702
+ basePath?: string;
701
703
  }
702
704
  /**
703
705
  * Generate markdown documentation pages for every command in a CLI.
@@ -715,13 +717,13 @@ interface GenerateDocsOptions {
715
717
  * .command('deploy <env>', 'Deploy to an environment')
716
718
  * .option('--force', 'Skip confirmation')
717
719
  *
718
- * const pages = generateDocs({ cli })
720
+ * const pages = generateDocs({ cli, basePath: '/docs/cli' })
719
721
  * for (const page of pages) {
720
722
  * fs.writeFileSync(`docs/${page.slug}.md`, page.content)
721
723
  * }
722
724
  * ```
723
725
  */
724
- declare function generateDocs({ cli }: GenerateDocsOptions): DocPage[];
726
+ declare function generateDocs({ cli, basePath }: GenerateDocsOptions): DocPage[];
725
727
  export type { GokeOutputStream, GokeConsole, GokeOptions, GokeProcess, GokeExecutionContext, GokeExecutionContextOverride, GokeFs, DocPage, GenerateDocsOptions };
726
728
  export { createConsole, Command, GokeProcessExit, openInBrowser, generateDocs };
727
729
  export type { ShellType };
@@ -1 +1 @@
1
- {"version":3,"file":"goke.d.ts","sourceRoot":"","sources":["../src/goke.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"goke.d.ts","sourceRoot":"","sources":["../src/goke.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,EAAmB,wBAAwB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,WAAW,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACzK,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAmB,aAAa,EAAW,MAAM,UAAU,CAAA;AAmNhF,cAAM,MAAM;IAwBD,OAAO,EAAE,MAAM;IAvBxB,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,8BAA8B;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAA;IACnB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,qEAAqE;IACrE,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;;;;OAKG;gBAEM,OAAO,EAAE,MAAM,EACtB,mBAAmB,CAAC,EAAE,MAAM,GAAG,oBAAoB;IA0CrD,KAAK;CAGN;AAMD;;;GAGG;AACH,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,IAC7B,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,GAC7B,GAAG,CAAC,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,GACjC,CAAC,CAAA;AAEP;;;;;GAKG;AACH,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,IAErC,CAAC,SAAS,GAAG,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,GAClE,CAAC,SAAS,GAAG,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,GAClE,CAAC,SAAS,GAAG,MAAM,KAAK,MAAM,IAAI,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,GACtD,MAAM,CAAA;AAER;;GAEG;AACH,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,IACpC,CAAC,SAAS,GAAG,MAAM,IAAI,MAAM,GAAG,GAAG,KAAK,GACxC,IAAI,CAAA;AAEN;;;;;GAKG;AACH,KAAK,gBAAgB,CAAC,CAAC,IACrB,CAAC,SAAS;IAAE,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,GAAG,CAAC,GAAG,OAAO,CAAA;AAEpG;;;;;GAKG;AACH,KAAK,iBAAiB,CAAC,CAAC,IACtB,CAAC,SAAS;IAAE,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,GAAG,CAAC,GAAG,OAAO,CAAA;AAErG;;;;;;;;;;;;;GAaG;AACH,KAAK,gBAAgB,CAAC,CAAC,IACrB,OAAO,SAAS,gBAAgB,CAAC,CAAC,CAAC,GAC/B,KAAK,GACL,SAAS,SAAS,gBAAgB,CAAC,CAAC,CAAC,GACnC,SAAS,SAAS,iBAAiB,CAAC,CAAC,CAAC,GACpC,KAAK,GACL,IAAI,GACN,KAAK,CAAA;AAEb;;;;;;;;GAQG;AACH,KAAK,WAAW,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,IAC7C,gBAAgB,CAAC,OAAO,CAAC,SAAS,IAAI,GAClC,gBAAgB,CAAC,MAAM,CAAC,SAAS,IAAI,GACnC;KAAG,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC;CAAE,GAChE;KAAG,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC;CAAE,GACnE;KAAG,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC;CAAE,CAAA;AAEtE;;;;;;;;;;;GAWG;AACH,KAAK,kBAAkB,CAAC,OAAO,SAAS,MAAM,IAC5C,OAAO,SAAS,GAAG,MAAM,IAAI,MAAM,GAAG,GAAG,MAAM,GAC/C,OAAO,SAAS,GAAG,MAAM,IAAI,MAAM,GAAG,GAAG,MAAM,GAC/C,OAAO,GAAG,SAAS,CAAA;AAErB;;;GAGG;AACH,KAAK,kBAAkB,CAAC,OAAO,SAAS,MAAM,IAC5C,OAAO,SAAS,GAAG,MAAM,IAAI,MAAM,GAAG,GAClC;KAAG,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC;CAAE,GAClE;KAAG,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC;CAAE,CAAA;AAEzE;;;;GAIG;AACH,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,SAAS,MAAM,EAAE,GAAG,EAAE,IACpE,CAAC,SAAS,GAAG,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE,GACnC,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC,GAClC,CAAC,SAAS,EAAE,GACV,GAAG,GACH,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAA;AAEnB;;;;;;;;;GASG;AACH,KAAK,cAAc,CAAC,CAAC,SAAS,MAAM,IAClC,CAAC,SAAS,OAAO,MAAM,GAAG,GAAG,MAAM,EAAE,GACrC,CAAC,SAAS,OAAO,MAAM,GAAG,GAAG,MAAM,EAAE,GACrC,CAAC,SAAS,IAAI,MAAM,GAAG,GAAG,MAAM,GAChC,CAAC,SAAS,IAAI,MAAM,GAAG,GAAG,MAAM,GAAG,SAAS,GAC5C,KAAK,CAAA;AAEP;;;GAGG;AACH,KAAK,kBAAkB,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,IACjD,CAAC,SAAS,SAAS,CAAC,MAAM,IAAI,SAAS,MAAM,EAAE,GAAG,MAAM,IAAI,SAAS,MAAM,EAAE,CAAC,GAC1E,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GACpC,kBAAkB,CAAC,IAAI,CAAC,GACxB,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,GACrD,EAAE,CAAA;AAER;;;;;;;;GAQG;AACH,KAAK,qBAAqB,CAAC,OAAO,SAAS,MAAM,IAC/C,kBAAkB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;AAE3C;;;;;GAKG;AACH,KAAK,iBAAiB,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAE3C;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,CAAC,OAAO,SAAS,MAAM,EAAE,IAAI,IAC1C;IACE,GAAG,qBAAqB,CAAC,OAAO,CAAC;IACjC,IAAI,GAAG,iBAAiB;IACxB,oBAAoB;CACrB,CAAA;AAEH,UAAU,UAAU;IAClB,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb;AAED,UAAU,aAAa;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,wBAAwB,CAAC,EAAE,OAAO,CAAA;CACnC;AAED,KAAK,YAAY,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,GAAG,WAAW,EAAE,CAAA;AAErE,KAAK,cAAc,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,MAAM,CAAA;AAExD,cAAM,OAAO,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,GAAG,EAAE;IAe7C,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,MAAM;IACnB,MAAM,EAAE,aAAa;IACrB,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IAjBvB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,EAAE,MAAM,EAAE,CAAA;IAEpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,UAAU,EAAE,CAAA;IAClB,aAAa,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;gBAGR,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,aAAa,YAAK,EAC1B,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IASvB,KAAK,CAAC,IAAI,EAAE,MAAM;IAKlB,mBAAmB;IAKnB,wBAAwB;IAKxB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,SAAkB;IAMtD,OAAO,CAAC,OAAO,EAAE,cAAc;IAK/B;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,aAAa,SAAS,MAAM,EAC5B,CAAC,SAAS,oBAAoB,EAE9B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,OAAO,EAAE,IAAI,GAAG,WAAW,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzD,MAAM,CAAC,aAAa,SAAS,MAAM,EACjC,OAAO,EAAE,aAAa,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,EAAE,IAAI,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAO7D,KAAK,CAAC,IAAI,EAAE,MAAM;IAKlB,MAAM;IAKN;;;;;;;;;;;;;;OAcG;IACH,MAAM,CACJ,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAC3E,IAAI;IAWP;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAO/E,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;IAuBrE,IAAI,gBAAgB,YAEnB;IAED,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED;;;OAGG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM;IAOtB;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAwLlB,UAAU;IAIV,aAAa;IAQb,iBAAiB;IAUjB;;;;OAIG;IACH,mBAAmB;IAkBnB;;OAEG;IACH,gBAAgB;CAwBjB;AAED,cAAM,aAAc,SAAQ,OAAO;gBACrB,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;CAG3B;AAsBD;;;GAGG;AACH,UAAU,gBAAgB;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED;;;;GAIG;AACH,UAAU,WAAW;IACnB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC7B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;CAC/B;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,gBAAgB,CAAA;IACxB,MAAM,EAAE,gBAAgB,CAAA;IACxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAA;CACjC;AAED,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAA;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,WAAW,CAAA;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,UAAU,4BAA4B;IACpC,gGAAgG;IAChG,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4FAA4F;IAC5F,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED,cAAM,eAAgB,SAAQ,KAAK;IACjC,IAAI,EAAE,MAAM,CAAA;gBAEA,IAAI,EAAE,MAAM;CAKzB;AAED;;GAEG;AACH,UAAU,WAAW;IACnB,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC,+EAA+E;IAC/E,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,uDAAuD;IACvD,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,gHAAgH;IAChH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED;;;;;;GAMG;AACH,iBAAS,aAAa,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAetF;AAwBD,UAAU,UAAU;IAClB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC3B,OAAO,EAAE;QACP,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;KACjB,CAAA;CACF;AAED,cAAM,IAAI,CAAC,IAAI,GAAG,EAAE,CAAE,SAAQ,YAAY;;IACxC,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAA;IAC7B,6FAA6F;IAC7F,WAAW,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAA;IACrG,aAAa,EAAE,aAAa,CAAA;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB;;OAEG;IACH,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;IACxB;;OAEG;IACH,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;IAE9B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAE3B,sEAAsE;IACtE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACjD,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;IACjC,qCAAqC;IACrC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAIrC;;;OAGG;gBACS,IAAI,SAAK,EAAE,OAAO,CAAC,EAAE,WAAW;IAsB5C,KAAK,CAAC,OAAO,CAAC,EAAE,WAAW;IA+B3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,sBAAsB,CAAC,QAAQ,CAAC,EAAE,4BAA4B,GAAG,oBAAoB;IA2B/E,qBAAqB,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAIvD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM;IAKlB;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc,SAAS,MAAM,EACnC,OAAO,EAAE,cAAc,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC;IAYhC;;;;;;;;;;;;OAYG;IACH,MAAM,CACJ,OAAO,SAAS,MAAM,EACtB,CAAC,SAAS,oBAAoB,EAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,CAAC,OAAO,SAAS,MAAM,EAC3B,OAAO,EAAE,OAAO,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAO3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;IACH,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI;IAC5B,GAAG,CACD,QAAQ,EAAE,CACR,OAAO,EAAE,IAAI,GAAG,iBAAiB,EACjC,OAAO,EAAE,oBAAoB,KAC1B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACxB,IAAI;IAgBP;;;OAGG;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY;IAO5B;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,SAAkB;IAMtD;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc;IAK/B;;;;OAIG;IACH,QAAQ,IAAI,MAAM;IAOlB;;;;OAIG;IACH,UAAU;IAIV;;;OAGG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,YAAY,UAAQ;IAwBrF;;;OAGG;IACH,aAAa;IAIb,OAAO,CAAC,aAAa;IAgBrB,mBAAmB;IAKnB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAYtB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WAAW;IA8CX;;;;;;;OAOG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAqOxC;;OAEG;IACG,KAAK,CACT,IAAI,WAAoB,EACxB;IACE,oDAAoD;IACpD,GAAU,GACX;;KAAK,GACL,OAAO,CAAC,UAAU,CAAC;IAsKtB,OAAO,CAAC,GAAG;IA4JX,iBAAiB;CA0FlB;AAID,UAAU,OAAO;IACf,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAA;IACf,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAA;IACZ,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,UAAU,mBAAmB;IAC3B,mDAAmD;IACnD,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACd,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,iBAAS,YAAY,CAAC,EAAE,GAAG,EAAE,QAAc,EAAE,EAAE,mBAAmB,GAAG,OAAO,EAAE,CA0H7E;AAiBD,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAA;AACjK,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA;AAC/E,YAAY,EAAE,SAAS,EAAE,CAAA;AACzB,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,WAAW,EAAE,qBAAqB,EAAE,aAAa,EAAE,CAAA;AAChI,eAAe,IAAI,CAAA"}
package/dist/goke.js CHANGED
@@ -1288,21 +1288,27 @@ class Goke extends EventEmitter {
1288
1288
  const bLength = b.name.split(' ').filter(Boolean).length;
1289
1289
  return bLength - aLength;
1290
1290
  });
1291
- // Search sub-commands mri() can throw coercion errors, catch them
1291
+ // Search sub-commands using two-pass matching:
1292
+ // 1. First pass: parse without schema coercion to find the matching command.
1293
+ // This avoids z.enum() or other schema validation throwing for the wrong
1294
+ // command's options before isMatched() can reject it.
1295
+ // 2. Second pass: re-parse with full coercion for the matched command only.
1292
1296
  try {
1293
1297
  for (const command of sortedCommands) {
1294
- const parsed = this.mri(argv.slice(2), command);
1298
+ const parsed = this.mri(argv.slice(2), command, true);
1295
1299
  const result = command.isMatched(parsed.args);
1296
1300
  if (result.matched) {
1297
1301
  shouldParse = false;
1298
- const matchedCommandName = parsed.args.slice(0, result.consumedArgs).join(' ');
1302
+ // Re-parse with coercion now that we know this is the right command
1303
+ const coerced = this.mri(argv.slice(2), command);
1304
+ const matchedCommandName = coerced.args.slice(0, result.consumedArgs).join(' ');
1299
1305
  const parsedInfo = {
1300
- ...parsed,
1301
- args: parsed.args.slice(result.consumedArgs),
1306
+ ...coerced,
1307
+ args: coerced.args.slice(result.consumedArgs),
1302
1308
  };
1303
1309
  this.setParsedInfo(parsedInfo, command, matchedCommandName);
1304
1310
  this.emit(`command:${matchedCommandName}`, command);
1305
- break; // Stop after first match (greedy matching)
1311
+ break;
1306
1312
  }
1307
1313
  }
1308
1314
  if (shouldParse) {
@@ -1397,8 +1403,8 @@ class Goke extends EventEmitter {
1397
1403
  }
1398
1404
  else {
1399
1405
  // Unknown command with no matching prefix: show error + root help
1400
- this.console.error(`Unknown command: ${this.args.join(' ')}`);
1401
- this.console.error(`Run "${this.name} --help" to see available commands.`);
1406
+ this.console.error(`Unknown command: ${this.args.join(' ')}\n`);
1407
+ this.outputHelp();
1402
1408
  }
1403
1409
  this.exit(1);
1404
1410
  }
@@ -1412,7 +1418,9 @@ class Goke extends EventEmitter {
1412
1418
  return parsedArgv;
1413
1419
  }
1414
1420
  mri(argv,
1415
- /** Matched command */ command) {
1421
+ /** Matched command */ command,
1422
+ /** Skip schema coercion (used during command matching to avoid throwing for wrong commands) */
1423
+ skipCoercion) {
1416
1424
  // All added options
1417
1425
  const cliOptions = [
1418
1426
  ...this.globalCommand.options,
@@ -1504,41 +1512,43 @@ class Goke extends EventEmitter {
1504
1512
  if (key !== '_') {
1505
1513
  const keys = key.split('.');
1506
1514
  let value = parsed[key];
1507
- // Apply schema coercion if this option has a schema.
1508
- // When value is boolean `true` and the option takes a value, it's mri's sentinel
1509
- // for "flag present, no value given":
1510
- // - Required options (<...>): preserve `true` so checkOptionValue() throws
1511
- // - Optional options ([...]) with schema AND a default: skip this
1512
- // key entirely so the preset default (written into `options` at
1513
- // the top of this function) survives. This keeps the type-level
1514
- // `HasSchemaDefault` promise honest at runtime.
1515
- // - Optional options ([...]) with schema and NO default: replace
1516
- // `true` with `undefined` so the caller sees "flag present, no value"
1517
- // as `undefined`.
1518
- const schemaInfo = schemaMap.get(key);
1519
- if (schemaInfo && value !== undefined) {
1520
- if (value === true && requiredValueOptions.has(key)) {
1521
- // Keep sentinel for checkOptionValue() to detect
1522
- }
1523
- else if (value === true && optionalValueOptions.has(key)) {
1524
- if (optionsWithDefault.has(key)) {
1525
- // Preserve the preset default — don't overwrite with undefined.
1526
- continue;
1515
+ if (!skipCoercion) {
1516
+ // Apply schema coercion if this option has a schema.
1517
+ // When value is boolean `true` and the option takes a value, it's mri's sentinel
1518
+ // for "flag present, no value given":
1519
+ // - Required options (<...>): preserve `true` so checkOptionValue() throws
1520
+ // - Optional options ([...]) with schema AND a default: skip this
1521
+ // key entirely so the preset default (written into `options` at
1522
+ // the top of this function) survives. This keeps the type-level
1523
+ // `HasSchemaDefault` promise honest at runtime.
1524
+ // - Optional options ([...]) with schema and NO default: replace
1525
+ // `true` with `undefined` so the caller sees "flag present, no value"
1526
+ // as `undefined`.
1527
+ const schemaInfo = schemaMap.get(key);
1528
+ if (schemaInfo && value !== undefined) {
1529
+ if (value === true && requiredValueOptions.has(key)) {
1530
+ // Keep sentinel for checkOptionValue() to detect
1531
+ }
1532
+ else if (value === true && optionalValueOptions.has(key)) {
1533
+ if (optionsWithDefault.has(key)) {
1534
+ // Preserve the preset default — don't overwrite with undefined.
1535
+ continue;
1536
+ }
1537
+ value = undefined;
1538
+ }
1539
+ else {
1540
+ value = coerceBySchema(value, schemaInfo.jsonSchema, schemaInfo.optionName);
1527
1541
  }
1528
- value = undefined;
1529
1542
  }
1530
- else {
1531
- value = coerceBySchema(value, schemaInfo.jsonSchema, schemaInfo.optionName);
1543
+ else if (value === true && optionalValueOptions.has(key)) {
1544
+ // Untyped optional-value flag with no schema: normalize bare `true`
1545
+ // to `''` so callers get a clean `string | undefined` shape. `''`
1546
+ // means "flag passed with no argument", distinct from `undefined`
1547
+ // (flag omitted). This matches the new type inference that treats
1548
+ // `[value]` as `string` instead of `string | boolean`.
1549
+ value = '';
1532
1550
  }
1533
1551
  }
1534
- else if (value === true && optionalValueOptions.has(key)) {
1535
- // Untyped optional-value flag with no schema: normalize bare `true`
1536
- // to `''` so callers get a clean `string | undefined` shape. `''`
1537
- // means "flag passed with no argument", distinct from `undefined`
1538
- // (flag omitted). This matches the new type inference that treats
1539
- // `[value]` as `string` instead of `string | boolean`.
1540
- value = '';
1541
- }
1542
1552
  setDotProp(options, keys, value);
1543
1553
  }
1544
1554
  }
@@ -1651,13 +1661,15 @@ class Goke extends EventEmitter {
1651
1661
  * .command('deploy <env>', 'Deploy to an environment')
1652
1662
  * .option('--force', 'Skip confirmation')
1653
1663
  *
1654
- * const pages = generateDocs({ cli })
1664
+ * const pages = generateDocs({ cli, basePath: '/docs/cli' })
1655
1665
  * for (const page of pages) {
1656
1666
  * fs.writeFileSync(`docs/${page.slug}.md`, page.content)
1657
1667
  * }
1658
1668
  * ```
1659
1669
  */
1660
- function generateDocs({ cli }) {
1670
+ function generateDocs({ cli, basePath = '.' }) {
1671
+ // Normalize: strip trailing slash
1672
+ basePath = basePath.replace(/\/+$/, '') || '.';
1661
1673
  const pages = [];
1662
1674
  // Collect global options (from globalCommand), excluding deprecated
1663
1675
  const globalOptions = cli.globalCommand.options.filter((o) => !o.deprecated);
@@ -1681,7 +1693,7 @@ function generateDocs({ cli }) {
1681
1693
  continue;
1682
1694
  const desc = cmd.description.split('\n')[0].trim();
1683
1695
  const slug = cmd.name.replace(/\s+/g, '-');
1684
- lines.push(`| [\`${cmd.name}\`](./${slug}.md) | ${desc} |`);
1696
+ lines.push(`| [\`${cmd.name}\`](${basePath}/${slug}.md) | ${desc} |`);
1685
1697
  }
1686
1698
  lines.push('');
1687
1699
  if (globalOptions.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goke",
3
- "version": "6.12.1",
3
+ "version": "6.12.2",
4
4
  "type": "module",
5
5
  "description": "Simple yet powerful framework for building command-line apps. Inspired by cac.",
6
6
  "repository": {
@@ -24,7 +24,6 @@
24
24
  "imports": {
25
25
  "#runtime": {
26
26
  "types": "./dist/runtime-node.d.ts",
27
- "development": "./src/runtime-node.ts",
28
27
  "node": "./dist/runtime-node.js",
29
28
  "default": "./dist/runtime-browser.js"
30
29
  }
@@ -1295,10 +1295,11 @@ describe('space-separated subcommands', () => {
1295
1295
  expect(stripAnsi(errOutput)).toContain('Unknown command: foo')
1296
1296
  })
1297
1297
 
1298
- test('unknown command without prefix outputs error', async () => {
1298
+ test('unknown command without prefix outputs error and help', async () => {
1299
1299
  let errOutput = ''
1300
+ let stdOutput = ''
1300
1301
  const cli = goke('mycli', {
1301
- stdout: { write() {} },
1302
+ stdout: { write(data) { stdOutput += data } },
1302
1303
  stderr: { write(data) { errOutput += data } },
1303
1304
  exit: () => {},
1304
1305
  })
@@ -1313,7 +1314,10 @@ describe('space-separated subcommands', () => {
1313
1314
 
1314
1315
  expect(cli.matchedCommand).toBeUndefined()
1315
1316
  expect(stripAnsi(errOutput)).toContain('Unknown command: something')
1316
- expect(stripAnsi(errOutput)).toContain('mycli --help')
1317
+ // Should output help so the user can see available commands
1318
+ expect(stripAnsi(stdOutput)).toContain('Usage:')
1319
+ expect(stripAnsi(stdOutput)).toContain('mcp login')
1320
+ expect(stripAnsi(stdOutput)).toContain('build')
1317
1321
  })
1318
1322
 
1319
1323
  test('no args without default command outputs root help', async () => {
@@ -1391,6 +1395,23 @@ describe('space-separated subcommands', () => {
1391
1395
  expect(receivedScript).toBe('deploy')
1392
1396
  })
1393
1397
 
1398
+ test('default command WITH positional args alongside other commands', async () => {
1399
+ let defaultScript: string | undefined
1400
+ let buildRan = false
1401
+ const cli = gokeTestable('mycli')
1402
+
1403
+ cli.command('[file]', 'Process a file').action(async (file) => {
1404
+ defaultScript = file
1405
+ })
1406
+ cli.command('build', 'Build project').action(async () => { buildRan = true })
1407
+
1408
+ // Passing an arg that is NOT a known command should route to the default
1409
+ await cli.parse(['node', 'bin', 'readme.md'], { run: true })
1410
+
1411
+ expect(defaultScript).toBe('readme.md')
1412
+ expect(buildRan).toBe(false)
1413
+ })
1414
+
1394
1415
  test('default command rejects unknown nonexistent command', async () => {
1395
1416
  let defaultRan = false
1396
1417
  let unknownFired = false
@@ -2671,3 +2692,170 @@ describe('getAction()', () => {
2671
2692
  expect(() => cmd.getAction()).toThrow(/No action registered/)
2672
2693
  })
2673
2694
  })
2695
+
2696
+ describe('command routing with conflicting enum options', () => {
2697
+ test('commands with same option name but different enums route correctly', async () => {
2698
+ const cli = gokeTestable('egaki')
2699
+ let matched = ''
2700
+
2701
+ cli.command('image <prompt>', 'Generate images')
2702
+ .option('-m, --model [model]', z.enum(['imagen-4', 'dall-e-3']).describe('Image model'))
2703
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}` })
2704
+
2705
+ cli.command('video <prompt>', 'Generate videos')
2706
+ .option('-m, --model [model]', z.enum(['veo-3', 'grok-video']).describe('Video model'))
2707
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}` })
2708
+
2709
+ await cli.parse(['node', 'bin', 'video', 'test', '--model', 'grok-video'])
2710
+ expect(matched).toBe('video:test:grok-video')
2711
+ })
2712
+
2713
+ test('first-defined command still works with its own enum values', async () => {
2714
+ const cli = gokeTestable('egaki')
2715
+ let matched = ''
2716
+
2717
+ cli.command('image <prompt>', 'Generate images')
2718
+ .option('-m, --model [model]', z.enum(['imagen-4', 'dall-e-3']).describe('Image model'))
2719
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}` })
2720
+
2721
+ cli.command('video <prompt>', 'Generate videos')
2722
+ .option('-m, --model [model]', z.enum(['veo-3', 'grok-video']).describe('Video model'))
2723
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}` })
2724
+
2725
+ await cli.parse(['node', 'bin', 'image', 'sunset', '--model', 'dall-e-3'])
2726
+ expect(matched).toBe('image:sunset:dall-e-3')
2727
+ })
2728
+
2729
+ test('parent child command matches before parent <arg>', async () => {
2730
+ const cli = gokeTestable('mycli')
2731
+ let matched = ''
2732
+
2733
+ cli.command('parent <arg>', 'Parent with positional')
2734
+ .action((arg) => { matched = `parent:${arg}` })
2735
+
2736
+ cli.command('parent child', 'Parent child subcommand')
2737
+ .action(() => { matched = 'parent child' })
2738
+
2739
+ await cli.parse(['node', 'bin', 'parent', 'child'])
2740
+ expect(matched).toBe('parent child')
2741
+ })
2742
+
2743
+ test('parent <arg> still works for non-subcommand args', async () => {
2744
+ const cli = gokeTestable('mycli')
2745
+ let matched = ''
2746
+
2747
+ cli.command('parent <arg>', 'Parent with positional')
2748
+ .action((arg) => { matched = `parent:${arg}` })
2749
+
2750
+ cli.command('parent child', 'Parent child subcommand')
2751
+ .action(() => { matched = 'parent child' })
2752
+
2753
+ await cli.parse(['node', 'bin', 'parent', 'something'])
2754
+ expect(matched).toBe('parent:something')
2755
+ })
2756
+
2757
+ test('multi-word commands with same first word and conflicting enums route correctly', async () => {
2758
+ const cli = gokeTestable('egaki')
2759
+ let matched = ''
2760
+
2761
+ cli.command('image create <prompt>', 'Create image')
2762
+ .option('--model [model]', z.enum(['imagen']).describe('Create model'))
2763
+ .action((prompt, options) => { matched = `create:${prompt}:${options.model}` })
2764
+
2765
+ cli.command('image edit <prompt>', 'Edit image')
2766
+ .option('--model [model]', z.enum(['edit-model']).describe('Edit model'))
2767
+ .action((prompt, options) => { matched = `edit:${prompt}:${options.model}` })
2768
+
2769
+ await cli.parse(['node', 'bin', 'image', 'edit', 'test', '--model', 'edit-model'])
2770
+ expect(matched).toBe('edit:test:edit-model')
2771
+ })
2772
+
2773
+ test('aliased command with conflicting enum routes correctly', async () => {
2774
+ const cli = gokeTestable('egaki')
2775
+ let matched = ''
2776
+
2777
+ cli.command('image <prompt>', 'Generate images')
2778
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2779
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}` })
2780
+
2781
+ cli.command('video <prompt>', 'Generate videos')
2782
+ .alias('v')
2783
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2784
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}` })
2785
+
2786
+ await cli.parse(['node', 'bin', 'v', 'test', '--model', 'veo'])
2787
+ expect(matched).toBe('video:test:veo')
2788
+ })
2789
+
2790
+ test('global boolean flag before command does not disable routing precheck', async () => {
2791
+ const cli = gokeTestable('egaki')
2792
+ let matched = ''
2793
+
2794
+ cli.option('--verbose', 'Verbose output')
2795
+
2796
+ cli.command('image <prompt>', 'Generate images')
2797
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2798
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}` })
2799
+
2800
+ cli.command('video <prompt>', 'Generate videos')
2801
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2802
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}` })
2803
+
2804
+ await cli.parse(['node', 'bin', '--verbose', 'video', 'test', '--model', 'veo'])
2805
+ expect(matched).toBe('video:test:veo')
2806
+ })
2807
+
2808
+ test('global value option before command keeps routing precheck enabled', async () => {
2809
+ const cli = gokeTestable('egaki')
2810
+ let matched = ''
2811
+
2812
+ cli.option('--config <path>', z.string().describe('Config path'))
2813
+
2814
+ cli.command('image <prompt>', 'Generate images')
2815
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2816
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}` })
2817
+
2818
+ cli.command('video <prompt>', 'Generate videos')
2819
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2820
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}` })
2821
+
2822
+ await cli.parse(['node', 'bin', '--config', 'config.json', 'video', 'test', '--model', 'veo'])
2823
+ expect(matched).toBe('video:test:veo')
2824
+ })
2825
+
2826
+ test('global value option with equals syntax keeps routing precheck enabled', async () => {
2827
+ const cli = gokeTestable('egaki')
2828
+ let matched = ''
2829
+
2830
+ cli.option('--config <path>', z.string().describe('Config path'))
2831
+
2832
+ cli.command('image <prompt>', 'Generate images')
2833
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2834
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}` })
2835
+
2836
+ cli.command('video <prompt>', 'Generate videos')
2837
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2838
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}` })
2839
+
2840
+ await cli.parse(['node', 'bin', '--config=config.json', 'video', 'test', '--model', 'veo'])
2841
+ expect(matched).toBe('video:test:veo')
2842
+ })
2843
+
2844
+ test('global boolean flag with explicit equals value keeps routing precheck enabled', async () => {
2845
+ const cli = gokeTestable('egaki')
2846
+ let matched = ''
2847
+
2848
+ cli.option('--verbose', 'Verbose output')
2849
+
2850
+ cli.command('image <prompt>', 'Generate images')
2851
+ .option('--model [model]', z.enum(['imagen']).describe('Image model'))
2852
+ .action((prompt, options) => { matched = `image:${prompt}:${options.model}` })
2853
+
2854
+ cli.command('video <prompt>', 'Generate videos')
2855
+ .option('--model [model]', z.enum(['veo']).describe('Video model'))
2856
+ .action((prompt, options) => { matched = `video:${prompt}:${options.model}` })
2857
+
2858
+ await cli.parse(['node', 'bin', '--verbose=false', 'video', 'test', '--model', 'veo'])
2859
+ expect(matched).toBe('video:test:veo')
2860
+ })
2861
+ })
@@ -358,6 +358,26 @@ describe('generateDocs', () => {
358
358
  expect(pages).toEqual([])
359
359
  })
360
360
 
361
+ test('supports basePath option for links', async () => {
362
+ const cli = gokeTestable('mycli')
363
+ cli.command('deploy', 'Deploy the app')
364
+ cli.command('status', 'Show status')
365
+
366
+ const pages = generateDocs({ cli, basePath: '/docs/cli' })
367
+ const index = pages.find((p) => p.slug === 'index')!
368
+ expect(index.content).toContain('[\`deploy\`](/docs/cli/deploy.md)')
369
+ expect(index.content).toContain('[\`status\`](/docs/cli/status.md)')
370
+ })
371
+
372
+ test('basePath with trailing slash is normalized', async () => {
373
+ const cli = gokeTestable('mycli')
374
+ cli.command('deploy', 'Deploy the app')
375
+
376
+ const pages = generateDocs({ cli, basePath: '/docs/cli/' })
377
+ const index = pages.find((p) => p.slug === 'index')!
378
+ expect(index.content).toContain('[\`deploy\`](/docs/cli/deploy.md)')
379
+ })
380
+
361
381
  test('skips deprecated options', async () => {
362
382
  const cli = gokeTestable('mycli')
363
383
  cli
package/src/goke.ts CHANGED
@@ -1927,22 +1927,28 @@ class Goke<Opts = {}> extends EventEmitter {
1927
1927
  return bLength - aLength
1928
1928
  })
1929
1929
 
1930
- // Search sub-commands mri() can throw coercion errors, catch them
1930
+ // Search sub-commands using two-pass matching:
1931
+ // 1. First pass: parse without schema coercion to find the matching command.
1932
+ // This avoids z.enum() or other schema validation throwing for the wrong
1933
+ // command's options before isMatched() can reject it.
1934
+ // 2. Second pass: re-parse with full coercion for the matched command only.
1931
1935
  try {
1932
1936
  for (const command of sortedCommands) {
1933
- const parsed = this.mri(argv.slice(2), command)
1937
+ const parsed = this.mri(argv.slice(2), command, true)
1934
1938
 
1935
1939
  const result = command.isMatched(parsed.args as string[])
1936
1940
  if (result.matched) {
1937
1941
  shouldParse = false
1938
- const matchedCommandName = parsed.args.slice(0, result.consumedArgs).join(' ')
1942
+ // Re-parse with coercion now that we know this is the right command
1943
+ const coerced = this.mri(argv.slice(2), command)
1944
+ const matchedCommandName = coerced.args.slice(0, result.consumedArgs).join(' ')
1939
1945
  const parsedInfo = {
1940
- ...parsed,
1941
- args: parsed.args.slice(result.consumedArgs),
1946
+ ...coerced,
1947
+ args: coerced.args.slice(result.consumedArgs),
1942
1948
  }
1943
1949
  this.setParsedInfo(parsedInfo, command, matchedCommandName)
1944
1950
  this.emit(`command:${matchedCommandName}`, command)
1945
- break // Stop after first match (greedy matching)
1951
+ break
1946
1952
  }
1947
1953
  }
1948
1954
 
@@ -2039,8 +2045,8 @@ class Goke<Opts = {}> extends EventEmitter {
2039
2045
  this.outputHelpForPrefix(firstArg, matchingCommands)
2040
2046
  } else {
2041
2047
  // Unknown command with no matching prefix: show error + root help
2042
- this.console.error(`Unknown command: ${this.args.join(' ')}`)
2043
- this.console.error(`Run "${this.name} --help" to see available commands.`)
2048
+ this.console.error(`Unknown command: ${this.args.join(' ')}\n`)
2049
+ this.outputHelp()
2044
2050
  }
2045
2051
  this.exit(1)
2046
2052
  }
@@ -2060,7 +2066,9 @@ class Goke<Opts = {}> extends EventEmitter {
2060
2066
 
2061
2067
  private mri(
2062
2068
  argv: string[],
2063
- /** Matched command */ command?: Command
2069
+ /** Matched command */ command?: Command,
2070
+ /** Skip schema coercion (used during command matching to avoid throwing for wrong commands) */
2071
+ skipCoercion?: boolean,
2064
2072
  ): ParsedArgv {
2065
2073
  // All added options
2066
2074
  const cliOptions = [
@@ -2167,37 +2175,39 @@ class Goke<Opts = {}> extends EventEmitter {
2167
2175
  const keys = key.split('.')
2168
2176
  let value = parsed[key]
2169
2177
 
2170
- // Apply schema coercion if this option has a schema.
2171
- // When value is boolean `true` and the option takes a value, it's mri's sentinel
2172
- // for "flag present, no value given":
2173
- // - Required options (<...>): preserve `true` so checkOptionValue() throws
2174
- // - Optional options ([...]) with schema AND a default: skip this
2175
- // key entirely so the preset default (written into `options` at
2176
- // the top of this function) survives. This keeps the type-level
2177
- // `HasSchemaDefault` promise honest at runtime.
2178
- // - Optional options ([...]) with schema and NO default: replace
2179
- // `true` with `undefined` so the caller sees "flag present, no value"
2180
- // as `undefined`.
2181
- const schemaInfo = schemaMap.get(key)
2182
- if (schemaInfo && value !== undefined) {
2183
- if (value === true && requiredValueOptions.has(key)) {
2184
- // Keep sentinel for checkOptionValue() to detect
2185
- } else if (value === true && optionalValueOptions.has(key)) {
2186
- if (optionsWithDefault.has(key)) {
2187
- // Preserve the preset default — don't overwrite with undefined.
2188
- continue
2178
+ if (!skipCoercion) {
2179
+ // Apply schema coercion if this option has a schema.
2180
+ // When value is boolean `true` and the option takes a value, it's mri's sentinel
2181
+ // for "flag present, no value given":
2182
+ // - Required options (<...>): preserve `true` so checkOptionValue() throws
2183
+ // - Optional options ([...]) with schema AND a default: skip this
2184
+ // key entirely so the preset default (written into `options` at
2185
+ // the top of this function) survives. This keeps the type-level
2186
+ // `HasSchemaDefault` promise honest at runtime.
2187
+ // - Optional options ([...]) with schema and NO default: replace
2188
+ // `true` with `undefined` so the caller sees "flag present, no value"
2189
+ // as `undefined`.
2190
+ const schemaInfo = schemaMap.get(key)
2191
+ if (schemaInfo && value !== undefined) {
2192
+ if (value === true && requiredValueOptions.has(key)) {
2193
+ // Keep sentinel for checkOptionValue() to detect
2194
+ } else if (value === true && optionalValueOptions.has(key)) {
2195
+ if (optionsWithDefault.has(key)) {
2196
+ // Preserve the preset default — don't overwrite with undefined.
2197
+ continue
2198
+ }
2199
+ value = undefined
2200
+ } else {
2201
+ value = coerceBySchema(value, schemaInfo.jsonSchema, schemaInfo.optionName)
2189
2202
  }
2190
- value = undefined
2191
- } else {
2192
- value = coerceBySchema(value, schemaInfo.jsonSchema, schemaInfo.optionName)
2203
+ } else if (value === true && optionalValueOptions.has(key)) {
2204
+ // Untyped optional-value flag with no schema: normalize bare `true`
2205
+ // to `''` so callers get a clean `string | undefined` shape. `''`
2206
+ // means "flag passed with no argument", distinct from `undefined`
2207
+ // (flag omitted). This matches the new type inference that treats
2208
+ // `[value]` as `string` instead of `string | boolean`.
2209
+ value = ''
2193
2210
  }
2194
- } else if (value === true && optionalValueOptions.has(key)) {
2195
- // Untyped optional-value flag with no schema: normalize bare `true`
2196
- // to `''` so callers get a clean `string | undefined` shape. `''`
2197
- // means "flag passed with no argument", distinct from `undefined`
2198
- // (flag omitted). This matches the new type inference that treats
2199
- // `[value]` as `string` instead of `string | boolean`.
2200
- value = ''
2201
2211
  }
2202
2212
 
2203
2213
  setDotProp(options, keys, value)
@@ -2316,6 +2326,8 @@ interface DocPage {
2316
2326
  interface GenerateDocsOptions {
2317
2327
  /** The Goke CLI instance to generate docs from. */
2318
2328
  cli: Goke<any>
2329
+ /** Base path prefix for links between pages (e.g. "/docs/cli"). Defaults to ".". */
2330
+ basePath?: string
2319
2331
  }
2320
2332
 
2321
2333
  /**
@@ -2334,13 +2346,15 @@ interface GenerateDocsOptions {
2334
2346
  * .command('deploy <env>', 'Deploy to an environment')
2335
2347
  * .option('--force', 'Skip confirmation')
2336
2348
  *
2337
- * const pages = generateDocs({ cli })
2349
+ * const pages = generateDocs({ cli, basePath: '/docs/cli' })
2338
2350
  * for (const page of pages) {
2339
2351
  * fs.writeFileSync(`docs/${page.slug}.md`, page.content)
2340
2352
  * }
2341
2353
  * ```
2342
2354
  */
2343
- function generateDocs({ cli }: GenerateDocsOptions): DocPage[] {
2355
+ function generateDocs({ cli, basePath = '.' }: GenerateDocsOptions): DocPage[] {
2356
+ // Normalize: strip trailing slash
2357
+ basePath = basePath.replace(/\/+$/, '') || '.'
2344
2358
  const pages: DocPage[] = []
2345
2359
 
2346
2360
  // Collect global options (from globalCommand), excluding deprecated
@@ -2367,7 +2381,7 @@ function generateDocs({ cli }: GenerateDocsOptions): DocPage[] {
2367
2381
  if (cmd.isDefaultCommand) continue
2368
2382
  const desc = cmd.description.split('\n')[0].trim()
2369
2383
  const slug = cmd.name.replace(/\s+/g, '-')
2370
- lines.push(`| [\`${cmd.name}\`](./${slug}.md) | ${desc} |`)
2384
+ lines.push(`| [\`${cmd.name}\`](${basePath}/${slug}.md) | ${desc} |`)
2371
2385
  }
2372
2386
  lines.push('')
2373
2387