@pothos/plugin-prisma 4.4.0 → 4.5.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dts/connection-helpers.d.ts.map +1 -1
  3. package/dts/global-types.d.ts +5 -3
  4. package/dts/global-types.d.ts.map +1 -1
  5. package/dts/index.d.ts.map +1 -1
  6. package/dts/model-loader.d.ts.map +1 -1
  7. package/dts/prisma-field-builder.d.ts +1 -1
  8. package/dts/prisma-field-builder.d.ts.map +1 -1
  9. package/dts/util/map-query.d.ts +3 -2
  10. package/dts/util/map-query.d.ts.map +1 -1
  11. package/dts/util/selections.d.ts +2 -1
  12. package/dts/util/selections.d.ts.map +1 -1
  13. package/esm/connection-helpers.d.ts.map +1 -1
  14. package/esm/connection-helpers.js +2 -1
  15. package/esm/connection-helpers.js.map +1 -1
  16. package/esm/field-builder.js +9 -6
  17. package/esm/field-builder.js.map +1 -1
  18. package/esm/global-types.d.ts +6 -4
  19. package/esm/global-types.d.ts.map +1 -1
  20. package/esm/index.d.ts.map +1 -1
  21. package/esm/index.js +2 -1
  22. package/esm/index.js.map +1 -1
  23. package/esm/model-loader.d.ts.map +1 -1
  24. package/esm/model-loader.js +2 -1
  25. package/esm/model-loader.js.map +1 -1
  26. package/esm/prisma-field-builder.d.ts +2 -2
  27. package/esm/prisma-field-builder.d.ts.map +1 -1
  28. package/esm/util/map-query.d.ts +3 -2
  29. package/esm/util/map-query.d.ts.map +1 -1
  30. package/esm/util/map-query.js +42 -28
  31. package/esm/util/map-query.js.map +1 -1
  32. package/esm/util/selections.d.ts +2 -1
  33. package/esm/util/selections.d.ts.map +1 -1
  34. package/esm/util/selections.js +4 -3
  35. package/esm/util/selections.js.map +1 -1
  36. package/lib/connection-helpers.js +2 -1
  37. package/lib/connection-helpers.js.map +1 -1
  38. package/lib/field-builder.js +9 -6
  39. package/lib/field-builder.js.map +1 -1
  40. package/lib/index.js +2 -1
  41. package/lib/index.js.map +1 -1
  42. package/lib/model-loader.js +2 -1
  43. package/lib/model-loader.js.map +1 -1
  44. package/lib/util/map-query.js +42 -28
  45. package/lib/util/map-query.js.map +1 -1
  46. package/lib/util/selections.js +4 -3
  47. package/lib/util/selections.js.map +1 -1
  48. package/package.json +5 -5
  49. package/src/connection-helpers.ts +5 -1
  50. package/src/field-builder.ts +3 -0
  51. package/src/global-types.ts +6 -4
  52. package/src/index.ts +11 -1
  53. package/src/model-loader.ts +5 -1
  54. package/src/prisma-field-builder.ts +2 -2
  55. package/src/util/map-query.ts +61 -14
  56. package/src/util/selections.ts +4 -1
