diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts index 10178f3f5..326eef46d 100644 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ b/graphql/codegen/src/cli/commands/generate-orm.ts @@ -35,6 +35,8 @@ export interface GenerateOrmOptions { output?: string; /** Authorization header */ authorization?: string; + /** Additional HTTP headers for endpoint requests */ + headers?: Record; /** Verbose output */ verbose?: boolean; /** Dry run - don't write files */ @@ -173,7 +175,7 @@ async function generateOrmForTarget( endpoint: config.endpoint || undefined, schema: config.schema || undefined, authorization: options.authorization || config.headers['Authorization'], - headers: config.headers, + headers: { ...config.headers, ...options.headers }, }); // 2. Run the codegen pipeline diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts index 4f36710b0..e039da494 100644 --- a/graphql/codegen/src/cli/commands/generate.ts +++ b/graphql/codegen/src/cli/commands/generate.ts @@ -37,6 +37,8 @@ export interface GenerateOptions { output?: string; /** Authorization header */ authorization?: string; + /** Additional HTTP headers for endpoint requests */ + headers?: Record; /** Verbose output */ verbose?: boolean; /** Dry run - don't write files */ @@ -174,7 +176,7 @@ async function generateForTarget( endpoint: config.endpoint || undefined, schema: config.schema || undefined, authorization: options.authorization || config.headers['Authorization'], - headers: config.headers, + headers: { ...config.headers, ...options.headers }, }); // 2. Run the codegen pipeline diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 9e67a4a83..988287511 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -7,6 +7,10 @@ import { generateCommand, type GenerateTargetResult, } from '@constructive-io/graphql-codegen/cli/commands/generate'; +import { + generateOrmCommand, + type GenerateOrmTargetResult, +} from '@constructive-io/graphql-codegen/cli/commands/generate-orm'; import { findConfigFile } from '@constructive-io/graphql-codegen/cli/commands/init'; import { ConstructiveOptions, @@ -20,16 +24,23 @@ Constructive GraphQL Codegen: Options: --help, -h Show this help message + --mode Generation mode: "hooks" (default) or "orm" --config Path to graphql-codegen config file --target Target name in config file --endpoint GraphQL endpoint URL --auth Authorization header value (e.g., "Bearer 123") - --out Output directory (default: graphql/codegen/dist) + --header "Name: Value" Optional HTTP header; repeat to add multiple + --out Output directory --dry-run Preview without writing files -v, --verbose Verbose output --database Database override for DB mode (defaults to PGDATABASE) --schemas Comma-separated schemas (required for DB mode) + +Examples: + cnc codegen --endpoint https://api.example.com/graphql + cnc codegen --mode orm --endpoint https://api.example.com/graphql + cnc codegen --mode hooks --schemas public --database mydb `; export default async ( @@ -42,6 +53,7 @@ export default async ( process.exit(0); } + const mode = (argv.mode as string) || 'hooks'; const endpointArg = (argv.endpoint as string) || ''; const outputArg = argv.out as string | undefined; const outDir = outputArg || 'codegen'; @@ -50,6 +62,11 @@ export default async ( const target = (argv.target as string) || ''; const dryRun = !!(argv['dry-run'] || argv.dryRun); const verbose = !!(argv.verbose || argv.v); + + if (mode !== 'hooks' && mode !== 'orm') { + console.error(`Error: Invalid mode "${mode}". Must be "hooks" or "orm".`); + process.exit(1); + } const resolvedConfigPath = configPath || findConfigFile() || ''; const hasConfigFile = Boolean(resolvedConfigPath); const outputForGenerate = outputArg || !hasConfigFile ? outDir : undefined; @@ -60,6 +77,19 @@ export default async ( : getEnvOptions(); const schemasArg = (argv.schemas as string) || ''; + // Parse repeatable --header args into a headers object + const headerArg = argv.header as string | string[] | undefined + const headerList = Array.isArray(headerArg) ? headerArg : headerArg ? [headerArg] : [] + const headers: Record = {} + for (const h of headerList) { + const idx = typeof h === 'string' ? h.indexOf(':') : -1 + if (idx <= 0) continue + const name = h.slice(0, idx).trim() + const value = h.slice(idx + 1).trim() + if (!name) continue + headers[name] = value + } + const runGenerate = async ({ endpoint, schema, @@ -67,17 +97,30 @@ export default async ( endpoint?: string; schema?: string; }) => { - const result = await generateCommand({ - config: configPath || undefined, - target: target || undefined, - endpoint, - schema, - output: outputForGenerate, - authorization: auth || undefined, - verbose, - dryRun, - }); - const targetResults: GenerateTargetResult[] = result.targets ?? []; + const result = mode === 'orm' + ? await generateOrmCommand({ + config: configPath || undefined, + target: target || undefined, + endpoint, + schema, + output: outputForGenerate, + authorization: auth || undefined, + headers, + verbose, + dryRun, + }) + : await generateCommand({ + config: configPath || undefined, + target: target || undefined, + endpoint, + schema, + output: outputForGenerate, + authorization: auth || undefined, + headers, + verbose, + dryRun, + }); + const targetResults: (GenerateTargetResult | GenerateOrmTargetResult)[] = result.targets ?? []; const hasNamedTargets = targetResults.length > 0 && (targetResults.length > 1 || targetResults[0]?.name !== 'default'); @@ -90,14 +133,20 @@ export default async ( if (target.tables?.length) { console.log(' Tables:'); - target.tables.forEach((table) => console.log(` - ${table}`)); + for (const table of target.tables) { + console.log(` - ${table}`); + } } if (target.filesWritten?.length) { console.log(' Files written:'); - target.filesWritten.forEach((file) => console.log(` - ${file}`)); + for (const file of target.filesWritten) { + console.log(` - ${file}`); + } } if (!target.success && target.errors?.length) { - target.errors.forEach((error) => console.error(` - ${error}`)); + for (const error of target.errors) { + console.error(` - ${error}`); + } } }); @@ -109,13 +158,18 @@ export default async ( if (!result.success) { console.error(result.message); - if (result.errors?.length) - result.errors.forEach((e) => console.error(' -', e)); + if (result.errors?.length) { + for (const e of result.errors) { + console.error(' -', e); + } + } process.exit(1); } console.log(result.message); if (result.filesWritten?.length) { - result.filesWritten.forEach((f) => console.log(f)); + for (const f of result.filesWritten) { + console.log(f); + } } };