@pothos/plugin-prisma 0.18.0 → 0.19.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 (163) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +403 -308
  3. package/esm/field-builder.js +3 -3
  4. package/esm/field-builder.js.map +1 -1
  5. package/esm/generator.js +4 -0
  6. package/esm/generator.js.map +1 -1
  7. package/esm/global-types.d.ts +23 -5
  8. package/esm/global-types.d.ts.map +1 -1
  9. package/esm/index.d.ts +4 -1
  10. package/esm/index.d.ts.map +1 -1
  11. package/esm/index.js +46 -1
  12. package/esm/index.js.map +1 -1
  13. package/esm/model-loader.d.ts +5 -6
  14. package/esm/model-loader.d.ts.map +1 -1
  15. package/esm/model-loader.js +12 -69
  16. package/esm/model-loader.js.map +1 -1
  17. package/esm/prisma-field-builder.d.ts +25 -6
  18. package/esm/prisma-field-builder.d.ts.map +1 -1
  19. package/esm/prisma-field-builder.js +83 -116
  20. package/esm/prisma-field-builder.js.map +1 -1
  21. package/esm/schema-builder.js +14 -4
  22. package/esm/schema-builder.js.map +1 -1
  23. package/esm/types.d.ts +73 -77
  24. package/esm/types.d.ts.map +1 -1
  25. package/esm/types.js +1 -0
  26. package/esm/types.js.map +1 -1
  27. package/esm/{cursors.d.ts → util/cursors.d.ts} +1 -1
  28. package/esm/util/cursors.d.ts.map +1 -0
  29. package/esm/{cursors.js → util/cursors.js} +0 -0
  30. package/esm/util/cursors.js.map +1 -0
  31. package/{lib/refs.d.ts → esm/util/datamodel.d.ts} +4 -8
  32. package/esm/util/datamodel.d.ts.map +1 -0
  33. package/esm/{refs.js → util/datamodel.js} +2 -25
  34. package/esm/util/datamodel.js.map +1 -0
  35. package/esm/util/deep-equal.d.ts +2 -0
  36. package/esm/util/deep-equal.d.ts.map +1 -0
  37. package/esm/util/deep-equal.js +39 -0
  38. package/esm/util/deep-equal.js.map +1 -0
  39. package/esm/util/loader-map.d.ts +6 -0
  40. package/esm/util/loader-map.d.ts.map +1 -0
  41. package/esm/{loader-map.js → util/loader-map.js} +10 -12
  42. package/esm/util/loader-map.js.map +1 -0
  43. package/esm/util/map-query.d.ts +6 -0
  44. package/esm/util/map-query.d.ts.map +1 -0
  45. package/esm/util/map-query.js +169 -0
  46. package/esm/util/map-query.js.map +1 -0
  47. package/esm/util/relation-map.d.ts +9 -0
  48. package/esm/util/relation-map.d.ts.map +1 -0
  49. package/esm/util/relation-map.js +20 -0
  50. package/esm/util/relation-map.js.map +1 -0
  51. package/esm/util/selections.d.ts +20 -0
  52. package/esm/util/selections.d.ts.map +1 -0
  53. package/esm/util/selections.js +139 -0
  54. package/esm/util/selections.js.map +1 -0
  55. package/lib/field-builder.js +9 -9
  56. package/lib/field-builder.js.map +1 -1
  57. package/lib/generator.js +4 -0
  58. package/lib/generator.js.map +1 -1
  59. package/lib/global-types.d.ts +23 -5
  60. package/lib/global-types.d.ts.map +1 -1
  61. package/lib/index.d.ts +4 -1
  62. package/lib/index.d.ts.map +1 -1
  63. package/lib/index.js +45 -0
  64. package/lib/index.js.map +1 -1
  65. package/lib/model-loader.d.ts +5 -6
  66. package/lib/model-loader.d.ts.map +1 -1
  67. package/lib/model-loader.js +13 -70
  68. package/lib/model-loader.js.map +1 -1
  69. package/lib/prisma-field-builder.d.ts +25 -6
  70. package/lib/prisma-field-builder.d.ts.map +1 -1
  71. package/lib/prisma-field-builder.js +89 -122
  72. package/lib/prisma-field-builder.js.map +1 -1
  73. package/lib/schema-builder.js +17 -7
  74. package/lib/schema-builder.js.map +1 -1
  75. package/lib/types.d.ts +73 -77
  76. package/lib/types.d.ts.map +1 -1
  77. package/lib/types.js +2 -0
  78. package/lib/types.js.map +1 -1
  79. package/lib/{cursors.d.ts → util/cursors.d.ts} +1 -1
  80. package/lib/util/cursors.d.ts.map +1 -0
  81. package/lib/{cursors.js → util/cursors.js} +0 -0
  82. package/lib/util/cursors.js.map +1 -0
  83. package/{esm/refs.d.ts → lib/util/datamodel.d.ts} +4 -8
  84. package/lib/util/datamodel.d.ts.map +1 -0
  85. package/lib/{refs.js → util/datamodel.js} +3 -29
  86. package/lib/util/datamodel.js.map +1 -0
  87. package/lib/util/deep-equal.d.ts +2 -0
  88. package/lib/util/deep-equal.d.ts.map +1 -0
  89. package/lib/util/deep-equal.js +43 -0
  90. package/lib/util/deep-equal.js.map +1 -0
  91. package/lib/util/loader-map.d.ts +6 -0
  92. package/lib/util/loader-map.d.ts.map +1 -0
  93. package/lib/{loader-map.js → util/loader-map.js} +10 -12
  94. package/lib/util/loader-map.js.map +1 -0
  95. package/lib/util/map-query.d.ts +6 -0
  96. package/lib/util/map-query.d.ts.map +1 -0
  97. package/lib/util/map-query.js +175 -0
  98. package/lib/util/map-query.js.map +1 -0
  99. package/lib/util/relation-map.d.ts +9 -0
  100. package/lib/util/relation-map.d.ts.map +1 -0
  101. package/lib/util/relation-map.js +24 -0
  102. package/lib/util/relation-map.js.map +1 -0
  103. package/lib/util/selections.d.ts +20 -0
  104. package/lib/util/selections.d.ts.map +1 -0
  105. package/lib/util/selections.js +148 -0
  106. package/lib/util/selections.js.map +1 -0
  107. package/package.json +5 -5
  108. package/src/field-builder.ts +3 -3
  109. package/src/generator.ts +18 -0
  110. package/src/global-types.ts +59 -12
  111. package/src/index.ts +75 -1
  112. package/src/model-loader.ts +19 -92
  113. package/src/prisma-field-builder.ts +194 -152
  114. package/src/schema-builder.ts +28 -7
  115. package/src/types.ts +138 -102
  116. package/src/{cursors.ts → util/cursors.ts} +1 -1
  117. package/src/{refs.ts → util/datamodel.ts} +3 -44
  118. package/src/util/deep-equal.ts +51 -0
  119. package/src/{loader-map.ts → util/loader-map.ts} +13 -13
  120. package/src/util/map-query.ts +327 -0
  121. package/src/util/relation-map.ts +36 -0
  122. package/src/util/selections.ts +192 -0
  123. package/esm/cursors.d.ts.map +0 -1
  124. package/esm/cursors.js.map +0 -1
  125. package/esm/loader-map.d.ts +0 -6
  126. package/esm/loader-map.d.ts.map +0 -1
  127. package/esm/loader-map.js.map +0 -1
  128. package/esm/refs.d.ts.map +0 -1
  129. package/esm/refs.js.map +0 -1
  130. package/esm/util/index.d.ts +0 -5
  131. package/esm/util/index.d.ts.map +0 -1
  132. package/esm/util/index.js +0 -16
  133. package/esm/util/index.js.map +0 -1
  134. package/esm/util/map-includes.d.ts +0 -6
  135. package/esm/util/map-includes.d.ts.map +0 -1
  136. package/esm/util/map-includes.js +0 -184
  137. package/esm/util/map-includes.js.map +0 -1
  138. package/esm/util/merge-includes.d.ts +0 -3
  139. package/esm/util/merge-includes.d.ts.map +0 -1
  140. package/esm/util/merge-includes.js +0 -91
  141. package/esm/util/merge-includes.js.map +0 -1
  142. package/lib/cursors.d.ts.map +0 -1
  143. package/lib/cursors.js.map +0 -1
  144. package/lib/loader-map.d.ts +0 -6
  145. package/lib/loader-map.d.ts.map +0 -1
  146. package/lib/loader-map.js.map +0 -1
  147. package/lib/refs.d.ts.map +0 -1
  148. package/lib/refs.js.map +0 -1
  149. package/lib/util/index.d.ts +0 -5
  150. package/lib/util/index.d.ts.map +0 -1
  151. package/lib/util/index.js +0 -30
  152. package/lib/util/index.js.map +0 -1
  153. package/lib/util/map-includes.d.ts +0 -6
  154. package/lib/util/map-includes.d.ts.map +0 -1
  155. package/lib/util/map-includes.js +0 -189
  156. package/lib/util/map-includes.js.map +0 -1
  157. package/lib/util/merge-includes.d.ts +0 -3
  158. package/lib/util/merge-includes.d.ts.map +0 -1
  159. package/lib/util/merge-includes.js +0 -96
  160. package/lib/util/merge-includes.js.map +0 -1
  161. package/src/util/index.ts +0 -26
  162. package/src/util/map-includes.ts +0 -328
  163. package/src/util/merge-includes.ts +0 -121
