Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ export default async (argv: Partial<Record<string, unknown>>, prompter: Inquirer
}
const client = getClient();
const selectFields = buildSelectFromPaths(argv.select ?? "");
const result = await client.query.currentUser({}, {
const result = await client.query.currentUser({
select: selectFields
}).execute();
console.log(JSON.stringify(result, null, 2));
Expand Down
19 changes: 16 additions & 3 deletions graphql/codegen/src/core/codegen/cli/custom-command-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,21 @@ function buildOrmCustomCall(
opName: string,
argsExpr: t.Expression,
selectExpr?: t.Expression,
hasArgs: boolean = true,
): t.Expression {
const callArgs: t.Expression[] = [argsExpr];
if (selectExpr) {
const callArgs: t.Expression[] = [];
if (hasArgs) {
// Operation has arguments: pass args as first param, select as second
callArgs.push(argsExpr);
if (selectExpr) {
callArgs.push(
t.objectExpression([
t.objectProperty(t.identifier('select'), selectExpr),
]),
);
}
} else if (selectExpr) {
// No arguments: pass { select } as the only param (ORM signature)
callArgs.push(
t.objectExpression([
t.objectProperty(t.identifier('select'), selectExpr),
Expand Down Expand Up @@ -343,12 +355,13 @@ export function generateCustomCommand(op: CleanOperation, options?: CustomComman
selectExpr = t.identifier('selectFields');
}

const hasArgs = op.args.length > 0;
bodyStatements.push(
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('result'),
t.awaitExpression(
buildOrmCustomCall(opKind, op.name, argsExpr, selectExpr),
buildOrmCustomCall(opKind, op.name, argsExpr, selectExpr, hasArgs),
),
),
]),
Expand Down
96 changes: 77 additions & 19 deletions graphql/codegen/src/core/codegen/cli/executor-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,21 @@ function createImportDeclaration(
return decl;
}

export function generateExecutorFile(toolName: string): GeneratedFile {
export interface ExecutorOptions {
/** Enable NodeHttpAdapter for *.localhost subdomain routing */
nodeHttpAdapter?: boolean;
}

export function generateExecutorFile(toolName: string, options?: ExecutorOptions): GeneratedFile {
const statements: t.Statement[] = [];

// Import NodeHttpAdapter for *.localhost subdomain routing
if (options?.nodeHttpAdapter) {
statements.push(
createImportDeclaration('./node-fetch', ['NodeHttpAdapter']),
);
}

statements.push(
createImportDeclaration('appstash', ['createConfigStore']),
);
Expand Down Expand Up @@ -191,20 +203,39 @@ export function generateExecutorFile(toolName: string): GeneratedFile {
]),
),

t.returnStatement(
t.callExpression(t.identifier('createClient'), [
t.objectExpression([
t.objectProperty(
t.identifier('endpoint'),
t.memberExpression(t.identifier('ctx'), t.identifier('endpoint')),
// Build createClient config — use NodeHttpAdapter for *.localhost endpoints
...(options?.nodeHttpAdapter
? [
t.returnStatement(
t.callExpression(t.identifier('createClient'), [
t.objectExpression([
t.objectProperty(
t.identifier('adapter'),
t.newExpression(t.identifier('NodeHttpAdapter'), [
t.memberExpression(t.identifier('ctx'), t.identifier('endpoint')),
t.identifier('headers'),
]),
),
]),
]),
),
t.objectProperty(
t.identifier('headers'),
t.identifier('headers'),
]
: [
t.returnStatement(
t.callExpression(t.identifier('createClient'), [
t.objectExpression([
t.objectProperty(
t.identifier('endpoint'),
t.memberExpression(t.identifier('ctx'), t.identifier('endpoint')),
),
t.objectProperty(
t.identifier('headers'),
t.identifier('headers'),
),
]),
]),
),
]),
]),
),
]);

const getClientFunc = t.functionDeclaration(
Expand All @@ -226,9 +257,17 @@ export function generateExecutorFile(toolName: string): GeneratedFile {
export function generateMultiTargetExecutorFile(
toolName: string,
targets: MultiTargetExecutorInput[],
options?: ExecutorOptions,
): GeneratedFile {
const statements: t.Statement[] = [];

// Import NodeHttpAdapter for *.localhost subdomain routing
if (options?.nodeHttpAdapter) {
statements.push(
createImportDeclaration('./node-fetch', ['NodeHttpAdapter']),
);
}

statements.push(
createImportDeclaration('appstash', ['createConfigStore']),
);
Expand Down Expand Up @@ -475,14 +514,33 @@ export function generateMultiTargetExecutorFile(
),
]),
),
t.returnStatement(
t.callExpression(t.identifier('createFn'), [
t.objectExpression([
t.objectProperty(t.identifier('endpoint'), t.identifier('endpoint')),
t.objectProperty(t.identifier('headers'), t.identifier('headers')),
// Build createClient config — use NodeHttpAdapter for *.localhost endpoints
...(options?.nodeHttpAdapter
? [
t.returnStatement(
t.callExpression(t.identifier('createFn'), [
t.objectExpression([
t.objectProperty(
t.identifier('adapter'),
t.newExpression(t.identifier('NodeHttpAdapter'), [
t.identifier('endpoint'),
t.identifier('headers'),
]),
),
]),
]),
),
]
: [
t.returnStatement(
t.callExpression(t.identifier('createFn'), [
t.objectExpression([
t.objectProperty(t.identifier('endpoint'), t.identifier('endpoint')),
t.objectProperty(t.identifier('headers'), t.identifier('headers')),
]),
]),
),
]),
]),
),
]);

const getClientFunc = t.functionDeclaration(
Expand Down
36 changes: 31 additions & 5 deletions graphql/codegen/src/core/codegen/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BuiltinNames, GraphQLSDKConfigTarget } from '../../../types/config';
import type { CleanOperation, CleanTable } from '../../../types/schema';
import type { CleanOperation, CleanTable, TypeRegistry } from '../../../types/schema';
import { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator';
import { generateCustomCommand } from './custom-command-generator';
import { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator';
Expand All @@ -11,7 +11,7 @@ import {
generateMultiTargetContextCommand,
} from './infra-generator';
import { generateTableCommand } from './table-command-generator';
import { generateUtilsFile } from './utils-generator';
import { generateUtilsFile, generateNodeFetchFile } from './utils-generator';

export interface GenerateCliOptions {
tables: CleanTable[];
Expand All @@ -20,6 +20,8 @@ export interface GenerateCliOptions {
mutations: CleanOperation[];
};
config: GraphQLSDKConfigTarget;
/** TypeRegistry from introspection, used to check field defaults */
typeRegistry?: TypeRegistry;
}

export interface GenerateCliResult {
Expand All @@ -43,20 +45,32 @@ export function generateCli(options: GenerateCliOptions): GenerateCliResult {
? cliConfig.toolName
: 'app';

const executorFile = generateExecutorFile(toolName);
// Use top-level nodeHttpAdapter from config (auto-enabled for CLI by generate.ts)
const useNodeHttpAdapter = !!config.nodeHttpAdapter;

const executorFile = generateExecutorFile(toolName, {
nodeHttpAdapter: useNodeHttpAdapter,
});
files.push(executorFile);

const utilsFile = generateUtilsFile();
files.push(utilsFile);

// Generate node HTTP adapter if configured (for *.localhost subdomain routing)
if (useNodeHttpAdapter) {
files.push(generateNodeFetchFile());
}

const contextFile = generateContextCommand(toolName);
files.push(contextFile);

const authFile = generateAuthCommand(toolName);
files.push(authFile);

for (const table of tables) {
const tableFile = generateTableCommand(table);
const tableFile = generateTableCommand(table, {
typeRegistry: options.typeRegistry,
});
files.push(tableFile);
}

Expand Down Expand Up @@ -99,12 +113,16 @@ export interface MultiTargetCliTarget {
mutations: CleanOperation[];
};
isAuthTarget?: boolean;
/** TypeRegistry from introspection, used to check field defaults */
typeRegistry?: TypeRegistry;
}

export interface GenerateMultiTargetCliOptions {
toolName: string;
builtinNames?: BuiltinNames;
targets: MultiTargetCliTarget[];
/** Enable NodeHttpAdapter for *.localhost subdomain routing */
nodeHttpAdapter?: boolean;
}

export function resolveBuiltinNames(
Expand Down Expand Up @@ -138,12 +156,19 @@ export function generateMultiTargetCli(
endpoint: t.endpoint,
ormImportPath: t.ormImportPath,
}));
const executorFile = generateMultiTargetExecutorFile(toolName, executorInputs);
const executorFile = generateMultiTargetExecutorFile(toolName, executorInputs, {
nodeHttpAdapter: !!options.nodeHttpAdapter,
});
files.push(executorFile);

const utilsFile = generateUtilsFile();
files.push(utilsFile);

// Generate node HTTP adapter if configured (for *.localhost subdomain routing)
if (options.nodeHttpAdapter) {
files.push(generateNodeFetchFile());
}

const contextFile = generateMultiTargetContextCommand(
toolName,
builtinNames.context,
Expand Down Expand Up @@ -174,6 +199,7 @@ export function generateMultiTargetCli(
const tableFile = generateTableCommand(table, {
targetName: target.name,
executorImportPath: '../../executor',
typeRegistry: target.typeRegistry,
});
files.push(tableFile);
}
Expand Down
Loading