@constructive-io/graphql-codegen 2.27.2 → 2.28.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/cli/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
+ #!/usr/bin/env node
1
2
  /**
2
3
  * CLI entry point for graphql-codegen
3
4
  */
4
- export {};
5
+ import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer';
6
+ export declare const commands: (argv: Partial<ParsedArgs>, prompter: Inquirerer, _options: CLIOptions) => Promise<Partial<ParsedArgs>>;
7
+ export declare const options: Partial<CLIOptions>;
package/cli/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  "use strict";
2
3
  /**
3
4
  * CLI entry point for graphql-codegen
@@ -36,12 +37,102 @@ var __importStar = (this && this.__importStar) || (function () {
36
37
  };
37
38
  })();
38
39
  Object.defineProperty(exports, "__esModule", { value: true });
39
- const commander_1 = require("commander");
40
+ exports.options = exports.commands = void 0;
41
+ const inquirerer_1 = require("inquirerer");
40
42
  const init_1 = require("./commands/init");
41
43
  const generate_1 = require("./commands/generate");
42
44
  const generate_orm_1 = require("./commands/generate-orm");
43
45
  const watch_1 = require("./watch");
44
46
  const config_1 = require("../types/config");
47
+ const usageText = `
48
+ graphql-codegen - CLI for generating GraphQL SDK from PostGraphile endpoints or schema files
49
+
50
+ Usage:
51
+ graphql-codegen <command> [options]
52
+
53
+ Commands:
54
+ init Initialize a new graphql-codegen configuration file
55
+ generate Generate SDK from GraphQL endpoint or schema file
56
+ generate-orm Generate Prisma-like ORM client from GraphQL endpoint or schema file
57
+ introspect Introspect a GraphQL endpoint or schema file and print table info
58
+
59
+ Options:
60
+ --help, -h Show this help message
61
+ --version, -v Show version number
62
+
63
+ Run 'graphql-codegen <command> --help' for more information on a command.
64
+ `;
65
+ const initUsageText = `
66
+ graphql-codegen init - Initialize a new graphql-codegen configuration file
67
+
68
+ Usage:
69
+ graphql-codegen init [options]
70
+
71
+ Options:
72
+ --directory, -d <dir> Target directory for the config file (default: .)
73
+ --force, -f Force overwrite existing config
74
+ --endpoint, -e <url> GraphQL endpoint URL to pre-populate
75
+ --output, -o <dir> Output directory to pre-populate (default: ./generated)
76
+ --help, -h Show this help message
77
+ `;
78
+ const generateUsageText = `
79
+ graphql-codegen generate - Generate SDK from GraphQL endpoint or schema file
80
+
81
+ Usage:
82
+ graphql-codegen generate [options]
83
+
84
+ Options:
85
+ --config, -c <path> Path to config file
86
+ --target, -t <name> Target name in config file
87
+ --endpoint, -e <url> GraphQL endpoint URL (overrides config)
88
+ --schema, -s <path> Path to GraphQL schema file (.graphql)
89
+ --output, -o <dir> Output directory (overrides config)
90
+ --authorization, -a <header> Authorization header value
91
+ --verbose, -v Verbose output
92
+ --dry-run Dry run - show what would be generated without writing files
93
+ --watch, -w Watch mode - poll endpoint for schema changes (in-memory)
94
+ --poll-interval <ms> Polling interval in milliseconds (default: 3000)
95
+ --debounce <ms> Debounce delay before regenerating (default: 800)
96
+ --touch <file> File to touch on schema change
97
+ --no-clear Do not clear terminal on regeneration
98
+ --help, -h Show this help message
99
+ `;
100
+ const generateOrmUsageText = `
101
+ graphql-codegen generate-orm - Generate Prisma-like ORM client from GraphQL endpoint or schema file
102
+
103
+ Usage:
104
+ graphql-codegen generate-orm [options]
105
+
106
+ Options:
107
+ --config, -c <path> Path to config file
108
+ --target, -t <name> Target name in config file
109
+ --endpoint, -e <url> GraphQL endpoint URL (overrides config)
110
+ --schema, -s <path> Path to GraphQL schema file (.graphql)
111
+ --output, -o <dir> Output directory (overrides config)
112
+ --authorization, -a <header> Authorization header value
113
+ --verbose, -v Verbose output
114
+ --dry-run Dry run - show what would be generated without writing files
115
+ --skip-custom-operations Skip custom operations (only generate table CRUD)
116
+ --watch, -w Watch mode - poll endpoint for schema changes (in-memory)
117
+ --poll-interval <ms> Polling interval in milliseconds (default: 3000)
118
+ --debounce <ms> Debounce delay before regenerating (default: 800)
119
+ --touch <file> File to touch on schema change
120
+ --no-clear Do not clear terminal on regeneration
121
+ --help, -h Show this help message
122
+ `;
123
+ const introspectUsageText = `
124
+ graphql-codegen introspect - Introspect a GraphQL endpoint or schema file and print table info
125
+
126
+ Usage:
127
+ graphql-codegen introspect [options]
128
+
129
+ Options:
130
+ --endpoint, -e <url> GraphQL endpoint URL
131
+ --schema, -s <path> Path to GraphQL schema file (.graphql)
132
+ --authorization, -a <header> Authorization header value
133
+ --json Output as JSON
134
+ --help, -h Show this help message
135
+ `;
45
136
  /**
46
137
  * Format duration in a human-readable way
47
138
  * - Under 1 second: show milliseconds (e.g., "123ms")
@@ -53,12 +144,10 @@ function formatDuration(ms) {
53
144
  }
54
145
  return `${(ms / 1000).toFixed(2)}s`;
55
146
  }
56
- const program = new commander_1.Command();
57
147
  /**
58
148
  * Load configuration for watch mode, merging CLI options with config file
59
149
  */