@@ -1,46 +1,66 @@
1
1
  /* eslint-disable no-underscore-dangle */
2
2
  import { GraphQLResolveInfo } from 'graphql';
3
3
  import {
4
+ CompatibleTypes,
5
+ FieldKind,
4
6
  FieldRef,
5
7
  InputFieldMap,
6
8
  MaybePromise,
7
9
  NormalizeArgs,
8
- ObjectFieldBuilder,
9
10
  ObjectRef,
10
11
  PluginName,
12
+ RootFieldBuilder,
11
13
  SchemaTypes,
14
+ TypeParam,
12
15
  } from '@pothos/core';
13
- import { prismaCursorConnectionQuery, wrapConnectionResult } from './cursors';
14
- import { getLoaderMapping, setLoaderMappings } from './loader-map';
15
- import { ModelLoader } from './model-loader';
16
16
  import { PrismaObjectRef } from './object-ref';
17
17
  import {
18
- getCursorFormatter,
19
- getCursorParser,
20
- getDelegateFromModel,
21
- getFindUniqueForRef,
22
- getRefFromModel,
23
- getRelation,
24
- } from './refs';
25
- import {
26
- PrismaDelegate,
27
18
  PrismaModelTypes,
28
19
  RelatedConnectionOptions,
29
20
  RelatedFieldOptions,
30
21
  RelationCountOptions,
31
22
  ShapeFromConnection,
23
+ VariantFieldOptions,
32
24
  } from './types';
