@pothos/plugin-prisma 3.36.0 → 3.38.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 (83) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +61 -44
  3. package/dts/connection-helpers.d.ts +17 -11
  4. package/dts/connection-helpers.d.ts.map +1 -1
  5. package/dts/index.d.ts +1 -1
  6. package/dts/index.d.ts.map +1 -1
  7. package/dts/prisma-field-builder.d.ts +2 -2
  8. package/dts/prisma-field-builder.d.ts.map +1 -1
  9. package/dts/types.d.ts +30 -30
  10. package/dts/types.d.ts.map +1 -1
  11. package/dts/util/cursors.d.ts +11 -5
  12. package/dts/util/cursors.d.ts.map +1 -1
  13. package/dts/util/relation-map.d.ts +1 -1
  14. package/dts/util/relation-map.d.ts.map +1 -1
  15. package/dts/util/selections.d.ts +1 -1
  16. package/dts/util/selections.d.ts.map +1 -1
  17. package/esm/connection-helpers.d.ts +17 -11
  18. package/esm/connection-helpers.d.ts.map +1 -1
  19. package/esm/connection-helpers.js +34 -2
  20. package/esm/connection-helpers.js.map +1 -1
  21. package/esm/field-builder.js +10 -10
  22. package/esm/field-builder.js.map +1 -1
  23. package/esm/generator.js +86 -74
  24. package/esm/generator.js.map +1 -1
  25. package/esm/index.d.ts +1 -1
  26. package/esm/index.d.ts.map +1 -1
  27. package/esm/index.js +5 -5
  28. package/esm/index.js.map +1 -1
  29. package/esm/model-loader.js +9 -9
  30. package/esm/model-loader.js.map +1 -1
  31. package/esm/prisma-field-builder.d.ts +2 -2
  32. package/esm/prisma-field-builder.d.ts.map +1 -1
  33. package/esm/prisma-field-builder.js +12 -12
  34. package/esm/prisma-field-builder.js.map +1 -1
  35. package/esm/schema-builder.js +13 -13
  36. package/esm/schema-builder.js.map +1 -1
  37. package/esm/types.d.ts +30 -30
  38. package/esm/types.d.ts.map +1 -1
  39. package/esm/util/cursors.d.ts +11 -5
  40. package/esm/util/cursors.d.ts.map +1 -1
  41. package/esm/util/cursors.js +33 -29
  42. package/esm/util/cursors.js.map +1 -1
  43. package/esm/util/get-client.js +2 -2
  44. package/esm/util/get-client.js.map +1 -1
  45. package/esm/util/loader-map.js +2 -2
  46. package/esm/util/loader-map.js.map +1 -1
  47. package/esm/util/map-query.js +24 -24
  48. package/esm/util/map-query.js.map +1 -1
  49. package/esm/util/relation-map.d.ts +1 -1
  50. package/esm/util/relation-map.d.ts.map +1 -1
  51. package/esm/util/selections.d.ts +1 -1
  52. package/esm/util/selections.d.ts.map +1 -1
  53. package/esm/util/selections.js +2 -2
  54. package/esm/util/selections.js.map +1 -1
  55. package/generated.ts +67 -0
  56. package/lib/connection-helpers.js +34 -2
  57. package/lib/connection-helpers.js.map +1 -1
  58. package/lib/field-builder.js +10 -10
  59. package/lib/field-builder.js.map +1 -1
  60. package/lib/generator.js +84 -72
  61. package/lib/generator.js.map +1 -1
  62. package/lib/index.js +5 -5
  63. package/lib/index.js.map +1 -1
  64. package/lib/model-loader.js +9 -9
  65. package/lib/model-loader.js.map +1 -1
  66. package/lib/prisma-field-builder.js +12 -12
  67. package/lib/prisma-field-builder.js.map +1 -1
  68. package/lib/schema-builder.js +13 -13
  69. package/lib/schema-builder.js.map +1 -1
  70. package/lib/util/cursors.js +33 -29
  71. package/lib/util/cursors.js.map +1 -1
  72. package/lib/util/get-client.js +2 -2
  73. package/lib/util/get-client.js.map +1 -1
  74. package/lib/util/loader-map.js +2 -2
  75. package/lib/util/loader-map.js.map +1 -1
  76. package/lib/util/map-query.js +24 -24
  77. package/lib/util/map-query.js.map +1 -1
  78. package/lib/util/selections.js +2 -2
  79. package/lib/util/selections.js.map +1 -1
  80. package/package.json +21 -11
  81. package/src/connection-helpers.ts +62 -5
  82. package/src/generator.ts +215 -193
  83. package/src/util/cursors.ts +8 -1
