@constructive-io/graphql-codegen 4.40.5 → 4.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -120,7 +120,10 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
120
120
  const pkField = pkFields[0];
121
121
  const pluralQueryName = table.query?.all ?? pluralName;
122
122
  const singleQueryName = table.query?.one;
123
- const singleResultFieldName = (0, utils_1.getSingleRowQueryName)(table);
123
+ // The unwrapped result key for findFirst/findOne — must be the friendly
124
+ // singular noun (e.g. "animal"), NOT the GraphQL by-id query name (e.g.
125
+ // "animalById"), so the surface aligns with the rest of the SDK.
126
+ const singleResultFieldName = singularName;
124
127
  const createMutationName = table.query?.create ?? `create${typeName}`;
125
128
  const updateMutationName = table.query?.update;
126
129
  const deleteMutationName = table.query?.delete;
@@ -133,6 +136,12 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
133
136
  const jt = allTables?.find((tb) => tb.name === r.junctionTable);
134
137
  return jt?.query?.delete != null;
135
138
  });
139
+ // Detect which bulk mutations are available for this table
140
+ const bulkInsertMutationName = table.query?.bulkInsert ?? null;
141
+ const bulkUpsertMutationName = table.query?.bulkUpsert ?? null;
142
+ const bulkUpdateMutationName = table.query?.bulkUpdate ?? null;
143
+ const bulkDeleteMutationName = table.query?.bulkDelete ?? null;
144
+ const hasBulk = !!(bulkInsertMutationName || bulkUpsertMutationName || bulkUpdateMutationName || bulkDeleteMutationName);
136
145
  const queryBuilderImports = [
137
146
  'QueryBuilder',
138
147
  'buildFindManyDocument',
@@ -142,6 +151,10 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
142
151
  'buildUpdateByPkDocument',
143
152
  'buildDeleteByPkDocument',
144
153
  ...(needsJunctionRemove ? ['buildJunctionRemoveDocument'] : []),
154
+ ...(bulkInsertMutationName ? ['buildBulkInsertDocument'] : []),
155
+ ...(bulkUpsertMutationName ? ['buildBulkUpsertDocument'] : []),
156
+ ...(bulkUpdateMutationName ? ['buildBulkUpdateDocument'] : []),
157
+ ...(bulkDeleteMutationName ? ['buildBulkDeleteDocument'] : []),
145
158
  ];
146
159
  statements.push(createImportDeclaration('../query-builder', queryBuilderImports));
147
160
  statements.push(createImportDeclaration('../select-types', [
@@ -151,6 +164,7 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
151
164
  'CreateArgs',
152
165
  'UpdateArgs',
153
166
  'DeleteArgs',
167
+ ...(hasBulk ? ['BulkInsertArgs', 'BulkUpsertArgs', 'BulkUpdateArgs', 'BulkDeleteArgs', 'BulkMutationResult'] : []),
154
168
  'InferSelectResult',
155
169
  'StrictSelect',
156
170
  ], true));
@@ -229,15 +243,17 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
229
243
  const findFirstTypeArgs = [
230
244
  (sel) => sel,
231
245
  () => t.tsTypeReference(t.identifier(whereTypeName)),
246
+ () => t.tsTypeReference(t.identifier(orderByTypeName)),
232
247
  ];
233
248
  const argsType = (sel) => t.tsTypeReference(t.identifier('FindFirstArgs'), t.tsTypeParameterInstantiation(findFirstTypeArgs.map(fn => fn(sel))));
234
249
  const retType = (sel) => t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
235
250
  t.tsTypeLiteral([
236
- t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation(t.tsTypeLiteral([
237
- t.tsPropertySignature(t.identifier('nodes'), t.tsTypeAnnotation(t.tsArrayType(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
251
+ t.tsPropertySignature(t.identifier(singleResultFieldName), t.tsTypeAnnotation(t.tsUnionType([
252
+ t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
238
253
  t.tsTypeReference(t.identifier(relationTypeName)),
239
254
  sel,
240
- ]))))),
255
+ ])),
256
+ t.tsNullKeyword(),
241
257
  ]))),
242
258
  ]),
243
259
  ])));
@@ -250,6 +266,10 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
250
266
  const selectExpr = t.memberExpression(t.identifier('args'), t.identifier('select'));