33
- import { queryFromInfo, SELF_RELATION } from './util';
34
- import { VariantFieldOptions } from '.';
25
+ import { prismaCursorConnectionQuery, wrapConnectionResult } from './util/cursors';
26
+ import {
27
+ getCursorFormatter,
28
+ getCursorParser,
29
+ getRefFromModel,
30
+ getRelation,
31
+ } from './util/datamodel';
32
+ import { FieldMap } from './util/relation-map';
33
+
34
+ // Workaround for FieldKind not being extended on Builder classes
35
+ const RootBuilder: {
36
+ // eslint-disable-next-line @typescript-eslint/prefer-function-type
37
+ new <Types extends SchemaTypes, Shape, Kind extends FieldKind>(
38
+ name: string,
39
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
40
+ kind: FieldKind,
41
+ graphqlKind: PothosSchemaTypes.PothosKindToGraphQLType[FieldKind],
42
+ ): PothosSchemaTypes.RootFieldBuilder<Types, Shape, Kind>;
43
+ } = RootFieldBuilder as never;
35
44
 
36
45
  export class PrismaObjectFieldBuilder<
37
46
  Types extends SchemaTypes,
38
47
  Model extends PrismaModelTypes,
39
48
  NeedsResolve extends boolean,
40
49
  Shape extends object = Model['Shape'],
