@pothos/plugin-prisma 3.54.0 → 3.56.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 (92) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +42 -1
  3. package/dts/connection-helpers.d.ts +3 -3
  4. package/dts/connection-helpers.d.ts.map +1 -1
  5. package/dts/global-types.d.ts +12 -4
  6. package/dts/global-types.d.ts.map +1 -1
  7. package/dts/index.d.ts +3 -1
  8. package/dts/index.d.ts.map +1 -1
  9. package/dts/interface-ref.d.ts +10 -0
  10. package/dts/interface-ref.d.ts.map +1 -0
  11. package/dts/model-loader.d.ts +7 -7
  12. package/dts/model-loader.d.ts.map +1 -1
  13. package/dts/prisma-field-builder.d.ts +4 -4
  14. package/dts/prisma-field-builder.d.ts.map +1 -1
  15. package/dts/types.d.ts +23 -7
  16. package/dts/types.d.ts.map +1 -1
  17. package/dts/util/cursors.d.ts.map +1 -1
  18. package/dts/util/datamodel.d.ts +3 -3
  19. package/dts/util/datamodel.d.ts.map +1 -1
  20. package/dts/util/map-query.d.ts.map +1 -1
  21. package/dts/util/usage.d.ts +1 -0
  22. package/dts/util/usage.d.ts.map +1 -1
  23. package/esm/connection-helpers.d.ts +3 -3
  24. package/esm/connection-helpers.d.ts.map +1 -1
  25. package/esm/connection-helpers.js.map +1 -1
  26. package/esm/global-types.d.ts +18 -10
  27. package/esm/global-types.d.ts.map +1 -1
  28. package/esm/global-types.js.map +1 -1
  29. package/esm/index.d.ts +3 -1
  30. package/esm/index.d.ts.map +1 -1
  31. package/esm/index.js +48 -3
  32. package/esm/index.js.map +1 -1
  33. package/esm/interface-ref.d.ts +10 -0
  34. package/esm/interface-ref.d.ts.map +1 -0
  35. package/esm/interface-ref.js +26 -0
  36. package/esm/interface-ref.js.map +1 -0
  37. package/esm/model-loader.d.ts +7 -7
  38. package/esm/model-loader.d.ts.map +1 -1
  39. package/esm/model-loader.js.map +1 -1
  40. package/esm/prisma-field-builder.d.ts +4 -4
  41. package/esm/prisma-field-builder.d.ts.map +1 -1
  42. package/esm/prisma-field-builder.js +3 -3
  43. package/esm/prisma-field-builder.js.map +1 -1
  44. package/esm/schema-builder.js +27 -0
  45. package/esm/schema-builder.js.map +1 -1
  46. package/esm/types.d.ts +25 -9
  47. package/esm/types.d.ts.map +1 -1
  48. package/esm/util/cursors.d.ts.map +1 -1
  49. package/esm/util/cursors.js +2 -4
  50. package/esm/util/cursors.js.map +1 -1
  51. package/esm/util/datamodel.d.ts +3 -3
  52. package/esm/util/datamodel.d.ts.map +1 -1
  53. package/esm/util/datamodel.js +3 -2
  54. package/esm/util/datamodel.js.map +1 -1
  55. package/esm/util/map-query.d.ts.map +1 -1
  56. package/esm/util/map-query.js +17 -12
  57. package/esm/util/map-query.js.map +1 -1
  58. package/esm/util/usage.d.ts +1 -0
  59. package/esm/util/usage.d.ts.map +1 -1
  60. package/esm/util/usage.js +30 -0
  61. package/esm/util/usage.js.map +1 -1
  62. package/lib/connection-helpers.js.map +1 -1
  63. package/lib/index.js +50 -2
  64. package/lib/index.js.map +1 -1
  65. package/lib/interface-ref.js +36 -0
  66. package/lib/interface-ref.js.map +1 -0
  67. package/lib/model-loader.js.map +1 -1
  68. package/lib/prisma-field-builder.js +3 -3
  69. package/lib/prisma-field-builder.js.map +1 -1
  70. package/lib/schema-builder.js +27 -0
  71. package/lib/schema-builder.js.map +1 -1
  72. package/lib/util/cursors.js +2 -4
  73. package/lib/util/cursors.js.map +1 -1
  74. package/lib/util/datamodel.js +3 -2
  75. package/lib/util/datamodel.js.map +1 -1
  76. package/lib/util/map-query.js +16 -11
  77. package/lib/util/map-query.js.map +1 -1
  78. package/lib/util/usage.js +33 -0
  79. package/lib/util/usage.js.map +1 -1
  80. package/package.json +1 -1
  81. package/src/connection-helpers.ts +6 -6
  82. package/src/global-types.ts +36 -11
  83. package/src/index.ts +56 -2
  84. package/src/interface-ref.ts +18 -0
  85. package/src/model-loader.ts +13 -7
  86. package/src/prisma-field-builder.ts +7 -10
  87. package/src/schema-builder.ts +44 -1
  88. package/src/types.ts +66 -9
  89. package/src/util/cursors.ts +2 -4
  90. package/src/util/datamodel.ts +8 -3
  91. package/src/util/map-query.ts +32 -13
  92. package/src/util/usage.ts +31 -0