60
150
  async function loadWatchConfig(options) {
61
- // Find config file
62
151
  let configPath = options.config;
63
152
  if (!configPath) {
64
153
  configPath = (0, init_1.findConfigFile)() ?? undefined;
@@ -122,25 +211,20 @@ async function loadWatchConfig(options) {
122
211
  }
123
212
  return (0, config_1.resolveConfig)(mergedTarget);
124
213
  }
125
- program
126
- .name('graphql-codegen')
127
- .description('CLI for generating GraphQL SDK from PostGraphile endpoints or schema files')
128
- .version('2.17.48');
129
- // Init command
130
- program
131
- .command('init')
132
- .description('Initialize a new graphql-codegen configuration file')
133
- .option('-d, --directory <dir>', 'Target directory for the config file', '.')
134
- .option('-f, --force', 'Force overwrite existing config', false)
135
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL to pre-populate')
136
- .option('-o, --output <dir>', 'Output directory to pre-populate', './generated')
137
- .action(async (options) => {
214
+ /**
215
+ * Init command handler
216
+ */
217
+ async function handleInit(argv) {
218
+ if (argv.help || argv.h) {
219
+ console.log(initUsageText);
220
+ process.exit(0);
221
+ }
138
222
  const startTime = performance.now();
139
223
  const result = await (0, init_1.initCommand)({
140
- directory: options.directory,
141
- force: options.force,
142
- endpoint: options.endpoint,
143
- output: options.output,
224
+ directory: argv.directory || argv.d || '.',
225
+ force: !!(argv.force || argv.f),
226
+ endpoint: argv.endpoint || argv.e,
227
+ output: argv.output || argv.o || './generated',
144
228
  });
145
229
  const duration = formatDuration(performance.now() - startTime);
146
230
  if (result.success) {
@@ -150,62 +234,75 @@ program
150
234
  console.error('x', result.message, `(${duration})`);
151
235
  process.exit(1);
152
236
  }
153
- });
154
- // Generate command
155
- program
156
- .command('generate')
157
- .description('Generate SDK from GraphQL endpoint or schema file')
158
- .option('-c, --config <path>', 'Path to config file')
159
- .option('-t, --target <name>', 'Target name in config file')
160
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL (overrides config)')
161
- .option('-s, --schema <path>', 'Path to GraphQL schema file (.graphql)')
162
- .option('-o, --output <dir>', 'Output directory (overrides config)')
163
- .option('-a, --authorization <header>', 'Authorization header value')
164
- .option('-v, --verbose', 'Verbose output', false)
165
- .option('--dry-run', 'Dry run - show what would be generated without writing files', false)
166
- .option('-w, --watch', 'Watch mode - poll endpoint for schema changes (in-memory)', false)
167
- .option('--poll-interval <ms>', 'Polling interval in milliseconds (default: 3000)', parseInt)
168
- .option('--debounce <ms>', 'Debounce delay before regenerating (default: 800)', parseInt)
169
- .option('--touch <file>', 'File to touch on schema change')
170
- .option('--no-clear', 'Do not clear terminal on regeneration')
171
- .action(async (options) => {
237
+ }
238
+ /**
239
+ * Generate command handler
240
+ */
241
+ async function handleGenerate(argv) {
242
+ if (argv.help || argv.h) {
243
+ console.log(generateUsageText);
244
+ process.exit(0);
245
+ }
172
246
  const startTime = performance.now();
173
- // Validate source options
174
- if (options.endpoint && options.schema) {
247
+ const config = argv.config || argv.c;
248
+ const target = argv.target || argv.t;
249
+ const endpoint = argv.endpoint || argv.e;
250
+ const schema = argv.schema || argv.s;
251
+ const output = argv.output || argv.o;
252
+ const authorization = argv.authorization || argv.a;
253
+ const verbose = !!(argv.verbose || argv.v);
254
+ const dryRun = !!(argv['dry-run'] || argv.dryRun);
255
+ const watch = !!(argv.watch || argv.w);
256
+ const pollInterval = argv['poll-interval'] !== undefined
257
+ ? parseInt(argv['poll-interval'], 10)
258
+ : undefined;
259
+ const debounce = argv.debounce !== undefined
260
+ ? parseInt(argv.debounce, 10)
261
+ : undefined;
262
+ const touch = argv.touch;
263
+ const clear = argv.clear !== false;
264
+ if (endpoint && schema) {
175
265
  console.error('x Cannot use both --endpoint and --schema. Choose one source.');
176
266
  process.exit(1);
177
267
  }
178
- // Watch mode (only for endpoint)
179
- if (options.watch) {
180
- if (options.schema) {
268
+ if (watch) {
269
+ if (schema) {
181
270
  console.error('x Watch mode is only supported with --endpoint, not --schema.');
182
271
  process.exit(1);
183
272
  }
184
- const config = await loadWatchConfig(options);
185
- if (!config) {
273
+ const watchConfig = await loadWatchConfig({
274
+ config,
275
+ target,
276
+ endpoint,
277
+ output,
278
+ pollInterval,
279
+ debounce,
280
+ touch,
281
+ clear,
282
+ });
283
+ if (!watchConfig) {
186
284
  process.exit(1);
187
285
  }
188
286
  await (0, watch_1.startWatch)({
189
- config,
287
+ config: watchConfig,
190
288
  generatorType: 'generate',
191
- verbose: options.verbose,
192
- authorization: options.authorization,
193
- configPath: options.config,
194
- target: options.target,
195
- outputDir: options.output,
289
+ verbose,
290
+ authorization,
291
+ configPath: config,
292
+ target,
293
+ outputDir: output,
196
294
  });
197
295
  return;
198
296
  }
199
- // Normal one-shot generation
200
297
  const result = await (0, generate_1.generateCommand)({
201
- config: options.config,
202
- target: options.target,
203
- endpoint: options.endpoint,
204
- schema: options.schema,
205
- output: options.output,
206
- authorization: options.authorization,
207
- verbose: options.verbose,
208
- dryRun: options.dryRun,
298
+ config,
299
+ target,
300
+ endpoint,
301
+ schema,
302
+ output,
303
+ authorization,
304
+ verbose,
305
+ dryRun,
209
306
  });
210
307
  const duration = formatDuration(performance.now() - startTime);
211
308
  const targetResults = result.targets ?? [];
@@ -213,19 +310,19 @@ program
213
310
  (targetResults.length > 1 || targetResults[0]?.name !== 'default');
214
311
  if (hasNamedTargets) {
215
312
  console.log(result.success ? '[ok]' : 'x', result.message);
216
- targetResults.forEach((target) => {
217
- const status = target.success ? '[ok]' : 'x';
218
- console.log(`\n${status} ${target.message}`);
219
- if (target.tables && target.tables.length > 0) {
313
+ targetResults.forEach((t) => {
314
+ const status = t.success ? '[ok]' : 'x';
315
+ console.log(`\n${status} ${t.message}`);
316
+ if (t.tables && t.tables.length > 0) {
220
317
  console.log(' Tables:');
221
- target.tables.forEach((table) => console.log(` - ${table}`));
318
+ t.tables.forEach((table) => console.log(` - ${table}`));
222
319
  }
223
- if (target.filesWritten && target.filesWritten.length > 0) {
320
+ if (t.filesWritten && t.filesWritten.length > 0) {
224
321
  console.log(' Files written:');
225
- target.filesWritten.forEach((file) => console.log(` - ${file}`));
322
+ t.filesWritten.forEach((file) => console.log(` - ${file}`));
226
323
  }
227
- if (!target.success && target.errors) {
228
- target.errors.forEach((error) => console.error(` - ${error}`));
324
+ if (!t.success && t.errors) {
325
+ t.errors.forEach((error) => console.error(` - ${error}`));
229
326
  }
230
327
  });
231
328
  if (!result.success) {
@@ -251,65 +348,78 @@ program
251
348
  }
252
349
  process.exit(1);
253
350
  }
254
- });
255
- // Generate ORM command
256
- program
257
- .command('generate-orm')
258
- .description('Generate Prisma-like ORM client from GraphQL endpoint or schema file')
259
- .option('-c, --config <path>', 'Path to config file')
260
- .option('-t, --target <name>', 'Target name in config file')
261
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL (overrides config)')
262
- .option('-s, --schema <path>', 'Path to GraphQL schema file (.graphql)')
263
- .option('-o, --output <dir>', 'Output directory (overrides config)')
264
- .option('-a, --authorization <header>', 'Authorization header value')
265
- .option('-v, --verbose', 'Verbose output', false)
266
- .option('--dry-run', 'Dry run - show what would be generated without writing files', false)
267
- .option('--skip-custom-operations', 'Skip custom operations (only generate table CRUD)', false)
268
- .option('-w, --watch', 'Watch mode - poll endpoint for schema changes (in-memory)', false)
269
- .option('--poll-interval <ms>', 'Polling interval in milliseconds (default: 3000)', parseInt)
270
- .option('--debounce <ms>', 'Debounce delay before regenerating (default: 800)', parseInt)
271
- .option('--touch <file>', 'File to touch on schema change')
272
- .option('--no-clear', 'Do not clear terminal on regeneration')
273
- .action(async (options) => {
351
+ }
352
+ /**
353
+ * Generate ORM command handler
354
+ */
355
+ async function handleGenerateOrm(argv) {
356
+ if (argv.help || argv.h) {
357
+ console.log(generateOrmUsageText);
358
+ process.exit(0);
359
+ }
274
360
  const startTime = performance.now();
275
- // Validate source options
276
- if (options.endpoint && options.schema) {
361
+ const config = argv.config || argv.c;
362
+ const target = argv.target || argv.t;
363
+ const endpoint = argv.endpoint || argv.e;
364
+ const schema = argv.schema || argv.s;
365
+ const output = argv.output || argv.o;
366
+ const authorization = argv.authorization || argv.a;
367
+ const verbose = !!(argv.verbose || argv.v);
368
+ const dryRun = !!(argv['dry-run'] || argv.dryRun);
369
+ const skipCustomOperations = !!(argv['skip-custom-operations'] || argv.skipCustomOperations);
370
+ const watch = !!(argv.watch || argv.w);
371
+ const pollInterval = argv['poll-interval'] !== undefined
372
+ ? parseInt(argv['poll-interval'], 10)
373
+ : undefined;
374
+ const debounce = argv.debounce !== undefined
375
+ ? parseInt(argv.debounce, 10)
376
+ : undefined;
377
+ const touch = argv.touch;
378
+ const clear = argv.clear !== false;
379
+ if (endpoint && schema) {
277
380
  console.error('x Cannot use both --endpoint and --schema. Choose one source.');
278
381
  process.exit(1);
279
382
  }
280
- // Watch mode (only for endpoint)
281
- if (options.watch) {
282
- if (options.schema) {
383
+ if (watch) {
384
+ if (schema) {
283
385
  console.error('x Watch mode is only supported with --endpoint, not --schema.');
284
386
  process.exit(1);
285
387
  }
286
- const config = await loadWatchConfig(options);
287
- if (!config) {
388
+ const watchConfig = await loadWatchConfig({
389
+ config,
390
+ target,
391
+ endpoint,
392
+ output,
393
+ pollInterval,
394
+ debounce,
395
+ touch,
396
+ clear,
397
+ });
398
+ if (!watchConfig) {
288
399
  process.exit(1);
289
400
  }
290
401
  await (0, watch_1.startWatch)({
291
- config,
402
+ config: watchConfig,
292
403
  generatorType: 'generate-orm',
293
- verbose: options.verbose,
294
- authorization: options.authorization,
295
- configPath: options.config,
296
- target: options.target,
297
- outputDir: options.output,
298
- skipCustomOperations: options.skipCustomOperations,
404
+ verbose,
405
+ authorization,
406
+ configPath: config,
407
+ target,
408
+ outputDir: output,
409
+ skipCustomOperations,
299
410
  });
300
411
  return;
301
412
  }
302
- // Normal one-shot generation
303
413
  const result = await (0, generate_orm_1.generateOrmCommand)({
304
- config: options.config,
305
- target: options.target,
306
- endpoint: options.endpoint,
307
- schema: options.schema,
308
- output: options.output,
309
- authorization: options.authorization,
310
- verbose: options.verbose,
311
- dryRun: options.dryRun,
312
- skipCustomOperations: options.skipCustomOperations,
414
+ config,
415
+ target,
416
+ endpoint,
417
+ schema,
418
+ output,
419
+ authorization,
420
+ verbose,
421
+ dryRun,
422
+ skipCustomOperations,
313
423
  });
314
424
  const duration = formatDuration(performance.now() - startTime);
315
425
  const targetResults = result.targets ?? [];
@@ -317,27 +427,27 @@ program
317
427
  (targetResults.length > 1 || targetResults[0]?.name !== 'default');
318
428
  if (hasNamedTargets) {
319
429
  console.log(result.success ? '[ok]' : 'x', result.message);
320
- targetResults.forEach((target) => {
321
- const status = target.success ? '[ok]' : 'x';
322
- console.log(`\n${status} ${target.message}`);
323
- if (target.tables && target.tables.length > 0) {
430
+ targetResults.forEach((t) => {
431
+ const status = t.success ? '[ok]' : 'x';
432
+ console.log(`\n${status} ${t.message}`);
433
+ if (t.tables && t.tables.length > 0) {
324
434
  console.log(' Tables:');
325
- target.tables.forEach((table) => console.log(` - ${table}`));
435
+ t.tables.forEach((table) => console.log(` - ${table}`));
326
436
  }
327
- if (target.customQueries && target.customQueries.length > 0) {
437
+ if (t.customQueries && t.customQueries.length > 0) {
328
438
  console.log(' Custom Queries:');
329
- target.customQueries.forEach((query) => console.log(` - ${query}`));
439
+ t.customQueries.forEach((query) => console.log(` - ${query}`));
330
440
  }
331
- if (target.customMutations && target.customMutations.length > 0) {
441
+ if (t.customMutations && t.customMutations.length > 0) {
332
442
  console.log(' Custom Mutations:');
333
- target.customMutations.forEach((mutation) => console.log(` - ${mutation}`));
443
+ t.customMutations.forEach((mutation) => console.log(` - ${mutation}`));
334
444
  }
335
- if (target.filesWritten && target.filesWritten.length > 0) {
445
+ if (t.filesWritten && t.filesWritten.length > 0) {
336
446
  console.log(' Files written:');
337
- target.filesWritten.forEach((file) => console.log(` - ${file}`));
447
+ t.filesWritten.forEach((file) => console.log(` - ${file}`));
338
448
  }
339
- if (!target.success && target.errors) {
340
- target.errors.forEach((error) => console.error(` - ${error}`));
449
+ if (!t.success && t.errors) {
450
+ t.errors.forEach((error) => console.error(` - ${error}`));
341
451
  }
342
452
  });
343
453
  if (!result.success) {
@@ -371,23 +481,25 @@ program
371
481
  }
372
482
  process.exit(1);
373
483
  }
374
- });
375
- // Introspect command (for debugging) - uses the new inference system
376
- program
377
- .command('introspect')
378
- .description('Introspect a GraphQL endpoint or schema file and print table info')
379
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL')
380
- .option('-s, --schema <path>', 'Path to GraphQL schema file (.graphql)')
381
- .option('-a, --authorization <header>', 'Authorization header value')
382
- .option('--json', 'Output as JSON', false)
383
- .action(async (options) => {
484
+ }
485
+ /**
486
+ * Introspect command handler
487
+ */
488
+ async function handleIntrospect(argv) {
489
+ if (argv.help || argv.h) {
490
+ console.log(introspectUsageText);
491
+ process.exit(0);
492
+ }
384
493
  const startTime = performance.now();
385
- // Validate source options
386
- if (!options.endpoint && !options.schema) {
494
+ const endpoint = argv.endpoint || argv.e;
495
+ const schema = argv.schema || argv.s;
496
+ const authorization = argv.authorization || argv.a;
497
+ const json = !!argv.json;
498
+ if (!endpoint && !schema) {
387
499
  console.error('x Either --endpoint or --schema must be provided.');
388
500
  process.exit(1);
389
501
  }
390
- if (options.endpoint && options.schema) {
502
+ if (endpoint && schema) {
391
503
  console.error('x Cannot use both --endpoint and --schema. Choose one source.');
392
504
  process.exit(1);
393
505
  }
@@ -395,15 +507,15 @@ program
395
507
  const { inferTablesFromIntrospection } = await Promise.resolve().then(() => __importStar(require('./introspect/infer-tables')));
396
508
  try {
397
509
  const source = createSchemaSource({
398
- endpoint: options.endpoint,
399
- schema: options.schema,
400
- authorization: options.authorization,
510
+ endpoint,
511
+ schema,
512
+ authorization,
401
513
  });
402
514
  console.log('Fetching schema from', source.describe(), '...');
403
515
  const { introspection } = await source.fetch();
404
516
  const tables = inferTablesFromIntrospection(introspection);
405
517
  const duration = formatDuration(performance.now() - startTime);
406
- if (options.json) {
518
+ if (json) {
407
519
  console.log(JSON.stringify(tables, null, 2));
408
520
  }
409
521
  else {
@@ -423,5 +535,90 @@ program
423
535
  console.error('x Failed to introspect schema:', err instanceof Error ? err.message : err, `(${duration})`);
424
536
  process.exit(1);
425
537
  }
426
- });
427
- program.parse();
538
+ }
539
+ const createCommandMap = () => {
540
+ return {
541
+ init: handleInit,
542
+ generate: handleGenerate,
543
+ 'generate-orm': handleGenerateOrm,
544
+ introspect: handleIntrospect,
545
+ };
546
+ };
547
+ const commands = async (argv, prompter, _options) => {
548
+ if (argv.version || argv.v) {
549
+ const pkg = (0, inquirerer_1.getPackageJson)(__dirname);
550
+ console.log(pkg.version);
551
+ process.exit(0);
552
+ }
553
+ const { first: command, newArgv } = (0, inquirerer_1.extractFirst)(argv);
554
+ if ((argv.help || argv.h) && !command) {
555
+ console.log(usageText);
556
+ process.exit(0);
557
+ }
558
+ if (command === 'help') {
559
+ console.log(usageText);
560
+ process.exit(0);
561
+ }
562
+ const commandMap = createCommandMap();
563
+ if (!command) {
564
+ const answer = await prompter.prompt(argv, [
565
+ {
566
+ type: 'autocomplete',
567
+ name: 'command',
568
+ message: 'What do you want to do?',
569
+ options: Object.keys(commandMap),
570
+ },
571
+ ]);
572
+ const selectedCommand = answer.command;
573
+ const commandFn = commandMap[selectedCommand];
574
+ if (commandFn) {
575
+ await commandFn(newArgv);
576
+ }
577
+ prompter.close();
578
+ return argv;
579
+ }
580
+ const commandFn = commandMap[command];
581
+ if (!commandFn) {
582
+ console.log(usageText);
583
+ await (0, inquirerer_1.cliExitWithError)(`Unknown command: ${command}`);
584
+ }
585
+ await commandFn(newArgv);
586
+ prompter.close();
587
+ return argv;
588
+ };
589
+ exports.commands = commands;
590
+ exports.options = {
591
+ minimistOpts: {
592
+ alias: {
593
+ v: 'version',
594
+ h: 'help',
595
+ c: 'config',
596
+ t: 'target',
597
+ e: 'endpoint',
598
+ s: 'schema',
599
+ o: 'output',
600
+ a: 'authorization',
601
+ d: 'directory',
602
+ f: 'force',
603
+ w: 'watch',
604
+ },
605
+ boolean: ['help', 'version', 'force', 'verbose', 'dry-run', 'watch', 'json', 'skip-custom-operations', 'clear'],
606
+ string: ['config', 'target', 'endpoint', 'schema', 'output', 'authorization', 'directory', 'touch', 'poll-interval', 'debounce'],
607
+ default: {
608
+ clear: true,
609
+ },
610
+ },
611
+ };
612
+ if (require.main === module) {
613
+ if (process.argv.includes('--version') || process.argv.includes('-v')) {
614
+ const pkg = (0, inquirerer_1.getPackageJson)(__dirname);
615
+ console.log(pkg.version);
616
+ process.exit(0);
617
+ }
618
+ const app = new inquirerer_1.CLI(exports.commands, exports.options);
619
+ app.run().then(() => {
620
+ }).catch((error) => {
621
+ console.error('Unexpected error:', error);
622
+ process.exit(1);
623
+ });
624
+ }
@@ -1,4 +1,7 @@
1
+ #!/usr/bin/env node
1
2
  /**
2
3
  * CLI entry point for graphql-codegen
3
4
  */
4
- export {};
5
+ import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer';
6
+ export declare const commands: (argv: Partial<ParsedArgs>, prompter: Inquirerer, _options: CLIOptions) => Promise<Partial<ParsedArgs>>;
7
+ export declare const options: Partial<CLIOptions>;
package/esm/cli/index.js CHANGED
@@ -1,12 +1,102 @@
1
+ #!/usr/bin/env node
1
2
  /**
2
3
  * CLI entry point for graphql-codegen
3
4
  */
4
- import { Command } from 'commander';
5
+ import { CLI, cliExitWithError, extractFirst, getPackageJson } from 'inquirerer';
5
6
  import { initCommand, findConfigFile, loadConfigFile } from './commands/init';
6
7
  import { generateCommand } from './commands/generate';
7
8
  import { generateOrmCommand } from './commands/generate-orm';
8
9
  import { startWatch } from './watch';
9
10
  import { isMultiConfig, mergeConfig, resolveConfig, } from '../types/config';
11
+ const usageText = `
12
+ graphql-codegen - CLI for generating GraphQL SDK from PostGraphile endpoints or schema files
13
+
14
+ Usage:
15
+ graphql-codegen <command> [options]
16
+
17
+ Commands:
18
+ init Initialize a new graphql-codegen configuration file
19
+ generate Generate SDK from GraphQL endpoint or schema file
20
+ generate-orm Generate Prisma-like ORM client from GraphQL endpoint or schema file
21
+ introspect Introspect a GraphQL endpoint or schema file and print table info
22
+
23
+ Options:
24
+ --help, -h Show this help message
25
+ --version, -v Show version number
26
+
27
+ Run 'graphql-codegen <command> --help' for more information on a command.
28
+ `;
29
+ const initUsageText = `
30
+ graphql-codegen init - Initialize a new graphql-codegen configuration file
31
+
32
+ Usage:
33
+ graphql-codegen init [options]
34
+
35
+ Options:
36
+ --directory, -d <dir> Target directory for the config file (default: .)
37
+ --force, -f Force overwrite existing config
38
+ --endpoint, -e <url> GraphQL endpoint URL to pre-populate
39
+ --output, -o <dir> Output directory to pre-populate (default: ./generated)
40
+ --help, -h Show this help message
41
+ `;
42
+ const generateUsageText = `
43
+ graphql-codegen generate - Generate SDK from GraphQL endpoint or schema file
44
+
45
+ Usage:
46
+ graphql-codegen generate [options]
47
+
48
+ Options:
49
+ --config, -c <path> Path to config file
50
+ --target, -t <name> Target name in config file
51
+ --endpoint, -e <url> GraphQL endpoint URL (overrides config)
52
+ --schema, -s <path> Path to GraphQL schema file (.graphql)
53
+ --output, -o <dir> Output directory (overrides config)
54
+ --authorization, -a <header> Authorization header value
55
+ --verbose, -v Verbose output
56
+ --dry-run Dry run - show what would be generated without writing files
57
+ --watch, -w Watch mode - poll endpoint for schema changes (in-memory)
58
+ --poll-interval <ms> Polling interval in milliseconds (default: 3000)
59
+ --debounce <ms> Debounce delay before regenerating (default: 800)
60
+ --touch <file> File to touch on schema change
61
+ --no-clear Do not clear terminal on regeneration
62
+ --help, -h Show this help message
63
+ `;
64
+ const generateOrmUsageText = `
65
+ graphql-codegen generate-orm - Generate Prisma-like ORM client from GraphQL endpoint or schema file
66
+
67
+ Usage:
68
+ graphql-codegen generate-orm [options]
69
+
70
+ Options:
71
+ --config, -c <path> Path to config file
72
+ --target, -t <name> Target name in config file
73
+ --endpoint, -e <url> GraphQL endpoint URL (overrides config)
74
+ --schema, -s <path> Path to GraphQL schema file (.graphql)
75
+ --output, -o <dir> Output directory (overrides config)
76
+ --authorization, -a <header> Authorization header value
77
+ --verbose, -v Verbose output
78
+ --dry-run Dry run - show what would be generated without writing files
79
+ --skip-custom-operations Skip custom operations (only generate table CRUD)
80
+ --watch, -w Watch mode - poll endpoint for schema changes (in-memory)
81
+ --poll-interval <ms> Polling interval in milliseconds (default: 3000)
82
+ --debounce <ms> Debounce delay before regenerating (default: 800)
83
+ --touch <file> File to touch on schema change
84
+ --no-clear Do not clear terminal on regeneration
85
+ --help, -h Show this help message
86
+ `;
87
+ const introspectUsageText = `
88
+ graphql-codegen introspect - Introspect a GraphQL endpoint or schema file and print table info
89
+
90
+ Usage:
91
+ graphql-codegen introspect [options]
92
+
93
+ Options:
94
+ --endpoint, -e <url> GraphQL endpoint URL
95
+ --schema, -s <path> Path to GraphQL schema file (.graphql)
96
+ --authorization, -a <header> Authorization header value
97
+ --json Output as JSON
98
+ --help, -h Show this help message
99
+ `;
10
100
  /**
11
101
  * Format duration in a human-readable way
12
102
  * - Under 1 second: show milliseconds (e.g., "123ms")
@@ -18,12 +108,10 @@ function formatDuration(ms) {
18
108
  }
19
109
  return `${(ms / 1000).toFixed(2)}s`;
20
110
  }
21
- const program = new Command();
22
111
  /**
23
112
  * Load configuration for watch mode, merging CLI options with config file
24
113
  */
25
114
  async function loadWatchConfig(options) {
26
- // Find config file
27
115
  let configPath = options.config;
28
116
  if (!configPath) {
29
117
  configPath = findConfigFile() ?? undefined;
@@ -87,25 +175,20 @@ async function loadWatchConfig(options) {
87
175
  }
88
176
  return resolveConfig(mergedTarget);
89
177
  }
90
- program
91
- .name('graphql-codegen')
92
- .description('CLI for generating GraphQL SDK from PostGraphile endpoints or schema files')
93
- .version('2.17.48');
94
- // Init command
95
- program
96
- .command('init')
97
- .description('Initialize a new graphql-codegen configuration file')
98
- .option('-d, --directory <dir>', 'Target directory for the config file', '.')
99
- .option('-f, --force', 'Force overwrite existing config', false)
100
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL to pre-populate')
101
- .option('-o, --output <dir>', 'Output directory to pre-populate', './generated')
102
- .action(async (options) => {
178
+ /**
179
+ * Init command handler
180
+ */
181
+ async function handleInit(argv) {
182
+ if (argv.help || argv.h) {
183
+ console.log(initUsageText);
184
+ process.exit(0);
185
+ }
103
186
  const startTime = performance.now();
104
187
  const result = await initCommand({
105
- directory: options.directory,
106
- force: options.force,
107
- endpoint: options.endpoint,
108
- output: options.output,
188
+ directory: argv.directory || argv.d || '.',
189
+ force: !!(argv.force || argv.f),
190
+ endpoint: argv.endpoint || argv.e,
191
+ output: argv.output || argv.o || './generated',
109
192
  });
110
193
  const duration = formatDuration(performance.now() - startTime);
111
194
  if (result.success) {
@@ -115,62 +198,75 @@ program
115
198
  console.error('x', result.message, `(${duration})`);
116
199
  process.exit(1);
117
200
  }
118
- });
119
- // Generate command
120
- program
121
- .command('generate')
122
- .description('Generate SDK from GraphQL endpoint or schema file')
123
- .option('-c, --config <path>', 'Path to config file')
124
- .option('-t, --target <name>', 'Target name in config file')
125
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL (overrides config)')
126
- .option('-s, --schema <path>', 'Path to GraphQL schema file (.graphql)')
127
- .option('-o, --output <dir>', 'Output directory (overrides config)')
128
- .option('-a, --authorization <header>', 'Authorization header value')
129
- .option('-v, --verbose', 'Verbose output', false)
130
- .option('--dry-run', 'Dry run - show what would be generated without writing files', false)
131
- .option('-w, --watch', 'Watch mode - poll endpoint for schema changes (in-memory)', false)
132
- .option('--poll-interval <ms>', 'Polling interval in milliseconds (default: 3000)', parseInt)
133
- .option('--debounce <ms>', 'Debounce delay before regenerating (default: 800)', parseInt)
134
- .option('--touch <file>', 'File to touch on schema change')
135
- .option('--no-clear', 'Do not clear terminal on regeneration')
136
- .action(async (options) => {
201
+ }
202
+ /**
203
+ * Generate command handler
204
+ */
205
+ async function handleGenerate(argv) {
206
+ if (argv.help || argv.h) {
207
+ console.log(generateUsageText);
208
+ process.exit(0);
209
+ }
137
210
  const startTime = performance.now();
138
- // Validate source options
139
- if (options.endpoint && options.schema) {
211
+ const config = argv.config || argv.c;
212
+ const target = argv.target || argv.t;
213
+ const endpoint = argv.endpoint || argv.e;
214
+ const schema = argv.schema || argv.s;
215
+ const output = argv.output || argv.o;
216
+ const authorization = argv.authorization || argv.a;
217
+ const verbose = !!(argv.verbose || argv.v);
218
+ const dryRun = !!(argv['dry-run'] || argv.dryRun);
219
+ const watch = !!(argv.watch || argv.w);
220
+ const pollInterval = argv['poll-interval'] !== undefined
221
+ ? parseInt(argv['poll-interval'], 10)
222
+ : undefined;
223
+ const debounce = argv.debounce !== undefined
224
+ ? parseInt(argv.debounce, 10)
225
+ : undefined;
226
+ const touch = argv.touch;
227
+ const clear = argv.clear !== false;
228
+ if (endpoint && schema) {
140
229
  console.error('x Cannot use both --endpoint and --schema. Choose one source.');
141
230
  process.exit(1);
142
231
  }
143
- // Watch mode (only for endpoint)
144
- if (options.watch) {
145
- if (options.schema) {
232
+ if (watch) {
233
+ if (schema) {
146
234
  console.error('x Watch mode is only supported with --endpoint, not --schema.');
147
235
  process.exit(1);
148
236
  }
149
- const config = await loadWatchConfig(options);
150
- if (!config) {
237
+ const watchConfig = await loadWatchConfig({
238
+ config,
239
+ target,
240
+ endpoint,
241
+ output,
242
+ pollInterval,
243
+ debounce,
244
+ touch,
245
+ clear,
246
+ });
247
+ if (!watchConfig) {
151
248
  process.exit(1);
152
249
  }
153
250
  await startWatch({
154
- config,
251
+ config: watchConfig,
155
252
  generatorType: 'generate',
156
- verbose: options.verbose,
157
- authorization: options.authorization,
158
- configPath: options.config,
159
- target: options.target,
160
- outputDir: options.output,
253
+ verbose,
254
+ authorization,
255
+ configPath: config,
256
+ target,
257
+ outputDir: output,
161
258
  });
162
259
  return;
163
260
  }
164
- // Normal one-shot generation
165
261
  const result = await generateCommand({
166
- config: options.config,
167
- target: options.target,
168
- endpoint: options.endpoint,
169
- schema: options.schema,
170
- output: options.output,
171
- authorization: options.authorization,
172
- verbose: options.verbose,
173
- dryRun: options.dryRun,
262
+ config,
263
+ target,
264
+ endpoint,
265
+ schema,
266
+ output,
267
+ authorization,
268
+ verbose,
269
+ dryRun,
174
270
  });
175
271
  const duration = formatDuration(performance.now() - startTime);
176
272
  const targetResults = result.targets ?? [];
@@ -178,19 +274,19 @@ program
178
274
  (targetResults.length > 1 || targetResults[0]?.name !== 'default');
179
275
  if (hasNamedTargets) {
180
276
  console.log(result.success ? '[ok]' : 'x', result.message);
181
- targetResults.forEach((target) => {
182
- const status = target.success ? '[ok]' : 'x';
183
- console.log(`\n${status} ${target.message}`);
184
- if (target.tables && target.tables.length > 0) {
277
+ targetResults.forEach((t) => {
278
+ const status = t.success ? '[ok]' : 'x';
279
+ console.log(`\n${status} ${t.message}`);
280
+ if (t.tables && t.tables.length > 0) {
185
281
  console.log(' Tables:');
186
- target.tables.forEach((table) => console.log(` - ${table}`));
282
+ t.tables.forEach((table) => console.log(` - ${table}`));
187
283
  }
188
- if (target.filesWritten && target.filesWritten.length > 0) {
284
+ if (t.filesWritten && t.filesWritten.length > 0) {
189
285
  console.log(' Files written:');
190
- target.filesWritten.forEach((file) => console.log(` - ${file}`));
286
+ t.filesWritten.forEach((file) => console.log(` - ${file}`));
191
287
  }
192
- if (!target.success && target.errors) {
193
- target.errors.forEach((error) => console.error(` - ${error}`));
288
+ if (!t.success && t.errors) {
289
+ t.errors.forEach((error) => console.error(` - ${error}`));
194
290
  }
195
291
  });
196
292
  if (!result.success) {
@@ -216,65 +312,78 @@ program
216
312
  }
217
313
  process.exit(1);
218
314
  }
219
- });
220
- // Generate ORM command
221
- program
222
- .command('generate-orm')
223
- .description('Generate Prisma-like ORM client from GraphQL endpoint or schema file')
224
- .option('-c, --config <path>', 'Path to config file')
225
- .option('-t, --target <name>', 'Target name in config file')
226
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL (overrides config)')
227
- .option('-s, --schema <path>', 'Path to GraphQL schema file (.graphql)')
228
- .option('-o, --output <dir>', 'Output directory (overrides config)')
229
- .option('-a, --authorization <header>', 'Authorization header value')
230
- .option('-v, --verbose', 'Verbose output', false)
231
- .option('--dry-run', 'Dry run - show what would be generated without writing files', false)
232
- .option('--skip-custom-operations', 'Skip custom operations (only generate table CRUD)', false)
233
- .option('-w, --watch', 'Watch mode - poll endpoint for schema changes (in-memory)', false)
234
- .option('--poll-interval <ms>', 'Polling interval in milliseconds (default: 3000)', parseInt)
235
- .option('--debounce <ms>', 'Debounce delay before regenerating (default: 800)', parseInt)
236
- .option('--touch <file>', 'File to touch on schema change')
237
- .option('--no-clear', 'Do not clear terminal on regeneration')
238
- .action(async (options) => {
315
+ }
316
+ /**
317
+ * Generate ORM command handler
318
+ */
319
+ async function handleGenerateOrm(argv) {
320
+ if (argv.help || argv.h) {
321
+ console.log(generateOrmUsageText);
322
+ process.exit(0);
323
+ }
239
324
  const startTime = performance.now();
240
- // Validate source options
241
- if (options.endpoint && options.schema) {
325
+ const config = argv.config || argv.c;
326
+ const target = argv.target || argv.t;
327
+ const endpoint = argv.endpoint || argv.e;
328
+ const schema = argv.schema || argv.s;
329
+ const output = argv.output || argv.o;
330
+ const authorization = argv.authorization || argv.a;
331
+ const verbose = !!(argv.verbose || argv.v);
332
+ const dryRun = !!(argv['dry-run'] || argv.dryRun);
333
+ const skipCustomOperations = !!(argv['skip-custom-operations'] || argv.skipCustomOperations);
334
+ const watch = !!(argv.watch || argv.w);
335
+ const pollInterval = argv['poll-interval'] !== undefined
336
+ ? parseInt(argv['poll-interval'], 10)
337
+ : undefined;
338
+ const debounce = argv.debounce !== undefined
339
+ ? parseInt(argv.debounce, 10)
340
+ : undefined;
341
+ const touch = argv.touch;
342
+ const clear = argv.clear !== false;
343
+ if (endpoint && schema) {
242
344
  console.error('x Cannot use both --endpoint and --schema. Choose one source.');
243
345
  process.exit(1);
244
346
  }
245
- // Watch mode (only for endpoint)
246
- if (options.watch) {
247
- if (options.schema) {
347
+ if (watch) {
348
+ if (schema) {
248
349
  console.error('x Watch mode is only supported with --endpoint, not --schema.');
249
350
  process.exit(1);
250
351
  }
251
- const config = await loadWatchConfig(options);
252
- if (!config) {
352
+ const watchConfig = await loadWatchConfig({
353
+ config,
354
+ target,
355
+ endpoint,
356
+ output,
357
+ pollInterval,
358
+ debounce,
359
+ touch,
360
+ clear,
361
+ });
362
+ if (!watchConfig) {
253
363
  process.exit(1);
254
364
  }
255
365
  await startWatch({
256
- config,
366
+ config: watchConfig,
257
367
  generatorType: 'generate-orm',
258
- verbose: options.verbose,
259
- authorization: options.authorization,
260
- configPath: options.config,
261
- target: options.target,
262
- outputDir: options.output,
263
- skipCustomOperations: options.skipCustomOperations,
368
+ verbose,
369
+ authorization,
370
+ configPath: config,
371
+ target,
372
+ outputDir: output,
373
+ skipCustomOperations,
264
374
  });
265
375
  return;
266
376
  }
267
- // Normal one-shot generation
268
377
  const result = await generateOrmCommand({
269
- config: options.config,
270
- target: options.target,
271
- endpoint: options.endpoint,
272
- schema: options.schema,
273
- output: options.output,
274
- authorization: options.authorization,
275
- verbose: options.verbose,
276
- dryRun: options.dryRun,
277
- skipCustomOperations: options.skipCustomOperations,
378
+ config,
379
+ target,
380
+ endpoint,
381
+ schema,
382
+ output,
383
+ authorization,
384
+ verbose,
385
+ dryRun,
386
+ skipCustomOperations,
278
387
  });
279
388
  const duration = formatDuration(performance.now() - startTime);
280
389
  const targetResults = result.targets ?? [];
@@ -282,27 +391,27 @@ program
282
391
  (targetResults.length > 1 || targetResults[0]?.name !== 'default');
283
392
  if (hasNamedTargets) {
284
393
  console.log(result.success ? '[ok]' : 'x', result.message);
285
- targetResults.forEach((target) => {
286
- const status = target.success ? '[ok]' : 'x';
287
- console.log(`\n${status} ${target.message}`);
288
- if (target.tables && target.tables.length > 0) {
394
+ targetResults.forEach((t) => {
395
+ const status = t.success ? '[ok]' : 'x';
396
+ console.log(`\n${status} ${t.message}`);
397
+ if (t.tables && t.tables.length > 0) {
289
398
  console.log(' Tables:');
290
- target.tables.forEach((table) => console.log(` - ${table}`));
399
+ t.tables.forEach((table) => console.log(` - ${table}`));
291
400
  }
292
- if (target.customQueries && target.customQueries.length > 0) {
401
+ if (t.customQueries && t.customQueries.length > 0) {
293
402
  console.log(' Custom Queries:');
294
- target.customQueries.forEach((query) => console.log(` - ${query}`));
403
+ t.customQueries.forEach((query) => console.log(` - ${query}`));
295
404
  }
296
- if (target.customMutations && target.customMutations.length > 0) {
405
+ if (t.customMutations && t.customMutations.length > 0) {
297
406
  console.log(' Custom Mutations:');
298
- target.customMutations.forEach((mutation) => console.log(` - ${mutation}`));
407
+ t.customMutations.forEach((mutation) => console.log(` - ${mutation}`));
299
408
  }
300
- if (target.filesWritten && target.filesWritten.length > 0) {
409
+ if (t.filesWritten && t.filesWritten.length > 0) {
301
410
  console.log(' Files written:');
302
- target.filesWritten.forEach((file) => console.log(` - ${file}`));
411
+ t.filesWritten.forEach((file) => console.log(` - ${file}`));
303
412
  }
304
- if (!target.success && target.errors) {
305
- target.errors.forEach((error) => console.error(` - ${error}`));
413
+ if (!t.success && t.errors) {
414
+ t.errors.forEach((error) => console.error(` - ${error}`));
306
415
  }
307
416
  });
308
417
  if (!result.success) {
@@ -336,23 +445,25 @@ program
336
445
  }
337
446
  process.exit(1);
338
447
  }
339
- });
340
- // Introspect command (for debugging) - uses the new inference system
341
- program
342
- .command('introspect')
343
- .description('Introspect a GraphQL endpoint or schema file and print table info')
344
- .option('-e, --endpoint <url>', 'GraphQL endpoint URL')
345
- .option('-s, --schema <path>', 'Path to GraphQL schema file (.graphql)')
346
- .option('-a, --authorization <header>', 'Authorization header value')
347
- .option('--json', 'Output as JSON', false)
348
- .action(async (options) => {
448
+ }
449
+ /**
450
+ * Introspect command handler
451
+ */
452
+ async function handleIntrospect(argv) {
453
+ if (argv.help || argv.h) {
454
+ console.log(introspectUsageText);
455
+ process.exit(0);
456
+ }
349
457
  const startTime = performance.now();
350
- // Validate source options
351
- if (!options.endpoint && !options.schema) {
458
+ const endpoint = argv.endpoint || argv.e;
459
+ const schema = argv.schema || argv.s;
460
+ const authorization = argv.authorization || argv.a;
461
+ const json = !!argv.json;
462
+ if (!endpoint && !schema) {
352
463
  console.error('x Either --endpoint or --schema must be provided.');
353
464
  process.exit(1);
354
465
  }
355
- if (options.endpoint && options.schema) {
466
+ if (endpoint && schema) {
356
467
  console.error('x Cannot use both --endpoint and --schema. Choose one source.');
357
468
  process.exit(1);
358
469
  }
@@ -360,15 +471,15 @@ program
360
471
  const { inferTablesFromIntrospection } = await import('./introspect/infer-tables');
361
472
  try {
362
473
  const source = createSchemaSource({
363
- endpoint: options.endpoint,
364
- schema: options.schema,
365
- authorization: options.authorization,
474
+ endpoint,
475
+ schema,
476
+ authorization,
366
477
  });
367
478
  console.log('Fetching schema from', source.describe(), '...');
368
479
  const { introspection } = await source.fetch();
369
480
  const tables = inferTablesFromIntrospection(introspection);
370
481
  const duration = formatDuration(performance.now() - startTime);
371
- if (options.json) {
482
+ if (json) {
372
483
  console.log(JSON.stringify(tables, null, 2));
373
484
  }
374
485
  else {
@@ -388,5 +499,89 @@ program
388
499
  console.error('x Failed to introspect schema:', err instanceof Error ? err.message : err, `(${duration})`);
389
500
  process.exit(1);
390
501
  }
391
- });
392
- program.parse();
502
+ }
503
+ const createCommandMap = () => {
504
+ return {
505
+ init: handleInit,
506
+ generate: handleGenerate,
507
+ 'generate-orm': handleGenerateOrm,
508
+ introspect: handleIntrospect,
509
+ };
510
+ };
511
+ export const commands = async (argv, prompter, _options) => {
512
+ if (argv.version || argv.v) {
513
+ const pkg = getPackageJson(__dirname);
514
+ console.log(pkg.version);
515
+ process.exit(0);
516
+ }
517
+ const { first: command, newArgv } = extractFirst(argv);
518
+ if ((argv.help || argv.h) && !command) {
519
+ console.log(usageText);
520
+ process.exit(0);
521
+ }
522
+ if (command === 'help') {
523
+ console.log(usageText);
524
+ process.exit(0);
525
+ }
526
+ const commandMap = createCommandMap();
527
+ if (!command) {
528
+ const answer = await prompter.prompt(argv, [
529
+ {
530
+ type: 'autocomplete',
531
+ name: 'command',
532
+ message: 'What do you want to do?',
533
+ options: Object.keys(commandMap),
534
+ },
535
+ ]);
536
+ const selectedCommand = answer.command;
537
+ const commandFn = commandMap[selectedCommand];
538
+ if (commandFn) {
539
+ await commandFn(newArgv);
540
+ }
541
+ prompter.close();
542
+ return argv;
543
+ }
544
+ const commandFn = commandMap[command];
545
+ if (!commandFn) {
546
+ console.log(usageText);
547
+ await cliExitWithError(`Unknown command: ${command}`);
548
+ }
549
+ await commandFn(newArgv);
550
+ prompter.close();
551
+ return argv;
552
+ };
553
+ export const options = {
554
+ minimistOpts: {
555
+ alias: {
556
+ v: 'version',
557
+ h: 'help',
558
+ c: 'config',
559
+ t: 'target',
560
+ e: 'endpoint',
561
+ s: 'schema',
562
+ o: 'output',
563
+ a: 'authorization',
564
+ d: 'directory',
565
+ f: 'force',
566
+ w: 'watch',
567
+ },
568
+ boolean: ['help', 'version', 'force', 'verbose', 'dry-run', 'watch', 'json', 'skip-custom-operations', 'clear'],
569
+ string: ['config', 'target', 'endpoint', 'schema', 'output', 'authorization', 'directory', 'touch', 'poll-interval', 'debounce'],
570
+ default: {
571
+ clear: true,
572
+ },
573
+ },
574
+ };
575
+ if (require.main === module) {
576
+ if (process.argv.includes('--version') || process.argv.includes('-v')) {
577
+ const pkg = getPackageJson(__dirname);
578
+ console.log(pkg.version);
579
+ process.exit(0);
580
+ }
581
+ const app = new CLI(commands, options);
582
+ app.run().then(() => {
583
+ }).catch((error) => {
584
+ console.error('Unexpected error:', error);
585
+ process.exit(1);
586
+ });
587
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-codegen",
3
- "version": "2.27.2",
3
+ "version": "2.28.0",
4
4
  "description": "CLI-based GraphQL SDK generator for PostGraphile endpoints with React Query hooks",
5
5
  "keywords": [
6
6
  "graphql",
@@ -54,11 +54,13 @@
54
54
  "dependencies": {
55
55
  "@babel/generator": "^7.28.6",
56
56
  "@babel/types": "^7.28.6",
57
+ "@inquirerer/utils": "^3.2.0",
57
58
  "ajv": "^8.17.1",
58
- "commander": "^12.1.0",
59
+ "find-and-require-package-json": "^0.9.0",
59
60
  "gql-ast": "^2.6.0",
60
61
  "graphql": "15.10.1",
61
- "inflekt": "^0.2.0",
62
+ "inflekt": "^0.3.0",
63
+ "inquirerer": "^4.4.0",
62
64
  "jiti": "^2.6.1",
63
65
  "oxfmt": "^0.13.0"
64
66
  },
@@ -75,16 +77,16 @@
75
77
  }
76
78
  },
77
79
  "devDependencies": {
78
- "@tanstack/react-query": "^5.90.16",
80
+ "@tanstack/react-query": "^5.90.19",
79
81
  "@types/babel__generator": "^7.27.0",
80
- "@types/jest": "^29.5.14",
82
+ "@types/jest": "^30.0.0",
81
83
  "@types/node": "^20.19.27",
82
- "@types/react": "^19.2.7",
83
- "jest": "^29.7.0",
84
+ "@types/react": "^19.2.8",
85
+ "jest": "^30.2.0",
84
86
  "react": "^19.2.3",
85
87
  "ts-jest": "^29.2.5",
86
88
  "tsx": "^4.21.0",
87
89
  "typescript": "^5.9.3"
88
90
  },
89
- "gitHead": "3ffd5718e86ea5fa9ca6e0930aeb510cf392f343"
91
+ "gitHead": "ec2b5f644c479626305ef85a05a6e7105c2c58cd"
90
92
  }