41
- > extends ObjectFieldBuilder<Types, Shape> {
42
- delegate: PrismaDelegate;
50
+ > extends RootBuilder<Types, Shape, 'PrismaObject'> {
43
51
  model: string;
52
+ prismaFieldMap: FieldMap;
53
+
54
+ exposeBoolean = this.createExpose('Boolean');
55
+ exposeFloat = this.createExpose('Float');
56
+ exposeInt = this.createExpose('Int');
57
+ exposeID = this.createExpose('ID');
58
+ exposeString = this.createExpose('String');
59
+ exposeBooleanList = this.createExpose(['Boolean']);
60
+ exposeFloatList = this.createExpose(['Float']);
61
+ exposeIntList = this.createExpose(['Int']);
62
+ exposeIDList = this.createExpose(['ID']);
63
+ exposeStringList = this.createExpose(['String']);
44
64
 
45
65
  relatedConnection: 'relay' extends PluginName
46
66
  ? <
@@ -97,10 +117,7 @@ export class PrismaObjectFieldBuilder<
97
117
  edgeOptions = {},
98
118
  ) {
99
119
  const relationField = getRelation(this.model, this.builder, name);
100
- const parentRef = getRefFromModel(this.model, this.builder);
101
120
  const ref = options.type ?? getRefFromModel(relationField.type, this.builder);
102
- const findUnique = getFindUniqueForRef(parentRef, this.builder);
103
- const loaderCache = ModelLoader.forModel(this.model, this.builder);
104
121
  let typeName: string | undefined;
105
122
 
106
123
  const formatCursor = getCursorFormatter(relationField.type, this.builder, cursor);
@@ -116,6 +133,24 @@ export class PrismaObjectFieldBuilder<
116
133
  }),
117
134
  });
118
135
 