@@ -2,6 +2,7 @@ import { PothosValidationError, getMappedArgumentValues } from '@pothos/core';
2
2
  import {
3
3
  type FieldNode,
4
4
  type FragmentDefinitionNode,
5
+ type FragmentSpreadNode,
5
6
  type GraphQLField,
6
7
  GraphQLIncludeDirective,
7
8
  type GraphQLInterfaceType,
@@ -42,6 +43,7 @@ function addTypeSelectionsForField(
42
43
  state: SelectionState,
43
44
  selection: FieldNode,
44
45
  indirectPath: string[],
46
+ deferred?: boolean,
45
47
  ) {
46
48
  if (selection.name.value.startsWith('__')) {
47
49
  return;
@@ -66,8 +68,8 @@ function addTypeSelectionsForField(
66
68
  [],
67
69
  pothosIndirectInclude.paths ?? [pothosIndirectInclude.path!],
68
70
  indirectPath,
69
- (resolvedType, field, path) => {
70
- addTypeSelectionsForField(resolvedType, context, info, state, field, path);
71
+ (resolvedType, field, path, deferred) => {
72
+ addTypeSelectionsForField(resolvedType, context, info, state, field, path, deferred);
71
73
  },
72
74
  );
73
75
  } else if (pothosIndirectInclude) {
@@ -78,6 +80,7 @@ function addTypeSelectionsForField(
78
80
  state,
79
81
  selection,
80
82
  indirectPath,
83
+ deferred,
81
84
  );
82
85
  return;
83
86
  }
@@ -97,7 +100,7 @@ function addTypeSelectionsForField(
97
100
  });
98
101
  }
99
102
 
100
- if (selection.selectionSet) {
103
+ if (selection.selectionSet && (!deferred || !state.skipDeferredFragments)) {
101
104
  addNestedSelections(type, context, info, state, selection.selectionSet, indirectPath);
102
105
  }
103
106
  }
@@ -109,13 +112,22 @@ function resolveIndirectIncludePaths(
109
112
  pathPrefix: { type?: string; name: string }[],
110
113
  includePaths: { type?: string; name: string }[][],
111
114
  path: string[],
112
- resolve: (type: GraphQLNamedType, field: FieldNode, path: string[]) => void,
115
+ resolve: (type: GraphQLNamedType, field: FieldNode, path: string[], deferred: boolean) => void,
116
+ deferred = false,
113
117
  ) {
114
118
  for (const includePath of includePaths) {
115
119
  if (pathPrefix.length > 0) {
116
- resolveIndirectInclude(type, info, selection, [...pathPrefix, ...includePath], path, resolve);
120
+ resolveIndirectInclude(
121
+ type,
122
+ info,
123
+ selection,
124
+ [...pathPrefix, ...includePath],
125
+ path,
126
+ resolve,
127
+ deferred,
128
+ );
117
129
  } else {
118
- resolveIndirectInclude(type, info, selection, includePath, path, resolve);
130
+ resolveIndirectInclude(type, info, selection, includePath, path, resolve, deferred);
119
131
  }
120
132
  }
121
133
  }
@@ -126,11 +138,12 @@ function resolveIndirectInclude(
126
138
  selection: FieldNode | FragmentDefinitionNode | InlineFragmentNode,
127
139
  includePath: { type?: string; name: string }[],
128
140
  path: string[],
129
- resolve: (type: GraphQLNamedType, field: FieldNode, path: string[]) => void,
141
+ resolve: (type: GraphQLNamedType, field: FieldNode, path: string[], deferred: boolean) => void,
142
+ deferred = false,
130
143
  expectedType = type,
131
144
  ) {
132
145
  if (includePath.length === 0) {
133
- resolve(type, selection as FieldNode, path);
146
+ resolve(type, selection as FieldNode, path, deferred);
134
147
  return;
135
148
  }
136
149
 
@@ -157,6 +170,7 @@ function resolveIndirectInclude(
157
170
  rest,
158
171
  [...path, sel.alias?.value ?? sel.name.value],
159
172
  resolve,
173
+ deferred,
160
174
  );
161
175
  }
162
176
  continue;
@@ -168,6 +182,7 @@ function resolveIndirectInclude(
168
182
  includePath,
169
183
  path,
170
184
  resolve,
185
+ deferred || isDeferredFragment(sel, info),
171
186
  include.type ? info.schema.getType(include.type)! : expectedType,
172
187
  );
173
188
 
@@ -182,6 +197,7 @@ function resolveIndirectInclude(
182
197
  includePath,
183
198
  path,
184
199
  resolve,
200
+ deferred || isDeferredFragment(sel, info),
185
201
  include.type ? info.schema.getType(include.type)! : expectedType,
186
202
  );
187
203
  }
