@@ -3,7 +3,7 @@ import { toKebabCase } from 'komoji';
33
44import { generateCode } from '../babel-ast' ;
55import { getGeneratedFileHeader } from '../utils' ;
6- import type { CleanOperation } from '../../../types/schema' ;
6+ import type { CleanOperation , CleanTypeRef } from '../../../types/schema' ;
77import type { GeneratedFile } from './executor-generator' ;
88import { buildQuestionsArray } from './arg-mapper' ;
99
@@ -100,10 +100,50 @@ function buildErrorCatch(errorMessage: string): t.CatchClause {
100100 ) ;
101101}
102102
103+ /**
104+ * Unwrap NON_NULL / LIST wrappers to get the underlying named type.
105+ */
106+ function unwrapType ( ref : CleanTypeRef ) : CleanTypeRef {
107+ if ( ( ref . kind === 'NON_NULL' || ref . kind === 'LIST' ) && ref . ofType ) {
108+ return unwrapType ( ref . ofType ) ;
109+ }
110+ return ref ;
111+ }
112+
113+ /**
114+ * Build a select object expression from return-type fields.
115+ * If the return type has known fields, generates { field1: true, field2: true, ... }.
116+ * Falls back to { clientMutationId: true } for mutations without known fields.
117+ */
118+ function buildSelectObject (
119+ returnType : CleanTypeRef ,
120+ isMutation : boolean ,
121+ ) : t . ObjectExpression {
122+ const base = unwrapType ( returnType ) ;
123+ if ( base . fields && base . fields . length > 0 ) {
124+ return t . objectExpression (
125+ base . fields . map ( ( f ) =>
126+ t . objectProperty ( t . identifier ( f . name ) , t . booleanLiteral ( true ) ) ,
127+ ) ,
128+ ) ;
129+ }
130+ // Fallback: all PostGraphile mutation payloads have clientMutationId
131+ if ( isMutation ) {
132+ return t . objectExpression ( [
133+ t . objectProperty (
134+ t . identifier ( 'clientMutationId' ) ,
135+ t . booleanLiteral ( true ) ,
136+ ) ,
137+ ] ) ;
138+ }
139+ return t . objectExpression ( [ ] ) ;
140+ }
141+
103142function buildOrmCustomCall (
104143 opKind : 'query' | 'mutation' ,
105144 opName : string ,
106145 argsExpr : t . Expression ,
146+ selectExpr : t . ObjectExpression ,
107147) : t . Expression {
108148 return t . callExpression (
109149 t . memberExpression (
@@ -115,7 +155,12 @@ function buildOrmCustomCall(
115155 ) ,
116156 t . identifier ( opName ) ,
117157 ) ,
118- [ argsExpr ] ,
158+ [
159+ argsExpr ,
160+ t . objectExpression ( [
161+ t . objectProperty ( t . identifier ( 'select' ) , selectExpr ) ,
162+ ] ) ,
163+ ] ,
119164 ) ,
120165 t . identifier ( 'execute' ) ,
121166 ) ,
@@ -139,13 +184,29 @@ export function generateCustomCommand(op: CleanOperation, options?: CustomComman
139184 imports . push ( 'getStore' ) ;
140185 }
141186
187+ // Check if any argument is an INPUT_OBJECT (i.e. takes JSON input like { input: SomeInput })
188+ const hasInputObjectArg = op . args . some ( ( arg ) => {
189+ const base = unwrapType ( arg . type ) ;
190+ return base . kind === 'INPUT_OBJECT' ;
191+ } ) ;
192+
193+ const utilsPath = options ?. executorImportPath
194+ ? options . executorImportPath . replace ( / \/ e x e c u t o r $ / , '/utils' )
195+ : '../utils' ;
196+
142197 statements . push (
143198 createImportDeclaration ( 'inquirerer' , [ 'CLIOptions' , 'Inquirerer' ] ) ,
144199 ) ;
145200 statements . push (
146201 createImportDeclaration ( executorPath , imports ) ,
147202 ) ;
148203
204+ if ( hasInputObjectArg ) {
205+ statements . push (
206+ createImportDeclaration ( utilsPath , [ 'parseMutationInput' ] ) ,
207+ ) ;
208+ }
209+
149210 const questionsArray =
150211 op . args . length > 0
151212 ? buildQuestionsArray ( op . args )
@@ -224,17 +285,36 @@ export function generateCustomCommand(op: CleanOperation, options?: CustomComman
224285 ] ) ,
225286 ) ;
226287
288+ // For mutations with INPUT_OBJECT args (like `input: SignUpInput`),
289+ // parse JSON strings from CLI into proper objects
290+ if ( hasInputObjectArg && op . args . length > 0 ) {
291+ bodyStatements . push (
292+ t . variableDeclaration ( 'const' , [
293+ t . variableDeclarator (
294+ t . identifier ( 'parsedAnswers' ) ,
295+ t . callExpression ( t . identifier ( 'parseMutationInput' ) , [
296+ t . identifier ( 'answers' ) ,
297+ ] ) ,
298+ ) ,
299+ ] ) ,
300+ ) ;
301+ }
302+
227303 const argsExpr =
228304 op . args . length > 0
229- ? t . identifier ( 'answers' )
305+ ? ( hasInputObjectArg
306+ ? t . identifier ( 'parsedAnswers' )
307+ : t . identifier ( 'answers' ) )
230308 : t . objectExpression ( [ ] ) ;
231309
310+ const selectExpr = buildSelectObject ( op . returnType , op . kind === 'mutation' ) ;
311+
232312 bodyStatements . push (
233313 t . variableDeclaration ( 'const' , [
234314 t . variableDeclarator (
235315 t . identifier ( 'result' ) ,
236316 t . awaitExpression (
237- buildOrmCustomCall ( opKind , op . name , argsExpr ) ,
317+ buildOrmCustomCall ( opKind , op . name , argsExpr , selectExpr ) ,
238318 ) ,
239319 ) ,
240320 ] ) ,
0 commit comments