136
+ const relationSelect = (
137
+ args: object,
138
+ context: object,
139
+ nestedQuery: (query: unknown) => unknown,
140
+ ) => ({
141
+ select: {
142
+ [name]: nestedQuery({
143
+ ...((typeof query === 'function' ? query(args, context) : query) as {}),
144
+ ...prismaCursorConnectionQuery({
145
+ parseCursor,
146
+ maxSize,
147
+ defaultSize,
148
+ args,
149
+ }),
150
+ }),
151
+ },
152
+ });
153
+
119
154
  const fieldRef = (
120
155
  this as unknown as {
121
156
  connection: (...args: unknown[]) => FieldRef<unknown>;
@@ -125,49 +160,40 @@ export class PrismaObjectFieldBuilder<
125
160
  ...options,
126
161
  extensions: {
127
162
  ...extensions,
128
- pothosPrismaQuery: getQuery,
129
- pothosPrismaRelation: name,
163
+ pothosPrismaLoaded: (value: Record<string, unknown>) => value[name] !== undefined,
164
+ pothosPrismaFallback:
165
+ resolve &&
166
+ ((
167
+ q: { take: number },
168
+ parent: unknown,
169
+ args: PothosSchemaTypes.DefaultConnectionArguments,
170
+ context: {},
171
+ info: GraphQLResolveInfo,
172
+ ) =>
173
+ Promise.resolve(
174
+ resolve(
175
+ {
176
+ ...q,
177
+ ...(typeof query === 'function' ? query(args, context) : query),
178
+ } as never,
179
+ parent,
180
+ args,
181
+ context,
182
+ info,
183
+ ),
184
+ ).then((result) => wrapConnectionResult(result, args, q.take, formatCursor))),
130
185
  },
131
186
  type: ref,
132
- resolve: async (
133
- parent: object,
187
+ select: relationSelect as never,
188
+ resolve: (
189
+ parent: unknown,
134
190
  args: PothosSchemaTypes.DefaultConnectionArguments,
135
191
  context: {},
136
- info: GraphQLResolveInfo,
137
192
  ) => {
138
193
  const connectionQuery = getQuery(args, context);
139
- const getResult = () => {
140
- const mapping = getLoaderMapping(context, info.path);
141
- const loadedValue = (parent as Record<string, unknown>)[name];
142
-
143
- if (
144
- // if we attempted to load the relation, and its missing it will be null
145
- // undefined means that the query was not constructed in a way that requested the relation
146
- loadedValue !== undefined &&
147
- mapping
148
- ) {
149
- if (loadedValue !== null && loadedValue !== undefined) {
150
- setLoaderMappings(context, info.path, mapping);
151
- }
152
-
153
- return loadedValue as {}[];
154
- }
155
-
156
- if (!resolve && !findUnique) {
157
- throw new Error(`Missing findUnique for Prisma type ${this.model}`);
158
- }
159
-
160
- const mergedQuery = { ...queryFromInfo(context, info), ...connectionQuery };
161
-
162
- if (resolve) {
163
- return resolve(mergedQuery, parent, args, context, info);
164
- }
165
-
166
- return loaderCache(parent).loadRelation(name, mergedQuery, context) as Promise<{}[]>;
167
- };
168
194
 
169
195
  return wrapConnectionResult(
170
- await getResult(),
196
+ (parent as Record<string, never>)[name],
171
197
  args,
172
198
  connectionQuery.take,
173
199
  formatCursor,
@@ -181,17 +207,9 @@ export class PrismaObjectFieldBuilder<
181
207
  ? (t: PothosSchemaTypes.ObjectFieldBuilder<SchemaTypes, { totalCount?: number }>) => ({
182
208
  totalCount: t.int({
183
209
  extensions: {
184
- pothosPrismaRelationCountForParent: name,
185
- },
186
- resolve: (parent, args, context) => {
187
- const loadedValue = parent.totalCount;
188
-
189
- if (loadedValue !== undefined) {
190
- return loadedValue;
191
- }
192
-
193
- return loaderCache(parent).loadCount(name, context);
210
+ pothosPrismaParentSelect: { _count: { select: { [name]: true } } },
194
211
  },
212
+ resolve: (parent, args, context) => parent.totalCount,
195
213
  }),
196
214
  ...(connectionOptions as { fields?: (t: unknown) => {} }).fields?.(t),
197
215
  })
@@ -215,11 +233,16 @@ export class PrismaObjectFieldBuilder<
215
233
  return fieldRef;
216
234
  } as never;
217
235
 
218
- constructor(name: string, builder: PothosSchemaTypes.SchemaBuilder<Types>, model: string) {
219
- super(name, builder);
236
+ constructor(
237
+ name: string,
238
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
239
+ model: string,
240
+ fieldMap: FieldMap,
241
+ ) {
242
+ super(name, builder, 'PrismaObject', 'Object');
220
243
 
221
244
  this.model = model;
222
- this.delegate = getDelegateFromModel(builder.options.prisma.client, model);
245
+ this.prismaFieldMap = fieldMap;
223
246
  }
224
247
 
225
248
  relation<
@@ -246,54 +269,35 @@ export class PrismaObjectFieldBuilder<
246
269
  ): FieldRef<Model['Relations'][Field]['Shape'], 'Object'> {
247
270
  const [name, options = {} as never] = allArgs;
248
271
  const relationField = getRelation(this.model, this.builder, name);
249
- const parentRef = getRefFromModel(this.model, this.builder);
250
272
  const ref = options.type ?? getRefFromModel(relationField.type, this.builder);
251
- const findUnique = getFindUniqueForRef(parentRef, this.builder);
252
- const loaderCache = ModelLoader.forModel(this.model, this.builder);
253
273
 
254
- const { query = {}, resolve, ...rest } = options;
274
+ const { query = {}, resolve, extensions, ...rest } = options;
275
+
276
+ const relationSelect = (
277
+ args: object,
278
+ context: object,
279
+ nestedQuery: (query: unknown) => unknown,
280
+ ) => ({ select: { [name]: nestedQuery(query) } });
255
281
 
256
282
  return this.field({
257
283
  ...rest,
258
284
  type: relationField.isList ? [ref] : ref,
259
285
  extensions: {
260
- ...options.extensions,
261
- pothosPrismaQuery: query,
262
- pothosPrismaRelation: name,
263
- },
264
- resolve: (parent, args, context, info) => {
265
- const mapping = getLoaderMapping(context, info.path);
266
-
267
- const loadedValue = (parent as Record<string, unknown>)[name];
268
-
269
- if (
270
- // if we attempted to load the relation, and its missing it will be null
271
- // undefined means that the query was not constructed in a way that requested the relation
272
- loadedValue !== undefined &&
273
- mapping
274
- ) {
275
- if (loadedValue !== null && loadedValue !== undefined) {
276
- setLoaderMappings(context, info.path, mapping);
277
- }
278
-
279
- return loadedValue as never;
280
- }
281
-
282
- const queryOptions = {
283
- ...((typeof query === 'function' ? query(args, context) : query) as {}),
284
- ...queryFromInfo(context, info),
285
- };
286
-
287
- if (resolve) {
288
- return resolve(queryOptions, parent, args as never, context, info) as never;
289
- }
290
-
291
- if (!findUnique) {
292
- throw new Error(`Missing findUnique for Prisma type ${this.model}`);
293
- }
294
-
295
- return loaderCache(parent).loadRelation(name, queryOptions, context) as never;
286
+ ...extensions,
287
+ pothosPrismaLoaded: (value: Record<string, unknown>) => value[name] !== undefined,
288
+ pothosPrismaFallback:
289
+ resolve &&
290
+ ((q: {}, parent: Shape, args: {}, context: {}, info: GraphQLResolveInfo) =>
291
+ resolve(
292
+ { ...q, ...(typeof query === 'function' ? query(args, context) : query) } as never,
293
+ parent,
294
+ args as never,
295
+ context,
296
+ info,
297
+ )),
296
298
  },
299
+ select: relationSelect as never,
300
+ resolve: (parent) => (parent as Record<string, never>)[name],
297
301
  }) as FieldRef<Model['Relations'][Field]['Shape'], 'Object'>;
298
302
  }
299
303
 
@@ -303,37 +307,22 @@ export class PrismaObjectFieldBuilder<
303
307
  >
304
308
  ): FieldRef<number, 'Object'> {
305
309
  const [name, options = {} as never] = allArgs;
306
- const parentRef = getRefFromModel(this.model, this.builder);
307
- const findUnique = getFindUniqueForRef(parentRef, this.builder);
308
- const loaderCache = ModelLoader.forModel(this.model, this.builder);
309
310
 
310
311
  const { resolve, ...rest } = options;
311
312
 
313
+ const countSelect = {
314
+ _count: {
315
+ select: { [name]: true },
316
+ },
317
+ };
318
+
312
319
  return this.field({
313
320
  ...rest,
314
321
  type: 'Int',
315
322
  nullable: false,
316
- extensions: {
317
- ...options.extensions,
318
- pothosPrismaRelationCount: name,
319
- },
320
- resolve: (parent, args, context, info) => {
321
- const loadedValue = (parent as { _count: Record<string, unknown> })._count?.[name];
322
-
323
- if (loadedValue !== undefined) {
324
- return loadedValue as never;
325
- }
326
-
327
- if (resolve) {
328
- return resolve(parent, args, context, info) as never;
329
- }
330
-
331
- if (!findUnique) {
332
- throw new Error(`Missing findUnique for Prisma type ${this.model}`);
333
- }
334
-
335
- return loaderCache(parent).loadCount(name, context) as never;
336
- },
323
+ select: countSelect as never,
324
+ resolve: (parent, args, context, info) =>
325
+ (parent as unknown as { _count: Record<string, never> })._count?.[name],
337
326
  }) as FieldRef<number, 'Object'>;
338
327
  }
339
328
 
@@ -352,34 +341,87 @@ export class PrismaObjectFieldBuilder<
352
341
  const [variant, options = {} as never] = allArgs;
353
342
  const ref: PrismaObjectRef<PrismaModelTypes> =
354
343
  typeof variant === 'string' ? getRefFromModel(variant, this.builder) : variant;
355
- const parentRef = getRefFromModel(this.model, this.builder);
356
- const findUnique = getFindUniqueForRef(parentRef, this.builder);
357
- const loaderCache = ModelLoader.forModel(this.model, this.builder);
344
+
345
+ const selfSelect = (args: object, context: object, nestedQuery: (query: unknown) => unknown) =>
346
+ nestedQuery({});
358
347
 
359
348
  return this.field({
360
349
  ...options,
361
350
  type: ref,
362
- extensions: {
363
- ...options.extensions,
364
- pothosPrismaRelation: SELF_RELATION,
365
- },
366
- resolve: (parent, args, context, info) => {
367
- const mapping = getLoaderMapping(context, info.path);
351
+ select: selfSelect as never,
352
+ resolve: (parent, args, context, info) => parent,
353
+ }) as FieldRef<Model['Shape'], 'Object'>;
354
+ }
368
355
 
369
- if (mapping) {
370
- setLoaderMappings(context, info.path, mapping);
356
+ expose<
357
+ Type extends TypeParam<Types>,
358
+ Nullable extends boolean,
359
+ ResolveReturnShape,
360
+ Name extends CompatibleTypes<Types, Model['Shape'], Type, Nullable>,
361
+ >(
362
+ ...args: NormalizeArgs<
363
+ [
364
+ name: Name,
365
+ options?: Omit<
366
+ PothosSchemaTypes.ObjectFieldOptions<
367
+ Types,
368
+ Shape,
369
+ Type,
370
+ Nullable,
371
+ {},
372
+ ResolveReturnShape
373
+ >,
374
+ 'resolve' | 'select'
375
+ >,
376
+ ]
377
+ >
378
+ ) {
379
+ const [name, options = {} as never] = args;
371
380
 
372
- return parent as never;
373
- }
381
+ const typeConfig = this.builder.configStore.getTypeConfig(this.typename, 'Object');
382
+ const usingSelect = !!typeConfig.extensions?.pothosPrismaSelect;
374
383
 
375
- const queryOptions = queryFromInfo(context, info);
384
+ return this.exposeField(name as never, {
385
+ ...options,
386
+ extensions: {
387
+ ...options.extensions,
388
+ pothosPrismaVariant: name,
389
+ pothosPrismaSelect: usingSelect && {
390
+ [name]: true,
391
+ },
392
+ },
393
+ });
394
+ }
376
395
 
377
- if (!findUnique) {
378
- throw new Error(`Missing findUnique for Prisma type ${this.model}`);
379
- }
396
+ private createExpose<Type extends TypeParam<Types>>(type: Type) {
397
+ return <
398
+ Nullable extends boolean,
399
+ ResolveReturnShape,
400
+ Name extends CompatibleTypes<Types, Model['Shape'], Type, Nullable>,
401
+ >(
402
+ ...args: NormalizeArgs<
403
+ [
404
+ name: Name,
405
+ options?: Omit<
406
+ PothosSchemaTypes.ObjectFieldOptions<
407
+ Types,
408
+ Shape,
409
+ Type,
410
+ Nullable,
411
+ {},
412
+ ResolveReturnShape
413
+ >,
414
+ 'resolve' | 'type' | 'select'
415
+ >,
416
+ ]
417
+ >
418
+ ) => {
419
+ const [name, options = {} as never] = args;
380
420
 
381
- return loaderCache(parent).loadSelf(queryOptions, context) as never;
382
- },
383
- }) as FieldRef<Model['Shape'], 'Object'>;
421
+ return this.expose(name as never, {
422
+ ...options,
423
+ type,
424
+ });
425
+ };
384
426
  }
