@pothos/plugin-prisma 0.17.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +403 -308
- package/esm/field-builder.js +12 -14
- 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 +12 -69
- 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 +86 -117
- 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 +16 -18
- package/lib/field-builder.js.map +1 -1
- package/lib/generator.js +4 -0
- 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 +45 -0
- 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 +13 -70
- 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 +90 -121
- package/lib/prisma-field-builder.js.map +1 -1
- package/lib/schema-builder.js +18 -7
- 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 +7 -7
- 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 +19 -92
- package/src/prisma-field-builder.ts +199 -147
- package/src/schema-builder.ts +29 -7
- package/src/types.ts +138 -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/.turbo/turbo-build.log +0 -17
- package/.turbo/turbo-test.log +0 -18
- package/.turbo/turbo-type.log +0 -5
- package/babel.config.js +0 -3
- 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/tsconfig.tsbuildinfo +0 -1
package/src/schema-builder.ts
CHANGED
|
@@ -10,21 +10,22 @@ import SchemaBuilder, {
|
|
|
10
10
|
TypeParam,
|
|
11
11
|
} from '@pothos/core';
|
|
12
12
|
import { PrismaObjectFieldBuilder } from './field-builder';
|
|
13
|
+
import { ModelLoader } from './model-loader';
|
|
13
14
|
import PrismaNodeRef from './node-ref';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { queryFromInfo } from './util';
|
|
15
|
+
import { PrismaModelTypes, PrismaNodeOptions } from './types';
|
|
16
|
+
import { getDelegateFromModel, getRefFromModel } from './util/datamodel';
|
|
17
|
+
import { queryFromInfo } from './util/map-query';
|
|
18
|
+
import { getRelationMap } from './util/relation-map';
|
|
17
19
|
|
|
18
20
|
const schemaBuilderProto = SchemaBuilder.prototype as PothosSchemaTypes.SchemaBuilder<SchemaTypes>;
|
|
19
21
|
|
|
20
22
|
schemaBuilderProto.prismaObject = function prismaObject(type, { fields, findUnique, ...options }) {
|
|
21
23
|
const ref = options.variant ? this.objectRef(options.variant) : getRefFromModel(type, this);
|
|
22
24
|
const name = options.variant ?? options.name ?? type;
|
|
25
|
+
const fieldMap = getRelationMap(this.options.prisma.client).get(type)!;
|
|
23
26
|
|
|
24
27
|
ref.name = name;
|
|
25
28
|
|
|
26
|
-
setFindUniqueForRef(ref, this, findUnique);
|
|
27
|
-
|
|
28
29
|
this.objectType(ref, {
|
|
29
30
|
...(options as {} as PothosSchemaTypes.ObjectFieldOptions<
|
|
30
31
|
SchemaTypes,
|
|
@@ -37,9 +38,30 @@ schemaBuilderProto.prismaObject = function prismaObject(type, { fields, findUniq
|
|
|
37
38
|
extensions: {
|
|
38
39
|
...options.extensions,
|
|
39
40
|
pothosPrismaInclude: options.include,
|
|
41
|
+
pothosPrismaModel: type,
|
|
42
|
+
pothosPrismaFieldMap: fieldMap,
|
|
43
|
+
pothosPrismaSelect: options.select,
|
|
44
|
+
pothosPrismaLoader: ModelLoader.forRef(
|
|
45
|
+
type,
|
|
46
|
+
(findUnique as never) ||
|
|
47
|
+
(() => {
|
|
48
|
+
throw new Error(`Missing findUnique for ${ref.name}`);
|
|
49
|
+
}),
|
|
50
|
+
this,
|
|
51
|
+
),
|
|
40
52
|
},
|
|
41
53
|
name,
|
|
42
|
-
fields: fields
|
|
54
|
+
fields: fields
|
|
55
|
+
? () =>
|
|
56
|
+
fields(
|
|
57
|
+
new PrismaObjectFieldBuilder(
|
|
58
|
+
name,
|
|
59
|
+
this,
|
|
60
|
+
type,
|
|
61
|
+
getRelationMap(this.options.prisma.client).get(type)!,
|
|
62
|
+
),
|
|
63
|
+
)
|
|
64
|
+
: undefined,
|
|
43
65
|
});
|
|
44
66
|
|
|
45
67
|
return ref as never;
|
|
@@ -55,7 +77,7 @@ schemaBuilderProto.prismaNode = function prismaNode(
|
|
|
55
77
|
name,
|
|
56
78
|
variant,
|
|
57
79
|
...options
|
|
58
|
-
}: PrismaNodeOptions<SchemaTypes,
|
|
80
|
+
}: PrismaNodeOptions<SchemaTypes, PrismaModelTypes, [], never, {}, {}>,
|
|
59
81
|
) {
|
|
60
82
|
const interfaceRef = this.nodeInterfaceRef?.();
|
|
61
83
|
|
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,86 @@ 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 & ShapeFromSelection<ExtractModel<Types, ParentShape>, { select: Select }>,
|
|
73
|
+
Type,
|
|
74
|
+
Nullable,
|
|
75
|
+
Args,
|
|
76
|
+
ResolveReturnShape
|
|
77
|
+
> & {
|
|
78
|
+
select?: ExtractModel<Types, ParentShape>['Select'] & Select;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
type PrismaObjectFieldsShape<
|
|
93
82
|
Types extends SchemaTypes,
|
|
94
83
|
Model extends PrismaModelTypes,
|
|
95
84
|
NeedsResolve extends boolean,
|
|
96
85
|
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
|
-
};
|
|
86
|
+
Select,
|
|
87
|
+
> = Model['Select'] extends Select
|
|
88
|
+
? (t: PrismaObjectFieldBuilder<Types, Model, NeedsResolve, Shape>) => FieldMap
|
|
89
|
+
: (t: PrismaSelectionFieldBuilder<Types, Model, Shape>) => FieldMap;
|
|
118
90
|
|
|
119
|
-
|
|
91
|
+
type PrismaSelectionFieldBuilder<
|
|
92
|
+
Types extends SchemaTypes,
|
|
120
93
|
Model extends PrismaModelTypes,
|
|
121
|
-
|
|
122
|
-
> =
|
|
94
|
+
Shape extends object,
|
|
95
|
+
> = PrismaObjectFieldBuilder<Types, Model, false, Shape>;
|
|
96
|
+
|
|
97
|
+
interface BaseSelection {
|
|
98
|
+
include?: unknown;
|
|
99
|
+
select?: unknown;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export type SelectedKeys<T> = { [K in keyof T]: T[K] extends false ? never : K }[keyof T];
|
|
103
|
+
|
|
104
|
+
export type ShapeFromSelection<Model extends PrismaModelTypes, Selection> = Normalize<
|
|
105
|
+
Selection extends BaseSelection
|
|
106
|
+
? unknown extends Selection['select']
|
|
107
|
+
? Model['Shape'] & RelationShapeFromInclude<Model, Selection['include']>
|
|
108
|
+
: Pick<Model['Shape'], SelectedKeys<Selection['select']>> &
|
|
109
|
+
RelationShapeFromInclude<Model, Selection['select']>
|
|
110
|
+
: Model['Shape']
|
|
111
|
+
>;
|
|
112
|
+
|
|
113
|
+
type RelationShapeFromInclude<Model extends PrismaModelTypes, Include> = Normalize<{
|
|
114
|
+
[K in SelectedKeys<Include> as K extends Model['RelationName']
|
|
115
|
+
? K
|
|
116
|
+
: never]: K extends keyof Model['Relations']
|
|
117
|
+
? Model['Relations'][K]['Shape'] extends unknown[]
|
|
118
|
+
? ShapeFromSelection<Model['Relations'][K]['Types'], Include[K]>[]
|
|
119
|
+
: ShapeFromSelection<Model['Relations'][K]['Types'], Include[K]>
|
|
120
|
+
: unknown;
|
|
121
|
+
}>;
|
|
123
122
|
|
|
124
123
|
export type PrismaObjectTypeOptions<
|
|
125
124
|
Types extends SchemaTypes,
|
|
126
125
|
Model extends PrismaModelTypes,
|
|
127
126
|
Interfaces extends InterfaceParam<Types>[],
|
|
128
127
|
FindUnique,
|
|
129
|
-
Include
|
|
128
|
+
Include,
|
|
129
|
+
Select,
|
|
130
130
|
Shape extends object,
|
|
131
131
|
> = NameOrVariant &
|
|
132
132
|
Omit<
|
|
@@ -134,13 +134,28 @@ export type PrismaObjectTypeOptions<
|
|
|
134
134
|
| PothosSchemaTypes.ObjectTypeWithInterfaceOptions<Types, Shape, Interfaces>,
|
|
135
135
|
'fields'
|
|
136
136
|
> & {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
fields?: PrismaObjectFieldsShape<
|
|
138
|
+
Types,
|
|
139
|
+
Model,
|
|
140
|
+
FindUnique extends null ? true : false,
|
|
141
|
+
Shape & (FindUnique extends null ? {} : { [prismaModelName]?: Model['Name'] }),
|
|
142
|
+
Select
|
|
143
|
+
>;
|
|
144
|
+
} & (
|
|
145
|
+
| {
|
|
146
|
+
include?: Include & Model['Include'];
|
|
147
|
+
select?: never;
|
|
148
|
+
findUnique: FindUnique &
|
|
149
|
+
(((parent: Shape, context: Types['Context']) => Model['Where']) | null);
|
|
150
|
+
}
|
|
151
|
+
| {
|
|
152
|
+
select: Model['Select'] & Select;
|
|
153
|
+
include?: never;
|
|
154
|
+
findUnique: (parent: Shape, context: Types['Context']) => Model['Where'];
|
|
155
|
+
}
|
|
156
|
+
);
|
|
142
157
|
|
|
143
|
-
|
|
158
|
+
type NameOrVariant =
|
|
144
159
|
| {
|
|
145
160
|
name?: never;
|
|
146
161
|
variant?: string;
|
|
@@ -154,7 +169,8 @@ export type PrismaNodeOptions<
|
|
|
154
169
|
Types extends SchemaTypes,
|
|
155
170
|
Model extends PrismaModelTypes,
|
|
156
171
|
Interfaces extends InterfaceParam<Types>[],
|
|
157
|
-
Include
|
|
172
|
+
Include,
|
|
173
|
+
Select,
|
|
158
174
|
Shape extends object,
|
|
159
175
|
> = NameOrVariant &
|
|
160
176
|
Omit<
|
|
@@ -162,7 +178,6 @@ export type PrismaNodeOptions<
|
|
|
162
178
|
| PothosSchemaTypes.ObjectTypeWithInterfaceOptions<Types, Shape, Interfaces>,
|
|
163
179
|
'fields' | 'isTypeOf'
|
|
164
180
|
> & {
|
|
165
|
-
include?: Include;
|
|
166
181
|
id: Omit<
|
|
167
182
|
FieldOptionsFromKind<
|
|
168
183
|
Types,
|
|
@@ -178,11 +193,26 @@ export type PrismaNodeOptions<
|
|
|
178
193
|
> & {
|
|
179
194
|
resolve: (parent: Shape, context: Types['Context']) => MaybePromise<OutputShape<Types, 'ID'>>;
|
|
180
195
|
};
|
|
181
|
-
fields?: PrismaObjectFieldsShape<
|
|
196
|
+
fields?: PrismaObjectFieldsShape<
|
|
197
|
+
Types,
|
|
198
|
+
Model,
|
|
199
|
+
false,
|
|
200
|
+
Shape & { [prismaModelName]?: Model['Name'] },
|
|
201
|
+
Select
|
|
202
|
+
>;
|
|
182
203
|
findUnique: (id: string, context: Types['Context']) => Model['Where'];
|
|
183
|
-
}
|
|
204
|
+
} & (
|
|
205
|
+
| {
|
|
206
|
+
include?: Include & Model['Include'];
|
|
207
|
+
select?: never;
|
|
208
|
+
}
|
|
209
|
+
| {
|
|
210
|
+
select: Model['Select'] & Select;
|
|
211
|
+
include?: never;
|
|
212
|
+
}
|
|
213
|
+
);
|
|
184
214
|
|
|
185
|
-
|
|
215
|
+
type QueryForField<
|
|
186
216
|
Types extends SchemaTypes,
|
|
187
217
|
Args extends InputFieldMap,
|
|
188
218
|
Include,
|
|
@@ -195,18 +225,19 @@ export type QueryForField<
|
|
|
195
225
|
) => Omit<Include, 'include' | 'select'>)
|
|
196
226
|
: never;
|
|
197
227
|
|
|
198
|
-
|
|
228
|
+
type QueryFromRelation<
|
|
199
229
|
Model extends PrismaModelTypes,
|
|
200
230
|
Field extends keyof Model['Include'],
|
|
201
231
|
> = Model['Include'][Field] extends infer Include
|
|
202
232
|
? Include extends {
|
|
203
|
-
include?: infer
|
|
233
|
+
include?: infer I;
|
|
234
|
+
select?: infer S;
|
|
204
235
|
}
|
|
205
|
-
? NonNullable<
|
|
236
|
+
? { include?: NonNullable<I>; select?: NonNullable<S> }
|
|
206
237
|
: never
|
|
207
238
|
: never;
|
|
208
239
|
|
|
209
|
-
|
|
240
|
+
type CursorFromRelation<
|
|
210
241
|
Model extends PrismaModelTypes,
|
|
211
242
|
Field extends Model['ListRelations'],
|
|
212
243
|
> = Field extends keyof Model['Include']
|
|
@@ -217,7 +248,7 @@ export type CursorFromRelation<
|
|
|
217
248
|
: never
|
|
218
249
|
: never;
|
|
219
250
|
|
|
220
|
-
|
|
251
|
+
type RefForRelation<
|
|
221
252
|
Model extends PrismaModelTypes,
|
|
222
253
|
Field extends keyof Model['Relations'],
|
|
223
254
|
> = Model['Relations'][Field] extends unknown[]
|
|
@@ -247,7 +278,7 @@ export type RelatedFieldOptions<
|
|
|
247
278
|
(NeedsResolve extends false
|
|
248
279
|
? {
|
|
249
280
|
resolve?: (
|
|
250
|
-
query:
|
|
281
|
+
query: QueryFromRelation<Model, Field & keyof Model['Include']>,
|
|
251
282
|
parent: Shape,
|
|
252
283
|
args: InputShapeFromFields<Args>,
|
|
253
284
|
context: Types['Context'],
|
|
@@ -258,7 +289,7 @@ export type RelatedFieldOptions<
|
|
|
258
289
|
}
|
|
259
290
|
: {
|
|
260
291
|
resolve: (
|
|
261
|
-
query:
|
|
292
|
+
query: QueryFromRelation<Model, Field & keyof Model['Include']>,
|
|
262
293
|
parent: Shape,
|
|
263
294
|
args: InputShapeFromFields<Args>,
|
|
264
295
|
context: Types['Context'],
|
|
@@ -472,31 +503,36 @@ export type RelatedConnectionOptions<
|
|
|
472
503
|
|
|
473
504
|
export type WithBrand<T> = T & { [typeBrandKey]: string };
|
|
474
505
|
|
|
475
|
-
export type IncludeMap = Record<string,
|
|
506
|
+
export type IncludeMap = Record<string, SelectionMap | boolean>;
|
|
476
507
|
|
|
477
|
-
export interface
|
|
478
|
-
|
|
479
|
-
|
|
508
|
+
export interface SelectionMap {
|
|
509
|
+
select?: Record<string, SelectionMap | boolean>;
|
|
510
|
+
include?: Record<string, SelectionMap | boolean>;
|
|
511
|
+
where?: {};
|
|
480
512
|
}
|
|
481
513
|
|
|
514
|
+
export type FieldSelection =
|
|
515
|
+
| Record<string, SelectionMap | boolean>
|
|
516
|
+
| ((
|
|
517
|
+
args: object,
|
|
518
|
+
context: object,
|
|
519
|
+
query: (
|
|
520
|
+
selection: SelectionMap | boolean | ((args: object, context: object) => SelectionMap),
|
|
521
|
+
) => SelectionMap | boolean,
|
|
522
|
+
) => SelectionMap);
|
|
523
|
+
|
|
482
524
|
export type LoaderMappings = Record<
|
|
483
525
|
string,
|
|
484
526
|
{
|
|
485
527
|
field: string;
|
|
486
|
-
alias?: string;
|
|
487
528
|
mappings: LoaderMappings;
|
|
488
529
|
indirectPath: string[];
|
|
489
|
-
}
|
|
530
|
+
}
|
|
490
531
|
>;
|
|
491
532
|
|
|
492
|
-
export interface
|
|
493
|
-
|
|
494
|
-
name: string;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
export interface IndirectLoadMap {
|
|
498
|
-
subFields: SubFieldInclude[];
|
|
499
|
-
path: string[];
|
|
533
|
+
export interface IndirectInclude {
|
|
534
|
+
getType: () => string;
|
|
535
|
+
path: { type?: string; name: string }[];
|
|
500
536
|
}
|
|
501
537
|
|
|
502
538
|
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) {
|