251
267
  const findFirstObjProps = [
252
268
  t.objectProperty(t.identifier('where'), t.optionalMemberExpression(t.identifier('args'), t.identifier('where'), false, true)),
269
+ t.objectProperty(t.identifier('orderBy'), t.tsAsExpression(t.optionalMemberExpression(t.identifier('args'), t.identifier('orderBy'), false, true), t.tsUnionType([
270
+ t.tsArrayType(t.tsStringKeyword()),
271
+ t.tsUndefinedKeyword(),
272
+ ]))),
253
273
  ];
254
274
  const bodyArgs = [
255
275
  t.stringLiteral(typeName),
@@ -257,9 +277,23 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
257
277
  selectExpr,
258
278
  t.objectExpression(findFirstObjProps),
259
279
  t.stringLiteral(whereTypeName),
280
+ t.stringLiteral(orderByTypeName),
260
281
  t.identifier('connectionFieldsMap'),
261
282
  ];
262
- classBody.push(createClassMethod('findFirst', createTypeParam(selectTypeName), [implParam], retType(sRef()), buildMethodBody('buildFindFirstDocument', bodyArgs, 'query', typeName, pluralQueryName)));
283
+ const transformDataParam = t.identifier('data');
284
+ const transformedNodesProp = t.tsPropertySignature(t.identifier('nodes'), t.tsTypeAnnotation(t.tsArrayType(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
285
+ t.tsTypeReference(t.identifier(relationTypeName)),
286
+ sRef(),
287
+ ])))));
288
+ transformedNodesProp.optional = true;
289
+ const transformedCollectionProp = t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation(t.tsTypeLiteral([transformedNodesProp])));
290
+ transformedCollectionProp.optional = true;
291
+ transformDataParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeLiteral([transformedCollectionProp]));
292
+ const firstNodeExpr = t.optionalMemberExpression(t.optionalMemberExpression(t.memberExpression(t.identifier('data'), t.identifier(pluralQueryName)), t.identifier('nodes'), false, true), t.numericLiteral(0), true, true);
293
+ const transformFn = t.arrowFunctionExpression([transformDataParam], t.objectExpression([
294
+ t.objectProperty(t.stringLiteral(singleResultFieldName), t.logicalExpression('??', firstNodeExpr, t.nullLiteral())),
295
+ ]));
296
+ classBody.push(createClassMethod('findFirst', createTypeParam(selectTypeName), [implParam], retType(sRef()), buildMethodBody('buildFindFirstDocument', bodyArgs, 'query', typeName, singleResultFieldName, [t.objectProperty(t.identifier('transform'), transformFn)])));
263
297
  }
264
298
  // ── findOne ────────────────────────────────────────────────────────────
265
299
  if ((0, utils_1.hasValidPrimaryKey)(table)) {
@@ -450,6 +484,134 @@ function generateModelFile(table, _useSharedTypes, options, allTables) {
450
484
  ];
451
485
  classBody.push(createClassMethod('delete', createTypeParam(selectTypeName), [implParam], retType(sRef()), buildMethodBody('buildDeleteByPkDocument', bodyArgs, 'mutation', typeName, deleteMutationName)));
452
486
  }
