@pothos/plugin-prisma 0.15.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 (147) hide show
  1. package/.turbo/turbo-build.log +17 -0
  2. package/.turbo/turbo-test.log +17 -0
  3. package/CHANGELOG.md +312 -0
  4. package/LICENSE +6 -0
  5. package/README.md +808 -0
  6. package/babel.config.js +3 -0
  7. package/bin/generator.js +2 -0
  8. package/esm/cursors.d.ts +55 -0
  9. package/esm/cursors.d.ts.map +1 -0
  10. package/esm/cursors.js +106 -0
  11. package/esm/cursors.js.map +1 -0
  12. package/esm/field-builder.d.ts +2 -0
  13. package/esm/field-builder.d.ts.map +1 -0
  14. package/esm/field-builder.js +51 -0
  15. package/esm/field-builder.js.map +1 -0
  16. package/esm/generator.d.ts +2 -0
  17. package/esm/generator.d.ts.map +1 -0
  18. package/esm/generator.js +82 -0
  19. package/esm/generator.js.map +1 -0
  20. package/esm/global-types.d.ts +52 -0
  21. package/esm/global-types.d.ts.map +1 -0
  22. package/esm/global-types.js +2 -0
  23. package/esm/global-types.js.map +1 -0
  24. package/esm/index.d.ts +11 -0
  25. package/esm/index.d.ts.map +1 -0
  26. package/esm/index.js +14 -0
  27. package/esm/index.js.map +1 -0
  28. package/esm/loader-map.d.ts +6 -0
  29. package/esm/loader-map.d.ts.map +1 -0
  30. package/esm/loader-map.js +35 -0
  31. package/esm/loader-map.js.map +1 -0
  32. package/esm/model-loader.d.ts +17 -0
  33. package/esm/model-loader.d.ts.map +1 -0
  34. package/esm/model-loader.js +89 -0
  35. package/esm/model-loader.js.map +1 -0
  36. package/esm/node-ref.d.ts +10 -0
  37. package/esm/node-ref.d.ts.map +1 -0
  38. package/esm/node-ref.js +18 -0
  39. package/esm/node-ref.js.map +1 -0
  40. package/esm/package.json +3 -0
  41. package/esm/prisma-field-builder.d.ts +22 -0
  42. package/esm/prisma-field-builder.d.ts.map +1 -0
  43. package/esm/prisma-field-builder.js +178 -0
  44. package/esm/prisma-field-builder.js.map +1 -0
  45. package/esm/refs.d.ts +13 -0
  46. package/esm/refs.d.ts.map +1 -0
  47. package/esm/refs.js +63 -0
  48. package/esm/refs.js.map +1 -0
  49. package/esm/schema-builder.d.ts +2 -0
  50. package/esm/schema-builder.d.ts.map +1 -0
  51. package/esm/schema-builder.js +69 -0
  52. package/esm/schema-builder.js.map +1 -0
  53. package/esm/types.d.ts +164 -0
  54. package/esm/types.d.ts.map +1 -0
  55. package/esm/types.js +2 -0
  56. package/esm/types.js.map +1 -0
  57. package/esm/util/index.d.ts +5 -0
  58. package/esm/util/index.d.ts.map +1 -0
  59. package/esm/util/index.js +16 -0
  60. package/esm/util/index.js.map +1 -0
  61. package/esm/util/map-includes.d.ts +5 -0
  62. package/esm/util/map-includes.d.ts.map +1 -0
  63. package/esm/util/map-includes.js +168 -0
  64. package/esm/util/map-includes.js.map +1 -0
  65. package/esm/util/merge-includes.d.ts +3 -0
  66. package/esm/util/merge-includes.d.ts.map +1 -0
  67. package/esm/util/merge-includes.js +91 -0
  68. package/esm/util/merge-includes.js.map +1 -0
  69. package/generated.ts +54 -0
  70. package/lib/cursors.d.ts +55 -0
  71. package/lib/cursors.d.ts.map +1 -0
  72. package/lib/cursors.js +112 -0
  73. package/lib/cursors.js.map +1 -0
  74. package/lib/field-builder.d.ts +2 -0
  75. package/lib/field-builder.d.ts.map +1 -0
  76. package/lib/field-builder.js +63 -0
  77. package/lib/field-builder.js.map +1 -0
  78. package/lib/generator.d.ts +2 -0
  79. package/lib/generator.d.ts.map +1 -0
  80. package/lib/generator.js +103 -0
  81. package/lib/generator.js.map +1 -0
  82. package/lib/global-types.d.ts +52 -0
  83. package/lib/global-types.d.ts.map +1 -0
  84. package/lib/global-types.js +3 -0
  85. package/lib/global-types.js.map +1 -0
  86. package/lib/index.d.ts +11 -0
  87. package/lib/index.d.ts.map +1 -0
  88. package/lib/index.js +40 -0
  89. package/lib/index.js.map +1 -0
  90. package/lib/loader-map.d.ts +6 -0
  91. package/lib/loader-map.d.ts.map +1 -0
  92. package/lib/loader-map.js +41 -0
  93. package/lib/loader-map.js.map +1 -0
  94. package/lib/model-loader.d.ts +17 -0
  95. package/lib/model-loader.d.ts.map +1 -0
  96. package/lib/model-loader.js +93 -0
  97. package/lib/model-loader.js.map +1 -0
  98. package/lib/node-ref.d.ts +10 -0
  99. package/lib/node-ref.d.ts.map +1 -0
  100. package/lib/node-ref.js +21 -0
  101. package/lib/node-ref.js.map +1 -0
  102. package/lib/prisma-field-builder.d.ts +22 -0
  103. package/lib/prisma-field-builder.d.ts.map +1 -0
  104. package/lib/prisma-field-builder.js +182 -0
  105. package/lib/prisma-field-builder.js.map +1 -0
  106. package/lib/refs.d.ts +13 -0
  107. package/lib/refs.d.ts.map +1 -0
  108. package/lib/refs.js +72 -0
  109. package/lib/refs.js.map +1 -0
  110. package/lib/schema-builder.d.ts +2 -0
  111. package/lib/schema-builder.d.ts.map +1 -0
  112. package/lib/schema-builder.js +93 -0
  113. package/lib/schema-builder.js.map +1 -0
  114. package/lib/types.d.ts +164 -0
  115. package/lib/types.d.ts.map +1 -0
  116. package/lib/types.js +4 -0
  117. package/lib/types.js.map +1 -0
  118. package/lib/util/index.d.ts +5 -0
  119. package/lib/util/index.d.ts.map +1 -0
  120. package/lib/util/index.js +30 -0
  121. package/lib/util/index.js.map +1 -0
  122. package/lib/util/map-includes.d.ts +5 -0
  123. package/lib/util/map-includes.d.ts.map +1 -0
  124. package/lib/util/map-includes.js +173 -0
  125. package/lib/util/map-includes.js.map +1 -0
  126. package/lib/util/merge-includes.d.ts +3 -0
  127. package/lib/util/merge-includes.d.ts.map +1 -0
  128. package/lib/util/merge-includes.js +96 -0
  129. package/lib/util/merge-includes.js.map +1 -0
  130. package/package.json +70 -0
  131. package/src/cursors.ts +159 -0
  132. package/src/field-builder.ts +115 -0
  133. package/src/generator.ts +184 -0
  134. package/src/global-types.ts +180 -0
  135. package/src/index.ts +18 -0
  136. package/src/loader-map.ts +48 -0
  137. package/src/model-loader.ts +135 -0
  138. package/src/node-ref.ts +29 -0
  139. package/src/prisma-field-builder.ts +324 -0
  140. package/src/refs.ts +110 -0
  141. package/src/schema-builder.ts +124 -0
  142. package/src/types.ts +470 -0
  143. package/src/util/index.ts +26 -0
  144. package/src/util/map-includes.ts +298 -0
  145. package/src/util/merge-includes.ts +121 -0
  146. package/tsconfig.json +21 -0
  147. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,324 @@