385
427
  }
@@ -10,21 +10,22 @@ import SchemaBuilder, {
10
10
  TypeParam,
11
11
  } from '@pothos/core';
12
12
  import { PrismaObjectFieldBuilder } from './field-builder';
13
+ import { ModelLoader } from './model-loader';
13
14
  import PrismaNodeRef from './node-ref';
14
- import { getDelegateFromModel, getRefFromModel, setFindUniqueForRef } from './refs';
15
- import { ModelTypes, PrismaDelegate, PrismaNodeOptions } from './types';
16
- import { queryFromInfo } from './util';
15
+ import { PrismaModelTypes, PrismaNodeOptions } from './types';
16
+ import { getDelegateFromModel, getRefFromModel } from './util/datamodel';
17
+ import { queryFromInfo } from './util/map-query';
18
+ import { getRelationMap } from './util/relation-map';
17
19
 
18
20
  const schemaBuilderProto = SchemaBuilder.prototype as PothosSchemaTypes.SchemaBuilder<SchemaTypes>;
19
21
 
20
22
  schemaBuilderProto.prismaObject = function prismaObject(type, { fields, findUnique, ...options }) {
21
23
  const ref = options.variant ? this.objectRef(options.variant) : getRefFromModel(type, this);
22
24
  const name = options.variant ?? options.name ?? type;
25
+ const fieldMap = getRelationMap(this.options.prisma.client).get(type)!;
23
26
 
24
27
  ref.name = name;
25
28
 
26
- setFindUniqueForRef(ref, this, findUnique);
27
-
28
29
  this.objectType(ref, {
29
30
  ...(options as {} as PothosSchemaTypes.ObjectFieldOptions<
30
31
  SchemaTypes,
@@ -38,9 +39,29 @@ schemaBuilderProto.prismaObject = function prismaObject(type, { fields, findUniq
38
39
  ...options.extensions,
39
40
  pothosPrismaInclude: options.include,
40
41
  pothosPrismaModel: type,
42
+ pothosPrismaFieldMap: fieldMap,
43
+ pothosPrismaSelect: options.select,
44
+ pothosPrismaLoader: ModelLoader.forRef(
45
+ type,
46
+ (findUnique as never) ||
47
+ (() => {
48
+ throw new Error(`Missing findUnique for ${ref.name}`);
49
+ }),
50
+ this,
51
+ ),
41
52
  },
42
53
  name,
43
- fields: fields ? () => fields(new PrismaObjectFieldBuilder(name, this, type)) : undefined,
54
+ fields: fields
55
+ ? () =>
56
+ fields(
57
+ new PrismaObjectFieldBuilder(
58
+ name,
59
+ this,
60
+ type,
61
+ getRelationMap(this.options.prisma.client).get(type)!,
62
+ ),
63
+ )
64
+ : undefined,
44
65
  });
45
66
 
46
67
  return ref as never;
@@ -56,7 +77,7 @@ schemaBuilderProto.prismaNode = function prismaNode(
56
77
  name,
57
78
  variant,
58
79
  ...options
59
- }: PrismaNodeOptions<SchemaTypes, ModelTypes<PrismaDelegate>, [], never, {}>,
80
+ }: PrismaNodeOptions<SchemaTypes, PrismaModelTypes, [], never, {}, {}>,
60
81
  ) {
61
82
  const interfaceRef = this.nodeInterfaceRef?.();
62
83