Skip to content

Commit dac6dce

Browse files
authored
Merge pull request #739 from constructive-io/devin/1771960154-cli-entry-point
feat(codegen): add CLI entry point generation option (cli.entryPoint)
2 parents b758178 + 51cf315 commit dac6dce

5 files changed

Lines changed: 77 additions & 2 deletions

File tree

graphql/codegen/src/core/codegen/cli/index.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
generateMultiTargetContextCommand,
1212
} from './infra-generator';
1313
import { generateTableCommand } from './table-command-generator';
14-
import { generateUtilsFile, generateNodeFetchFile } from './utils-generator';
14+
import { generateUtilsFile, generateNodeFetchFile, generateEntryPointFile } from './utils-generator';
1515

1616
export interface GenerateCliOptions {
1717
tables: CleanTable[];
@@ -91,6 +91,13 @@ export function generateCli(options: GenerateCliOptions): GenerateCliResult {
9191
);
9292
files.push(commandMapFile);
9393

94+
// Generate entry point if configured
95+
const generateEntryPoint =
96+
typeof cliConfig === 'object' && !!cliConfig.entryPoint;
97+
if (generateEntryPoint) {
98+
files.push(generateEntryPointFile());
99+
}
100+
94101
return {
95102
files,
96103
stats: {
@@ -123,6 +130,8 @@ export interface GenerateMultiTargetCliOptions {
123130
targets: MultiTargetCliTarget[];
124131
/** Enable NodeHttpAdapter for *.localhost subdomain routing */
125132
nodeHttpAdapter?: boolean;
133+
/** Generate a runnable index.ts entry point */
134+
entryPoint?: boolean;
126135
}
127136

128137
export function resolveBuiltinNames(
@@ -232,6 +241,11 @@ export function generateMultiTargetCli(
232241
});
233242
files.push(commandMapFile);
234243

244+
// Generate entry point if configured
245+
if (options.entryPoint) {
246+
files.push(generateEntryPointFile());
247+
}
248+
235249
return {
236250
files,
237251
stats: {
@@ -267,5 +281,5 @@ export {
267281
export type { MultiTargetDocsInput } from './docs-generator';
268282
export { resolveDocsConfig } from '../docs-utils';
269283
export type { GeneratedDocFile, McpTool } from '../docs-utils';
270-
export { generateUtilsFile } from './utils-generator';
284+
export { generateUtilsFile, generateEntryPointFile } from './utils-generator';
271285
export type { GeneratedFile, MultiTargetExecutorInput } from './executor-generator';

graphql/codegen/src/core/codegen/cli/utils-generator.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,21 @@ export function generateNodeFetchFile(): GeneratedFile {
7676
),
7777
};
7878
}
79+
80+
/**
81+
* Generate an index.ts entry point file for the CLI.
82+
*
83+
* Creates a runnable entry point that imports the command map,
84+
* handles --version and --tty flags, and starts the CLI.
85+
* This is off by default (cliEntryPoint: false) since many projects
86+
* provide their own entry point with custom configuration.
87+
*/
88+
export function generateEntryPointFile(): GeneratedFile {
89+
return {
90+
fileName: 'index.ts',
91+
content: readTemplateFile(
92+
'cli-entry.ts',
93+
'CLI entry point',
94+
),
95+
};
96+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* CLI entry point for running the generated CLI application.
3+
*
4+
* Creates an inquirerer CLI instance with the generated command map,
5+
* handles --version and --tty flags, and runs the CLI.
6+
*
7+
* NOTE: This file is read at codegen time and written to output.
8+
* Any changes here will affect all generated CLI entry points.
9+
*/
10+
11+
import { CLI, CLIOptions, getPackageJson } from 'inquirerer';
12+
import { commands } from './commands';
13+
14+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
15+
const pkg = getPackageJson(__dirname);
16+
console.log(pkg.version);
17+
process.exit(0);
18+
}
19+
20+
// Check for --tty false to enable non-interactive mode (noTty)
21+
const ttyIdx = process.argv.indexOf('--tty');
22+
const noTty = ttyIdx !== -1 && process.argv[ttyIdx + 1] === 'false';
23+
24+
const options: Partial<CLIOptions> = {
25+
noTty,
26+
minimistOpts: { alias: { v: 'version', h: 'help' } },
27+
};
28+
29+
const app = new CLI(commands, options);
30+
app.run().catch((e) => {
31+
console.error('Unexpected error:', e);
32+
process.exit(1);
33+
});

graphql/codegen/src/core/generate.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ export async function generateMulti(
696696
builtinNames: cliConfig.builtinNames,
697697
targets: cliTargets,
698698
nodeHttpAdapter: multiNodeHttpAdapter,
699+
entryPoint: cliConfig.entryPoint,
699700
});
700701

701702
const cliFilesToWrite = files.map((file) => ({

graphql/codegen/src/types/config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,15 @@ export interface CliConfig {
199199
* context -> 'context' (renamed to 'env' on collision)
200200
*/
201201
builtinNames?: BuiltinNames;
202+
203+
/**
204+
* Generate a runnable index.ts entry point for the CLI.
205+
* When true, generates an index.ts that imports the command map,
206+
* handles --version and --tty flags, and starts the inquirerer CLI.
207+
* Useful for projects that want a ready-to-run CLI without a custom entry point.
208+
* @default false
209+
*/
210+
entryPoint?: boolean;
202211
}
203212

204213
/**

0 commit comments

Comments
 (0)