@@ -9,6 +9,7 @@ import SchemaBuilder, {
9
9
  PothosError,
10
10
  SchemaTypes,
11
11
  } from '@pothos/core';
12
+ import { PrismaInterfaceRef } from './interface-ref';
12
13
  import { ModelLoader } from './model-loader';
13
14
  import { PrismaNodeRef } from './node-ref';
14
15
  import { PrismaObjectRef } from './object-ref';
@@ -29,7 +30,7 @@ schemaBuilderProto.prismaObject = function prismaObject(
29
30
  ) {
30
31
  const ref = options.variant
31
32
  ? new PrismaObjectRef(options.variant, type)
32
- : getRefFromModel(type, this);
33
+ : (getRefFromModel(type, this) as PrismaObjectRef<PrismaModelTypes>);
33
34
  const name = options.variant ?? options.name ?? type;
34
35
  const fieldMap = getRelationMap(getDMMF(this)).get(type)!;
35
36
  const idSelection = ModelLoader.getDefaultIDSelection(ref, type, this);
@@ -64,6 +65,48 @@ schemaBuilderProto.prismaObject = function prismaObject(
64
65
  return ref as never;
65
66
  };
66
67
 
68
+ schemaBuilderProto.prismaInterface = function prismaInterface(
69
+ type,
70
+ { fields, findUnique, select, include, description, ...options },
71
+ ) {
72
+ const ref = options.variant
73
+ ? new PrismaInterfaceRef(options.variant, type)
74
+ : (getRefFromModel(type, this, 'interface') as PrismaInterfaceRef<PrismaModelTypes>);
75
+ const name = options.variant ?? options.name ?? type;
76
+ const fieldMap = getRelationMap(getDMMF(this)).get(type)!;
77
+ const idSelection = ModelLoader.getDefaultIDSelection(ref, type, this);
78
+
79
+ ref.name = name;
80
+
81
+ this.interfaceType(ref, {
82
+ ...(options as {}),
83
+ description: getModelDescription(type, this, description),
84
+ extensions: {
85
+ ...options.extensions,
86
+ pothosPrismaInclude: include,
87
+ pothosPrismaModel: type,
88
+ pothosPrismaFieldMap: fieldMap,
89
+ pothosPrismaSelect: select && { ...idSelection, ...(select as {}) },
90
+ pothosPrismaLoader: ModelLoader.forRef(ref, type, findUnique as never, this),
91
+ },
92
+ name,
93
+ fields: fields
94
+ ? () =>
95
+ fields(
96
+ new PrismaObjectFieldBuilder(
97
+ name,
98
+ this,
99
+ type,
100
+ getRelationMap(getDMMF(this)).get(type)!,
101
+ 'Interface',
102
+ ),
103
+ )
104
+ : undefined,
105
+ });
106
+
107
+ return ref as never;
108
+ };
109
+
67
110
  schemaBuilderProto.prismaNode = function prismaNode(
68
111
  this: PothosSchemaTypes.SchemaBuilder<SchemaTypes> & {
69
112
  nodeInterfaceRef?: () => InterfaceRef<unknown>;
package/src/types.ts CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  typeBrandKey,
22
22
  TypeParam,
23
23
  } from '@pothos/core';
24
- import { PrismaObjectRef } from './object-ref';
24
+ import { PrismaInterfaceRef, PrismaRef } from './interface-ref';
25
25
  import type { PrismaObjectFieldBuilder } from './prisma-field-builder';
26
26
 
27
27
  export interface PrismaDelegate {
@@ -228,6 +228,60 @@ export type PrismaObjectTypeOptions<
228
228
  > = PrismaObjectRefOptions<Types, Model, FindUnique, Include, Select, Shape> &
229
229
  PrismaObjectImplementationOptions<Types, Model, Interfaces, FindUnique, Select, Shape>;
230
230
 
231
+ export type PrismaInterfaceRefOptions<
232
+ Types extends SchemaTypes,
233
+ Model extends PrismaModelTypes,
234
+ FindUnique,
235
+ Include,
236
+ Select,
237
+ Shape extends object,
238
+ > = NameOrVariant &
239
+ (
240
+ | {
241
+ include?: Include & Model['Include'];
242
+ select?: never;
243
+ findUnique?: FindUnique &
244
+ (((parent: Shape, context: Types['Context']) => Model['WhereUnique']) | null);
245
+ }
246
+ | {
247
+ select: Model['Select'] & Select;
248
+ include?: never;
249
+ findUnique?: (parent: Shape, context: Types['Context']) => Model['WhereUnique'];
250
+ }
251
+ );
252
+
253
+ export type PrismaInterfaceImplementationOptions<
254
+ Types extends SchemaTypes,
255
+ Model extends PrismaModelTypes,
256
+ Interfaces extends InterfaceParam<Types>[],
257
+ FindUnique,
258
+ Select,
259
+ Shape extends object,
260
+ > = Omit<
261
+ PothosSchemaTypes.InterfaceTypeOptions<Types, Shape, Interfaces>,
262
+ 'fields' | 'description'
263
+ > & {
264
+ description?: string | false;
265
+ fields?: PrismaObjectFieldsShape<
266
+ Types,
267
+ Model,
268
+ FindUnique extends null ? true : false,
269
+ Shape & (FindUnique extends null ? {} : { [prismaModelName]?: Model['Name'] }),
270
+ Select
271
+ >;
272
+ };
273
+
274
+ export type PrismaInterfaceTypeOptions<
275
+ Types extends SchemaTypes,
276
+ Model extends PrismaModelTypes,
277
+ Interfaces extends InterfaceParam<Types>[],
278
+ FindUnique,
279
+ Include,
280
+ Select,
281
+ Shape extends object,
282
+ > = PrismaInterfaceRefOptions<Types, Model, FindUnique, Include, Select, Shape> &
283
+ PrismaInterfaceImplementationOptions<Types, Model, Interfaces, FindUnique, Select, Shape>;
284
+
231
285
  type NameOrVariant =
232
286
  | {
233
287
  name?: never;
@@ -394,14 +448,14 @@ export type RelatedFieldOptions<
394
448
  >;
395
449
  }) & {
396
450
  description?: string | false;
397
- type?: PrismaObjectRef<TypesForRelation<Types, Model, Field>>;
451
+ type?: PrismaRef<TypesForRelation<Types, Model, Field>>;
398
452
  query?: QueryForField<Types, Args, Model['Include'][Field & keyof Model['Include']]>;
399
453
  };
400
454
 
401
455
  export type VariantFieldOptions<
402
456
  Types extends SchemaTypes,
403
457
  Model extends PrismaModelTypes,
404
- Variant extends PrismaObjectRef<Model>,
458
+ Variant extends PrismaRef<Model>,
405
459
  Args extends InputFieldMap,
406
460
  isNull,
407
461
  Shape,
@@ -458,10 +512,10 @@ export type PrismaFieldOptions<
458
512
  Types extends SchemaTypes,
459
513
  ParentShape,
460
514
  Type extends
461
- | PrismaObjectRef<PrismaModelTypes>
515
+ | PrismaRef<PrismaModelTypes>
462
516
  | keyof Types['PrismaTypes']
463
517
  | [keyof Types['PrismaTypes']]
464
- | [PrismaObjectRef<PrismaModelTypes>],
518
+ | [PrismaRef<PrismaModelTypes>],
465
519
  Model extends PrismaModelTypes,
466
520
  Param extends TypeParam<Types>,
467
521
  Args extends InputFieldMap,
@@ -494,10 +548,10 @@ export type PrismaFieldWithInputOptions<
494
548
  Args extends Record<string, InputFieldRef<unknown, 'Arg'>>,
495
549
  Fields extends Record<string, InputFieldRef<unknown, 'InputObject'>>,
496
550
  Type extends
497
- | PrismaObjectRef<PrismaModelTypes>
551
+ | PrismaRef<PrismaModelTypes>
498
552
  | keyof Types['PrismaTypes']
499
553
  | [keyof Types['PrismaTypes']]
500
- | [PrismaObjectRef<PrismaModelTypes>],
554
+ | [PrismaRef<PrismaModelTypes>],
501
555
  Model extends PrismaModelTypes,
502
556
  Param extends TypeParam<Types>,
503
557
  Nullable extends FieldNullability<Param>,
@@ -562,7 +616,10 @@ export type PrismaFieldResolver<
562
616
  export type PrismaConnectionFieldOptions<
563
617
  Types extends SchemaTypes,
564
618
  ParentShape,
565
- Type extends PrismaObjectRef<PrismaModelTypes> | keyof Types['PrismaTypes'],
619
+ Type extends
620
+ | PrismaRef<PrismaModelTypes>
621
+ | PrismaInterfaceRef<PrismaModelTypes>
622
+ | keyof Types['PrismaTypes'],
566
623
  Model extends PrismaModelTypes,
567
624
  Param extends OutputType<Types>,
568
625
  Nullable extends boolean,
@@ -665,7 +722,7 @@ export type RelatedConnectionOptions<
665
722
  ? {
666
723
  description?: string | false;
667
724
  query?: QueryForField<Types, Args, Model['Include'][Field & keyof Model['Include']]>;
668
- type?: PrismaObjectRef<TypesForRelation<Types, Model, Field>>;
725
+ type?: PrismaRef<TypesForRelation<Types, Model, Field>>;
669
726
  cursor: CursorFromRelation<Model, Field>;
670
727
  defaultSize?: number | ((args: ConnectionArgs, ctx: Types['Context']) => number);
671
728
  maxSize?: number | ((args: ConnectionArgs, ctx: Types['Context']) => number);
@@ -8,6 +8,7 @@ import {
8
8
  } from '@pothos/core';
9
9
  import { getModel } from './datamodel';
10
10
  import { DMMFField } from './get-client';
11
+ import { extendWithUsage } from './usage';
11
12
 
12
13
  const DEFAULT_MAX_SIZE = 100;
13
14
  const DEFAULT_SIZE = 20;
@@ -339,10 +340,7 @@ export async function resolvePrismaCursorConnection<T extends {}>(
339
340
  }) => MaybePromise<readonly T[]>,
340
341
  ) {
341
342
  const query = prismaCursorConnectionQuery(options);
342
- const results = await resolve({
343
- ...options.query,
344
- ...query,
345
- });
343
+ const results = await resolve(extendWithUsage(options.query, query));
346
344
 
347
345
  if (!results) {
348
346
  return results;
@@ -1,9 +1,10 @@
1
1
  import { ObjectRef, PothosSchemaError, SchemaTypes } from '@pothos/core';
2
+ import { PrismaInterfaceRef, PrismaRef } from '../interface-ref';
2
3
  import { PrismaObjectRef } from '../object-ref';
3
4
  import { PrismaClient, PrismaDelegate, PrismaModelTypes } from '../types';
4
5
  import { getDMMF } from './get-client';
5
6
 
6
- export const refMap = new WeakMap<object, Map<string, PrismaObjectRef<PrismaModelTypes>>>();
7
+ export const refMap = new WeakMap<object, Map<string, PrismaRef<PrismaModelTypes>>>();
7
8
  export const findUniqueMap = new WeakMap<
8
9
  object,
9
10
  Map<ObjectRef<unknown>, ((args: unknown, ctx: {}) => unknown) | null>
@@ -17,14 +18,18 @@ export const includeForRefMap = new WeakMap<
17
18
  export function getRefFromModel<Types extends SchemaTypes>(
18
19
  name: string,
19
20
  builder: PothosSchemaTypes.SchemaBuilder<Types>,
20
- ): PrismaObjectRef<PrismaModelTypes> {
21
+ type: 'object' | 'interface' = 'object',
22
+ ): PrismaRef<PrismaModelTypes> {
21
23
  if (!refMap.has(builder)) {
22
24
  refMap.set(builder, new Map());
23
25
  }
24
26
  const cache = refMap.get(builder)!;
25
27
 
26
28
  if (!cache.has(name)) {
27
- cache.set(name, new PrismaObjectRef(name, name));
29
+ cache.set(
30
+ name,
31
+ type === 'object' ? new PrismaObjectRef(name, name) : new PrismaInterfaceRef(name, name),
32
+ );
28
33
  }
29
34
 
30
35
  return cache.get(name)!;
@@ -6,10 +6,12 @@ import {
6
6
  getArgumentValues,
7
7
  getNamedType,
8
8
  GraphQLField,
9
+ GraphQLInterfaceType,
9
10
  GraphQLNamedType,
10
11
  GraphQLObjectType,
11
12
  GraphQLResolveInfo,
12
13
  InlineFragmentNode,
14
+ isInterfaceType,
13
15
  isObjectType,
14
16
  Kind,
15
17
  SelectionSetNode,
@@ -84,7 +86,7 @@ function addTypeSelectionsForField(
84
86
  return;
85
87
  }
86
88
 
87
- if (!isObjectType(type)) {
89
+ if (!(isObjectType(type) || isInterfaceType(type))) {
88
90
  return;
89
91
  }
90
92
 
@@ -143,7 +145,7 @@ function resolveIndirectInclude(
143
145
  for (const sel of selection.selectionSet.selections) {
144
146
  switch (sel.kind) {
145
147
  case Kind.FIELD:
146
- if (sel.name.value === include.name && isObjectType(type)) {
148
+ if (sel.name.value === include.name && (isObjectType(type) || isInterfaceType(type))) {
147
149
  const returnType = getNamedType(type.getFields()[sel.name.value].type);
148
150
 
149
151
  resolveIndirectInclude(
@@ -196,13 +198,14 @@ function resolveIndirectInclude(
196
198
  }
197
199
 
198
200
  function addNestedSelections(
199
- type: GraphQLObjectType,
201
+ type: GraphQLObjectType | GraphQLInterfaceType,
200
202
  context: object,
201
203
  info: GraphQLResolveInfo,
202
204
  state: SelectionState,
203
205
  selections: SelectionSetNode,
204
206
  indirectPath: string[],
205
207
  ) {
208
+ let parentType = type;
206
209
  for (const selection of selections.selections) {
207
210
  switch (selection.kind) {
208
211
  case Kind.FIELD:
@@ -210,12 +213,19 @@ function addNestedSelections(
210
213
 
211
214
  continue;
212
215
  case Kind.FRAGMENT_SPREAD:
213
- if (info.fragments[selection.name.value].typeCondition.name.value !== type.name) {
216
+ parentType = info.schema.getType(
217
+ info.fragments[selection.name.value].typeCondition.name.value,
218
+ )! as GraphQLObjectType;
219
+ if (
220
+ isObjectType(type)
221
+ ? parentType.name !== type.name
222
+ : parentType.extensions?.pothosPrismaModel !== type.extensions.pothosPrismaModel
223
+ ) {
214
224
  continue;
215
225
  }
216
226
 
217
227
  addNestedSelections(
218
- type,
228
+ parentType,
219
229
  context,
220
230
  info,
221
231
  state,
@@ -226,11 +236,18 @@ function addNestedSelections(
226
236
  continue;
227
237
 
228
238
  case Kind.INLINE_FRAGMENT:
229
- if (selection.typeCondition && selection.typeCondition.name.value !== type.name) {
239
+ parentType = selection.typeCondition
240
+ ? (info.schema.getType(selection.typeCondition.name.value) as GraphQLObjectType)
241
+ : type;
242
+ if (
243
+ isObjectType(type)
244
+ ? parentType.name !== type.name
245
+ : parentType.extensions?.pothosPrismaModel !== type.extensions.pothosPrismaModel
246
+ ) {
230
247
  continue;
231
248
  }
232
249
 
233
- addNestedSelections(type, context, info, state, selection.selectionSet, indirectPath);
250
+ addNestedSelections(parentType, context, info, state, selection.selectionSet, indirectPath);
234
251
 
235
252
  continue;
236
253
 
@@ -243,7 +260,7 @@ function addNestedSelections(
243
260
  }
244
261
 
245
262
  function addFieldSelection(
246
- type: GraphQLObjectType,
263
+ type: GraphQLObjectType | GraphQLInterfaceType,
247
264
  context: object,
248
265
  info: GraphQLResolveInfo,
249
266
  state: SelectionState,
@@ -454,8 +471,10 @@ export function selectionStateFromInfo(
454
471
 
455
472
  const state = createStateForType(type, info);
456
473
 
457
- if (!isObjectType(type)) {
458
- throw new PothosValidationError('Prisma plugin can only resolve includes for object types');
474
+ if (!(isObjectType(type) || isInterfaceType(type))) {
475
+ throw new PothosValidationError(
476
+ 'Prisma plugin can only resolve includes for object and interface types',
477
+ );
459
478
  }
460
479
 
461
480
  addFieldSelection(type, context, info, state, info.fieldNodes[0], []);
@@ -503,7 +522,7 @@ function normalizeInclude(path: string[], type: GraphQLNamedType): IndirectInclu
503
522
 
504
523
  const normalized: { name: string; type: string }[] = [];
505
524
 
506
- if (!isObjectType(currentType)) {
525
+ if (!(isObjectType(currentType) || isInterfaceType(currentType))) {
507
526
  throw new PothosValidationError(`Expected ${currentType} to be an Object type`);
508
527
  }
509
528
 
@@ -516,8 +535,8 @@ function normalizeInclude(path: string[], type: GraphQLNamedType): IndirectInclu
516
535
 
517
536
  currentType = getNamedType(field.type);
518
537
 
519
- if (!isObjectType(currentType)) {
520
- throw new PothosValidationError(`Expected ${currentType} to be an Object type`);
538
+ if (!(isObjectType(currentType) || isInterfaceType(currentType))) {
539
+ throw new PothosValidationError(`Expected ${currentType} to be an Object or Interface type`);
521
540
  }
522
541
 
523
542
  normalized.push({ name: fieldName, type: currentType.name });
package/src/util/usage.ts CHANGED
@@ -8,6 +8,9 @@ export function wrapWithUsageCheck<T extends Object>(obj: T): T {
8
8
  get() {
9
9
  return used;
10
10
  },
11
+ set(value: boolean) {
12
+ used = value;
13
+ },
11
14
  enumerable: false,
12
15
  });
13
16
 
@@ -31,3 +34,31 @@ export function wrapWithUsageCheck<T extends Object>(obj: T): T {
31
34
  export function isUsed(obj: object): boolean {
32
35
  return !(usageSymbol in obj) || (obj as { [usageSymbol]: boolean })[usageSymbol];
33
36
  }
37
+
38
+ export function extendWithUsage<T extends object, U extends object>(
39
+ original: T,
40
+ extension: U,
41
+ ): T & U {
42
+ if (!(usageSymbol in original)) {
43
+ return { ...original, ...extension };
44
+ }
45
+
46
+ const result = { ...extension };
47
+
48
+ for (const key of [usageSymbol, ...Object.keys(original)]) {
49
+ if (key in result) {
50
+ // eslint-disable-next-line no-continue
51
+ continue;
52
+ }
53
+
54
+ Object.defineProperty(result, key, {
55
+ enumerable: key !== usageSymbol,
56
+ configurable: key !== usageSymbol,
57
+ get() {
58
+ return original[key as keyof T];
59
+ },
60
+ });
61
+ }
62
+
63
+ return result as T & U;
64
+ }