package/package.json CHANGED
@@ -1,17 +1,27 @@
1
1
  {
2
2
  "name": "@pothos/plugin-prisma",
3
- "version": "3.36.0",
3
+ "version": "3.38.0",
4
4
  "description": "A Pothos plugin for more efficient integration with prisma",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./dts/index.d.ts",
7
7
  "module": "./esm/index.js",
8
8
  "exports": {
9
- "import": {
10
- "default": "./esm/index.js"
9
+ ".": {
10
+ "import": {
11
+ "default": "./esm/index.js"
12
+ },
13
+ "require": {
14
+ "types": "./dts/index.d.ts",
15
+ "default": "./lib/index.js"
16
+ }
11
17
  },
12
- "require": {
13
- "types": "./dts/index.d.ts",
14
- "default": "./lib/index.js"
18
+ "./generated": {
19
+ "import": {
20
+ "default": "./esm/generated.ts"
21
+ },
22
+ "require": {
23
+ "default": "./generated.ts"
24
+ }
15
25
  }
16
26
  },
17
27
  "repository": {
@@ -40,7 +50,7 @@
40
50
  "access": "public"
41
51
  },
42
52
  "dependencies": {
43
- "@prisma/generator-helper": "^4.5.0"
53
+ "@prisma/generator-helper": "^4.7.1"
44
54
  },
45
55
  "prisma": {
46
56
  "seed": "node prisma/seed.mjs"
@@ -52,14 +62,14 @@
52
62
  "typescript": ">=4.7.2"
53
63
  },
54
64
  "devDependencies": {
55
- "@prisma/client": "^4.5.0",
65
+ "@prisma/client": "^4.7.1",
56
66
  "graphql": "16.6.0",
57
67
  "graphql-tag": "^2.12.6",
58
- "prisma": "^4.5.0",
59
- "@pothos/core": "3.23.0",
68
+ "prisma": "^4.7.1",
69
+ "@pothos/core": "3.23.1",
60
70
  "@pothos/plugin-complexity": "3.11.7",
61
71
  "@pothos/plugin-errors": "3.9.0",
62
- "@pothos/plugin-relay": "3.29.0",
72
+ "@pothos/plugin-relay": "3.30.0",
63
73
  "@pothos/plugin-simple-objects": "3.6.7",
64
74
  "@pothos/test-utils": "1.4.7"
65
75
  },
@@ -1,6 +1,7 @@
1
- import { SchemaTypes } from '@pothos/core';
1
+ import { ObjectRef, SchemaTypes } from '@pothos/core';
2
+ import { ModelLoader } from './model-loader';
2
3
  import { PrismaObjectRef } from './object-ref';
3
- import type { PrismaModelTypes } from './types';
4
+ import type { PrismaModelTypes, ShapeFromSelection } from './types';
4
5
  import {
5
6
  getCursorFormatter,
6
7
  getCursorParser,
@@ -8,41 +9,72 @@ import {
8
9
  wrapConnectionResult,
9
10
  } from './util/cursors';
10
11
  import { getRefFromModel } from './util/datamodel';
12
+ import { getDMMF } from './util/get-client';
13
+ import { getRelationMap } from './util/relation-map';
14
+ import { createState, mergeSelection, selectionToQuery } from './util/selections';
11
15
 
12
16
  export const prismaModelKey = Symbol.for('Pothos.prismaModelKey');
13
17
 
14
18
  export function prismaConnectionHelpers<
15
19
  Types extends SchemaTypes,
16
20
  RefOrType extends PrismaObjectRef<PrismaModelTypes> | keyof Types['PrismaTypes'],
21
+ Select extends Model['Select'] & {},
17
22
  Model extends PrismaModelTypes = RefOrType extends PrismaObjectRef<infer T>
18
23
  ? T & PrismaModelTypes
19
24
  : Types['PrismaTypes'][RefOrType & keyof Types['PrismaTypes']] & PrismaModelTypes,
20
25
  Shape = RefOrType extends PrismaObjectRef<PrismaModelTypes, infer T> ? T : Model['Shape'],
26
+ EdgeShape = Model['Include'] extends Select
27
+ ? Shape
28
+ : ShapeFromSelection<Model, { select: Select }>,
29
+ NodeShape = EdgeShape,
21
30
  >(
22
31
  builder: PothosSchemaTypes.SchemaBuilder<Types>,
23
32
  refOrType: RefOrType,
24
33
  options: {
25
34
  cursor: string & keyof Model['WhereUnique'];
35
+ select?: (nestedSelection: <T extends {} | true>(selection?: T) => T) => Select;
26
36
  defaultSize?:
27
37
  | number
28
38
  | ((args: PothosSchemaTypes.DefaultConnectionArguments, ctx: {}) => number);
29
39
  maxSize?: number | ((args: PothosSchemaTypes.DefaultConnectionArguments, ctx: {}) => number);
40
+ resolveNode?: (edge: EdgeShape) => NodeShape;
30
41
  },
31
42
  ) {
32
43
  const modelName =
33
44
  typeof refOrType === 'string' ? refOrType : (refOrType as PrismaObjectRef<Model>).modelName;
45
+ const ref =
46
+ typeof refOrType === 'string'
47
+ ? getRefFromModel(modelName, builder)
48
+ : (refOrType as ObjectRef<unknown>);
34
49
  const formatCursor = getCursorFormatter(modelName, builder, options.cursor);
35
50
  const parseCursor = getCursorParser(modelName, builder, options.cursor);
51
+ const cursorSelection = ModelLoader.getCursorSelection(ref, modelName, options.cursor, builder);
52
+ const fieldMap = getRelationMap(getDMMF(builder)).get(modelName)!;
36
53
 
37
54
  function resolve(
38
- list: (Shape & {})[],
55
+ list: (EdgeShape & {})[],
39
56
  args: PothosSchemaTypes.DefaultConnectionArguments,
40
57
  ctx: Types['Context'],
41
58
  ) {
42
- return wrapConnectionResult(list, args, getQuery(args, ctx).take, formatCursor);
59
+ return wrapConnectionResult(
60
+ list,
61
+ args,
62
+ getQueryArgs(args, ctx).take,
63
+ formatCursor,
64
+ null,
65
+ (options?.resolveNode as never) ?? ((edge: unknown) => edge),
66
+ ) as unknown as {
67
+ edges: (Omit<EdgeShape, 'cursor' | 'node'> & { node: NodeShape; cursor: string })[];
68
+ pageInfo: {
69
+ startCursor: string | null;
70
+ endCursor: string | null;
71
+ hasPreviousPage: boolean;
72
+ hasNextPage: boolean;
73
+ };
74
+ };
43
75
  }
44
76
 
45
- function getQuery(args: PothosSchemaTypes.DefaultConnectionArguments, ctx: Types['Context']) {
77
+ function getQueryArgs(args: PothosSchemaTypes.DefaultConnectionArguments, ctx: Types['Context']) {
46
78
  return prismaCursorConnectionQuery({
47
79
  args,
48
80
  ctx,
@@ -55,11 +87,36 @@ export function prismaConnectionHelpers<
55
87
  });
56
88
  }
57
89
 
90
+ function getQuery(
91
+ args: PothosSchemaTypes.DefaultConnectionArguments,
92
+ ctx: Types['Context'],
93
+ nestedSelection: <T extends true | {}>(selection?: T, path?: string[]) => T,
94
+ ) {
95
+ const nestedSelect: Record<string, unknown> | true = options.select
96
+ ? { select: options.select((sel) => nestedSelection(sel, ['edges', 'node'])) }
97
+ : nestedSelection(true, ['edges', 'node']);
98
+
99
+ const selectState = createState(fieldMap, 'select');
100
+
101
+ mergeSelection(selectState, { select: cursorSelection });
102
+
103
+ if (typeof nestedSelect === 'object' && nestedSelect) {
104
+ mergeSelection(selectState, nestedSelect);
105
+ }
106
+
107
+ return {
108
+ ...getQueryArgs(args, ctx),
109
+ ...selectionToQuery(selectState),
110
+ } as unknown as ReturnType<typeof getQueryArgs> &
111
+ (Model['Select'] extends Select ? {} : { select: Select });
112
+ }
113
+
58
114
  return {
59
115
  ref: (typeof refOrType === 'string'
60
116
  ? getRefFromModel(refOrType, builder)
61
117
  : refOrType) as PrismaObjectRef<Model>,
62
118
  resolve,
119
+ select: options.select ?? {},
63
120
  getQuery,
64
121
  };
65
122
  }
package/src/generator.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  import { mkdir, writeFile } from 'fs';
6
6
  import { dirname, resolve as resolvePath } from 'path';
7
7
  import ts, { ListFormat, ScriptKind, ScriptTarget, SyntaxKind, version } from 'typescript';
8
- import { generatorHandler } from '@prisma/generator-helper';
8
+ import { DMMF, generatorHandler } from '@prisma/generator-helper';
9
9
 
10
10
  const MIN_TS_VERSION = [4, 5, 2];
11
11
 
@@ -42,210 +42,232 @@ generatorHandler({
42
42
  options.otherGenerators.find((gen) => gen.provider.value === 'prisma-client-js')!.output!
43
43
  .value;
44
44
 
45
- const importStatement = ts.factory.createImportDeclaration(
46
- [],
47
- [],
48
- ts.factory.createImportClause(
49
- true,
50
- undefined,
51
- ts.factory.createNamedImports([
52
- ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier('Prisma')),
53
- ...options.dmmf.datamodel.models.map((model) =>
54
- ts.factory.createImportSpecifier(
55
- false,
56
- undefined,
57
- ts.factory.createIdentifier(model.name),
58
- ),
59
- ),
60
- ]),
61
- ),
62
- ts.factory.createStringLiteral(prismaLocation),
63
- );
45
+ const outputLocation = options.generator.output?.value ?? defaultOutput;
46
+ const prismaTypes = buildTypes(options.dmmf);
64
47
 
65
- function getOrderByTypeName(type: string) {
66
- const possibleTypes = [
67
- `${type}OrderByWithRelationInput`,
68
- `${type}OrderByWithRelationAndSearchRelevanceInput`,
69
- ];
48
+ await generateOutput(options.dmmf, prismaTypes, prismaLocation, outputLocation);
70
49
 
71
- const orderBy = options.dmmf.schema.inputObjectTypes.prisma?.find((inputType) =>
72
- possibleTypes.includes(inputType.name),
50
+ if (outputLocation === defaultOutput) {
51
+ await generateOutput(
52
+ options.dmmf,
53
+ prismaTypes,
54
+ prismaLocation.replace('../', '../../'),
55
+ outputLocation.replace('/generated.ts', '/esm/generated.ts'),
73
56
  );
57
+ }
58
+ },
59
+ });
74
60
 
75
- if (!orderBy) {
76
- return possibleTypes[0];
77
- }
61
+ async function generateOutput(
62
+ dmmf: DMMF.Document,
63
+ prismaTypes: ts.InterfaceDeclaration,
64
+ prismaLocation: string,
65
+ outputLocation: string,
66
+ ) {
67
+ const importStatement = ts.factory.createImportDeclaration(
68
+ [],
69
+ [],
70
+ ts.factory.createImportClause(
71
+ true,
72
+ undefined,
73
+ ts.factory.createNamedImports([
74
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier('Prisma')),
75
+ ...dmmf.datamodel.models.map((model) =>
76
+ ts.factory.createImportSpecifier(
77
+ false,
78
+ undefined,
79
+ ts.factory.createIdentifier(model.name),
80
+ ),
81
+ ),
82
+ ]),
83
+ ),
84
+ ts.factory.createStringLiteral(prismaLocation),
85
+ );
78
86
 
79
- return orderBy.name;
80
- }
87
+ const printer = ts.createPrinter({});
81
88
 
82
- const modelTypes = options.dmmf.datamodel.models.map((model) => {
83
- const relations = model.fields.filter((field) => !!field.relationName);
84
- const listRelations = model.fields.filter((field) => !!field.relationName && field.isList);
89
+ const sourcefile = ts.createSourceFile(
90
+ outputLocation,
91
+ '',
92
+ ScriptTarget.ESNext,
93
+ false,
94
+ ScriptKind.TS,
95
+ );
85
96
 
86
- return ts.factory.createPropertySignature(
87
- [],
88
- model.name,
89
- undefined,
97
+ const nodes = ts.factory.createNodeArray([importStatement, prismaTypes]);
90
98
 
91
- ts.factory.createTypeLiteralNode([
92
- ts.factory.createPropertySignature(
93
- [],
94
- 'Name',
95
- undefined,
96
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(model.name)),
97
- ),
98
- ts.factory.createPropertySignature(
99
- [],
100
- 'Shape',
101
- undefined,
102
- ts.factory.createTypeReferenceNode(model.name),
103
- ),
104
- ts.factory.createPropertySignature(
105
- [],
106
- 'Include',
107
- undefined,
108
- relations.length > 0
109
- ? ts.factory.createTypeReferenceNode(`Prisma.${model.name}Include`)
110
- : ts.factory.createTypeReferenceNode('never'),
111
- ),
112
- ts.factory.createPropertySignature(
113
- [],
114
- 'Select',
115
- undefined,
116
- ts.factory.createTypeReferenceNode(`Prisma.${model.name}Select`),
117
- ),
118
- ts.factory.createPropertySignature(
119
- [],
120
- 'OrderBy',
121
- undefined,
122
- ts.factory.createTypeReferenceNode(`Prisma.${getOrderByTypeName(model.name)}`),
123
- ),
124
- ts.factory.createPropertySignature(
125
- [],
126
- 'WhereUnique',
127
- undefined,
128
- ts.factory.createTypeReferenceNode(`Prisma.${model.name}WhereUniqueInput`),
129
- ),
130
- ts.factory.createPropertySignature(
131
- [],
132
- 'Where',
133
- undefined,
134
- ts.factory.createTypeReferenceNode(`Prisma.${model.name}WhereInput`),
135
- ),
136
- ts.factory.createPropertySignature(
137
- [],
138
- 'RelationName',
139
- undefined,
140
- relations.length > 0
141
- ? ts.factory.createUnionTypeNode(
142
- relations.map((field) =>
143
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(field.name)),
144
- ),
145
- )
146
- : ts.factory.createTypeReferenceNode('never'),
147
- ),
148
- ts.factory.createPropertySignature(
149
- [],
150
- 'ListRelations',
151
- undefined,
152
- listRelations.length > 0
153
- ? ts.factory.createUnionTypeNode(
154
- listRelations.map((field) =>
155
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(field.name)),
156
- ),
157
- )
158
- : ts.factory.createTypeReferenceNode('never'),
159
- ),
160
- ts.factory.createPropertySignature(
161
- [],
162
- 'Relations',
163
- undefined,
164
- ts.factory.createTypeLiteralNode(
165
- relations.map((field) => {
166
- const typeName = field.type;
167
-
168
- return ts.factory.createPropertySignature(
169
- [],
170
- field.name,
171
- undefined,
172
- ts.factory.createTypeLiteralNode([
173
- ts.factory.createPropertySignature(
174
- [],
175
- 'Shape',
176
- undefined,
177
- field.isList
178
- ? ts.factory.createArrayTypeNode(
179
- ts.factory.createTypeReferenceNode(typeName),
180
- )
181
- : field.isRequired
182
- ? ts.factory.createTypeReferenceNode(typeName)
183
- : ts.factory.createUnionTypeNode([
184
- ts.factory.createTypeReferenceNode(typeName),
185
- ts.factory.createLiteralTypeNode(ts.factory.createNull()),
186
- ]),
187
- ),
188
- ts.factory.createPropertySignature(
189
- [],
190
- 'Types',
191
- undefined,
192
- ts.factory.createIndexedAccessTypeNode(
193
- ts.factory.createTypeReferenceNode('PrismaTypes'),
194
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(typeName)),
195
- ),
196
- ),
197
- ]),
198
- );
199
- }),
200
- ),
201
- ),
202
- ]),
203
- );
99
+ const result = printer.printList(ListFormat.SourceFileStatements, nodes, sourcefile);
100
+
101
+ await new Promise<void>((resolve, reject) => {
102
+ mkdir(dirname(sourcefile.fileName), { recursive: true }, (err) => {
103
+ if (err) {
104
+ reject(err);
105
+ } else {
106
+ resolve();
107
+ }
204
108
  });
109
+ });
205
110
 
206
- const prismaTypes = ts.factory.createInterfaceDeclaration(
207
- [],
208
- [
209
- ts.factory.createModifier(SyntaxKind.ExportKeyword),
210
- ts.factory.createModifier(SyntaxKind.DefaultKeyword),
211
- ],
212
- 'PrismaTypes',
213
- [],
214
- [],
215
- modelTypes,
216
- );
217
- const printer = ts.createPrinter({});
218
-
219
- const sourcefile = ts.createSourceFile(
220
- options.generator.output!.value,
221
- '',
222
- ScriptTarget.ESNext,
223
- false,
224
- ScriptKind.TS,
111
+ return new Promise<void>((resolve, reject) => {
112
+ writeFile(sourcefile.fileName, `/* eslint-disable */\n${result}`, (err) => {
113
+ if (err) {
114
+ reject(err);
115
+ } else {
116
+ resolve();
117
+ }
118
+ });
119
+ });
120
+ }
121
+
122
+ function buildTypes(dmmf: DMMF.Document) {
123
+ function getOrderByTypeName(type: string) {
124
+ const possibleTypes = [
125
+ `${type}OrderByWithRelationInput`,
126
+ `${type}OrderByWithRelationAndSearchRelevanceInput`,
127
+ ];
128
+
129
+ const orderBy = dmmf.schema.inputObjectTypes.prisma?.find((inputType) =>
130
+ possibleTypes.includes(inputType.name),
225
131
  );
226
132
 
227
- const nodes = ts.factory.createNodeArray([importStatement, prismaTypes]);
133
+ if (!orderBy) {
134
+ return possibleTypes[0];
135
+ }
228
136
 
229
- const result = printer.printList(ListFormat.SourceFileStatements, nodes, sourcefile);
137
+ return orderBy.name;
138
+ }
230
139
 
231
- await new Promise<void>((resolve, reject) => {
232
- mkdir(dirname(sourcefile.fileName), { recursive: true }, (err) => {
233
- if (err) {
234
- reject(err);
235
- } else {
236
- resolve();
237
- }
238
- });
239
- });
140
+ const modelTypes = dmmf.datamodel.models.map((model) => {
141
+ const relations = model.fields.filter((field) => !!field.relationName);
142
+ const listRelations = model.fields.filter((field) => !!field.relationName && field.isList);
240
143
 
241
- return new Promise<void>((resolve, reject) => {
242
- writeFile(sourcefile.fileName, `/* eslint-disable */\n${result}`, (err) => {
243
- if (err) {
244
- reject(err);
245
- } else {
246
- resolve();
247
- }
248
- });
249
- });
250
- },
251
- });
144
+ return ts.factory.createPropertySignature(
145
+ [],
146
+ model.name,
147
+ undefined,
148
+
149
+ ts.factory.createTypeLiteralNode([
150
+ ts.factory.createPropertySignature(
151
+ [],
152
+ 'Name',
153
+ undefined,
154
+ ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(model.name)),
155
+ ),
156
+ ts.factory.createPropertySignature(
157
+ [],
158
+ 'Shape',
159
+ undefined,
160
+ ts.factory.createTypeReferenceNode(model.name),
161
+ ),
162
+ ts.factory.createPropertySignature(
163
+ [],
164
+ 'Include',
165
+ undefined,
166
+ relations.length > 0
167
+ ? ts.factory.createTypeReferenceNode(`Prisma.${model.name}Include`)
168
+ : ts.factory.createTypeReferenceNode('never'),
169
+ ),
170
+ ts.factory.createPropertySignature(
171
+ [],
172
+ 'Select',
173
+ undefined,
174
+ ts.factory.createTypeReferenceNode(`Prisma.${model.name}Select`),
175
+ ),
176
+ ts.factory.createPropertySignature(
177
+ [],
178
+ 'OrderBy',
179
+ undefined,
180
+ ts.factory.createTypeReferenceNode(`Prisma.${getOrderByTypeName(model.name)}`),
181
+ ),
182
+ ts.factory.createPropertySignature(
183
+ [],
184
+ 'WhereUnique',
185
+ undefined,
186
+ ts.factory.createTypeReferenceNode(`Prisma.${model.name}WhereUniqueInput`),
187
+ ),
188
+ ts.factory.createPropertySignature(
189
+ [],
190
+ 'Where',
191
+ undefined,
192
+ ts.factory.createTypeReferenceNode(`Prisma.${model.name}WhereInput`),
193
+ ),
194
+ ts.factory.createPropertySignature(
195
+ [],
196
+ 'RelationName',
197
+ undefined,
198
+ relations.length > 0
199
+ ? ts.factory.createUnionTypeNode(
200
+ relations.map((field) =>
201
+ ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(field.name)),
202
+ ),
203
+ )
204
+ : ts.factory.createTypeReferenceNode('never'),
205
+ ),
206
+ ts.factory.createPropertySignature(
207
+ [],
208
+ 'ListRelations',
209
+ undefined,
210
+ listRelations.length > 0
211
+ ? ts.factory.createUnionTypeNode(
212
+ listRelations.map((field) =>
213
+ ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(field.name)),
214
+ ),
215
+ )
216
+ : ts.factory.createTypeReferenceNode('never'),
217
+ ),
218
+ ts.factory.createPropertySignature(
219
+ [],
220
+ 'Relations',
221
+ undefined,
222
+ ts.factory.createTypeLiteralNode(
223
+ relations.map((field) => {
224
+ const typeName = field.type;
225
+
226
+ return ts.factory.createPropertySignature(
227
+ [],
228
+ field.name,
229
+ undefined,
230
+ ts.factory.createTypeLiteralNode([
231
+ ts.factory.createPropertySignature(
232
+ [],
233
+ 'Shape',
234
+ undefined,
235
+ field.isList
236
+ ? ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(typeName))
237
+ : field.isRequired
238
+ ? ts.factory.createTypeReferenceNode(typeName)
239
+ : ts.factory.createUnionTypeNode([
240
+ ts.factory.createTypeReferenceNode(typeName),
241
+ ts.factory.createLiteralTypeNode(ts.factory.createNull()),
242
+ ]),
243
+ ),
244
+ ts.factory.createPropertySignature(
245
+ [],
246
+ 'Types',
247
+ undefined,
248
+ ts.factory.createIndexedAccessTypeNode(
249
+ ts.factory.createTypeReferenceNode('PrismaTypes'),
250
+ ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(typeName)),
251
+ ),
252
+ ),
253
+ ]),
254
+ );
255
+ }),
256
+ ),
257
+ ),
258
+ ]),
259
+ );
260
+ });
261
+
262
+ return ts.factory.createInterfaceDeclaration(
263
+ [],
264
+ [
265
+ ts.factory.createModifier(SyntaxKind.ExportKeyword),
266
+ ts.factory.createModifier(SyntaxKind.DefaultKeyword),
267
+ ],
268
+ 'PrismaTypes',
269
+ [],
270
+ [],
271
+ modelTypes,
272
+ );
273
+ }
@@ -261,7 +261,8 @@ export function wrapConnectionResult<T extends {}>(
261
261
  args: PothosSchemaTypes.DefaultConnectionArguments,
262
262
  take: number,
263
263
  cursor: (node: T) => string,
264
- totalCount?: number | (() => MaybePromise<number>),
264
+ totalCount?: null | number | (() => MaybePromise<number>),
265
+ resolveNode?: (node: unknown) => unknown,
265
266
  ) {
266
267
  const gotFullResults = results.length === Math.abs(take);
267
268
  const hasNextPage = args.before ? true : gotFullResults;
@@ -273,6 +274,12 @@ export function wrapConnectionResult<T extends {}>(
273
274
  const edges = nodes.map((value, index) =>
274
275
  value == null
275
276
  ? null
277
+ : resolveNode
278
+ ? {
279
+ ...value,
280
+ cursor: cursor(value),
281
+ node: resolveNode(value),
282
+ }
276
283
  : {
277
284
  cursor: cursor(value),
278
285
  node: value,