1
+ /* eslint-disable no-underscore-dangle */
2
+ import { GraphQLResolveInfo } from 'graphql';
3
+ import {
4
+ FieldRef,
5
+ InputFieldMap,
6
+ MaybePromise,
7
+ NormalizeArgs,
8
+ ObjectFieldBuilder,
9
+ ObjectRef,
10
+ PluginName,
11
+ SchemaTypes,
12
+ } from '@pothos/core';
13
+ import { prismaCursorConnectionQuery, wrapConnectionResult } from './cursors';
14
+ import { getLoaderMapping, setLoaderMappings } from './loader-map';
15
+ import { ModelLoader } from './model-loader';
16
+ import { getDelegateFromModel, getFindUniqueForRef, getRefFromModel, getRelation } from './refs';
17
+ import {
18
+ PrismaDelegate,
19
+ PrismaModelTypes,
20
+ RelatedConnectionOptions,
21
+ RelatedFieldOptions,
22
+ RelationCountOptions,
23
+ } from './types';
24
+ import { queryFromInfo } from './util';
25
+
26
+ export class PrismaObjectFieldBuilder<
27
+ Types extends SchemaTypes,
28
+ Model extends PrismaModelTypes,
29
+ NeedsResolve extends boolean,
30
+ Shape extends object = Model['Shape'],
31
+ > extends ObjectFieldBuilder<Types, Shape> {
32
+ delegate: PrismaDelegate;
33
+ model: string;
34
+
35
+ relatedConnection: 'relay' extends PluginName
36
+ ? <
37
+ Field extends Model['ListRelations'],
38
+ Nullable extends boolean,
39
+ Args extends InputFieldMap,
40
+ ResolveReturnShape,
41
+ >(
42
+ ...args: NormalizeArgs<
43
+ [
44
+ field: Field,
45
+ options: RelatedConnectionOptions<Types, Model, Field, Nullable, Args, NeedsResolve>,
46
+ connectionOptions?: PothosSchemaTypes.ConnectionObjectOptions<
47
+ Types,
48
+ ObjectRef<Shape>,
49
+ ResolveReturnShape
50
+ >,
51
+ edgeOptions?: PothosSchemaTypes.ConnectionEdgeObjectOptions<
52
+ Types,
53
+ ObjectRef<Shape>,
54
+ ResolveReturnShape
55
+ >,
56
+ ]
57
+ >
58
+ ) => FieldRef<PothosSchemaTypes.ConnectionShapeHelper<Types, Shape, Nullable>['shape']>
59
+ : '@pothos/plugin-relay is required to use this method' = function relatedConnection(
60
+ this: PrismaObjectFieldBuilder<SchemaTypes, Model, boolean>,
61
+ name: string,
62
+ {
63
+ maxSize,
64
+ defaultSize,
65
+ cursor,
66
+ query,
67
+ resolve,
68
+ extensions,
69
+ totalCount,
70
+ ...options
71
+ }: {
72
+ totalCount?: boolean;
73
+ maxSize?: number;
74
+ defaultSize?: number;
75
+ cursor: string;
76
+ extensions: {};
77
+ query: ((args: {}, ctx: {}) => {}) | {};
78
+ resolve: (query: {}, parent: unknown, args: {}, ctx: {}, info: {}) => MaybePromise<{}[]>;
79
+ },
80
+ connectionOptions = {},
81
+ edgeOptions = {},
82
+ ) {
83
+ const relationField = getRelation(this.model, this.builder, name);
84
+ const parentRef = getRefFromModel(this.model, this.builder);
85
+ const relationTypeName =
86
+ typeof relationField.type === 'string' ? relationField.type : relationField.type.name;
87
+ const ref = getRefFromModel(relationTypeName, this.builder);
88
+ const findUnique = getFindUniqueForRef(parentRef, this.builder);
89
+ const loaderCache = ModelLoader.forModel(this.model, this.builder);
90
+ let typeName: string | undefined;
91
+
92
+ const getQuery = (args: PothosSchemaTypes.DefaultConnectionArguments, ctx: {}) => ({
93
+ ...((typeof query === 'function' ? query(args, ctx) : query) as {}),
94
+ ...prismaCursorConnectionQuery({
95
+ column: cursor,
96
+ maxSize,
97
+ defaultSize,
98
+ args,
99
+ }),
100
+ });
101
+
102
+ const fieldRef = (
103
+ this as unknown as {
104
+ connection: (...args: unknown[]) => FieldRef<unknown>;
105
+ }
106
+ ).connection(
107
+ {
108
+ ...options,
109
+ extensions: {
110
+ ...extensions,
111
+ pothosPrismaQuery: getQuery,
112
+ pothosPrismaRelation: name,
113
+ },
114
+ type: ref,
115
+ resolve: async (
116
+ parent: object,
117
+ args: PothosSchemaTypes.DefaultConnectionArguments,
118
+ context: {},
119
+ info: GraphQLResolveInfo,
120
+ ) => {
121
+ const connectionQuery = getQuery(args, context);
122
+ const getResult = () => {
123
+ const mapping = getLoaderMapping(context, info.path);
124
+ const loadedValue = (parent as Record<string, unknown>)[name];
125
+
126
+ if (
127
+ // if we attempted to load the relation, and its missing it will be null
128
+ // undefined means that the query was not constructed in a way that requested the relation
129
+ loadedValue !== undefined &&
130
+ mapping
131
+ ) {
132
+ if (loadedValue !== null && loadedValue !== undefined) {
133
+ setLoaderMappings(context, info.path, mapping);
134
+ }
135
+
136
+ return loadedValue as {}[];
137
+ }
138
+
139
+ if (!resolve && !findUnique) {
140
+ throw new Error(`Missing findUnique for Prisma type ${this.model}`);
141
+ }
142
+
143
+ const mergedQuery = { ...queryFromInfo(context, info), ...connectionQuery };
144
+
145
+ if (resolve) {
146
+ return resolve(mergedQuery, parent, args, context, info);
147
+ }
148
+
149
+ return loaderCache(parent).loadRelation(name, mergedQuery, context) as Promise<{}[]>;
150
+ };
151
+
152
+ return wrapConnectionResult(
153
+ await getResult(),
154
+ args,
155
+ connectionQuery.take,
156
+ cursor,
157
+ (parent as { _count?: Record<string, number> })._count?.[name],
158
+ );
159
+ },
160
+ },
161
+ {
162
+ ...connectionOptions,
163
+ fields: totalCount
164
+ ? (t: PothosSchemaTypes.ObjectFieldBuilder<SchemaTypes, { totalCount?: number }>) => ({
165
+ totalCount: t.int({
166
+ extensions: {
167
+ pothosPrismaRelationCountForParent: name,
168
+ },
169
+ resolve: (parent, args, context) => {
170
+ const loadedValue = parent.totalCount;
171
+
172
+ if (loadedValue !== undefined) {
173
+ return loadedValue;
174
+ }
175
+
176
+ return loaderCache(parent).loadCount(name, context);
177
+ },
178
+ }),
179
+ ...(connectionOptions as { fields?: (t: unknown) => {} }).fields?.(t),
180
+ })
181
+ : (connectionOptions as { fields: undefined }).fields,
182
+ extensions: {
183
+ ...(connectionOptions as Record<string, {}> | undefined)?.extensions,
184
+ pothosPrismaIndirectInclude: {
185
+ getType: () => {
186
+ if (!typeName) {
187
+ typeName = this.builder.configStore.getTypeConfig(ref).name;
188
+ }
189
+ return typeName;
190
+ },
191
+ path: [{ name: 'edges' }, { name: 'node' }],
192
+ },
193
+ },
194
+ },
195
+ edgeOptions,
196
+ );
197
+
198
+ return fieldRef;
199
+ } as never;
200
+
201
+ constructor(name: string, builder: PothosSchemaTypes.SchemaBuilder<Types>, model: string) {
202
+ super(name, builder);
203
+
204
+ this.model = model;
205
+ this.delegate = getDelegateFromModel(builder.options.prisma.client, model);
206
+ }
207
+
208
+ relation<
209
+ Field extends Model['Fields'],
210
+ Nullable extends boolean,
211
+ Args extends InputFieldMap,
212
+ ResolveReturnShape,
213
+ >(
214
+ ...allArgs: NormalizeArgs<
215
+ [
216
+ name: Field,
217
+ options?: RelatedFieldOptions<
218
+ Types,
219
+ Model,
220
+ Field,
221
+ Nullable,
222
+ Args,
223
+ ResolveReturnShape,
224
+ NeedsResolve,
225
+ Shape
226
+ >,
227
+ ]
228
+ >
229
+ ): FieldRef<Model['Relations'][Field]['Shape'], 'Object'> {
230
+ const [name, options = {} as never] = allArgs;
231
+ const relationField = getRelation(this.model, this.builder, name);
232
+ const parentRef = getRefFromModel(this.model, this.builder);
233
+ const relationTypeName =
234
+ typeof relationField.type === 'string' ? relationField.type : relationField.type.name;
235
+ const ref = getRefFromModel(relationTypeName, this.builder);
236
+ const findUnique = getFindUniqueForRef(parentRef, this.builder);
237
+ const loaderCache = ModelLoader.forModel(this.model, this.builder);
238
+
239
+ const { query = {}, resolve, ...rest } = options;
240
+
241
+ return this.field({
242
+ ...rest,
243
+ type: relationField.isList ? [ref] : ref,
244
+ extensions: {
245
+ ...options.extensions,
246
+ pothosPrismaQuery: query,
247
+ pothosPrismaRelation: name,
248
+ },
249
+ resolve: (parent, args, context, info) => {
250
+ const mapping = getLoaderMapping(context, info.path);
251
+
252
+ const loadedValue = (parent as Record<string, unknown>)[name];
253
+
254
+ if (
255
+ // if we attempted to load the relation, and its missing it will be null
256
+ // undefined means that the query was not constructed in a way that requested the relation
257
+ loadedValue !== undefined &&
258
+ mapping
259
+ ) {
260
+ if (loadedValue !== null && loadedValue !== undefined) {
261
+ setLoaderMappings(context, info.path, mapping);
262
+ }
263
+
264
+ return loadedValue as never;
265
+ }
266
+
267
+ const queryOptions = {
268
+ ...((typeof query === 'function' ? query(args, context) : query) as {}),
269
+ ...queryFromInfo(context, info),
270
+ };
271
+
272
+ if (resolve) {
273
+ return resolve(queryOptions, parent, args as never, context, info) as never;
274
+ }
275
+
276
+ if (!findUnique) {
277
+ throw new Error(`Missing findUnique for Prisma type ${this.model}`);
278
+ }
279
+
280
+ return loaderCache(parent).loadRelation(name, queryOptions, context) as never;
281
+ },
282
+ }) as FieldRef<Model['Relations'][Field]['Shape'], 'Object'>;
283
+ }
284
+
285
+ relationCount<Field extends Model['Fields']>(
286
+ ...allArgs: NormalizeArgs<
287
+ [name: Field, options?: RelationCountOptions<Types, Shape, NeedsResolve>]
288
+ >
289
+ ): FieldRef<number, 'Object'> {
290
+ const [name, options = {} as never] = allArgs;
291
+ const parentRef = getRefFromModel(this.model, this.builder);
292
+ const findUnique = getFindUniqueForRef(parentRef, this.builder);
293
+ const loaderCache = ModelLoader.forModel(this.model, this.builder);
294
+
295
+ const { resolve, ...rest } = options;
296
+
297
+ return this.field({
298
+ ...rest,
299
+ type: 'Int',
300
+ nullable: false,
301
+ extensions: {
302
+ ...options.extensions,
303
+ pothosPrismaRelationCount: name,
304
+ },
305
+ resolve: (parent, args, context, info) => {
306
+ const loadedValue = (parent as { _count: Record<string, unknown> })._count?.[name];
307
+
308
+ if (loadedValue !== undefined) {
309
+ return loadedValue as never;
310
+ }
311
+
312
+ if (resolve) {
313
+ return resolve(parent, args, context, info) as never;
314
+ }
315
+
316
+ if (!findUnique) {
317
+ throw new Error(`Missing findUnique for Prisma type ${this.model}`);
318
+ }
319
+
320
+ return loaderCache(parent).loadCount(name, context) as never;
321
+ },
322
+ }) as FieldRef<number, 'Object'>;
323
+ }
324
+ }
package/src/refs.ts ADDED
@@ -0,0 +1,110 @@
1
+ import { ObjectRef, SchemaTypes } from '@pothos/core';
2
+ import { Prisma } from '../tests/client';
3
+ import { PrismaDelegate } from './types';
4
+
5
+ export const refMap = new WeakMap<object, Map<string, ObjectRef<unknown>>>();
6
+ export const findUniqueMap = new WeakMap<
7
+ object,
8
+ Map<ObjectRef<unknown>, ((args: unknown, ctx: {}) => unknown) | null>
9
+ >();
10
+
11
+ export const includeForRefMap = new WeakMap<
12
+ object,
13
+ Map<ObjectRef<unknown>, Record<string, unknown> | null>
14
+ >();
15
+
16
+ export function getRefFromModel<Types extends SchemaTypes>(
17
+ name: string,
18
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
19
+ ): ObjectRef<unknown> {
20
+ if (!refMap.has(builder)) {
21
+ refMap.set(builder, new Map());
22
+ }
23
+ const cache = refMap.get(builder)!;
24
+
25
+ if (!cache.has(name)) {
26
+ cache.set(name, builder.objectRef(name));
27
+ }
28
+
29
+ return cache.get(name)!;
30
+ }
31
+
32
+ export function getFindUniqueForRef<Types extends SchemaTypes>(
33
+ ref: ObjectRef<unknown>,
34
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
35
+ ) {
36
+ if (!findUniqueMap.has(builder)) {
37
+ findUniqueMap.set(builder, new Map());
38
+ }
39
+ const cache = findUniqueMap.get(builder)!;
40
+
41
+ if (!cache.has(ref)) {
42
+ return null;
43
+ }
44
+
45
+ return cache.get(ref)! as (args: unknown, context: Types['Context']) => unknown;
46
+ }
47
+
48
+ export function setFindUniqueForRef<Types extends SchemaTypes>(
49
+ ref: ObjectRef<unknown>,
50
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ findUnique: ((args: any, context: Types['Context']) => unknown) | null,
53
+ ) {
54
+ if (!findUniqueMap.has(builder)) {
55
+ findUniqueMap.set(builder, new Map());
56
+ }
57
+ const cache = findUniqueMap.get(builder)!;
58
+
59
+ cache.set(ref, findUnique);
60
+ }
61
+
62
+ export function getRelation<Types extends SchemaTypes>(
63
+ name: string,
64
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
65
+ relation: string,
66
+ ) {
67
+ const { client } = builder.options.prisma;
68
+ // eslint-disable-next-line no-underscore-dangle
69
+ const dmmf = (client as unknown as { _dmmf: { modelMap: Record<string, Prisma.DMMF.Model> } })
70
+ ._dmmf;
71
+ const modelData = dmmf.modelMap[name];
72
+
73
+ if (!modelData) {
74
+ throw new Error(`Model '${name}' not found in DMMF`);
75
+ }
76
+
77
+ const fieldData = modelData.fields.find((field) => field.name === relation);
78
+
79
+ if (!fieldData) {
80
+ throw new Error(`Field '${relation}' not found in model '${name}'`);
81
+ }
82
+
83
+ if (fieldData.kind !== 'object') {
84
+ throw new Error(`Field ${relation} of model '${name}' is not a relation (${fieldData.kind})`);
85
+ }
86
+
87
+ return fieldData;
88
+ }
89
+
90
+ export function getRelatedDelegate<Types extends SchemaTypes>(
91
+ name: string,
92
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
93
+ relation: string,
94
+ ) {
95
+ const fieldData = getRelation(name, builder, relation);
96
+
97
+ return fieldData.type;
98
+ }
99
+
100
+ export function getDelegateFromModel(client: Record<string, unknown>, model: string) {
101
+ const lowerCase = `${model.slice(0, 1).toLowerCase()}${model.slice(1)}`;
102
+
103
+ const delegate = lowerCase in client ? client[lowerCase] : null;
104
+
105
+ if (!delegate) {
106
+ throw new Error(`Unable to find delegate for model ${model}`);
107
+ }
108
+
109
+ return delegate as PrismaDelegate;
110
+ }
@@ -0,0 +1,124 @@
1
+ import './global-types';
2
+ import { GraphQLResolveInfo } from 'graphql';
3
+ import SchemaBuilder, {
4
+ brandWithType,
5
+ FieldNullability,
6
+ FieldRef,
7
+ InterfaceRef,
8
+ OutputType,
9
+ SchemaTypes,
10
+ TypeParam,
11
+ } from '@pothos/core';
12
+ import { PrismaObjectFieldBuilder } from './field-builder';
13
+ import PrismaNodeRef from './node-ref';
14
+ import { getDelegateFromModel, getRefFromModel, setFindUniqueForRef } from './refs';
15
+ import { ModelTypes, PrismaDelegate, PrismaNodeOptions } from './types';
16
+ import { queryFromInfo } from './util';
17
+
18
+ const schemaBuilderProto = SchemaBuilder.prototype as PothosSchemaTypes.SchemaBuilder<SchemaTypes>;
19
+
20
+ schemaBuilderProto.prismaObject = function prismaObject(type, { fields, findUnique, ...options }) {
21
+ const ref = getRefFromModel(type, this);
22
+ const name = options.name ?? type;
23
+
24
+ ref.name = name;
25
+
26
+ setFindUniqueForRef(ref, this, findUnique);
27
+
28
+ this.objectType(ref, {
29
+ ...(options as {} as PothosSchemaTypes.ObjectFieldOptions<
30
+ SchemaTypes,
31
+ unknown,
32
+ TypeParam<SchemaTypes>,
33
+ FieldNullability<SchemaTypes>,
34
+ {},
35
+ unknown
36
+ >),
37
+ extensions: {
38
+ ...options.extensions,
39
+ pothosPrismaInclude: options.include,
40
+ },
41
+ name,
42
+ fields: fields ? () => fields(new PrismaObjectFieldBuilder(name, this, type)) : undefined,
43
+ });
44
+
45
+ return ref as never;
46
+ };
47
+
48
+ schemaBuilderProto.prismaNode = function prismaNode(
49
+ this: PothosSchemaTypes.SchemaBuilder<SchemaTypes> & {
50
+ nodeInterfaceRef?: () => InterfaceRef<unknown>;
51
+ },
52
+ type: keyof SchemaTypes['PrismaTypes'],
53
+ {
54
+ findUnique,
55
+ name,
56
+ ...options
57
+ }: PrismaNodeOptions<SchemaTypes, ModelTypes<PrismaDelegate>, [], never, {}>,
58
+ ) {
59
+ const interfaceRef = this.nodeInterfaceRef?.();
60
+
61
+ if (!interfaceRef) {
62
+ throw new TypeError('builder.prismaNode requires @pothos/plugin-relay to be installed');
63
+ }
64
+
65
+ const typeName = name ?? type;
66
+ const delegate = getDelegateFromModel(this.options.prisma.client, type);
67
+ const nodeRef = new PrismaNodeRef(typeName);
68
+ const extendedOptions = {
69
+ ...options,
70
+ interfaces: [interfaceRef, ...(options.interfaces ?? [])],
71
+ extensions: {
72
+ ...options.extensions,
73
+ pothosPrismaInclude: options.include,
74
+ },
75
+ isTypeOf: (val: unknown) => nodeRef.hasBrand(val),
76
+ findUnique: (parent: unknown, context: {}) =>
77
+ findUnique(options.id.resolve(parent as never, context) as string, context),
78
+ loadWithoutCache: async (
79
+ id: string,
80
+ context: SchemaTypes['Context'],
81
+ info: GraphQLResolveInfo,
82
+ ) => {
83
+ const query = queryFromInfo(context, info, typeName);
84
+ const record = await delegate.findUnique({
85
+ ...query,
86
+ rejectOnNotFound: true,
87
+ where: findUnique(id, context),
88
+ } as never);
89
+
90
+ brandWithType(record, typeName as OutputType<SchemaTypes>);
91
+
92
+ return record;
93
+ },
94
+ };
95
+
96
+ const ref = this.prismaObject(type, extendedOptions as never);
97
+
98
+ this.configStore.onTypeConfig(ref, (nodeConfig) => {
99
+ this.objectField(ref, 'id', (t) =>
100
+ (
101
+ t as unknown as {
102
+ globalID: (options: Record<string, unknown>) => FieldRef<unknown>;
103
+ }
104
+ ).globalID({
105
+ ...options.id,
106
+ nullable: false,
107
+ args: {},
108
+ resolve: async (
109
+ parent: never,
110
+ args: object,
111
+ context: object,
112
+ info: GraphQLResolveInfo,
113
+ ) => ({
114
+ type: nodeConfig.name,
115
+ id: await options.id.resolve(parent, context),
116
+ }),
117
+ }),
118
+ );
119
+ });
120
+
121
+ this.configStore.associateRefWithName(nodeRef, typeName);
122
+
123
+ return nodeRef;
124
+ } as never;