487
+ // ── bulkCreate ──────────────────────────────────────────────────────────
488
+ if (bulkInsertMutationName) {
489
+ const bulkInsertInputTypeName = `BulkCreate${typeName}Input`;
490
+ const dataType = () => t.tsIndexedAccessType(t.tsTypeReference(t.identifier(createInputTypeName)), t.tsLiteralType(t.stringLiteral(singularName)));
491
+ const argsType = (sel) => t.tsTypeReference(t.identifier('BulkInsertArgs'), t.tsTypeParameterInstantiation([sel, dataType()]));
492
+ const retType = (sel) => t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
493
+ t.tsTypeReference(t.identifier('BulkMutationResult'), t.tsTypeParameterInstantiation([
494
+ t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
495
+ t.tsTypeReference(t.identifier(relationTypeName)),
496
+ sel,
497
+ ])),
498
+ ])),
499
+ ])));
500
+ const implParam = t.identifier('args');
501
+ implParam.typeAnnotation = t.tsTypeAnnotation(t.tsIntersectionType([
502
+ argsType(sRef()),
503
+ t.tsTypeLiteral([requiredSelectProp()]),
504
+ strictSelectGuard(selectTypeName),
505
+ ]));
506
+ const selectExpr = t.memberExpression(t.identifier('args'), t.identifier('select'));
507
+ const bodyArgs = [
508
+ t.stringLiteral(typeName),
509
+ t.stringLiteral(bulkInsertMutationName),
510
+ selectExpr,
511
+ t.memberExpression(t.identifier('args'), t.identifier('data')),
512
+ t.stringLiteral(bulkInsertInputTypeName),
513
+ t.memberExpression(t.identifier('args'), t.identifier('onConflict')),
514
+ t.identifier('connectionFieldsMap'),
515
+ ];
516
+ classBody.push(createClassMethod('bulkCreate', createTypeParam(selectTypeName), [implParam], retType(sRef()), buildMethodBody('buildBulkInsertDocument', bodyArgs, 'mutation', typeName, bulkInsertMutationName)));
517
+ }
518
+ // ── bulkUpsert ─────────────────────────────────────────────────────────
519
+ if (bulkUpsertMutationName) {
520
+ const bulkUpsertInputTypeName = `BulkUpsert${typeName}Input`;
521
+ const dataType = () => t.tsIndexedAccessType(t.tsTypeReference(t.identifier(createInputTypeName)), t.tsLiteralType(t.stringLiteral(singularName)));
522
+ const argsType = (sel) => t.tsTypeReference(t.identifier('BulkUpsertArgs'), t.tsTypeParameterInstantiation([sel, dataType()]));
523
+ const retType = (sel) => t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
524
+ t.tsTypeReference(t.identifier('BulkMutationResult'), t.tsTypeParameterInstantiation([
525
+ t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
526
+ t.tsTypeReference(t.identifier(relationTypeName)),
527
+ sel,
528
+ ])),
529
+ ])),
530
+ ])));
531
+ const implParam = t.identifier('args');
532
+ implParam.typeAnnotation = t.tsTypeAnnotation(t.tsIntersectionType([
533
+ argsType(sRef()),
534
+ t.tsTypeLiteral([requiredSelectProp()]),
535
+ strictSelectGuard(selectTypeName),
536
+ ]));
537
+ const selectExpr = t.memberExpression(t.identifier('args'), t.identifier('select'));
538
+ const bodyArgs = [
539
+ t.stringLiteral(typeName),
540
+ t.stringLiteral(bulkUpsertMutationName),
541
+ selectExpr,
542
+ t.memberExpression(t.identifier('args'), t.identifier('data')),
543
+ t.stringLiteral(bulkUpsertInputTypeName),
544
+ t.memberExpression(t.identifier('args'), t.identifier('onConflict')),
545
+ t.identifier('connectionFieldsMap'),
546
+ ];
547
+ classBody.push(createClassMethod('bulkUpsert', createTypeParam(selectTypeName), [implParam], retType(sRef()), buildMethodBody('buildBulkUpsertDocument', bodyArgs, 'mutation', typeName, bulkUpsertMutationName)));
548
+ }
549
+ // ── bulkUpdate ─────────────────────────────────────────────────────────
550
+ if (bulkUpdateMutationName) {
551
+ const bulkUpdateInputTypeName = `BulkUpdate${typeName}Input`;
552
+ const argsType = (sel) => t.tsTypeReference(t.identifier('BulkUpdateArgs'), t.tsTypeParameterInstantiation([
553
+ sel,
554
+ t.tsTypeReference(t.identifier(whereTypeName)),
555
+ t.tsTypeReference(t.identifier(patchTypeName)),
556
+ ]));
557
+ const retType = (sel) => t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
558
+ t.tsTypeReference(t.identifier('BulkMutationResult'), t.tsTypeParameterInstantiation([
559
+ t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
560
+ t.tsTypeReference(t.identifier(relationTypeName)),
561
+ sel,
562
+ ])),
563
+ ])),
564
+ ])));
565
+ const implParam = t.identifier('args');
566
+ implParam.typeAnnotation = t.tsTypeAnnotation(t.tsIntersectionType([
567
+ argsType(sRef()),
568
+ t.tsTypeLiteral([requiredSelectProp()]),
569
+ strictSelectGuard(selectTypeName),
570
+ ]));
571
+ const selectExpr = t.memberExpression(t.identifier('args'), t.identifier('select'));
572
+ const bodyArgs = [
573
+ t.stringLiteral(typeName),
574
+ t.stringLiteral(bulkUpdateMutationName),
575
+ selectExpr,
576
+ t.memberExpression(t.identifier('args'), t.identifier('where')),
577
+ t.memberExpression(t.identifier('args'), t.identifier('data')),
578
+ t.stringLiteral(bulkUpdateInputTypeName),
579
+ t.identifier('connectionFieldsMap'),
580
+ ];
581
+ classBody.push(createClassMethod('bulkUpdate', createTypeParam(selectTypeName), [implParam], retType(sRef()), buildMethodBody('buildBulkUpdateDocument', bodyArgs, 'mutation', typeName, bulkUpdateMutationName)));
582
+ }
583
+ // ── bulkDelete ─────────────────────────────────────────────────────────
584
+ if (bulkDeleteMutationName) {
585
+ const bulkDeleteInputTypeName = `BulkDelete${typeName}Input`;
586
+ const argsType = (sel) => t.tsTypeReference(t.identifier('BulkDeleteArgs'), t.tsTypeParameterInstantiation([
587
+ sel,
588
+ t.tsTypeReference(t.identifier(whereTypeName)),
589
+ ]));
590
+ const retType = (sel) => t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
591
+ t.tsTypeReference(t.identifier('BulkMutationResult'), t.tsTypeParameterInstantiation([
592
+ t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
593
+ t.tsTypeReference(t.identifier(relationTypeName)),
594
+ sel,
595
+ ])),
596
+ ])),
597
+ ])));
598
+ const implParam = t.identifier('args');
599
+ implParam.typeAnnotation = t.tsTypeAnnotation(t.tsIntersectionType([
600
+ argsType(sRef()),
601
+ t.tsTypeLiteral([requiredSelectProp()]),
602
+ strictSelectGuard(selectTypeName),
603
+ ]));
604
+ const selectExpr = t.memberExpression(t.identifier('args'), t.identifier('select'));
605
+ const bodyArgs = [
606
+ t.stringLiteral(typeName),
607
+ t.stringLiteral(bulkDeleteMutationName),
608
+ selectExpr,
609
+ t.memberExpression(t.identifier('args'), t.identifier('where')),
610
+ t.stringLiteral(bulkDeleteInputTypeName),
611
+ t.identifier('connectionFieldsMap'),
612
+ ];
613
+ classBody.push(createClassMethod('bulkDelete', createTypeParam(selectTypeName), [implParam], retType(sRef()), buildMethodBody('buildBulkDeleteDocument', bodyArgs, 'mutation', typeName, bulkDeleteMutationName)));
614
+ }
453
615
  // ── M:N add/remove methods ────────────────────────────────────────────
