@constructive-io/graphql-codegen 2.27.2 → 2.27.3

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