@pothos/plugin-prisma 3.53.0 → 3.55.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.
- package/CHANGELOG.md +12 -0
- package/README.md +63 -1
- package/dts/connection-helpers.d.ts +3 -3
- package/dts/connection-helpers.d.ts.map +1 -1
- package/dts/global-types.d.ts +15 -4
- package/dts/global-types.d.ts.map +1 -1
- package/dts/index.d.ts +3 -1
- package/dts/index.d.ts.map +1 -1
- package/dts/interface-ref.d.ts +10 -0
- package/dts/interface-ref.d.ts.map +1 -0
- package/dts/model-loader.d.ts +7 -7
- package/dts/model-loader.d.ts.map +1 -1
- package/dts/prisma-field-builder.d.ts +4 -4
- package/dts/prisma-field-builder.d.ts.map +1 -1
- package/dts/types.d.ts +23 -7
- package/dts/types.d.ts.map +1 -1
- package/dts/util/datamodel.d.ts +3 -3
- package/dts/util/datamodel.d.ts.map +1 -1
- package/dts/util/map-query.d.ts +2 -1
- package/dts/util/map-query.d.ts.map +1 -1
- package/dts/util/usage.d.ts +4 -0
- package/dts/util/usage.d.ts.map +1 -0
- package/esm/connection-helpers.d.ts +3 -3
- package/esm/connection-helpers.d.ts.map +1 -1
- package/esm/connection-helpers.js.map +1 -1
- package/esm/field-builder.js +59 -17
- package/esm/field-builder.js.map +1 -1
- package/esm/global-types.d.ts +21 -10
- package/esm/global-types.d.ts.map +1 -1
- package/esm/global-types.js.map +1 -1
- package/esm/index.d.ts +3 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +48 -3
- package/esm/index.js.map +1 -1
- package/esm/interface-ref.d.ts +10 -0
- package/esm/interface-ref.d.ts.map +1 -0
- package/esm/interface-ref.js +26 -0
- package/esm/interface-ref.js.map +1 -0
- package/esm/model-loader.d.ts +7 -7
- package/esm/model-loader.d.ts.map +1 -1
- package/esm/model-loader.js.map +1 -1
- package/esm/prisma-field-builder.d.ts +4 -4
- package/esm/prisma-field-builder.d.ts.map +1 -1
- package/esm/prisma-field-builder.js +3 -3
- package/esm/prisma-field-builder.js.map +1 -1
- package/esm/schema-builder.js +27 -0
- package/esm/schema-builder.js.map +1 -1
- package/esm/types.d.ts +25 -9
- package/esm/types.d.ts.map +1 -1
- package/esm/util/datamodel.d.ts +3 -3
- package/esm/util/datamodel.d.ts.map +1 -1
- package/esm/util/datamodel.js +3 -2
- package/esm/util/datamodel.js.map +1 -1
- package/esm/util/map-query.d.ts +2 -1
- package/esm/util/map-query.d.ts.map +1 -1
- package/esm/util/map-query.js +21 -14
- package/esm/util/map-query.js.map +1 -1
- package/esm/util/usage.d.ts +4 -0
- package/esm/util/usage.d.ts.map +1 -0
- package/esm/util/usage.js +29 -0
- package/esm/util/usage.js.map +1 -0
- package/lib/connection-helpers.js.map +1 -1
- package/lib/field-builder.js +62 -21
- package/lib/field-builder.js.map +1 -1
- package/lib/index.js +50 -2
- package/lib/index.js.map +1 -1
- package/lib/interface-ref.js +36 -0
- package/lib/interface-ref.js.map +1 -0
- package/lib/model-loader.js.map +1 -1
- package/lib/prisma-field-builder.js +3 -3
- package/lib/prisma-field-builder.js.map +1 -1
- package/lib/schema-builder.js +27 -0
- package/lib/schema-builder.js.map +1 -1
- package/lib/util/datamodel.js +3 -2
- package/lib/util/datamodel.js.map +1 -1
- package/lib/util/map-query.js +20 -13
- package/lib/util/map-query.js.map +1 -1
- package/lib/util/usage.js +51 -0
- package/lib/util/usage.js.map +1 -0
- package/package.json +2 -2
- package/src/connection-helpers.ts +6 -6
- package/src/field-builder.ts +90 -15
- package/src/global-types.ts +39 -11
- package/src/index.ts +56 -2
- package/src/interface-ref.ts +18 -0
- package/src/model-loader.ts +13 -7
- package/src/prisma-field-builder.ts +7 -10
- package/src/schema-builder.ts +44 -1
- package/src/types.ts +66 -9
- package/src/util/datamodel.ts +8 -3
- package/src/util/map-query.ts +38 -14
- package/src/util/usage.ts +33 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ObjectRef, SchemaTypes } from '@pothos/core';
|
|
2
|
+
import { PrismaRef } from './interface-ref';
|
|
2
3
|
import { ModelLoader } from './model-loader';
|
|
3
|
-
import { PrismaObjectRef } from './object-ref';
|
|
4
4
|
import type { PrismaModelTypes, ShapeFromSelection, UniqueFieldsFromWhereUnique } from './types';
|
|
5
5
|
import {
|
|
6
6
|
getCursorFormatter,
|
|
@@ -17,12 +17,12 @@ export const prismaModelKey = Symbol.for('Pothos.prismaModelKey');
|
|
|
17
17
|
|
|
18
18
|
export function prismaConnectionHelpers<
|
|
19
19
|
Types extends SchemaTypes,
|
|
20
|
-
RefOrType extends
|
|
20
|
+
RefOrType extends PrismaRef<PrismaModelTypes> | keyof Types['PrismaTypes'],
|
|
21
21
|
Select extends Model['Select'] & {},
|
|
22
|
-
Model extends PrismaModelTypes = RefOrType extends
|
|
22
|
+
Model extends PrismaModelTypes = RefOrType extends PrismaRef<infer T>
|
|
23
23
|
? T & PrismaModelTypes
|
|
24
24
|
: Types['PrismaTypes'][RefOrType & keyof Types['PrismaTypes']] & PrismaModelTypes,
|
|
25
|
-
Shape = RefOrType extends
|
|
25
|
+
Shape = RefOrType extends PrismaRef<PrismaModelTypes, infer T> ? T : Model['Shape'],
|
|
26
26
|
EdgeShape = Model['Include'] extends Select
|
|
27
27
|
? Shape
|
|
28
28
|
: ShapeFromSelection<Types, Model, { select: Select }>,
|
|
@@ -41,7 +41,7 @@ export function prismaConnectionHelpers<
|
|
|
41
41
|
},
|
|
42
42
|
) {
|
|
43
43
|
const modelName =
|
|
44
|
-
typeof refOrType === 'string' ? refOrType : (refOrType as
|
|
44
|
+
typeof refOrType === 'string' ? refOrType : (refOrType as PrismaRef<Model>).modelName;
|
|
45
45
|
const ref =
|
|
46
46
|
typeof refOrType === 'string'
|
|
47
47
|
? getRefFromModel(modelName, builder)
|
|
@@ -119,7 +119,7 @@ export function prismaConnectionHelpers<
|
|
|
119
119
|
return {
|
|
120
120
|
ref: (typeof refOrType === 'string'
|
|
121
121
|
? getRefFromModel(refOrType, builder)
|
|
122
|
-
: refOrType) as
|
|
122
|
+
: refOrType) as PrismaRef<Model>,
|
|
123
123
|
resolve,
|
|
124
124
|
select: options.select ?? {},
|
|
125
125
|
getQuery,
|
package/src/field-builder.ts
CHANGED
|
@@ -3,8 +3,10 @@ import {
|
|
|
3
3
|
FieldKind,
|
|
4
4
|
FieldRef,
|
|
5
5
|
InputFieldMap,
|
|
6
|
+
isThenable,
|
|
6
7
|
MaybePromise,
|
|
7
8
|
ObjectRef,
|
|
9
|
+
PothosError,
|
|
8
10
|
RootFieldBuilder,
|
|
9
11
|
SchemaTypes,
|
|
10
12
|
} from '@pothos/core';
|
|
@@ -13,6 +15,7 @@ import { PrismaConnectionFieldOptions, PrismaModelTypes } from './types';
|
|
|
13
15
|
import { getCursorFormatter, getCursorParser, resolvePrismaCursorConnection } from './util/cursors';
|
|
14
16
|
import { getRefFromModel } from './util/datamodel';
|
|
15
17
|
import { queryFromInfo } from './util/map-query';
|
|
18
|
+
import { isUsed } from './util/usage';
|
|
16
19
|
|
|
17
20
|
const fieldBuilderProto = RootFieldBuilder.prototype as PothosSchemaTypes.RootFieldBuilder<
|
|
18
21
|
SchemaTypes,
|
|
@@ -32,9 +35,18 @@ fieldBuilderProto.prismaField = function prismaField({ type, resolve, ...options
|
|
|
32
35
|
...(options as {}),
|
|
33
36
|
type: typeParam,
|
|
34
37
|
resolve: (parent: never, args: unknown, context: {}, info: GraphQLResolveInfo) => {
|
|
35
|
-
const query = queryFromInfo({
|
|
38
|
+
const query = queryFromInfo({
|
|
39
|
+
context,
|
|
40
|
+
info,
|
|
41
|
+
withUsageCheck: !!this.builder.options.prisma?.onUnusedQuery,
|
|
42
|
+
});
|
|
36
43
|
|
|
37
|
-
return
|
|
44
|
+
return checkIfQueryIsUsed(
|
|
45
|
+
this.builder,
|
|
46
|
+
query,
|
|
47
|
+
info,
|
|
48
|
+
resolve(query, parent, args as never, context, info) as never,
|
|
49
|
+
);
|
|
38
50
|
},
|
|
39
51
|
}) as never;
|
|
40
52
|
};
|
|
@@ -57,9 +69,18 @@ fieldBuilderProto.prismaFieldWithInput = function prismaFieldWithInput({
|
|
|
57
69
|
...(options as {}),
|
|
58
70
|
type: typeParam,
|
|
59
71
|
resolve: (parent: never, args: unknown, context: {}, info: GraphQLResolveInfo) => {
|
|
60
|
-
const query = queryFromInfo({
|
|
72
|
+
const query = queryFromInfo({
|
|
73
|
+
context,
|
|
74
|
+
info,
|
|
75
|
+
withUsageCheck: !!this.builder.options.prisma?.onUnusedQuery,
|
|
76
|
+
});
|
|
61
77
|
|
|
62
|
-
return
|
|
78
|
+
return checkIfQueryIsUsed(
|
|
79
|
+
this.builder,
|
|
80
|
+
query,
|
|
81
|
+
info,
|
|
82
|
+
resolve(query, parent, args as never, context, info) as never,
|
|
83
|
+
);
|
|
63
84
|
},
|
|
64
85
|
}) as never;
|
|
65
86
|
};
|
|
@@ -114,17 +135,20 @@ fieldBuilderProto.prismaConnection = function prismaConnection<
|
|
|
114
135
|
args: PothosSchemaTypes.DefaultConnectionArguments,
|
|
115
136
|
context: {},
|
|
116
137
|
info: GraphQLResolveInfo,
|
|
117
|
-
) =>
|
|
118
|
-
|
|
138
|
+
) => {
|
|
139
|
+
const query = queryFromInfo({
|
|
140
|
+
context,
|
|
141
|
+
info,
|
|
142
|
+
select: cursorSelection as {},
|
|
143
|
+
paths: [['nodes'], ['edges', 'node']],
|
|
144
|
+
typeName,
|
|
145
|
+
withUsageCheck: !!this.builder.options.prisma?.onUnusedQuery,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
return resolvePrismaCursorConnection(
|
|
119
149
|
{
|
|
120
150
|
parent,
|
|
121
|
-
query
|
|
122
|
-
context,
|
|
123
|
-
info,
|
|
124
|
-
select: cursorSelection as {},
|
|
125
|
-
paths: [['nodes'], ['edges', 'node']],
|
|
126
|
-
typeName,
|
|
127
|
-
}),
|
|
151
|
+
query,
|
|
128
152
|
ctx: context,
|
|
129
153
|
parseCursor,
|
|
130
154
|
maxSize,
|
|
@@ -133,8 +157,15 @@ fieldBuilderProto.prismaConnection = function prismaConnection<
|
|
|
133
157
|
totalCount: totalCount && (() => totalCount(parent, args as never, context, info)),
|
|
134
158
|
},
|
|
135
159
|
formatCursor,
|
|
136
|
-
(
|
|
137
|
-
|
|
160
|
+
(q) =>
|
|
161
|
+
checkIfQueryIsUsed(
|
|
162
|
+
this.builder,
|
|
163
|
+
query,
|
|
164
|
+
info,
|
|
165
|
+
resolve(q as never, parent, args as never, context, info) as never,
|
|
166
|
+
),
|
|
167
|
+
);
|
|
168
|
+
},
|
|
138
169
|
},
|
|
139
170
|
connectionOptions instanceof ObjectRef
|
|
140
171
|
? connectionOptions
|
|
@@ -163,3 +194,47 @@ fieldBuilderProto.prismaConnection = function prismaConnection<
|
|
|
163
194
|
|
|
164
195
|
return fieldRef;
|
|
165
196
|
} as never;
|
|
197
|
+
|
|
198
|
+
function checkIfQueryIsUsed<Types extends SchemaTypes, T>(
|
|
199
|
+
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
200
|
+
query: object,
|
|
201
|
+
info: GraphQLResolveInfo,
|
|
202
|
+
result: T,
|
|
203
|
+
): T {
|
|
204
|
+
const { onUnusedQuery } = builder.options.prisma || {};
|
|
205
|
+
if (!onUnusedQuery) {
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (isThenable(result)) {
|
|
210
|
+
return result.then((resolved) => {
|
|
211
|
+
if (!isUsed(query)) {
|
|
212
|
+
onUnused();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return resolved;
|
|
216
|
+
}) as T;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!isUsed(query)) {
|
|
220
|
+
onUnused();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return result;
|
|
224
|
+
|
|
225
|
+
function onUnused() {
|
|
226
|
+
if (typeof onUnusedQuery === 'function') {
|
|
227
|
+
onUnusedQuery(info);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const message = `Prisma query was unused in resolver for ${info.parentType.name}.${info.fieldName}`;
|
|
232
|
+
|
|
233
|
+
if (onUnusedQuery === 'error') {
|
|
234
|
+
throw new PothosError(message);
|
|
235
|
+
} else if (onUnusedQuery === 'warn') {
|
|
236
|
+
// eslint-disable-next-line no-console
|
|
237
|
+
console.warn(message);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
package/src/global-types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
3
|
+
import { GraphQLResolveInfo } from 'graphql';
|
|
3
4
|
import {
|
|
4
5
|
FieldKind,
|
|
5
6
|
FieldMap,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
ShapeFromTypeParam,
|
|
16
17
|
TypeParam,
|
|
17
18
|
} from '@pothos/core';
|
|
19
|
+
import { PrismaInterfaceRef, PrismaRef } from './interface-ref';
|
|
18
20
|
import { PrismaNodeRef } from './node-ref';
|
|
19
21
|
import { prismaModelKey, PrismaObjectRef } from './object-ref';
|
|
20
22
|
import { PrismaObjectFieldBuilder as InternalPrismaObjectFieldBuilder } from './prisma-field-builder';
|
|
@@ -24,6 +26,7 @@ import {
|
|
|
24
26
|
PrismaConnectionShape,
|
|
25
27
|
PrismaFieldOptions,
|
|
26
28
|
PrismaFieldWithInputOptions,
|
|
29
|
+
PrismaInterfaceTypeOptions,
|
|
27
30
|
prismaModelName,
|
|
28
31
|
PrismaModelTypes,
|
|
29
32
|
PrismaNodeOptions,
|
|
@@ -52,6 +55,7 @@ declare global {
|
|
|
52
55
|
models?: boolean;
|
|
53
56
|
fields?: boolean;
|
|
54
57
|
};
|
|
58
|
+
onUnusedQuery?: null | 'warn' | 'error' | ((info: GraphQLResolveInfo) => void);
|
|
55
59
|
}
|
|
56
60
|
| {
|
|
57
61
|
filterConnectionTotalCount?: boolean;
|
|
@@ -63,6 +67,7 @@ declare global {
|
|
|
63
67
|
models?: boolean;
|
|
64
68
|
fields?: boolean;
|
|
65
69
|
};
|
|
70
|
+
onUnusedQuery?: null | 'warn' | 'error' | ((info: GraphQLResolveInfo) => void);
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
|
|
@@ -122,6 +127,29 @@ declare global {
|
|
|
122
127
|
ShapeFromSelection<Types, Model, { select: Select; include: Include }>
|
|
123
128
|
>;
|
|
124
129
|
|
|
130
|
+
prismaInterface: <
|
|
131
|
+
Name extends keyof Types['PrismaTypes'],
|
|
132
|
+
Interfaces extends InterfaceParam<Types>[],
|
|
133
|
+
FindUnique,
|
|
134
|
+
Model extends PrismaModelTypes & Types['PrismaTypes'][Name],
|
|
135
|
+
Include = unknown,
|
|
136
|
+
Select = unknown,
|
|
137
|
+
>(
|
|
138
|
+
name: Name,
|
|
139
|
+
options: PrismaInterfaceTypeOptions<
|
|
140
|
+
Types,
|
|
141
|
+
Model,
|
|
142
|
+
Interfaces,
|
|
143
|
+
FindUnique,
|
|
144
|
+
Include,
|
|
145
|
+
Select,
|
|
146
|
+
ShapeFromSelection<Types, Model, { select: Select; include: Include }>
|
|
147
|
+
>,
|
|
148
|
+
) => PrismaInterfaceRef<
|
|
149
|
+
Model,
|
|
150
|
+
ShapeFromSelection<Types, Model, { select: Select; include: Include }>
|
|
151
|
+
>;
|
|
152
|
+
|
|
125
153
|
prismaObjectField: <
|
|
126
154
|
Type extends PrismaObjectRef<PrismaModelTypes, {}> | keyof Types['PrismaTypes'],
|
|
127
155
|
Model extends PrismaModelTypes = Type extends PrismaObjectRef<infer M, {}>
|
|
@@ -194,10 +222,10 @@ declare global {
|
|
|
194
222
|
prismaField: <
|
|
195
223
|
Args extends InputFieldMap,
|
|
196
224
|
TypeParam extends
|
|
197
|
-
|
|
|
225
|
+
| PrismaRef<PrismaModelTypes>
|
|
198
226
|
| keyof Types['PrismaTypes']
|
|
199
227
|
| [keyof Types['PrismaTypes']]
|
|
200
|
-
| [
|
|
228
|
+
| [PrismaRef<PrismaModelTypes>],
|
|
201
229
|
Nullable extends FieldNullability<Type>,
|
|
202
230
|
ResolveShape,
|
|
203
231
|
ResolveReturnShape,
|
|
@@ -207,9 +235,9 @@ declare global {
|
|
|
207
235
|
Model extends PrismaModelTypes = PrismaModelTypes &
|
|
208
236
|
(TypeParam extends [keyof Types['PrismaTypes']]
|
|
209
237
|
? Types['PrismaTypes'][TypeParam[0]]
|
|
210
|
-
: TypeParam extends [
|
|
238
|
+
: TypeParam extends [PrismaRef<PrismaModelTypes>]
|
|
211
239
|
? TypeParam[0][typeof prismaModelKey]
|
|
212
|
-
: TypeParam extends
|
|
240
|
+
: TypeParam extends PrismaRef<PrismaModelTypes>
|
|
213
241
|
? TypeParam[typeof prismaModelKey]
|
|
214
242
|
: TypeParam extends keyof Types['PrismaTypes']
|
|
215
243
|
? Types['PrismaTypes'][TypeParam]
|
|
@@ -231,14 +259,14 @@ declare global {
|
|
|
231
259
|
|
|
232
260
|
prismaConnection: 'relay' extends PluginName
|
|
233
261
|
? <
|
|
234
|
-
Type extends
|
|
262
|
+
Type extends PrismaRef<PrismaModelTypes> | keyof Types['PrismaTypes'],
|
|
235
263
|
Nullable extends boolean,
|
|
236
264
|
ResolveReturnShape,
|
|
237
265
|
Args extends InputFieldMap = {},
|
|
238
|
-
Model extends PrismaModelTypes = Type extends
|
|
266
|
+
Model extends PrismaModelTypes = Type extends PrismaRef<infer T>
|
|
239
267
|
? T
|
|
240
268
|
: PrismaModelTypes & Types['PrismaTypes'][Type & keyof Types['PrismaTypes']],
|
|
241
|
-
Shape = Type extends
|
|
269
|
+
Shape = Type extends PrismaRef<PrismaModelTypes, infer S> ? S : Model['Shape'],
|
|
242
270
|
ConnectionInterfaces extends InterfaceParam<Types>[] = [],
|
|
243
271
|
EdgeInterfaces extends InterfaceParam<Types>[] = [],
|
|
244
272
|
>(
|
|
@@ -287,10 +315,10 @@ declare global {
|
|
|
287
315
|
? <
|
|
288
316
|
Fields extends Record<string, InputFieldRef<unknown, 'InputObject'>>,
|
|
289
317
|
TypeParam extends
|
|
290
|
-
|
|
|
318
|
+
| PrismaRef<PrismaModelTypes>
|
|
291
319
|
| keyof Types['PrismaTypes']
|
|
292
320
|
| [keyof Types['PrismaTypes']]
|
|
293
|
-
| [
|
|
321
|
+
| [PrismaRef<PrismaModelTypes>],
|
|
294
322
|
Type extends TypeParam extends [unknown]
|
|
295
323
|
? [ObjectRef<Model['Shape']>]
|
|
296
324
|
: ObjectRef<Model['Shape']>,
|
|
@@ -303,9 +331,9 @@ declare global {
|
|
|
303
331
|
Model extends PrismaModelTypes = PrismaModelTypes &
|
|
304
332
|
(TypeParam extends [keyof Types['PrismaTypes']]
|
|
305
333
|
? Types['PrismaTypes'][TypeParam[0]]
|
|
306
|
-
: TypeParam extends [
|
|
334
|
+
: TypeParam extends [PrismaRef<PrismaModelTypes>]
|
|
307
335
|
? TypeParam[0][typeof prismaModelKey]
|
|
308
|
-
: TypeParam extends
|
|
336
|
+
: TypeParam extends PrismaRef<PrismaModelTypes>
|
|
309
337
|
? TypeParam[typeof prismaModelKey]
|
|
310
338
|
: TypeParam extends keyof Types['PrismaTypes']
|
|
311
339
|
? Types['PrismaTypes'][TypeParam]
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,8 @@ import SchemaBuilder, {
|
|
|
6
6
|
BasePlugin,
|
|
7
7
|
BuildCache,
|
|
8
8
|
PothosOutputFieldConfig,
|
|
9
|
+
PothosSchemaError,
|
|
10
|
+
PothosTypeConfig,
|
|
9
11
|
SchemaTypes,
|
|
10
12
|
} from '@pothos/core';
|
|
11
13
|
import { ModelLoader } from './model-loader';
|
|
@@ -17,6 +19,7 @@ import { getLoaderMapping, setLoaderMappings } from './util/loader-map';
|
|
|
17
19
|
import { queryFromInfo, selectionStateFromInfo } from './util/map-query';
|
|
18
20
|
|
|
19
21
|
export { prismaConnectionHelpers } from './connection-helpers';
|
|
22
|
+
export { PrismaInterfaceRef } from './interface-ref';
|
|
20
23
|
export { PrismaNodeRef } from './node-ref';
|
|
21
24
|
export { PrismaObjectRef } from './object-ref';
|
|
22
25
|
export * from './types';
|
|
@@ -47,6 +50,37 @@ export class PrismaPlugin<Types extends SchemaTypes> extends BasePlugin<Types> {
|
|
|
47
50
|
super(cache, pluginName);
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
override onTypeConfig(typeConfig: PothosTypeConfig): PothosTypeConfig {
|
|
54
|
+
if (typeConfig.kind !== 'Object' && typeConfig.kind !== 'Interface') {
|
|
55
|
+
return typeConfig;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let model = typeConfig.extensions?.pothosPrismaModel as string | undefined;
|
|
59
|
+
|
|
60
|
+
typeConfig.interfaces.forEach((iface) => {
|
|
61
|
+
const interfaceModel = this.buildCache.getTypeConfig(iface, 'Interface').extensions
|
|
62
|
+
?.pothosPrismaModel as string | undefined;
|
|
63
|
+
|
|
64
|
+
if (interfaceModel) {
|
|
65
|
+
if (model && model !== interfaceModel) {
|
|
66
|
+
throw new PothosSchemaError(
|
|
67
|
+
`PrismaObjects must be based on the same prisma model as any PrismaInterfaces they extend. ${typeConfig.name} uses ${model} and ${iface.name} uses ${interfaceModel}`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
model = interfaceModel;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
...typeConfig,
|
|
77
|
+
extensions: {
|
|
78
|
+
...typeConfig.extensions,
|
|
79
|
+
pothosPrismaModel: model,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
50
84
|
override onOutputFieldConfig(
|
|
51
85
|
fieldConfig: PothosOutputFieldConfig<Types>,
|
|
52
86
|
): PothosOutputFieldConfig<Types> | null {
|
|
@@ -85,7 +119,7 @@ export class PrismaPlugin<Types extends SchemaTypes> extends BasePlugin<Types> {
|
|
|
85
119
|
return resolver;
|
|
86
120
|
}
|
|
87
121
|
|
|
88
|
-
const parentConfig = this.buildCache.getTypeConfig(fieldConfig.parentType
|
|
122
|
+
const parentConfig = this.buildCache.getTypeConfig(fieldConfig.parentType);
|
|
89
123
|
const loadedCheck = fieldConfig.extensions?.pothosPrismaLoaded as
|
|
90
124
|
| undefined
|
|
91
125
|
| ((val: unknown) => boolean);
|
|
@@ -97,8 +131,28 @@ export class PrismaPlugin<Types extends SchemaTypes> extends BasePlugin<Types> {
|
|
|
97
131
|
| undefined
|
|
98
132
|
| ((query: {}, parent: unknown, args: {}, context: {}, info: {}) => unknown);
|
|
99
133
|
|
|
134
|
+
const parentTypes = new Set([fieldConfig.parentType]);
|
|
135
|
+
|
|
136
|
+
if (parentConfig.kind === 'Interface' || parentConfig.kind === 'Object') {
|
|
137
|
+
parentConfig.interfaces.forEach((iface) => {
|
|
138
|
+
const interfaceConfig = this.buildCache.getTypeConfig(iface, 'Interface');
|
|
139
|
+
if (interfaceConfig.extensions?.pothosPrismaModel) {
|
|
140
|
+
parentTypes.add(interfaceConfig.name);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
100
145
|
return (parent, args, context, info) => {
|
|
101
|
-
|
|
146
|
+
let mapping = getLoaderMapping(context, info.path, info.parentType.name);
|
|
147
|
+
|
|
148
|
+
if (!mapping) {
|
|
149
|
+
for (const parentType of parentTypes) {
|
|
150
|
+
mapping = getLoaderMapping(context, info.path, parentType);
|
|
151
|
+
if (mapping) {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
102
156
|
|
|
103
157
|
if ((!loadedCheck || loadedCheck(parent)) && mapping) {
|
|
104
158
|
setLoaderMappings(context, info, mapping);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InterfaceRef } from '@pothos/core';
|
|
2
|
+
import { prismaModelKey, PrismaObjectRef } from './object-ref';
|
|
3
|
+
import type { PrismaModelTypes } from './types';
|
|
4
|
+
|
|
5
|
+
export type PrismaRef<Model extends PrismaModelTypes, T = {}> =
|
|
6
|
+
| PrismaObjectRef<Model, T>
|
|
7
|
+
| PrismaInterfaceRef<Model, T>;
|
|
8
|
+
|
|
9
|
+
export class PrismaInterfaceRef<Model extends PrismaModelTypes, T = {}> extends InterfaceRef<T> {
|
|
10
|
+
[prismaModelKey]!: Model;
|
|
11
|
+
modelName: string;
|
|
12
|
+
|
|
13
|
+
constructor(name: string, modelName: string) {
|
|
14
|
+
super(name);
|
|
15
|
+
|
|
16
|
+
this.modelName = modelName;
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/model-loader.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createContextCache,
|
|
3
|
+
InterfaceRef,
|
|
4
|
+
ObjectRef,
|
|
5
|
+
PothosSchemaError,
|
|
6
|
+
SchemaTypes,
|
|
7
|
+
} from '@pothos/core';
|
|
2
8
|
import { getDelegateFromModel, getModel } from './util/datamodel';
|
|
3
9
|
import { getClient } from './util/get-client';
|
|
4
10
|
import {
|
|
@@ -32,7 +38,7 @@ export class ModelLoader {
|
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
static forRef<Types extends SchemaTypes>(
|
|
35
|
-
ref: ObjectRef<unknown>,
|
|
41
|
+
ref: ObjectRef<unknown> | InterfaceRef<unknown>,
|
|
36
42
|
modelName: string,
|
|
37
43
|
findUnique: ((model: Record<string, unknown>, ctx: {}) => unknown) | undefined,
|
|
38
44
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
@@ -78,7 +84,7 @@ export class ModelLoader {
|
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
static getDefaultFindBy<Types extends SchemaTypes>(
|
|
81
|
-
ref: ObjectRef<unknown>,
|
|
87
|
+
ref: ObjectRef<unknown> | InterfaceRef<unknown>,
|
|
82
88
|
modelName: string,
|
|
83
89
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
84
90
|
) {
|
|
@@ -115,7 +121,7 @@ export class ModelLoader {
|
|
|
115
121
|
}
|
|
116
122
|
|
|
117
123
|
static getDefaultFindUnique<Types extends SchemaTypes>(
|
|
118
|
-
ref: ObjectRef<unknown>,
|
|
124
|
+
ref: ObjectRef<unknown> | InterfaceRef<unknown>,
|
|
119
125
|
modelName: string,
|
|
120
126
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
121
127
|
): (model: Record<string, unknown>) => {} {
|
|
@@ -125,7 +131,7 @@ export class ModelLoader {
|
|
|
125
131
|
}
|
|
126
132
|
|
|
127
133
|
static getDefaultIDSelection<Types extends SchemaTypes>(
|
|
128
|
-
ref: ObjectRef<unknown>,
|
|
134
|
+
ref: ObjectRef<unknown> | InterfaceRef<unknown>,
|
|
129
135
|
modelName: string,
|
|
130
136
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
131
137
|
): Record<string, boolean> {
|
|
@@ -145,7 +151,7 @@ export class ModelLoader {
|
|
|
145
151
|
}
|
|
146
152
|
|
|
147
153
|
static getCursorSelection<Types extends SchemaTypes>(
|
|
148
|
-
ref: ObjectRef<unknown>,
|
|
154
|
+
ref: ObjectRef<unknown> | InterfaceRef<unknown>,
|
|
149
155
|
modelName: string,
|
|
150
156
|
cursor: string,
|
|
151
157
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
@@ -174,7 +180,7 @@ export class ModelLoader {
|
|
|
174
180
|
}
|
|
175
181
|
|
|
176
182
|
static getFindUniqueForField<Types extends SchemaTypes>(
|
|
177
|
-
ref: ObjectRef<unknown>,
|
|
183
|
+
ref: ObjectRef<unknown> | InterfaceRef<unknown>,
|
|
178
184
|
modelName: string,
|
|
179
185
|
fieldName: string,
|
|
180
186
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
@@ -18,8 +18,8 @@ import {
|
|
|
18
18
|
ShapeFromTypeParam,
|
|
19
19
|
TypeParam,
|
|
20
20
|
} from '@pothos/core';
|
|
21
|
+
import { PrismaRef } from './interface-ref';
|
|
21
22
|
import { ModelLoader } from './model-loader';
|
|
22
|
-
import { PrismaObjectRef } from './object-ref';
|
|
23
23
|
import {
|
|
24
24
|
PrismaConnectionShape,
|
|
25
25
|
PrismaModelTypes,
|
|
@@ -367,8 +367,9 @@ export class PrismaObjectFieldBuilder<
|
|
|
367
367
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
368
368
|
model: string,
|
|
369
369
|
fieldMap: FieldMap,
|
|
370
|
+
graphqlKind: PothosSchemaTypes.PothosKindToGraphQLType[FieldKind] = 'Object',
|
|
370
371
|
) {
|
|
371
|
-
super(name, builder, 'PrismaObject',
|
|
372
|
+
super(name, builder, 'PrismaObject', graphqlKind);
|
|
372
373
|
|
|
373
374
|
this.model = model;
|
|
374
375
|
this.prismaFieldMap = fieldMap;
|
|
@@ -473,18 +474,14 @@ export class PrismaObjectFieldBuilder<
|
|
|
473
474
|
}) as FieldRef<number, 'Object'>;
|
|
474
475
|
}
|
|
475
476
|
|
|
476
|
-
variant<
|
|
477
|
-
Variant extends Model['Name'] | PrismaObjectRef<Model>,
|
|
478
|
-
Args extends InputFieldMap,
|
|
479
|
-
Nullable,
|
|
480
|
-
>(
|
|
477
|
+
variant<Variant extends Model['Name'] | PrismaRef<Model>, Args extends InputFieldMap, Nullable>(
|
|
481
478
|
variant: Variant,
|
|
482
479
|
...allArgs: NormalizeArgs<
|
|
483
480
|
[
|
|
484
481
|
options: VariantFieldOptions<
|
|
485
482
|
Types,
|
|
486
483
|
Model,
|
|
487
|
-
Variant extends
|
|
484
|
+
Variant extends PrismaRef<Model> ? Variant : PrismaRef<Model>,
|
|
488
485
|
Args,
|
|
489
486
|
Nullable,
|
|
490
487
|
Shape
|
|
@@ -493,7 +490,7 @@ export class PrismaObjectFieldBuilder<
|
|
|
493
490
|
>
|
|
494
491
|
): FieldRef<Model['Shape'], 'Object'> {
|
|
495
492
|
const [{ isNull, nullable, ...options } = {} as never] = allArgs;
|
|
496
|
-
const ref:
|
|
493
|
+
const ref: PrismaRef<PrismaModelTypes> =
|
|
497
494
|
typeof variant === 'string' ? getRefFromModel(variant, this.builder) : variant;
|
|
498
495
|
|
|
499
496
|
const selfSelect = (args: object, context: object, nestedQuery: (query: unknown) => unknown) =>
|
|
@@ -550,7 +547,7 @@ export class PrismaObjectFieldBuilder<
|
|
|
550
547
|
) {
|
|
551
548
|
const [name, options = {} as never] = args;
|
|
552
549
|
|
|
553
|
-
const typeConfig = this.builder.configStore.getTypeConfig(this.typename
|
|
550
|
+
const typeConfig = this.builder.configStore.getTypeConfig(this.typename);
|
|
554
551
|
const usingSelect = !!typeConfig.extensions?.pothosPrismaSelect;
|
|
555
552
|
|
|
556
553
|
return this.exposeField<Type, Nullable, never>(name as never, {
|
package/src/schema-builder.ts
CHANGED
|
@@ -9,6 +9,7 @@ import SchemaBuilder, {
|
|
|
9
9
|
PothosError,
|
|
10
10
|
SchemaTypes,
|
|
11
11
|
} from '@pothos/core';
|
|
12
|
+
import { PrismaInterfaceRef } from './interface-ref';
|
|
12
13
|
import { ModelLoader } from './model-loader';
|
|
13
14
|
import { PrismaNodeRef } from './node-ref';
|
|
14
15
|
import { PrismaObjectRef } from './object-ref';
|
|
@@ -29,7 +30,7 @@ schemaBuilderProto.prismaObject = function prismaObject(
|
|
|
29
30
|
) {
|
|
30
31
|
const ref = options.variant
|
|
31
32
|
? new PrismaObjectRef(options.variant, type)
|
|
32
|
-
: getRefFromModel(type, this);
|
|
33
|
+
: (getRefFromModel(type, this) as PrismaObjectRef<PrismaModelTypes>);
|
|
33
34
|
const name = options.variant ?? options.name ?? type;
|
|
34
35
|
const fieldMap = getRelationMap(getDMMF(this)).get(type)!;
|
|
35
36
|
const idSelection = ModelLoader.getDefaultIDSelection(ref, type, this);
|
|
@@ -64,6 +65,48 @@ schemaBuilderProto.prismaObject = function prismaObject(
|
|
|
64
65
|
return ref as never;
|
|
65
66
|
};
|
|
66
67
|
|
|
68
|
+
schemaBuilderProto.prismaInterface = function prismaInterface(
|
|
69
|
+
type,
|
|
70
|
+
{ fields, findUnique, select, include, description, ...options },
|
|
71
|
+
) {
|
|
72
|
+
const ref = options.variant
|
|
73
|
+
? new PrismaInterfaceRef(options.variant, type)
|
|
74
|
+
: (getRefFromModel(type, this, 'interface') as PrismaInterfaceRef<PrismaModelTypes>);
|
|
75
|
+
const name = options.variant ?? options.name ?? type;
|
|
76
|
+
const fieldMap = getRelationMap(getDMMF(this)).get(type)!;
|
|
77
|
+
const idSelection = ModelLoader.getDefaultIDSelection(ref, type, this);
|
|
78
|
+
|
|
79
|
+
ref.name = name;
|
|
80
|
+
|
|
81
|
+
this.interfaceType(ref, {
|
|
82
|
+
...(options as {}),
|
|
83
|
+
description: getModelDescription(type, this, description),
|
|
84
|
+
extensions: {
|
|
85
|
+
...options.extensions,
|
|
86
|
+
pothosPrismaInclude: include,
|
|
87
|
+
pothosPrismaModel: type,
|
|
88
|
+
pothosPrismaFieldMap: fieldMap,
|
|
89
|
+
pothosPrismaSelect: select && { ...idSelection, ...(select as {}) },
|
|
90
|
+
pothosPrismaLoader: ModelLoader.forRef(ref, type, findUnique as never, this),
|
|
91
|
+
},
|
|
92
|
+
name,
|
|
93
|
+
fields: fields
|
|
94
|
+
? () =>
|
|
95
|
+
fields(
|
|
96
|
+
new PrismaObjectFieldBuilder(
|
|
97
|
+
name,
|
|
98
|
+
this,
|
|
99
|
+
type,
|
|
100
|
+
getRelationMap(getDMMF(this)).get(type)!,
|
|
101
|
+
'Interface',
|
|
102
|
+
),
|
|
103
|
+
)
|
|
104
|
+
: undefined,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return ref as never;
|
|
108
|
+
};
|
|
109
|
+
|
|
67
110
|
schemaBuilderProto.prismaNode = function prismaNode(
|
|
68
111
|
this: PothosSchemaTypes.SchemaBuilder<SchemaTypes> & {
|
|
69
112
|
nodeInterfaceRef?: () => InterfaceRef<unknown>;
|