454
616
  for (const rel of m2nRels) {
455
617
  if (!rel.fieldName)
@@ -167,9 +167,10 @@ export interface FindManyArgs<TSelect, TWhere, TOrderBy> {
167
167
  /**
168
168
  * Arguments for findFirst/findUnique operations
169
169
  */
170
- export interface FindFirstArgs<TSelect, TWhere> {
170
+ export interface FindFirstArgs<TSelect, TWhere, TOrderBy> {
171
171
  select?: TSelect;
172
172
  where?: TWhere;
173
+ orderBy?: TOrderBy[];
173
174
  }
174
175
  /**
175
176
  * Arguments for create operations
@@ -471,7 +471,7 @@ function generateSingleQueryHook(table, options = {}) {
471
471
  t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)),
472
472
  t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation((0, hooks_ast_1.selectionConfigType)((0, hooks_ast_1.typeRef)(selectTypeName)))),
473
473
  ];
474
- statements.push((0, hooks_ast_1.exportAsyncFunction)(fetchFnName, null, [(0, hooks_ast_1.createFunctionParam)('params', t.tsTypeLiteral(fImplProps))], fBody));
474
+ statements.push((0, hooks_ast_1.exportAsyncFunction)(fetchFnName, null, [(0, hooks_ast_1.createFunctionParam)('params', t.tsTypeLiteral(fImplProps))], fBody, (0, hooks_ast_1.typeRef)('Promise', [t.tsAnyKeyword()])));
475
475
  }
476
476
  // Prefetch function
477
477
  if (reactQueryEnabled) {
@@ -283,8 +283,8 @@ export function parseFindManyArgs<T = Record<string, unknown>>(
283
283
 
284
284
  /**
285
285
  * Build findFirst args from CLI argv.
286
- * Like parseFindManyArgs but only includes select and where
287
- * (no pagination flags — findFirst returns the first matching record).
286
+ * Like parseFindManyArgs but without pagination flags (no limit/offset/after/before/last)
287
+ * — findFirst returns the first matching record. Supports select, where, and orderBy.
288
288
  */
289
289
  export function parseFindFirstArgs<T = Record<string, unknown>>(
290
290
  argv: Record<string, unknown>,
@@ -293,10 +293,12 @@ export function parseFindFirstArgs<T = Record<string, unknown>>(
293
293
  const select = parseSelectFlag(argv, defaultSelect);
294
294
  const parsed = unflattenDotNotation(argv);
295
295
  const where = parsed.where;
296
+ const orderBy = parseOrderByFlag(argv);
296
297
 
297
298
  return {
298
299
  select,
299
300
  ...(where !== undefined ? { where } : {}),
301
+ ...(orderBy !== undefined ? { orderBy } : {}),
300
302
  } as unknown as T;
301
303
  }
302
304
 
@@ -343,8 +343,9 @@ export function buildFindFirstDocument<TSelect, TWhere>(
343
343
  operationName: string,
344
344
  queryField: string,
345
345
  select: TSelect,
346
- args: { where?: TWhere },
346
+ args: { where?: TWhere; orderBy?: string[] },
347
347
  filterTypeName: string,
348
+ orderByTypeName: string,
348
349
  connectionFieldsMap?: Record<string, Record<string, string>>,
349
350
  ): { document: string; variables: Record<string, unknown> } {
350
351
  const selections = select
@@ -376,6 +377,16 @@ export function buildFindFirstDocument<TSelect, TWhere>(
376
377
  queryArgs,
377
378
  variables,
378
379
  );
380
+ addVariable(
381
+ {
382
+ varName: 'orderBy',
383
+ typeName: '[' + orderByTypeName + '!]',
384
+ value: args.orderBy?.length ? args.orderBy : undefined,
385
+ },
386
+ variableDefinitions,
387
+ queryArgs,
388
+ variables,
389
+ );
379
390
 
380
391
  const document = t.document({
381
392
  definitions: [
@@ -962,3 +973,161 @@ function buildValueAst(
962
973
 
963
974
  throw new Error('Unsupported value type: ' + typeof value);
964
975
  }
976
+
977
+ // ============================================================================
978
+ // Bulk Mutation Document Builders
979
+ // ============================================================================
980
+
981
+ export function buildBulkInsertDocument<TSelect, TData>(
982
+ operationName: string,
983
+ mutationField: string,
984
+ select: TSelect,
985
+ data: TData[],
986
+ inputTypeName: string,
987
+ onConflict?: unknown,
988
+ connectionFieldsMap?: Record<string, Record<string, string>>,
989
+ ): { document: string; variables: Record<string, unknown> } {
990
+ const selections = select
991
+ ? buildSelections(
992
+ select as Record<string, unknown>,
993
+ connectionFieldsMap,
994
+ operationName,
995
+ )
996
+ : [t.field({ name: 'id' })];
997
+
998
+ return {
999
+ document: buildInputMutationDocument({
1000
+ operationName,
1001
+ mutationField,
1002
+ inputTypeName,
1003
+ resultSelections: [
1004
+ t.field({ name: 'affectedCount' }),
1005
+ t.field({
1006
+ name: 'returning',
1007
+ selectionSet: t.selectionSet({ selections }),
1008
+ }),
1009
+ ],
1010
+ }),
1011
+ variables: {
1012
+ input: {
1013
+ values: data,
1014
+ ...(onConflict ? { onConflict } : {}),
1015
+ },
1016
+ },
1017
+ };
1018
+ }
1019
+
1020
+ export function buildBulkUpsertDocument<TSelect, TData>(
1021
+ operationName: string,
1022
+ mutationField: string,
1023
+ select: TSelect,
1024
+ data: TData[],
1025
+ inputTypeName: string,
1026
+ onConflict: unknown,
1027
+ connectionFieldsMap?: Record<string, Record<string, string>>,
1028
+ ): { document: string; variables: Record<string, unknown> } {
1029
+ const selections = select
1030
+ ? buildSelections(
1031
+ select as Record<string, unknown>,
1032
+ connectionFieldsMap,
1033
+ operationName,
1034
+ )
1035
+ : [t.field({ name: 'id' })];
1036
+
1037
+ return {
1038
+ document: buildInputMutationDocument({
1039
+ operationName,
1040
+ mutationField,
1041
+ inputTypeName,
1042
+ resultSelections: [
1043
+ t.field({ name: 'affectedCount' }),
1044
+ t.field({
1045
+ name: 'returning',
1046
+ selectionSet: t.selectionSet({ selections }),
1047
+ }),
1048
+ ],
1049
+ }),
1050
+ variables: {
1051
+ input: {
1052
+ values: data,
1053
+ onConflict,
1054
+ },
1055
+ },
1056
+ };
1057
+ }
1058
+
1059
+ export function buildBulkUpdateDocument<TSelect, TWhere, TData>(
1060
+ operationName: string,
1061
+ mutationField: string,
1062
+ select: TSelect,
1063
+ where: TWhere,
1064
+ data: TData,
1065
+ inputTypeName: string,
1066
+ connectionFieldsMap?: Record<string, Record<string, string>>,
1067
+ ): { document: string; variables: Record<string, unknown> } {
1068
+ const selections = select
1069
+ ? buildSelections(
1070
+ select as Record<string, unknown>,
1071
+ connectionFieldsMap,
1072
+ operationName,
1073
+ )
1074
+ : [t.field({ name: 'id' })];
1075
+
1076
+ return {
1077
+ document: buildInputMutationDocument({
1078
+ operationName,
1079
+ mutationField,
1080
+ inputTypeName,
1081
+ resultSelections: [
1082
+ t.field({ name: 'affectedCount' }),
1083
+ t.field({
1084
+ name: 'returning',
1085
+ selectionSet: t.selectionSet({ selections }),
1086
+ }),
1087
+ ],
1088
+ }),
1089
+ variables: {
1090
+ input: {
1091
+ where,
1092
+ patch: data,
1093
+ },
1094
+ },
1095
+ };
1096
+ }
1097
+
1098
+ export function buildBulkDeleteDocument<TSelect, TWhere>(
1099
+ operationName: string,
1100
+ mutationField: string,
1101
+ select: TSelect,
1102
+ where: TWhere,
1103
+ inputTypeName: string,
1104
+ connectionFieldsMap?: Record<string, Record<string, string>>,
1105
+ ): { document: string; variables: Record<string, unknown> } {
1106
+ const selections = select
1107
+ ? buildSelections(
1108
+ select as Record<string, unknown>,
1109
+ connectionFieldsMap,
1110
+ operationName,
1111
+ )
1112
+ : [t.field({ name: 'id' })];
1113
+
1114
+ return {
1115
+ document: buildInputMutationDocument({
1116
+ operationName,
1117
+ mutationField,
1118
+ inputTypeName,
1119
+ resultSelections: [
1120
+ t.field({ name: 'affectedCount' }),
1121
+ t.field({
1122
+ name: 'returning',
1123
+ selectionSet: t.selectionSet({ selections }),
1124
+ }),
1125
+ ],
1126
+ }),
1127
+ variables: {
1128
+ input: {
1129
+ where,
1130
+ },
1131
+ },
1132
+ };
1133
+ }
@@ -32,9 +32,10 @@ export interface FindManyArgs<TSelect, TWhere, TOrderBy = never> {
32
32
  offset?: number;
33
33
  }
34
34
 
35
- export interface FindFirstArgs<TSelect, TWhere> {
35
+ export interface FindFirstArgs<TSelect, TWhere, TOrderBy> {
36
36
  select?: TSelect;
37
37
  where?: TWhere;
38
+ orderBy?: TOrderBy[];
38
39
  }
39
40
 
40
41
  export interface CreateArgs<TSelect, TData> {
@@ -61,6 +62,34 @@ export interface DeleteArgs<TWhere, TSelect = undefined> {
61
62
  select?: TSelect;
62
63
  }
63
64
 
65
+ export interface BulkInsertArgs<TSelect, TData, TOnConflict = unknown> {
66
+ data: TData[];
67
+ select?: TSelect;
68
+ onConflict?: TOnConflict;
69
+ }
70
+
71
+ export interface BulkUpsertArgs<TSelect, TData, TOnConflict = unknown> {
72
+ data: TData[];
73
+ select?: TSelect;
74
+ onConflict: TOnConflict;
75
+ }
76
+
77
+ export interface BulkUpdateArgs<TSelect, TWhere, TData> {
78
+ where: TWhere;
79
+ data: TData;
80
+ select?: TSelect;
81
+ }
82
+
83
+ export interface BulkDeleteArgs<TSelect, TWhere> {
84
+ where: TWhere;
85
+ select?: TSelect;
86
+ }
87
+
88
+ export interface BulkMutationResult<T> {
89
+ affectedCount: number;
90
+ returning: T[];
91
+ }
92
+
64
93
  type DepthLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
65
94
  type DecrementDepth = {
66
95
  0: 0;
@@ -101,6 +101,14 @@ export declare function getUpdateMutationName(table: Table): string;
101
101
  * Get the GraphQL mutation name for deleting
102
102
  */
103
103
  export declare function getDeleteMutationName(table: Table): string;
104
+ export declare function getBulkCreateMutationHookName(table: Table): string;
105
+ export declare function getBulkUpsertMutationHookName(table: Table): string;
106
+ export declare function getBulkUpdateMutationHookName(table: Table): string;
107
+ export declare function getBulkDeleteMutationHookName(table: Table): string;
108
+ export declare function getBulkCreateMutationFileName(table: Table): string;
109
+ export declare function getBulkUpsertMutationFileName(table: Table): string;
110
+ export declare function getBulkUpdateMutationFileName(table: Table): string;
111
+ export declare function getBulkDeleteMutationFileName(table: Table): string;
104
112
  /**
105
113
  * Get PostGraphile filter type name
106
114
  * e.g., "CarFilter"
@@ -20,6 +20,14 @@ exports.getSingleRowQueryName = getSingleRowQueryName;
20
20
  exports.getCreateMutationName = getCreateMutationName;
21
21
  exports.getUpdateMutationName = getUpdateMutationName;
22
22
  exports.getDeleteMutationName = getDeleteMutationName;
23
+ exports.getBulkCreateMutationHookName = getBulkCreateMutationHookName;
24
+ exports.getBulkUpsertMutationHookName = getBulkUpsertMutationHookName;
25
+ exports.getBulkUpdateMutationHookName = getBulkUpdateMutationHookName;
26
+ exports.getBulkDeleteMutationHookName = getBulkDeleteMutationHookName;
27
+ exports.getBulkCreateMutationFileName = getBulkCreateMutationFileName;
28
+ exports.getBulkUpsertMutationFileName = getBulkUpsertMutationFileName;
29
+ exports.getBulkUpdateMutationFileName = getBulkUpdateMutationFileName;
30
+ exports.getBulkDeleteMutationFileName = getBulkDeleteMutationFileName;
23
31
  exports.getFilterTypeName = getFilterTypeName;
24
32
  exports.getOrderByTypeName = getOrderByTypeName;
25
33
  exports.getConditionTypeName = getConditionTypeName;
@@ -201,6 +209,37 @@ function getDeleteMutationName(table) {
201
209
  return table.query?.delete || `delete${table.name}`;
202
210
  }
203
211
  // ============================================================================
212
+ // Bulk mutation naming helpers
213
+ // ============================================================================
214
+ function getBulkCreateMutationHookName(table) {
215
+ const { typeName } = getTableNames(table);
216
+ return `useBulkCreate${typeName}Mutation`;
217
+ }
218
+ function getBulkUpsertMutationHookName(table) {
219
+ const { typeName } = getTableNames(table);
220
+ return `useBulkUpsert${typeName}Mutation`;
221
+ }
222
+ function getBulkUpdateMutationHookName(table) {
223
+ const { typeName } = getTableNames(table);
224
+ return `useBulkUpdate${typeName}Mutation`;
225
+ }
226
+ function getBulkDeleteMutationHookName(table) {
227
+ const { typeName } = getTableNames(table);
228
+ return `useBulkDelete${typeName}Mutation`;
229
+ }
230
+ function getBulkCreateMutationFileName(table) {
231
+ return `${getBulkCreateMutationHookName(table)}.ts`;
232
+ }
233
+ function getBulkUpsertMutationFileName(table) {
234
+ return `${getBulkUpsertMutationHookName(table)}.ts`;
235
+ }
236
+ function getBulkUpdateMutationFileName(table) {
237
+ return `${getBulkUpdateMutationHookName(table)}.ts`;
238
+ }
239
+ function getBulkDeleteMutationFileName(table) {
240
+ return `${getBulkDeleteMutationHookName(table)}.ts`;
241
+ }
242
+ // ============================================================================
204
243
  // Type names
205
244
  // ============================================================================
206
245
  /**