@@ -216,6 +232,10 @@ function addNestedSelections(
216
232
 
217
233
  continue;
218
234
  case Kind.FRAGMENT_SPREAD:
235
+ if (state.skipDeferredFragments && isDeferredFragment(selection, info)) {
236
+ continue;
237
+ }
238
+
219
239
  parentType = info.schema.getType(
220
240
  info.fragments[selection.name.value].typeCondition.name.value,
221
241
  )! as GraphQLObjectType;
@@ -235,6 +255,10 @@ function addNestedSelections(
235
255
  continue;
236
256
 
237
257
  case Kind.INLINE_FRAGMENT:
258
+ if (state.skipDeferredFragments && isDeferredFragment(selection, info)) {
259
+ continue;
260
+ }
261
+
238
262
  parentType = selection.typeCondition
239
263
  ? (info.schema.getType(selection.typeCondition.name.value) as GraphQLObjectType)
240
264
  : type;
@@ -314,6 +338,7 @@ function addFieldSelection(
314
338
  info,
315
339
  ),
316
340
  info,
341
+ state.skipDeferredFragments,
317
342
  state,
318
343
  );
319
344
 
@@ -333,7 +358,7 @@ function addFieldSelection(
333
358
  normalizedIndirectInclude?.paths ??
334
359
  (normalizedIndirectInclude?.path ? [normalizedIndirectInclude.path] : []),
335
360
  [],
336
- (resolvedType, resolvedField, path) => {
361
+ (resolvedType, resolvedField, path, deferred) => {
337
362
  addTypeSelectionsForField(
338
363
  resolvedType,
339
364
  context,
@@ -341,6 +366,7 @@ function addFieldSelection(
341
366
  fieldState,
342
367
  resolvedField,
343
368
  path,
369
+ deferred,
344
370
  );
345
371
  },
346
372
  );
@@ -408,6 +434,7 @@ export function queryFromInfo<
408
434
  path = [],
409
435
  paths = [],
410
436
  withUsageCheck = false,
437
+ skipDeferredFragments = true,
411
438
  }: {
412
439
  context: object;
413
440
  info: GraphQLResolveInfo;
@@ -415,6 +442,7 @@ export function queryFromInfo<
415
442
  path?: string[];
416
443
  paths?: string[][];
417
444
  withUsageCheck?: boolean;
445
+ skipDeferredFragments?: boolean;
418
446
  } & (
419
447
  | { include?: Include; select?: never }
420
448
  | { select?: Select; include?: never }
@@ -440,7 +468,7 @@ export function queryFromInfo<
440
468
  info.fieldNodes[0],
441
469
  pothosIndirectInclude?.path ?? [],
442
470
  [],
443
- (indirectType, indirectField, subPath) => {
471
+ (indirectType, indirectField, subPath, deferred) => {
444
472
  resolveIndirectIncludePaths(
445
473
  indirectType,
446
474
  info,
@@ -450,10 +478,11 @@ export function queryFromInfo<
450
478
  ? paths.map((p) => p.map((n) => (typeof n === 'string' ? { name: n } : n)))
451
479
  : [path.map((n) => (typeof n === 'string' ? { name: n } : n))],
452
480
  subPath,
453
- (resolvedType, resolvedField, nested) => {
481
+ (resolvedType, resolvedField, nested, deferred) => {
454
482
  state = createStateForType(
455
483
  typeName ? type : resolvedType,
456
484
  info,
485
+ skipDeferredFragments,
457
486
  undefined,
458
487
  initialSelection,
459
488
  );
@@ -465,19 +494,21 @@ export function queryFromInfo<
465
494
  state,
466
495
  resolvedField,
467
496
  nested,
497
+ deferred,
468
498
  );
469
499
  },
500
+ deferred,
470
501
  );
471
502
  },
472
503
  );
473
504
  } else {
474
- state = createStateForType(type, info, undefined, initialSelection);
505
+ state = createStateForType(type, info, skipDeferredFragments, undefined, initialSelection);
475
506
 
476
507
  addTypeSelectionsForField(type, context, info, state, info.fieldNodes[0], []);
477
508
  }
478
509
 
479
510
  if (!state) {
480
- state = createStateForType(type, info, undefined, initialSelection);
511
+ state = createStateForType(type, info, skipDeferredFragments, undefined, initialSelection);
481
512
  }
482
513
 
483
514
  setLoaderMappings(context, info, state.mappings);
@@ -490,11 +521,12 @@ export function queryFromInfo<
490
521
  export function selectionStateFromInfo(
491
522
  context: object,
492
523
  info: GraphQLResolveInfo,
524
+ skipDeferredFragments: boolean,
493
525
  typeName?: string,
494
526
  ) {
495
527
  const type = typeName ? info.schema.getTypeMap()[typeName] : info.parentType;
496
528
 
497
- const state = createStateForType(type, info);
529
+ const state = createStateForType(type, info, skipDeferredFragments);
498
530
 
499
531
  if (!(isObjectType(type) || isInterfaceType(type))) {
500
532
  throw new PothosValidationError(
@@ -510,6 +542,7 @@ export function selectionStateFromInfo(
510
542
  function createStateForType(
511
543
  type: GraphQLNamedType,
512
544
  info: GraphQLResolveInfo,
545
+ skipDeferredFragments: boolean,
513
546
  parent?: SelectionState,
514
547
  initialSelections?: SelectionMap,
515
548
  ) {
@@ -520,6 +553,7 @@ function createStateForType(
520
553
  const state = createState(
521
554
  fieldMap,
522
555
  targetType.extensions?.pothosPrismaSelect ? 'select' : 'include',
556
+ skipDeferredFragments,
523
557
  parent,
524
558
  );
525
559
 
@@ -592,3 +626,16 @@ function fieldSkipped(info: GraphQLResolveInfo, selection: FieldNode) {
592
626
 
593
627
  return false;
594
628
  }
629
+
630
+ function isDeferredFragment(
631
+ node: FragmentSpreadNode | InlineFragmentNode,
632
+ info: GraphQLResolveInfo,
633
+ ) {
634
+ const deferDirective = info.schema.getDirective('defer');
635
+ if (!deferDirective) {
636
+ return false;
637
+ }
638
+
639
+ const defer = getDirectiveValues(deferDirective, node, info.variableValues);
640
+ return !!defer && defer.if !== false;
641
+ }
@@ -13,6 +13,7 @@ export interface SelectionState {
13
13
  relations: Map<string, SelectionState>;
14
14
  mappings: LoaderMappings;
15
15
  parent?: SelectionState;
16
+ skipDeferredFragments: boolean;
16
17
  }
17
18
 
18
19
  export function selectionCompatible(
@@ -92,6 +93,7 @@ export function mergeState(state: SelectionState, newState: SelectionState) {
92
93
  export function createState(
93
94
  fieldMap: FieldMap,
94
95
  mode: SelectionMode,
96
+ skipDeferredFragments: boolean,
95
97
  parent?: SelectionState,
96
98
  ): SelectionState {
97
99
  return {
@@ -103,6 +105,7 @@ export function createState(
103
105
  counts: new Map(),
104
106
  relations: new Map(),
105
107
  mappings: {},
108
+ skipDeferredFragments,
106
109
  };
107
110
  }
108
111
 
@@ -148,7 +151,7 @@ export function mergeSelection(state: SelectionState, { select, include, ...quer
148
151
  if (state.relations.has(key)) {
149
152
  mergeSelection(state.relations.get(key)!, selection);
150
153
  } else {
151
- const relatedState = createState(childMap, 'select');
154
+ const relatedState = createState(childMap, 'select', state.skipDeferredFragments);
152
155
  mergeSelection(relatedState, selection);
153
156
  state.relations.set(key, relatedState);
154
157
  }