@pothos/plugin-drizzle 0.0.1

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 (179) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +6 -0
  3. package/README.md +437 -0
  4. package/TODO.md +21 -0
  5. package/drizzle/meta/_journal.json +1 -0
  6. package/drizzle.config.ts +10 -0
  7. package/dts/drizzle-field-builder.d.ts +124 -0
  8. package/dts/drizzle-field-builder.d.ts.map +1 -0
  9. package/dts/field-builder.d.ts +2 -0
  10. package/dts/field-builder.d.ts.map +1 -0
  11. package/dts/global-types.d.ts +92 -0
  12. package/dts/global-types.d.ts.map +1 -0
  13. package/dts/index.d.ts +13 -0
  14. package/dts/index.d.ts.map +1 -0
  15. package/dts/interface-ref.d.ts +9 -0
  16. package/dts/interface-ref.d.ts.map +1 -0
  17. package/dts/model-loader.d.ts +44 -0
  18. package/dts/model-loader.d.ts.map +1 -0
  19. package/dts/node-ref.d.ts +5 -0
  20. package/dts/node-ref.d.ts.map +1 -0
  21. package/dts/object-ref.d.ts +14 -0
  22. package/dts/object-ref.d.ts.map +1 -0
  23. package/dts/schema-builder.d.ts +2 -0
  24. package/dts/schema-builder.d.ts.map +1 -0
  25. package/dts/types.d.ts +147 -0
  26. package/dts/types.d.ts.map +1 -0
  27. package/dts/utils/config.d.ts +7 -0
  28. package/dts/utils/config.d.ts.map +1 -0
  29. package/dts/utils/cursors.d.ts +58 -0
  30. package/dts/utils/cursors.d.ts.map +1 -0
  31. package/dts/utils/deep-equal.d.ts +2 -0
  32. package/dts/utils/deep-equal.d.ts.map +1 -0
  33. package/dts/utils/drizzle-graphql.d.ts +18 -0
  34. package/dts/utils/drizzle-graphql.d.ts.map +1 -0
  35. package/dts/utils/loader-map.d.ts +11 -0
  36. package/dts/utils/loader-map.d.ts.map +1 -0
  37. package/dts/utils/map-query.d.ts +30 -0
  38. package/dts/utils/map-query.d.ts.map +1 -0
  39. package/dts/utils/refs.d.ts +5 -0
  40. package/dts/utils/refs.d.ts.map +1 -0
  41. package/dts/utils/selections.d.ts +22 -0
  42. package/dts/utils/selections.d.ts.map +1 -0
  43. package/dts/utils/usage.d.ts +5 -0
  44. package/dts/utils/usage.d.ts.map +1 -0
  45. package/esm/drizzle-field-builder.d.ts +216 -0
  46. package/esm/drizzle-field-builder.d.ts.map +1 -0
  47. package/esm/field-builder.d.ts +2 -0
  48. package/esm/field-builder.d.ts.map +1 -0
  49. package/esm/global-types.d.ts +124 -0
  50. package/esm/global-types.d.ts.map +1 -0
  51. package/esm/index.d.ts +13 -0
  52. package/esm/index.d.ts.map +1 -0
  53. package/esm/interface-ref.d.ts +9 -0
  54. package/esm/interface-ref.d.ts.map +1 -0
  55. package/esm/model-loader.d.ts +45 -0
  56. package/esm/model-loader.d.ts.map +1 -0
  57. package/esm/node-ref.d.ts +5 -0
  58. package/esm/node-ref.d.ts.map +1 -0
  59. package/esm/object-ref.d.ts +14 -0
  60. package/esm/object-ref.d.ts.map +1 -0
  61. package/esm/package.json +3 -0
  62. package/esm/schema-builder.d.ts +2 -0
  63. package/esm/schema-builder.d.ts.map +1 -0
  64. package/esm/src/drizzle-field-builder.js +215 -0
  65. package/esm/src/drizzle-field-builder.js.map +1 -0
  66. package/esm/src/field-builder.js +77 -0
  67. package/esm/src/field-builder.js.map +1 -0
  68. package/esm/src/global-types.js +2 -0
  69. package/esm/src/global-types.js.map +1 -0
  70. package/esm/src/index.js +107 -0
  71. package/esm/src/index.js.map +1 -0
  72. package/esm/src/interface-ref.js +26 -0
  73. package/esm/src/interface-ref.js.map +1 -0
  74. package/esm/src/model-loader.js +168 -0
  75. package/esm/src/model-loader.js.map +1 -0
  76. package/esm/src/node-ref.js +4 -0
  77. package/esm/src/node-ref.js.map +1 -0
  78. package/esm/src/object-ref.js +38 -0
  79. package/esm/src/object-ref.js.map +1 -0
  80. package/esm/src/schema-builder.js +190 -0
  81. package/esm/src/schema-builder.js.map +1 -0
  82. package/esm/src/types.js +2 -0
  83. package/esm/src/types.js.map +1 -0
  84. package/esm/src/utils/config.js +15 -0
  85. package/esm/src/utils/config.js.map +1 -0
  86. package/esm/src/utils/cursors.js +316 -0
  87. package/esm/src/utils/cursors.js.map +1 -0
  88. package/esm/src/utils/deep-equal.js +44 -0
  89. package/esm/src/utils/deep-equal.js.map +1 -0
  90. package/esm/src/utils/drizzle-graphql.js +176 -0
  91. package/esm/src/utils/drizzle-graphql.js.map +1 -0
  92. package/esm/src/utils/loader-map.js +35 -0
  93. package/esm/src/utils/loader-map.js.map +1 -0
  94. package/esm/src/utils/map-query.js +284 -0
  95. package/esm/src/utils/map-query.js.map +1 -0
  96. package/esm/src/utils/refs.js +14 -0
  97. package/esm/src/utils/refs.js.map +1 -0
  98. package/esm/src/utils/selections.js +136 -0
  99. package/esm/src/utils/selections.js.map +1 -0
  100. package/esm/src/utils/usage.js +59 -0
  101. package/esm/src/utils/usage.js.map +1 -0
  102. package/esm/types.d.ts +161 -0
  103. package/esm/types.d.ts.map +1 -0
  104. package/esm/utils/config.d.ts +7 -0
  105. package/esm/utils/config.d.ts.map +1 -0
  106. package/esm/utils/cursors.d.ts +58 -0
  107. package/esm/utils/cursors.d.ts.map +1 -0
  108. package/esm/utils/deep-equal.d.ts +2 -0
  109. package/esm/utils/deep-equal.d.ts.map +1 -0
  110. package/esm/utils/drizzle-graphql.d.ts +18 -0
  111. package/esm/utils/drizzle-graphql.d.ts.map +1 -0
  112. package/esm/utils/loader-map.d.ts +11 -0
  113. package/esm/utils/loader-map.d.ts.map +1 -0
  114. package/esm/utils/map-query.d.ts +30 -0
  115. package/esm/utils/map-query.d.ts.map +1 -0
  116. package/esm/utils/refs.d.ts +5 -0
  117. package/esm/utils/refs.d.ts.map +1 -0
  118. package/esm/utils/selections.d.ts +22 -0
  119. package/esm/utils/selections.d.ts.map +1 -0
  120. package/esm/utils/usage.d.ts +5 -0
  121. package/esm/utils/usage.d.ts.map +1 -0
  122. package/lib/src/drizzle-field-builder.js +225 -0
  123. package/lib/src/drizzle-field-builder.js.map +1 -0
  124. package/lib/src/field-builder.js +82 -0
  125. package/lib/src/field-builder.js.map +1 -0
  126. package/lib/src/global-types.js +6 -0
  127. package/lib/src/global-types.js.map +1 -0
  128. package/lib/src/index.js +180 -0
  129. package/lib/src/index.js.map +1 -0
  130. package/lib/src/interface-ref.js +36 -0
  131. package/lib/src/interface-ref.js.map +1 -0
  132. package/lib/src/model-loader.js +176 -0
  133. package/lib/src/model-loader.js.map +1 -0
  134. package/lib/src/node-ref.js +15 -0
  135. package/lib/src/node-ref.js.map +1 -0
  136. package/lib/src/object-ref.js +56 -0
  137. package/lib/src/object-ref.js.map +1 -0
  138. package/lib/src/schema-builder.js +236 -0
  139. package/lib/src/schema-builder.js.map +1 -0
  140. package/lib/src/types.js +13 -0
  141. package/lib/src/types.js.map +1 -0
  142. package/lib/src/utils/config.js +26 -0
  143. package/lib/src/utils/config.js.map +1 -0
  144. package/lib/src/utils/cursors.js +362 -0
  145. package/lib/src/utils/cursors.js.map +1 -0
  146. package/lib/src/utils/deep-equal.js +55 -0
  147. package/lib/src/utils/deep-equal.js.map +1 -0
  148. package/lib/src/utils/drizzle-graphql.js +192 -0
  149. package/lib/src/utils/drizzle-graphql.js.map +1 -0
  150. package/lib/src/utils/loader-map.js +57 -0
  151. package/lib/src/utils/loader-map.js.map +1 -0
  152. package/lib/src/utils/map-query.js +308 -0
  153. package/lib/src/utils/map-query.js.map +1 -0
  154. package/lib/src/utils/refs.js +33 -0
  155. package/lib/src/utils/refs.js.map +1 -0
  156. package/lib/src/utils/selections.js +163 -0
  157. package/lib/src/utils/selections.js.map +1 -0
  158. package/lib/src/utils/usage.js +84 -0
  159. package/lib/src/utils/usage.js.map +1 -0
  160. package/package.json +66 -0
  161. package/src/drizzle-field-builder.ts +500 -0
  162. package/src/field-builder.ts +168 -0
  163. package/src/global-types.ts +481 -0
  164. package/src/index.ts +175 -0
  165. package/src/interface-ref.ts +24 -0
  166. package/src/model-loader.ts +235 -0
  167. package/src/node-ref.ts +8 -0
  168. package/src/object-ref.ts +51 -0
  169. package/src/schema-builder.ts +299 -0
  170. package/src/types.ts +640 -0
  171. package/src/utils/config.ts +28 -0
  172. package/src/utils/cursors.ts +446 -0
  173. package/src/utils/deep-equal.ts +58 -0
  174. package/src/utils/drizzle-graphql.ts +235 -0
  175. package/src/utils/loader-map.ts +51 -0
  176. package/src/utils/map-query.ts +582 -0
  177. package/src/utils/refs.ts +25 -0
  178. package/src/utils/selections.ts +209 -0
  179. package/src/utils/usage.ts +64 -0
