@@ -111,40 +111,47 @@ function unwrapType(ref: CleanTypeRef): CleanTypeRef {
111111}
112112
113113/**
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.
114+ * Check if the return type (after unwrapping) is an OBJECT type.
117115 */
118- function buildSelectObject (
116+ function hasObjectReturnType ( returnType : CleanTypeRef ) : boolean {
117+ const base = unwrapType ( returnType ) ;
118+ return base . kind === 'OBJECT' ;
119+ }
120+
121+ /**
122+ * Build a default select string from the return type's top-level scalar fields.
123+ * For OBJECT return types with known fields, generates a comma-separated list
124+ * of all top-level field names (e.g. 'clientMutationId,result').
125+ * Falls back to 'clientMutationId' for mutations without known fields.
126+ */
127+ function buildDefaultSelectString (
119128 returnType : CleanTypeRef ,
120129 isMutation : boolean ,
121- ) : t . ObjectExpression {
130+ ) : string {
122131 const base = unwrapType ( returnType ) ;
123132 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- ) ;
133+ return base . fields . map ( ( f ) => f . name ) . join ( ',' ) ;
129134 }
130- // Fallback: all PostGraphile mutation payloads have clientMutationId
131135 if ( isMutation ) {
132- return t . objectExpression ( [
133- t . objectProperty (
134- t . identifier ( 'clientMutationId' ) ,
135- t . booleanLiteral ( true ) ,
136- ) ,
137- ] ) ;
136+ return 'clientMutationId' ;
138137 }
139- return t . objectExpression ( [ ] ) ;
138+ return '' ;
140139}
141140
142141function buildOrmCustomCall (
143142 opKind : 'query' | 'mutation' ,
144143 opName : string ,
145144 argsExpr : t . Expression ,
146- selectExpr : t . ObjectExpression ,
145+ selectExpr ? : t . Expression ,
147146) : t . Expression {
147+ const callArgs : t . Expression [ ] = [ argsExpr ] ;
148+ if ( selectExpr ) {
149+ callArgs . push (
150+ t . objectExpression ( [
151+ t . objectProperty ( t . identifier ( 'select' ) , selectExpr ) ,
152+ ] ) ,
153+ ) ;
154+ }
148155 return t . callExpression (
149156 t . memberExpression (
150157 t . callExpression (
@@ -155,12 +162,7 @@ function buildOrmCustomCall(
155162 ) ,
156163 t . identifier ( opName ) ,
157164 ) ,
158- [
159- argsExpr ,
160- t . objectExpression ( [
161- t . objectProperty ( t . identifier ( 'select' ) , selectExpr ) ,
162- ] ) ,
163- ] ,
165+ callArgs ,
164166 ) ,
165167 t . identifier ( 'execute' ) ,
166168 ) ,
@@ -190,6 +192,9 @@ export function generateCustomCommand(op: CleanOperation, options?: CustomComman
190192 return base . kind === 'INPUT_OBJECT' ;
191193 } ) ;
192194
195+ // Check if return type is OBJECT (needs --select flag)
196+ const isObjectReturn = hasObjectReturnType ( op . returnType ) ;
197+
193198 const utilsPath = options ?. executorImportPath
194199 ? options . executorImportPath . replace ( / \/ e x e c u t o r $ / , '/utils' )
195200 : '../utils' ;
@@ -201,9 +206,17 @@ export function generateCustomCommand(op: CleanOperation, options?: CustomComman
201206 createImportDeclaration ( executorPath , imports ) ,
202207 ) ;
203208
209+ // Build the list of utils imports needed
210+ const utilsImports : string [ ] = [ ] ;
204211 if ( hasInputObjectArg ) {
212+ utilsImports . push ( 'parseMutationInput' ) ;
213+ }
214+ if ( isObjectReturn ) {
215+ utilsImports . push ( 'buildSelectFromPaths' ) ;
216+ }
217+ if ( utilsImports . length > 0 ) {
205218 statements . push (
206- createImportDeclaration ( utilsPath , [ 'parseMutationInput' ] ) ,
219+ createImportDeclaration ( utilsPath , utilsImports ) ,
207220 ) ;
208221 }
209222
@@ -307,7 +320,28 @@ export function generateCustomCommand(op: CleanOperation, options?: CustomComman
307320 : t . identifier ( 'answers' ) )
308321 : t . objectExpression ( [ ] ) ;
309322
310- const selectExpr = buildSelectObject ( op . returnType , op . kind === 'mutation' ) ;
323+ // For OBJECT return types, generate runtime select from --select flag
324+ // For scalar return types, no select is needed
325+ let selectExpr : t . Expression | undefined ;
326+ if ( isObjectReturn ) {
327+ const defaultSelect = buildDefaultSelectString ( op . returnType , op . kind === 'mutation' ) ;
328+ // Generate: const selectFields = buildSelectFromPaths(argv.select ?? 'defaultFields')
329+ bodyStatements . push (
330+ t . variableDeclaration ( 'const' , [
331+ t . variableDeclarator (
332+ t . identifier ( 'selectFields' ) ,
333+ t . callExpression ( t . identifier ( 'buildSelectFromPaths' ) , [
334+ t . logicalExpression (
335+ '??' ,
336+ t . memberExpression ( t . identifier ( 'argv' ) , t . identifier ( 'select' ) ) ,
337+ t . stringLiteral ( defaultSelect ) ,
338+ ) ,
339+ ] ) ,
340+ ) ,
341+ ] ) ,
342+ ) ;
343+ selectExpr = t . identifier ( 'selectFields' ) ;
344+ }
311345
312346 bodyStatements . push (
313347 t . variableDeclaration ( 'const' , [
0 commit comments