@pothos/plugin-prisma 0.17.2 → 3.0.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 +22 -0
- package/README.md +403 -308
- package/esm/field-builder.js +11 -13
- package/esm/field-builder.js.map +1 -1
- package/esm/generator.js +4 -0
- package/esm/generator.js.map +1 -1
- package/esm/global-types.d.ts +23 -5
- package/esm/global-types.d.ts.map +1 -1
- package/esm/index.d.ts +4 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +46 -1
- package/esm/index.js.map +1 -1
- package/esm/model-loader.d.ts +5 -6
- package/esm/model-loader.d.ts.map +1 -1
- package/esm/model-loader.js +18 -78
- package/esm/model-loader.js.map +1 -1
- package/esm/prisma-field-builder.d.ts +25 -6
- package/esm/prisma-field-builder.d.ts.map +1 -1
- package/esm/prisma-field-builder.js +88 -119
- package/esm/prisma-field-builder.js.map +1 -1
- package/esm/schema-builder.js +15 -4
- package/esm/schema-builder.js.map +1 -1
- package/esm/types.d.ts +73 -77
- package/esm/types.d.ts.map +1 -1
- package/esm/types.js +1 -0
- package/esm/types.js.map +1 -1
- package/esm/{cursors.d.ts → util/cursors.d.ts} +10 -8
- package/esm/util/cursors.d.ts.map +1 -0
- package/esm/{cursors.js → util/cursors.js} +34 -13
- package/esm/util/cursors.js.map +1 -0
- package/{lib/refs.d.ts → esm/util/datamodel.d.ts} +9 -8
- package/esm/util/datamodel.d.ts.map +1 -0
- package/esm/{refs.js → util/datamodel.js} +27 -30
- package/esm/util/datamodel.js.map +1 -0
- package/esm/util/deep-equal.d.ts +2 -0
- package/esm/util/deep-equal.d.ts.map +1 -0
- package/esm/util/deep-equal.js +39 -0
- package/esm/util/deep-equal.js.map +1 -0
- package/esm/util/loader-map.d.ts +6 -0
- package/esm/util/loader-map.d.ts.map +1 -0
- package/esm/{loader-map.js → util/loader-map.js} +10 -12
- package/esm/util/loader-map.js.map +1 -0
- package/esm/util/map-query.d.ts +6 -0
- package/esm/util/map-query.d.ts.map +1 -0
- package/esm/util/map-query.js +169 -0
- package/esm/util/map-query.js.map +1 -0
- package/esm/util/relation-map.d.ts +9 -0
- package/esm/util/relation-map.d.ts.map +1 -0
- package/esm/util/relation-map.js +20 -0
- package/esm/util/relation-map.js.map +1 -0
- package/esm/util/selections.d.ts +20 -0
- package/esm/util/selections.d.ts.map +1 -0
- package/esm/util/selections.js +139 -0
- package/esm/util/selections.js.map +1 -0
- package/lib/field-builder.js +20 -18
- package/lib/field-builder.js.map +1 -1
- package/lib/generator.js +9 -1
- package/lib/generator.js.map +1 -1
- package/lib/global-types.d.ts +23 -5
- package/lib/global-types.d.ts.map +1 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +50 -1
- package/lib/index.js.map +1 -1
- package/lib/model-loader.d.ts +5 -6
- package/lib/model-loader.d.ts.map +1 -1
- package/lib/model-loader.js +19 -79
- package/lib/model-loader.js.map +1 -1
- package/lib/prisma-field-builder.d.ts +25 -6
- package/lib/prisma-field-builder.d.ts.map +1 -1
- package/lib/prisma-field-builder.js +92 -123
- package/lib/prisma-field-builder.js.map +1 -1
- package/lib/schema-builder.js +23 -8
- package/lib/schema-builder.js.map +1 -1
- package/lib/types.d.ts +73 -77
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -1
- package/lib/{cursors.d.ts → util/cursors.d.ts} +10 -8
- package/lib/util/cursors.d.ts.map +1 -0
- package/lib/{cursors.js → util/cursors.js} +39 -14
- package/lib/util/cursors.js.map +1 -0
- package/{esm/refs.d.ts → lib/util/datamodel.d.ts} +9 -8
- package/lib/util/datamodel.d.ts.map +1 -0
- package/lib/{refs.js → util/datamodel.js} +32 -35
- package/lib/util/datamodel.js.map +1 -0
- package/lib/util/deep-equal.d.ts +2 -0
- package/lib/util/deep-equal.d.ts.map +1 -0
- package/lib/util/deep-equal.js +43 -0
- package/lib/util/deep-equal.js.map +1 -0
- package/lib/util/loader-map.d.ts +6 -0
- package/lib/util/loader-map.d.ts.map +1 -0
- package/lib/{loader-map.js → util/loader-map.js} +10 -12
- package/lib/util/loader-map.js.map +1 -0
- package/lib/util/map-query.d.ts +6 -0
- package/lib/util/map-query.d.ts.map +1 -0
- package/lib/util/map-query.js +175 -0
- package/lib/util/map-query.js.map +1 -0
- package/lib/util/relation-map.d.ts +9 -0
- package/lib/util/relation-map.d.ts.map +1 -0
- package/lib/util/relation-map.js +24 -0
- package/lib/util/relation-map.js.map +1 -0
- package/lib/util/selections.d.ts +20 -0
- package/lib/util/selections.d.ts.map +1 -0
- package/lib/util/selections.js +148 -0
- package/lib/util/selections.js.map +1 -0
- package/package.json +8 -8
- package/src/field-builder.ts +12 -12
- package/src/generator.ts +18 -0
- package/src/global-types.ts +59 -12
- package/src/index.ts +75 -1
- package/src/model-loader.ts +27 -106
- package/src/prisma-field-builder.ts +199 -147
- package/src/schema-builder.ts +29 -7
- package/src/types.ts +149 -102
- package/src/{cursors.ts → util/cursors.ts} +45 -20
- package/src/{refs.ts → util/datamodel.ts} +36 -40
- package/src/util/deep-equal.ts +51 -0
- package/src/{loader-map.ts → util/loader-map.ts} +13 -13
- package/src/util/map-query.ts +327 -0
- package/src/util/relation-map.ts +36 -0
- package/src/util/selections.ts +192 -0
- package/esm/cursors.d.ts.map +0 -1
- package/esm/cursors.js.map +0 -1
- package/esm/loader-map.d.ts +0 -6
- package/esm/loader-map.d.ts.map +0 -1
- package/esm/loader-map.js.map +0 -1
- package/esm/refs.d.ts.map +0 -1
- package/esm/refs.js.map +0 -1
- package/esm/util/index.d.ts +0 -5
- package/esm/util/index.d.ts.map +0 -1
- package/esm/util/index.js +0 -16
- package/esm/util/index.js.map +0 -1
- package/esm/util/map-includes.d.ts +0 -6
- package/esm/util/map-includes.d.ts.map +0 -1
- package/esm/util/map-includes.js +0 -184
- package/esm/util/map-includes.js.map +0 -1
- package/esm/util/merge-includes.d.ts +0 -3
- package/esm/util/merge-includes.d.ts.map +0 -1
- package/esm/util/merge-includes.js +0 -91
- package/esm/util/merge-includes.js.map +0 -1
- package/lib/cursors.d.ts.map +0 -1
- package/lib/cursors.js.map +0 -1
- package/lib/loader-map.d.ts +0 -6
- package/lib/loader-map.d.ts.map +0 -1
- package/lib/loader-map.js.map +0 -1
- package/lib/refs.d.ts.map +0 -1
- package/lib/refs.js.map +0 -1
- package/lib/util/index.d.ts +0 -5
- package/lib/util/index.d.ts.map +0 -1
- package/lib/util/index.js +0 -30
- package/lib/util/index.js.map +0 -1
- package/lib/util/map-includes.d.ts +0 -6
- package/lib/util/map-includes.d.ts.map +0 -1
- package/lib/util/map-includes.js +0 -189
- package/lib/util/map-includes.js.map +0 -1
- package/lib/util/merge-includes.d.ts +0 -3
- package/lib/util/merge-includes.d.ts.map +0 -1
- package/lib/util/merge-includes.js +0 -96
- package/lib/util/merge-includes.js.map +0 -1
- package/src/util/index.ts +0 -26
- package/src/util/map-includes.ts +0 -328
- package/src/util/merge-includes.ts +0 -121
package/src/types.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
InterfaceParam,
|
|
11
11
|
ListResolveValue,
|
|
12
12
|
MaybePromise,
|
|
13
|
+
Normalize,
|
|
13
14
|
ObjectRef,
|
|
14
15
|
OutputShape,
|
|
15
16
|
OutputType,
|
|
@@ -26,52 +27,17 @@ export interface PrismaDelegate {
|
|
|
26
27
|
findUnique: (...args: any[]) => Promise<unknown>;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
[K in keyof T]: T[K] extends (args: {}) => {
|
|
31
|
-
then: (cb: (result: unknown) => unknown) => unknown;
|
|
32
|
-
}
|
|
33
|
-
? K
|
|
34
|
-
: never;
|
|
35
|
-
}[keyof T];
|
|
36
|
-
|
|
37
|
-
export type ModelTypes<Model extends {}> = Model extends {
|
|
38
|
-
findUnique: (
|
|
39
|
-
options: infer UniqueOptions & {
|
|
40
|
-
where?: infer Where | null | undefined;
|
|
41
|
-
select?: infer Select | null | undefined;
|
|
42
|
-
} & (
|
|
43
|
-
| {
|
|
44
|
-
include?: infer Include | null | undefined;
|
|
45
|
-
}
|
|
46
|
-
| {}
|
|
47
|
-
),
|
|
48
|
-
) => infer Chain & {
|
|
49
|
-
then: (cb: (result: infer Shape | null) => unknown) => unknown;
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
? PrismaModelTypes & {
|
|
53
|
-
Shape: Shape;
|
|
54
|
-
Include: unknown extends Include ? never : Include;
|
|
55
|
-
Where: Where;
|
|
56
|
-
Fields: keyof Select;
|
|
57
|
-
ListRelation: ListRelationFields<Include> & string;
|
|
58
|
-
Relations: {
|
|
59
|
-
[RelationName in RelationKeys<Chain>]: Chain[RelationName] extends (args: {}) => {
|
|
60
|
-
then: (cb: (result: infer Relation) => unknown) => unknown;
|
|
61
|
-
}
|
|
62
|
-
? { Shape: Relation; Types: PrismaModelTypes }
|
|
63
|
-
: never;
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
: never;
|
|
30
|
+
export const prismaModelName = Symbol.for('Pothos.prismaModelName');
|
|
67
31
|
|
|
68
32
|
export interface PrismaModelTypes {
|
|
69
33
|
Name: string;
|
|
70
34
|
Shape: {};
|
|
71
35
|
Include: unknown;
|
|
36
|
+
Select: unknown;
|
|
72
37
|
Where: {};
|
|
73
38
|
Fields: string;
|
|
74
39
|
ListRelations: string;
|
|
40
|
+
RelationName: string;
|
|
75
41
|
Relations: Record<
|
|
76
42
|
string,
|
|
77
43
|
{
|
|
@@ -81,52 +47,97 @@ export interface PrismaModelTypes {
|
|
|
81
47
|
>;
|
|
82
48
|
}
|
|
83
49
|
|
|
84
|
-
|
|
85
|
-
[
|
|
86
|
-
|
|
87
|
-
|
|
50
|
+
type ExtractModel<Types extends SchemaTypes, ParentShape> = ParentShape extends {
|
|
51
|
+
[prismaModelName]?: infer Name;
|
|
52
|
+
}
|
|
53
|
+
? Types['PrismaTypes'][Name & keyof Types['PrismaTypes']] extends infer Model
|
|
54
|
+
? Model extends PrismaModelTypes
|
|
55
|
+
? Model
|
|
88
56
|
: never
|
|
89
|
-
: never
|
|
90
|
-
|
|
57
|
+
: never
|
|
58
|
+
: never;
|
|
91
59
|
|
|
92
|
-
export type
|
|
60
|
+
export type PrismaObjectFieldOptions<
|
|
61
|
+
Types extends SchemaTypes,
|
|
62
|
+
ParentShape,
|
|
63
|
+
Type extends TypeParam<Types>,
|
|
64
|
+
Nullable extends FieldNullability<Type>,
|
|
65
|
+
Args extends InputFieldMap,
|
|
66
|
+
Select,
|
|
67
|
+
ResolveReturnShape,
|
|
68
|
+
> = PothosSchemaTypes.ObjectFieldOptions<
|
|
69
|
+
Types,
|
|
70
|
+
unknown extends Select
|
|
71
|
+
? ParentShape
|
|
72
|
+
: ParentShape &
|
|
73
|
+
ShapeFromSelection<
|
|
74
|
+
ExtractModel<Types, ParentShape>,
|
|
75
|
+
{ select: Select extends (...args: any[]) => infer S ? S : Select }
|
|
76
|
+
>,
|
|
77
|
+
Type,
|
|
78
|
+
Nullable,
|
|
79
|
+
Args,
|
|
80
|
+
ResolveReturnShape
|
|
81
|
+
> & {
|
|
82
|
+
select?: Select &
|
|
83
|
+
(
|
|
84
|
+
| ExtractModel<Types, ParentShape>['Select']
|
|
85
|
+
| ((
|
|
86
|
+
args: InputShapeFromFields<Args>,
|
|
87
|
+
ctx: Types['Context'],
|
|
88
|
+
) => ExtractModel<Types, ParentShape>['Select'])
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
type PrismaObjectFieldsShape<
|
|
93
93
|
Types extends SchemaTypes,
|
|
94
94
|
Model extends PrismaModelTypes,
|
|
95
95
|
NeedsResolve extends boolean,
|
|
96
96
|
Shape extends object,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
: {
|
|
102
|
-
[K in keyof Include &
|
|
103
|
-
keyof Model['Relations']]: Model['Relations'][K]['Shape'] extends infer RelationShape
|
|
104
|
-
? RelationShape extends (infer ItemShape)[]
|
|
105
|
-
? (ItemShape &
|
|
106
|
-
(Include[K] extends { include?: infer NestedInclude & object }
|
|
107
|
-
? ShapeFromInclude<Model['Relations'][K]['Types'], NestedInclude>
|
|
108
|
-
: {}))[]
|
|
109
|
-
: RelationShape &
|
|
110
|
-
(
|
|
111
|
-
| (Include[K] extends { include?: infer NestedInclude & object }
|
|
112
|
-
? ShapeFromInclude<Model['Relations'][K]['Types'], NestedInclude>
|
|
113
|
-
: {})
|
|
114
|
-
| null
|
|
115
|
-
)
|
|
116
|
-
: never;
|
|
117
|
-
};
|
|
97
|
+
Select,
|
|
98
|
+
> = Model['Select'] extends Select
|
|
99
|
+
? (t: PrismaObjectFieldBuilder<Types, Model, NeedsResolve, Shape>) => FieldMap
|
|
100
|
+
: (t: PrismaSelectionFieldBuilder<Types, Model, Shape>) => FieldMap;
|
|
118
101
|
|
|
119
|
-
|
|
102
|
+
type PrismaSelectionFieldBuilder<
|
|
103
|
+
Types extends SchemaTypes,
|
|
120
104
|
Model extends PrismaModelTypes,
|
|
121
|
-
|
|
122
|
-
> =
|
|
105
|
+
Shape extends object,
|
|
106
|
+
> = PrismaObjectFieldBuilder<Types, Model, false, Shape>;
|
|
107
|
+
|
|
108
|
+
interface BaseSelection {
|
|
109
|
+
include?: unknown;
|
|
110
|
+
select?: unknown;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export type SelectedKeys<T> = { [K in keyof T]: T[K] extends false ? never : K }[keyof T];
|
|
114
|
+
|
|
115
|
+
export type ShapeFromSelection<Model extends PrismaModelTypes, Selection> = Normalize<
|
|
116
|
+
Selection extends BaseSelection
|
|
117
|
+
? unknown extends Selection['select']
|
|
118
|
+
? Model['Shape'] & RelationShapeFromInclude<Model, Selection['include']>
|
|
119
|
+
: Pick<Model['Shape'], SelectedKeys<Selection['select']>> &
|
|
120
|
+
RelationShapeFromInclude<Model, Selection['select']>
|
|
121
|
+
: Model['Shape']
|
|
122
|
+
>;
|
|
123
|
+
|
|
124
|
+
type RelationShapeFromInclude<Model extends PrismaModelTypes, Include> = Normalize<{
|
|
125
|
+
[K in SelectedKeys<Include> as K extends Model['RelationName']
|
|
126
|
+
? K
|
|
127
|
+
: never]: K extends keyof Model['Relations']
|
|
128
|
+
? Model['Relations'][K]['Shape'] extends unknown[]
|
|
129
|
+
? ShapeFromSelection<Model['Relations'][K]['Types'], Include[K]>[]
|
|
130
|
+
: ShapeFromSelection<Model['Relations'][K]['Types'], Include[K]>
|
|
131
|
+
: unknown;
|
|
132
|
+
}>;
|
|
123
133
|
|
|
124
134
|
export type PrismaObjectTypeOptions<
|
|
125
135
|
Types extends SchemaTypes,
|
|
126
136
|
Model extends PrismaModelTypes,
|
|
127
137
|
Interfaces extends InterfaceParam<Types>[],
|
|
128
138
|
FindUnique,
|
|
129
|
-
Include
|
|
139
|
+
Include,
|
|
140
|
+
Select,
|
|
130
141
|
Shape extends object,
|
|
131
142
|
> = NameOrVariant &
|
|
132
143
|
Omit<
|
|
@@ -134,13 +145,28 @@ export type PrismaObjectTypeOptions<
|
|
|
134
145
|
| PothosSchemaTypes.ObjectTypeWithInterfaceOptions<Types, Shape, Interfaces>,
|
|
135
146
|
'fields'
|
|
136
147
|
> & {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
148
|
+
fields?: PrismaObjectFieldsShape<
|
|
149
|
+
Types,
|
|
150
|
+
Model,
|
|
151
|
+
FindUnique extends null ? true : false,
|
|
152
|
+
Shape & (FindUnique extends null ? {} : { [prismaModelName]?: Model['Name'] }),
|
|
153
|
+
Select
|
|
154
|
+
>;
|
|
155
|
+
} & (
|
|
156
|
+
| {
|
|
157
|
+
include?: Include & Model['Include'];
|
|
158
|
+
select?: never;
|
|
159
|
+
findUnique: FindUnique &
|
|
160
|
+
(((parent: Shape, context: Types['Context']) => Model['Where']) | null);
|
|
161
|
+
}
|
|
162
|
+
| {
|
|
163
|
+
select: Model['Select'] & Select;
|
|
164
|
+
include?: never;
|
|
165
|
+
findUnique: (parent: Shape, context: Types['Context']) => Model['Where'];
|
|
166
|
+
}
|
|
167
|
+
);
|
|
142
168
|
|
|
143
|
-
|
|
169
|
+
type NameOrVariant =
|
|
144
170
|
| {
|
|
145
171
|
name?: never;
|
|
146
172
|
variant?: string;
|
|
@@ -154,7 +180,8 @@ export type PrismaNodeOptions<
|
|
|
154
180
|
Types extends SchemaTypes,
|
|
155
181
|
Model extends PrismaModelTypes,
|
|
156
182
|
Interfaces extends InterfaceParam<Types>[],
|
|
157
|
-
Include
|
|
183
|
+
Include,
|
|
184
|
+
Select,
|
|
158
185
|
Shape extends object,
|
|
159
186
|
> = NameOrVariant &
|
|
160
187
|
Omit<
|
|
@@ -162,7 +189,6 @@ export type PrismaNodeOptions<
|
|
|
162
189
|
| PothosSchemaTypes.ObjectTypeWithInterfaceOptions<Types, Shape, Interfaces>,
|
|
163
190
|
'fields' | 'isTypeOf'
|
|
164
191
|
> & {
|
|
165
|
-
include?: Include;
|
|
166
192
|
id: Omit<
|
|
167
193
|
FieldOptionsFromKind<
|
|
168
194
|
Types,
|
|
@@ -178,11 +204,26 @@ export type PrismaNodeOptions<
|
|
|
178
204
|
> & {
|
|
179
205
|
resolve: (parent: Shape, context: Types['Context']) => MaybePromise<OutputShape<Types, 'ID'>>;
|
|
180
206
|
};
|
|
181
|
-
fields?: PrismaObjectFieldsShape<
|
|
207
|
+
fields?: PrismaObjectFieldsShape<
|
|
208
|
+
Types,
|
|
209
|
+
Model,
|
|
210
|
+
false,
|
|
211
|
+
Shape & { [prismaModelName]?: Model['Name'] },
|
|
212
|
+
Select
|
|
213
|
+
>;
|
|
182
214
|
findUnique: (id: string, context: Types['Context']) => Model['Where'];
|
|
183
|
-
}
|
|
215
|
+
} & (
|
|
216
|
+
| {
|
|
217
|
+
include?: Include & Model['Include'];
|
|
218
|
+
select?: never;
|
|
219
|
+
}
|
|
220
|
+
| {
|
|
221
|
+
select: Model['Select'] & Select;
|
|
222
|
+
include?: never;
|
|
223
|
+
}
|
|
224
|
+
);
|
|
184
225
|
|
|
185
|
-
|
|
226
|
+
type QueryForField<
|
|
186
227
|
Types extends SchemaTypes,
|
|
187
228
|
Args extends InputFieldMap,
|
|
188
229
|
Include,
|
|
@@ -195,18 +236,19 @@ export type QueryForField<
|
|
|
195
236
|
) => Omit<Include, 'include' | 'select'>)
|
|
196
237
|
: never;
|
|
197
238
|
|
|
198
|
-
|
|
239
|
+
type QueryFromRelation<
|
|
199
240
|
Model extends PrismaModelTypes,
|
|
200
241
|
Field extends keyof Model['Include'],
|
|
201
242
|
> = Model['Include'][Field] extends infer Include
|
|
202
243
|
? Include extends {
|
|
203
|
-
include?: infer
|
|
244
|
+
include?: infer I;
|
|
245
|
+
select?: infer S;
|
|
204
246
|
}
|
|
205
|
-
? NonNullable<
|
|
247
|
+
? { include?: NonNullable<I>; select?: NonNullable<S> }
|
|
206
248
|
: never
|
|
207
249
|
: never;
|
|
208
250
|
|
|
209
|
-
|
|
251
|
+
type CursorFromRelation<
|
|
210
252
|
Model extends PrismaModelTypes,
|
|
211
253
|
Field extends Model['ListRelations'],
|
|
212
254
|
> = Field extends keyof Model['Include']
|
|
@@ -217,7 +259,7 @@ export type CursorFromRelation<
|
|
|
217
259
|
: never
|
|
218
260
|
: never;
|
|
219
261
|
|
|
220
|
-
|
|
262
|
+
type RefForRelation<
|
|
221
263
|
Model extends PrismaModelTypes,
|
|
222
264
|
Field extends keyof Model['Relations'],
|
|
223
265
|
> = Model['Relations'][Field] extends unknown[]
|
|
@@ -247,7 +289,7 @@ export type RelatedFieldOptions<
|
|
|
247
289
|
(NeedsResolve extends false
|
|
248
290
|
? {
|
|
249
291
|
resolve?: (
|
|
250
|
-
query:
|
|
292
|
+
query: QueryFromRelation<Model, Field & keyof Model['Include']>,
|
|
251
293
|
parent: Shape,
|
|
252
294
|
args: InputShapeFromFields<Args>,
|
|
253
295
|
context: Types['Context'],
|
|
@@ -258,7 +300,7 @@ export type RelatedFieldOptions<
|
|
|
258
300
|
}
|
|
259
301
|
: {
|
|
260
302
|
resolve: (
|
|
261
|
-
query:
|
|
303
|
+
query: QueryFromRelation<Model, Field & keyof Model['Include']>,
|
|
262
304
|
parent: Shape,
|
|
263
305
|
args: InputShapeFromFields<Args>,
|
|
264
306
|
context: Types['Context'],
|
|
@@ -472,31 +514,36 @@ export type RelatedConnectionOptions<
|
|
|
472
514
|
|
|
473
515
|
export type WithBrand<T> = T & { [typeBrandKey]: string };
|
|
474
516
|
|
|
475
|
-
export type IncludeMap = Record<string,
|
|
517
|
+
export type IncludeMap = Record<string, SelectionMap | boolean>;
|
|
476
518
|
|
|
477
|
-
export interface
|
|
478
|
-
|
|
479
|
-
|
|
519
|
+
export interface SelectionMap {
|
|
520
|
+
select?: Record<string, SelectionMap | boolean>;
|
|
521
|
+
include?: Record<string, SelectionMap | boolean>;
|
|
522
|
+
where?: {};
|
|
480
523
|
}
|
|
481
524
|
|
|
525
|
+
export type FieldSelection =
|
|
526
|
+
| Record<string, SelectionMap | boolean>
|
|
527
|
+
| ((
|
|
528
|
+
args: object,
|
|
529
|
+
context: object,
|
|
530
|
+
query: (
|
|
531
|
+
selection: SelectionMap | boolean | ((args: object, context: object) => SelectionMap),
|
|
532
|
+
) => SelectionMap | boolean,
|
|
533
|
+
) => SelectionMap);
|
|
534
|
+
|
|
482
535
|
export type LoaderMappings = Record<
|
|
483
536
|
string,
|
|
484
537
|
{
|
|
485
538
|
field: string;
|
|
486
|
-
alias?: string;
|
|
487
539
|
mappings: LoaderMappings;
|
|
488
540
|
indirectPath: string[];
|
|
489
|
-
}
|
|
541
|
+
}
|
|
490
542
|
>;
|
|
491
543
|
|
|
492
|
-
export interface
|
|
493
|
-
|
|
494
|
-
name: string;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
export interface IndirectLoadMap {
|
|
498
|
-
subFields: SubFieldInclude[];
|
|
499
|
-
path: string[];
|
|
544
|
+
export interface IndirectInclude {
|
|
545
|
+
getType: () => string;
|
|
546
|
+
path: { type?: string; name: string }[];
|
|
500
547
|
}
|
|
501
548
|
|
|
502
549
|
export type ShapeFromConnection<T> = T extends { shape: unknown } ? T['shape'] : never;
|
|
@@ -4,22 +4,34 @@ import { MaybePromise } from '@pothos/core';
|
|
|
4
4
|
const DEFAULT_MAX_SIZE = 100;
|
|
5
5
|
const DEFAULT_SIZE = 20;
|
|
6
6
|
|
|
7
|
-
function
|
|
7
|
+
export function formatCursorChunk(value: unknown) {
|
|
8
8
|
if (value instanceof Date) {
|
|
9
|
-
return
|
|
9
|
+
return `D:${String(Number(value))}`;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
switch (typeof value) {
|
|
13
13
|
case 'number':
|
|
14
|
-
return
|
|
14
|
+
return `N:${value}`;
|
|
15
15
|
case 'string':
|
|
16
|
-
return
|
|
16
|
+
return `S:${value}`;
|
|
17
17
|
default:
|
|
18
18
|
throw new TypeError(`Unsupported cursor type ${typeof value}`);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function
|
|
22
|
+
export function formatCursor(fields: string | string[]) {
|
|
23
|
+
return (value: Record<string, unknown>) => {
|
|
24
|
+
if (typeof fields === 'string') {
|
|
25
|
+
return Buffer.from(`GPC:${formatCursorChunk(value[fields])}`).toString('base64');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return Buffer.from(`GPC:J:${JSON.stringify(fields.map((name) => value[name]))}`).toString(
|
|
29
|
+
'base64',
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function parseRawCursor(cursor: unknown) {
|
|
23
35
|
if (typeof cursor !== 'string') {
|
|
24
36
|
throw new TypeError('Cursor must be a string');
|
|
25
37
|
}
|
|
@@ -35,6 +47,8 @@ function parseCursor(cursor: unknown) {
|
|
|
35
47
|
return Number.parseInt(value, 10);
|
|
36
48
|
case 'D':
|
|
37
49
|
return new Date(Number.parseInt(value, 10));
|
|
50
|
+
case 'J':
|
|
51
|
+
return JSON.parse(value) as unknown;
|
|
38
52
|
default:
|
|
39
53
|
throw new TypeError(`Invalid cursor type ${type}`);
|
|
40
54
|
}
|
|
@@ -43,11 +57,29 @@ function parseCursor(cursor: unknown) {
|
|
|
43
57
|
}
|
|
44
58
|
}
|
|
45
59
|
|
|
46
|
-
|
|
60
|
+
export function parseCompositeCursor(fields: string[]) {
|
|
61
|
+
return (cursor: string) => {
|
|
62
|
+
const parsed = parseRawCursor(cursor) as unknown[];
|
|
63
|
+
|
|
64
|
+
if (!Array.isArray(parsed)) {
|
|
65
|
+
throw new TypeError(`Expected compound cursor to contain an array, but got ${parsed}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const record: Record<string, unknown> = {};
|
|
69
|
+
|
|
70
|
+
fields.forEach((field, i) => {
|
|
71
|
+
record[field] = parsed[i];
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return record;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface PrismaCursorConnectionQueryOptions {
|
|
47
79
|
args: PothosSchemaTypes.DefaultConnectionArguments;
|
|
48
80
|
defaultSize?: number;
|
|
49
81
|
maxSize?: number;
|
|
50
|
-
|
|
82
|
+
parseCursor: (cursor: string) => Record<string, unknown>;
|
|
51
83
|
}
|
|
52
84
|
|
|
53
85
|
interface ResolvePrismaCursorConnectionOptions extends PrismaCursorConnectionQueryOptions {
|
|
@@ -59,7 +91,7 @@ export function prismaCursorConnectionQuery({
|
|
|
59
91
|
args: { before, after, first, last },
|
|
60
92
|
maxSize = DEFAULT_MAX_SIZE,
|
|
61
93
|
defaultSize = DEFAULT_SIZE,
|
|
62
|
-
|
|
94
|
+
parseCursor,
|
|
63
95
|
}: PrismaCursorConnectionQueryOptions) {
|
|
64
96
|
if (first != null && first < 0) {
|
|
65
97
|
throw new TypeError('Argument "first" must be a non-negative integer');
|
|
@@ -96,9 +128,7 @@ export function prismaCursorConnectionQuery({
|
|
|
96
128
|
return cursor == null
|
|
97
129
|
? { take, skip: 0 }
|
|
98
130
|
: {
|
|
99
|
-
cursor:
|
|
100
|
-
[column]: parseCursor(cursor),
|
|
101
|
-
},
|
|
131
|
+
cursor: parseCursor(cursor),
|
|
102
132
|
take,
|
|
103
133
|
skip: 1,
|
|
104
134
|
};
|
|
@@ -108,7 +138,7 @@ export function wrapConnectionResult<T extends {}>(
|
|
|
108
138
|
results: T[],
|
|
109
139
|
args: PothosSchemaTypes.DefaultConnectionArguments,
|
|
110
140
|
take: number,
|
|
111
|
-
|
|
141
|
+
cursor: (node: T) => string,
|
|
112
142
|
totalCount?: number,
|
|
113
143
|
) {
|
|
114
144
|
const gotFullResults = results.length === Math.abs(take);
|
|
@@ -122,7 +152,7 @@ export function wrapConnectionResult<T extends {}>(
|
|
|
122
152
|
value == null
|
|
123
153
|
? null
|
|
124
154
|
: {
|
|
125
|
-
cursor:
|
|
155
|
+
cursor: cursor(value),
|
|
126
156
|
node: value,
|
|
127
157
|
},
|
|
128
158
|
);
|
|
@@ -141,6 +171,7 @@ export function wrapConnectionResult<T extends {}>(
|
|
|
141
171
|
|
|
142
172
|
export async function resolvePrismaCursorConnection<T extends {}>(
|
|
143
173
|
options: ResolvePrismaCursorConnectionOptions,
|
|
174
|
+
cursor: (node: T) => string,
|
|
144
175
|
resolve: (query: { include?: {}; cursor?: {}; take: number; skip: number }) => MaybePromise<T[]>,
|
|
145
176
|
) {
|
|
146
177
|
const query = prismaCursorConnectionQuery(options);
|
|
@@ -149,11 +180,5 @@ export async function resolvePrismaCursorConnection<T extends {}>(
|
|
|
149
180
|
...query,
|
|
150
181
|
});
|
|
151
182
|
|
|
152
|
-
return wrapConnectionResult(
|
|
153
|
-
results,
|
|
154
|
-
options.args,
|
|
155
|
-
query.take,
|
|
156
|
-
options.column,
|
|
157
|
-
options.totalCount,
|
|
158
|
-
);
|
|
183
|
+
return wrapConnectionResult(results, options.args, query.take, cursor, options.totalCount);
|
|
159
184
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ObjectRef, SchemaTypes } from '@pothos/core';
|
|
2
|
-
import { Prisma } from '
|
|
3
|
-
import { PrismaObjectRef } from '
|
|
4
|
-
import { PrismaDelegate } from '
|
|
5
|
-
import {
|
|
2
|
+
import { Prisma } from '../../tests/client';
|
|
3
|
+
import { PrismaObjectRef } from '../object-ref';
|
|
4
|
+
import { PrismaDelegate, PrismaModelTypes } from '../types';
|
|
5
|
+
import { formatCursor, parseCompositeCursor, parseRawCursor } from './cursors';
|
|
6
6
|
|
|
7
7
|
export const refMap = new WeakMap<object, Map<string, PrismaObjectRef<PrismaModelTypes>>>();
|
|
8
8
|
export const findUniqueMap = new WeakMap<
|
|
@@ -31,40 +31,29 @@ export function getRefFromModel<Types extends SchemaTypes>(
|
|
|
31
31
|
return cache.get(name)!;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export function
|
|
35
|
-
|
|
34
|
+
export function getRelation<Types extends SchemaTypes>(
|
|
35
|
+
name: string,
|
|
36
36
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
37
|
+
relation: string,
|
|
37
38
|
) {
|
|
38
|
-
|
|
39
|
-
findUniqueMap.set(builder, new Map());
|
|
40
|
-
}
|
|
41
|
-
const cache = findUniqueMap.get(builder)!;
|
|
39
|
+
const modelData = getModel(name, builder);
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
41
|
+
const fieldData = modelData.fields.find((field) => field.name === relation);
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
}
|
|
43
|
+
if (!fieldData) {
|
|
44
|
+
throw new Error(`Field '${relation}' not found in model '${name}'`);
|
|
45
|
+
}
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
-
findUnique: ((args: any, context: Types['Context']) => unknown) | null,
|
|
55
|
-
) {
|
|
56
|
-
if (!findUniqueMap.has(builder)) {
|
|
57
|
-
findUniqueMap.set(builder, new Map());
|
|
47
|
+
if (fieldData.kind !== 'object') {
|
|
48
|
+
throw new Error(`Field ${relation} of model '${name}' is not a relation (${fieldData.kind})`);
|
|
58
49
|
}
|
|
59
|
-
const cache = findUniqueMap.get(builder)!;
|
|
60
50
|
|
|
61
|
-
|
|
51
|
+
return fieldData;
|
|
62
52
|
}
|
|
63
53
|
|
|
64
|
-
export function
|
|
54
|
+
export function getModel<Types extends SchemaTypes>(
|
|
65
55
|
name: string,
|
|
66
56
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
67
|
-
relation: string,
|
|
68
57
|
) {
|
|
69
58
|
const { client } = builder.options.prisma;
|
|
70
59
|
// eslint-disable-next-line no-underscore-dangle
|
|
@@ -76,27 +65,34 @@ export function getRelation<Types extends SchemaTypes>(
|
|
|
76
65
|
throw new Error(`Model '${name}' not found in DMMF`);
|
|
77
66
|
}
|
|
78
67
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (!fieldData) {
|
|
82
|
-
throw new Error(`Field '${relation}' not found in model '${name}'`);
|
|
83
|
-
}
|
|
68
|
+
return modelData;
|
|
69
|
+
}
|
|
84
70
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
71
|
+
export function getCursorFormatter<Types extends SchemaTypes>(
|
|
72
|
+
name: string,
|
|
73
|
+
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
74
|
+
cursor: string,
|
|
75
|
+
) {
|
|
76
|
+
const modelData = getModel(name, builder);
|
|
77
|
+
const primaryKey = modelData.primaryKey?.name ?? modelData.primaryKey?.fields.join('_');
|
|
88
78
|
|
|
89
|
-
return
|
|
79
|
+
return formatCursor(cursor === primaryKey ? modelData.primaryKey!.fields : cursor);
|
|
90
80
|
}
|
|
91
81
|
|
|
92
|
-
export function
|
|
82
|
+
export function getCursorParser<Types extends SchemaTypes>(
|
|
93
83
|
name: string,
|
|
94
84
|
builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
|
95
|
-
|
|
85
|
+
cursor: string,
|
|
96
86
|
) {
|
|
97
|
-
const
|
|
87
|
+
const modelData = getModel(name, builder);
|
|
88
|
+
const primaryKey = modelData.primaryKey?.name ?? modelData.primaryKey?.fields.join('_');
|
|
89
|
+
|
|
90
|
+
const parser =
|
|
91
|
+
cursor === primaryKey ? parseCompositeCursor(modelData.primaryKey!.fields) : parseRawCursor;
|
|
98
92
|
|
|
99
|
-
return
|
|
93
|
+
return (rawCursor: string) => ({
|
|
94
|
+
[cursor]: parser(rawCursor),
|
|
95
|
+
});
|
|
100
96
|
}
|
|
101
97
|
|
|
102
98
|
export function getDelegateFromModel(client: Record<string, unknown>, model: string) {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* eslint-disable no-continue */
|
|
2
|
+
export function deepEqual(left: unknown, right: unknown, ignore?: Set<string>) {
|
|
3
|
+
if (left === right) {
|
|
4
|
+
return true;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (left && right && typeof left === 'object' && typeof right === 'object') {
|
|
8
|
+
if (Array.isArray(left)) {
|
|
9
|
+
if (!Array.isArray(right)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { length } = left;
|
|
14
|
+
|
|
15
|
+
if (right.length !== length) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < length; i += 1) {
|
|
20
|
+
if (!deepEqual(left[i], right[i])) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const keys = Object.keys(left);
|
|
29
|
+
const keyLength = keys.length;
|
|
30
|
+
|
|
31
|
+
if (keyLength !== Object.keys(right).length) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const key of keys) {
|
|
36
|
+
if (ignore?.has(key)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (
|
|
41
|
+
!deepEqual((left as Record<string, unknown>)[key], (right as Record<string, unknown>)[key])
|
|
42
|
+
) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return false;
|
|
51
|
+
}
|