@@ -0,0 +1,582 @@
1
+ /* eslint-disable no-continue */
2
+ import {
3
+ DBQueryConfig,
4
+ RelationalSchemaConfig,
5
+ TableRelationalConfig,
6
+ TablesRelationalConfig,
7
+ } from 'drizzle-orm';
8
+ import {
9
+ FieldNode,
10
+ FragmentDefinitionNode,
11
+ getArgumentValues,
12
+ getDirectiveValues,
13
+ getNamedType,
14
+ GraphQLField,
15
+ GraphQLIncludeDirective,
16
+ GraphQLInterfaceType,
17
+ GraphQLNamedType,
18
+ GraphQLObjectType,
19
+ GraphQLResolveInfo,
20
+ GraphQLSkipDirective,
21
+ InlineFragmentNode,
22
+ isInterfaceType,
23
+ isObjectType,
24
+ Kind,
25
+ SelectionSetNode,
26
+ } from 'graphql';
27
+ import { PothosValidationError } from '@pothos/core';
28
+ import { type DrizzleFieldSelection } from '../types';
29
+ import { LoaderMappings, setLoaderMappings } from './loader-map';
30
+ import {
31
+ createState,
32
+ mergeSelection,
33
+ selectionCompatible,
34
+ SelectionMap,
35
+ SelectionState,
36
+ selectionToQuery,
37
+ } from './selections';
38
+ import { wrapWithUsageCheck } from './usage';
39
+ import { PothosDrizzleSchemaConfig } from './config';
40
+
41
+ export interface IndirectInclude {
42
+ getType: () => string;
43
+ path?: { type?: string; name: string }[];
44
+ paths?: { type?: string; name: string }[][];
45
+ }
46
+
47
+ function addTypeSelectionsForField(
48
+ config: PothosDrizzleSchemaConfig,
49
+ type: GraphQLNamedType,
50
+ context: object,
51
+ info: GraphQLResolveInfo,
52
+ state: SelectionState,
53
+ selection: FieldNode,
54
+ indirectPath: string[],
55
+ ) {
56
+ if (selection.name.value.startsWith('__')) {
57
+ return;
58
+ }
59
+
60
+ const { pothosDrizzleSelect, pothosIndirectInclude } = (type.extensions ?? {}) as {
61
+ pothosIndirectInclude?: IndirectInclude;
62
+ pothosDrizzleSelect?: DBQueryConfig<'one', false>;
63
+ };
64
+
65
+ if (
66
+ (!!pothosIndirectInclude?.path && pothosIndirectInclude.path.length > 0) ||
67
+ (!!pothosIndirectInclude?.paths && pothosIndirectInclude.paths.length === 0)
68
+ ) {
69
+ resolveIndirectIncludePaths(
70
+ type,
71
+ info,
72
+ selection,
73
+ [],
74
+ pothosIndirectInclude.paths ?? [pothosIndirectInclude.path!],
75
+ indirectPath,
76
+ (resolvedType, field, path) => {
77
+ addTypeSelectionsForField(config, resolvedType, context, info, state, field, path);
78
+ },
79
+ );
80
+ } else if (pothosIndirectInclude) {
81
+ addTypeSelectionsForField(
82
+ config,
83
+ info.schema.getType(pothosIndirectInclude.getType())!,
84
+ context,
85
+ info,
86
+ state,
87
+ selection,
88
+ indirectPath,
89
+ );
90
+ return;
91
+ }
92
+
93
+ if (!(isObjectType(type) || isInterfaceType(type))) {
94
+ return;
95
+ }
96
+
97
+ if (pothosDrizzleSelect) {
98
+ mergeSelection(config, state, { ...pothosDrizzleSelect });
99
+ }
100
+
101
+ if (selection.selectionSet) {
102
+ addNestedSelections(config, type, context, info, state, selection.selectionSet, indirectPath);
103
+ }
104
+ }
105
+
106
+ function resolveIndirectIncludePaths(
107
+ type: GraphQLNamedType,
108
+ info: GraphQLResolveInfo,
109
+ selection: FieldNode | FragmentDefinitionNode | InlineFragmentNode,
110
+ pathPrefix: { type?: string; name: string }[],
111
+ includePaths: { type?: string; name: string }[][],
112
+ path: string[],
113
+ resolve: (type: GraphQLNamedType, field: FieldNode, path: string[]) => void,
114
+ ) {
115
+ for (const includePath of includePaths) {
116
+ if (pathPrefix.length > 0) {
117
+ resolveIndirectInclude(type, info, selection, [...pathPrefix, ...includePath], path, resolve);
118
+ } else {
119
+ resolveIndirectInclude(type, info, selection, includePath, path, resolve);
120
+ }
121
+ }
122
+ }
123
+
124
+ function resolveIndirectInclude(
125
+ type: GraphQLNamedType,
126
+ info: GraphQLResolveInfo,
127
+ selection: FieldNode | FragmentDefinitionNode | InlineFragmentNode,
128
+ includePath: { type?: string; name: string }[],
129
+ path: string[],
130
+ resolve: (type: GraphQLNamedType, field: FieldNode, path: string[]) => void,
131
+ ) {
132
+ if (includePath.length === 0) {
133
+ resolve(type, selection as FieldNode, path);
134
+ return;
135
+ }
136
+
137
+ const [include, ...rest] = includePath;
138
+ if (!selection.selectionSet || !include) {
139
+ return;
140
+ }
141
+
142
+ for (const sel of selection.selectionSet.selections) {
143
+ switch (sel.kind) {
144
+ case Kind.FIELD:
145
+ if (
146
+ !fieldSkipped(info, sel) &&
147
+ sel.name.value === include.name &&
148
+ (isObjectType(type) || isInterfaceType(type))
149
+ ) {
150
+ const returnType = getNamedType(type.getFields()[sel.name.value].type);
151
+
152
+ resolveIndirectInclude(
153
+ returnType,
154
+ info,
155
+ sel,
156
+ rest,
157
+ [...path, sel.alias?.value ?? sel.name.value],
158
+ resolve,
159
+ );
160
+ }
161
+ continue;
162
+ case Kind.FRAGMENT_SPREAD:
163
+ if (
164
+ !include.type ||
165
+ info.fragments[sel.name.value].typeCondition.name.value === include.type
166
+ ) {
167
+ resolveIndirectInclude(
168
+ include.type ? info.schema.getType(include.type)! : type,
169
+ info,
170
+ info.fragments[sel.name.value],
171
+ includePath,
172
+ path,
173
+ resolve,
174
+ );
175
+ }
176
+
177
+ continue;
178
+
179
+ case Kind.INLINE_FRAGMENT:
180
+ if (!sel.typeCondition || !include.type || sel.typeCondition.name.value === include.type) {
181
+ resolveIndirectInclude(
182
+ sel.typeCondition ? info.schema.getType(sel.typeCondition.name.value)! : type,
183
+ info,
184
+ sel,
185
+ includePath,
186
+ path,
187
+ resolve,
188
+ );
189
+ }
190
+
191
+ continue;
192
+
193
+ default:
194
+ throw new PothosValidationError(
195
+ `Unsupported selection kind ${(selection as { kind: string }).kind}`,
196
+ );
197
+ }
198
+ }
199
+ }
200
+
201
+ function addNestedSelections(
202
+ config: PothosDrizzleSchemaConfig,
203
+ type: GraphQLInterfaceType | GraphQLObjectType,
204
+ context: object,
205
+ info: GraphQLResolveInfo,
206
+ state: SelectionState,
207
+ selections: SelectionSetNode,
208
+ indirectPath: string[],
209
+ ) {
210
+ let parentType = type;
211
+ for (const selection of selections.selections) {
212
+ switch (selection.kind) {
213
+ case Kind.FIELD:
214
+ addFieldSelection(config, type, context, info, state, selection, indirectPath);
215
+
216
+ continue;
217
+ case Kind.FRAGMENT_SPREAD:
218
+ parentType = info.schema.getType(
219
+ info.fragments[selection.name.value].typeCondition.name.value,
220
+ )! as GraphQLObjectType;
221
+ if (
222
+ isObjectType(type)
223
+ ? parentType.name !== type.name
224
+ : parentType.extensions?.pothosDrizzleModel !== type.extensions.pothosDrizzleModel
225
+ ) {
226
+ continue;
227
+ }
228
+
229
+ addNestedSelections(
230
+ config,
231
+ parentType,
232
+ context,
233
+ info,
234
+ state,
235
+ info.fragments[selection.name.value].selectionSet,
236
+ indirectPath,
237
+ );
238
+
239
+ continue;
240
+
241
+ case Kind.INLINE_FRAGMENT:
242
+ parentType = selection.typeCondition
243
+ ? (info.schema.getType(selection.typeCondition.name.value) as GraphQLObjectType)
244
+ : type;
245
+ if (
246
+ isObjectType(type)
247
+ ? parentType.name !== type.name
248
+ : parentType.extensions?.pothosDrizzleModel !== type.extensions.pothosDrizzleModel
249
+ ) {
250
+ continue;
251
+ }
252
+
253
+ addNestedSelections(
254
+ config,
255
+ parentType,
256
+ context,
257
+ info,
258
+ state,
259
+ selection.selectionSet,
260
+ indirectPath,
261
+ );
262
+
263
+ continue;
264
+
265
+ default:
266
+ throw new PothosValidationError(
267
+ `Unsupported selection kind ${(selection as { kind: string }).kind}`,
268
+ );
269
+ }
270
+ }
271
+ }
272
+
273
+ function addFieldSelection(
274
+ config: PothosDrizzleSchemaConfig,
275
+ type: GraphQLInterfaceType | GraphQLObjectType,
276
+ context: object,
277
+ info: GraphQLResolveInfo,
278
+ state: SelectionState,
279
+ selection: FieldNode,
280
+ indirectPath: string[],
281
+ ) {
282
+ if (selection.name.value.startsWith('__') || fieldSkipped(info, selection)) {
283
+ return;
284
+ }
285
+ const field = type.getFields()[selection.name.value];
286
+ if (!field) {
287
+ throw new PothosValidationError(`Unknown field ${selection.name.value} on ${type.name}`);
288
+ }
289
+
290
+ const fieldSelect = field.extensions?.pothosDrizzleSelect as DrizzleFieldSelection | undefined;
291
+
292
+ let fieldSelectionMap: DBQueryConfig<'one', false> | undefined;
293
+ let mappings: LoaderMappings = {};
294
+ if (typeof fieldSelect === 'function') {
295
+ const args = getArgumentValues(field, selection, info.variableValues) as Record<
296
+ string,
297
+ unknown
298
+ >;
299
+ fieldSelectionMap = fieldSelect(
300
+ args,
301
+ context,
302
+ (rawQuery, indirectInclude, expectedType) => {
303
+ const returnType = getNamedType(field.type);
304
+ const query = typeof rawQuery === 'function' ? rawQuery(args, context) : rawQuery;
305
+ const normalizedIndirectInclude = Array.isArray(indirectInclude)
306
+ ? normalizeInclude(
307
+ indirectInclude,
308
+ getIndirectType(returnType, info),
309
+ expectedType ? getNamedType(info.schema.getType(expectedType)) : undefined,
310
+ )
311
+ : indirectInclude;
312
+ const fieldState = createStateForSelection(
313
+ config,
314
+ getIndirectType(
315
+ normalizedIndirectInclude
316
+ ? info.schema.getType(normalizedIndirectInclude.getType())!
317
+ : returnType,
318
+ info,
319
+ ),
320
+ state,
321
+ );
322
+
323
+ if (typeof query === 'object' && Object.keys(query).length > 0) {
324
+ mergeSelection(config, fieldState, { columns: {}, ...query });
325
+ }
326
+ if (
327
+ (!!normalizedIndirectInclude?.path && normalizedIndirectInclude.path.length > 0) ||
328
+ (!!normalizedIndirectInclude?.paths && normalizedIndirectInclude.paths.length > 0)
329
+ ) {
330
+ resolveIndirectIncludePaths(
331
+ returnType,
332
+ info,
333
+ selection,
334
+ (returnType.extensions?.pothosIndirectInclude as { path: [] })?.path ?? [],
335
+ normalizedIndirectInclude.paths ?? [normalizedIndirectInclude.path!],
336
+ [],
337
+ (resolvedType, resolvedField, path) => {
338
+ addTypeSelectionsForField(
339
+ config,
340
+ resolvedType,
341
+ context,
342
+ info,
343
+ fieldState,
344
+ resolvedField,
345
+ path,
346
+ );
347
+ },
348
+ );
349
+ }
350
+ addTypeSelectionsForField(config, returnType, context, info, fieldState, selection, []);
351
+ // eslint-disable-next-line prefer-destructuring
352
+ mappings = fieldState.mappings;
353
+ return selectionToQuery(fieldState);
354
+ },
355
+ (path) => {
356
+ const returnType = getNamedType(field.type);
357
+ let node: FieldNode | null = null;
358
+ resolveIndirectInclude(
359
+ returnType,
360
+ info,
361
+ selection,
362
+ path.map((name) => ({
363
+ name,
364
+ })),
365
+ [],
366
+ (_, resolvedField) => {
367
+ node = resolvedField;
368
+ },
369
+ );
370
+ return node;
371
+ },
372
+ );
373
+ } else {
374
+ fieldSelectionMap = fieldSelect!;
375
+ }
376
+
377
+ if (fieldSelect && selectionCompatible(state, fieldSelectionMap, true)) {
378
+ mergeSelection(config, state, fieldSelectionMap);
379
+ // eslint-disable-next-line no-param-reassign
380
+ state.mappings[selection.alias?.value ?? selection.name.value] = {
381
+ field: selection.name.value,
382
+ type: type.name,
383
+ mappings,
384
+ indirectPath,
385
+ };
386
+ }
387
+ }
388
+
389
+ export interface QueryFromInfoOptions<T extends SelectionMap> {
390
+ config: PothosDrizzleSchemaConfig;
391
+ context: object;
392
+ info: GraphQLResolveInfo;
393
+ typeName?: string;
394
+ select?: T;
395
+ path?: string[];
396
+ paths?: string[][];
397
+ withUsageCheck?: boolean;
398
+ }
399
+
400
+ export function queryFromInfo<T extends SelectionMap>({
401
+ withUsageCheck,
402
+ ...options
403
+ }: QueryFromInfoOptions<T>): T {
404
+ const state = stateFromInfo(options);
405
+
406
+ setLoaderMappings(options.context, options.info, state.mappings);
407
+
408
+ const query = selectionToQuery(state) as T;
409
+
410
+ return withUsageCheck ? wrapWithUsageCheck(query) : query;
411
+ }
412
+
413
+ export function stateFromInfo<T extends SelectionMap>({
414
+ config,
415
+ context,
416
+ info,
417
+ typeName,
418
+ select,
419
+ path = [],
420
+ paths = [],
421
+ }: QueryFromInfoOptions<T>) {
422
+ const returnType = getNamedType(info.returnType);
423
+ const type = typeName ? info.schema.getTypeMap()[typeName] : returnType;
424
+
425
+ let state: SelectionState | undefined;
426
+
427
+ if (path.length > 0 || paths.length > 0) {
428
+ const { pothosIndirectInclude } = (returnType.extensions ?? {}) as {
429
+ pothosIndirectInclude?: IndirectInclude;
430
+ };
431
+
432
+ resolveIndirectInclude(
433
+ returnType,
434
+ info,
435
+ info.fieldNodes[0],
436
+ pothosIndirectInclude?.path ?? [],
437
+ [],
438
+ (indirectType, indirectField, subPath) => {
439
+ resolveIndirectIncludePaths(
440
+ indirectType,
441
+ info,
442
+ indirectField,
443
+ [],
444
+ paths.length > 0
445
+ ? paths.map((p) => p.map((n) => (typeof n === 'string' ? { name: n } : n)))
446
+ : [path.map((n) => (typeof n === 'string' ? { name: n } : n))],
447
+ subPath,
448
+ (resolvedType, resolvedField, nested) => {
449
+ state = createStateForSelection(config, resolvedType, undefined, select);
450
+
451
+ addTypeSelectionsForField(
452
+ config,
453
+ typeName ? type : resolvedType,
454
+ context,
455
+ info,
456
+ state,
457
+ resolvedField,
458
+ nested,
459
+ );
460
+ },
461
+ );
462
+ },
463
+ );
464
+ } else {
465
+ state = createStateForSelection(config, type, undefined, select);
466
+
467
+ addTypeSelectionsForField(config, type, context, info, state, info.fieldNodes[0], []);
468
+ }
469
+
470
+ if (!state) {
471
+ state = createStateForSelection(config, type, undefined, select);
472
+ }
473
+
474
+ return state;
475
+ }
476
+
477
+ export function selectionStateFromInfo(
478
+ config: PothosDrizzleSchemaConfig,
479
+ context: object,
480
+ info: GraphQLResolveInfo,
481
+ typeName?: string,
482
+ ) {
483
+ const type = typeName ? info.schema.getTypeMap()[typeName] : info.parentType;
484
+
485
+ const state = createStateForSelection(config, type);
486
+
487
+ if (!(isObjectType(type) || isInterfaceType(type))) {
488
+ throw new PothosValidationError(
489
+ 'Drizzle plugin can only resolve selections for object and interface types',
490
+ );
491
+ }
492
+
493
+ addFieldSelection(config, type, context, info, state, info.fieldNodes[0], []);
494
+
495
+ return state;
496
+ }
497
+
498
+ function createStateForSelection(
499
+ config: PothosDrizzleSchemaConfig,
500
+ type: GraphQLNamedType,
501
+ parent?: SelectionState,
502
+ initialSelections?: SelectionMap,
503
+ ) {
504
+ const { pothosDrizzleTable } = (type.extensions ?? {}) as {
505
+ pothosDrizzleTable?: TableRelationalConfig;
506
+ };
507
+
508
+ if (!pothosDrizzleTable) {
509
+ throw new PothosValidationError(`Expected ${type.name} to have a table config`);
510
+ }
511
+
512
+ const state = createState(pothosDrizzleTable, parent);
513
+
514
+ if (initialSelections) {
515
+ mergeSelection(config, state, initialSelections);
516
+ }
517
+
518
+ return state;
519
+ }
520
+
521
+ export function getIndirectType(type: GraphQLNamedType, info: GraphQLResolveInfo) {
522
+ let targetType = type;
523
+
524
+ while (targetType.extensions?.pothosIndirectInclude) {
525
+ targetType = info.schema.getType(
526
+ (targetType.extensions?.pothosIndirectInclude as IndirectInclude).getType(),
527
+ )!;
528
+ }
529
+
530
+ return targetType;
531
+ }
532
+
533
+ export function normalizeInclude(
534
+ path: string[],
535
+ type: GraphQLNamedType,
536
+ expectedType?: GraphQLNamedType,
537
+ ): IndirectInclude {
538
+ let currentType = path.length > 0 ? type : expectedType ?? type;
539
+
540
+ const normalized: { name: string; type: string }[] = [];
541
+
542
+ if (!(isObjectType(currentType) || isInterfaceType(currentType))) {
543
+ throw new PothosValidationError(`Expected ${currentType} to be an Object type`);
544
+ }
545
+
546
+ for (const fieldName of path) {
547
+ const field: GraphQLField<unknown, unknown> = currentType.getFields()[fieldName];
548
+
549
+ if (!field) {
550
+ throw new PothosValidationError(`Expected ${currentType} to have a field ${fieldName}`);
551
+ }
552
+
553
+ currentType = getNamedType(field.type);
554
+
555
+ if (!(isObjectType(currentType) || isInterfaceType(currentType))) {
556
+ throw new PothosValidationError(`Expected ${currentType} to be an Object or Interface type`);
557
+ }
558
+
559
+ normalized.push({ name: fieldName, type: currentType.name });
560
+ }
561
+
562
+ return {
563
+ getType: () =>
564
+ expectedType?.name ??
565
+ (normalized.length > 0 ? normalized[normalized.length - 1].type : type.name),
566
+ path: normalized,
567
+ };
568
+ }
569
+
570
+ function fieldSkipped(info: GraphQLResolveInfo, selection: FieldNode) {
571
+ const skip = getDirectiveValues(GraphQLSkipDirective, selection, info.variableValues);
572
+ if (skip?.if === true) {
573
+ return true;
574
+ }
575
+
576
+ const include = getDirectiveValues(GraphQLIncludeDirective, selection, info.variableValues);
577
+ if (include?.if === false) {
578
+ return true;
579
+ }
580
+
581
+ return false;
582
+ }
@@ -0,0 +1,25 @@
1
+ import { SchemaTypes } from '@pothos/core';
2
+ import { DrizzleInterfaceRef, DrizzleRef } from '../interface-ref';
3
+ import { DrizzleObjectRef } from '../object-ref';
4
+
5
+ export const refMap = new WeakMap<object, Map<string, DrizzleRef<never>>>();
6
+
7
+ export function getRefFromModel<Types extends SchemaTypes>(
8
+ name: string,
9
+ builder: PothosSchemaTypes.SchemaBuilder<Types>,
10
+ type: 'interface' | 'object' = 'object',
11
+ ): DrizzleRef<Types> {
12
+ if (!refMap.has(builder)) {
13
+ refMap.set(builder, new Map());
14
+ }
15
+ const cache = refMap.get(builder)!;
16
+
17
+ if (!cache.has(name)) {
18
+ cache.set(
19
+ name,
20
+ type === 'object' ? new DrizzleObjectRef(name, name) : new DrizzleInterfaceRef(name, name),
21
+ );
22
+ }
23
+
24
+ return cache.get(name)! as never;
25
+ }