@pothos/plugin-drizzle 0.18.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 +345 -0
- package/README.md +784 -221
- package/dts/connection-helpers.d.ts +18 -8
- package/dts/connection-helpers.d.ts.map +1 -1
- package/dts/drizzle-field-builder.d.ts +4 -11
- package/dts/drizzle-field-builder.d.ts.map +1 -1
- package/dts/global-types.d.ts.map +1 -1
- package/dts/index.d.ts.map +1 -1
- package/dts/model-loader.d.ts +18 -17
- package/dts/model-loader.d.ts.map +1 -1
- package/dts/types.d.ts +80 -20
- package/dts/types.d.ts.map +1 -1
- package/dts/utils/adapter.d.ts +39 -0
- package/dts/utils/adapter.d.ts.map +1 -0
- package/dts/utils/await-selections.d.ts +12 -0
- package/dts/utils/await-selections.d.ts.map +1 -0
- package/dts/utils/config.d.ts +23 -3
- package/dts/utils/config.d.ts.map +1 -1
- package/dts/utils/cursors.d.ts +6 -6
- package/dts/utils/cursors.d.ts.map +1 -1
- package/dts/utils/map-query.d.ts +22 -21
- package/dts/utils/map-query.d.ts.map +1 -1
- package/dts/utils/path-info.d.ts +13 -0
- package/dts/utils/path-info.d.ts.map +1 -0
- package/dts/utils/relation-filter.d.ts +48 -0
- package/dts/utils/relation-filter.d.ts.map +1 -0
- package/dts/utils/selections.d.ts +2 -21
- package/dts/utils/selections.d.ts.map +1 -1
- package/esm/connection-helpers.d.ts +18 -8
- package/esm/connection-helpers.d.ts.map +1 -1
- package/esm/connection-helpers.js +52 -19
- package/esm/connection-helpers.js.map +1 -1
- package/esm/drizzle-field-builder.d.ts +4 -11
- package/esm/drizzle-field-builder.d.ts.map +1 -1
- package/esm/drizzle-field-builder.js +138 -96
- package/esm/drizzle-field-builder.js.map +1 -1
- package/esm/field-builder.js +61 -47
- package/esm/field-builder.js.map +1 -1
- package/esm/global-types.d.ts.map +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +37 -61
- package/esm/index.js.map +1 -1
- package/esm/model-loader.d.ts +18 -17
- package/esm/model-loader.d.ts.map +1 -1
- package/esm/model-loader.js +76 -45
- package/esm/model-loader.js.map +1 -1
- package/esm/schema-builder.js +40 -149
- package/esm/schema-builder.js.map +1 -1
- package/esm/types.d.ts +80 -20
- package/esm/types.d.ts.map +1 -1
- package/esm/types.js.map +1 -1
- package/esm/utils/adapter.d.ts +39 -0
- package/esm/utils/adapter.d.ts.map +1 -0
- package/esm/utils/adapter.js +137 -0
- package/esm/utils/adapter.js.map +1 -0
- package/esm/utils/await-selections.d.ts +12 -0
- package/esm/utils/await-selections.d.ts.map +1 -0
- package/esm/utils/await-selections.js +19 -0
- package/esm/utils/await-selections.js.map +1 -0
- package/esm/utils/config.d.ts +23 -3
- package/esm/utils/config.d.ts.map +1 -1
- package/esm/utils/config.js +1 -4
- package/esm/utils/config.js.map +1 -1
- package/esm/utils/cursors.d.ts +6 -6
- package/esm/utils/cursors.d.ts.map +1 -1
- package/esm/utils/cursors.js +55 -90
- package/esm/utils/cursors.js.map +1 -1
- package/esm/utils/map-query.d.ts +22 -21
- package/esm/utils/map-query.d.ts.map +1 -1
- package/esm/utils/map-query.js +40 -354
- package/esm/utils/map-query.js.map +1 -1
- package/esm/utils/path-info.d.ts +13 -0
- package/esm/utils/path-info.d.ts.map +1 -0
- package/esm/utils/path-info.js +37 -0
- package/esm/utils/path-info.js.map +1 -0
- package/esm/utils/relation-filter.d.ts +48 -0
- package/esm/utils/relation-filter.d.ts.map +1 -0
- package/esm/utils/relation-filter.js +92 -0
- package/esm/utils/relation-filter.js.map +1 -0
- package/esm/utils/selections.d.ts +2 -21
- package/esm/utils/selections.d.ts.map +1 -1
- package/esm/utils/selections.js +1 -133
- package/esm/utils/selections.js.map +1 -1
- package/lib/connection-helpers.js +51 -18
- package/lib/connection-helpers.js.map +1 -1
- package/lib/drizzle-field-builder.js +136 -94
- package/lib/drizzle-field-builder.js.map +1 -1
- package/lib/field-builder.js +58 -44
- package/lib/field-builder.js.map +1 -1
- package/lib/index.js +36 -60
- package/lib/index.js.map +1 -1
- package/lib/model-loader.js +76 -45
- package/lib/model-loader.js.map +1 -1
- package/lib/schema-builder.js +40 -149
- package/lib/schema-builder.js.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/adapter.js +147 -0
- package/lib/utils/adapter.js.map +1 -0
- package/lib/utils/await-selections.js +20 -0
- package/lib/utils/await-selections.js.map +1 -0
- package/lib/utils/config.js +1 -4
- package/lib/utils/config.js.map +1 -1
- package/lib/utils/cursors.js +47 -88
- package/lib/utils/cursors.js.map +1 -1
- package/lib/utils/map-query.js +28 -359
- package/lib/utils/map-query.js.map +1 -1
- package/lib/utils/path-info.js +39 -0
- package/lib/utils/path-info.js.map +1 -0
- package/lib/utils/relation-filter.js +91 -0
- package/lib/utils/relation-filter.js.map +1 -0
- package/lib/utils/selections.js +3 -158
- package/lib/utils/selections.js.map +1 -1
- package/package.json +8 -6
- package/src/connection-helpers.ts +167 -53
- package/src/drizzle-field-builder.ts +296 -176
- package/src/field-builder.ts +110 -77
- package/src/global-types.ts +0 -32
- package/src/index.ts +42 -68
- package/src/model-loader.ts +110 -71
- package/src/schema-builder.ts +76 -169
- package/src/types.ts +175 -44
- package/src/utils/adapter.ts +197 -0
- package/src/utils/await-selections.ts +31 -0
- package/src/utils/config.ts +1 -5
- package/src/utils/cursors.ts +53 -81
- package/src/utils/map-query.ts +51 -734
- package/src/utils/path-info.ts +40 -0
- package/src/utils/relation-filter.ts +185 -0
- package/src/utils/selections.ts +2 -207
- package/dts/utils/deep-equal.d.ts +0 -2
- package/dts/utils/deep-equal.d.ts.map +0 -1
- package/dts/utils/drizzle-graphql.d.ts +0 -2
- package/dts/utils/drizzle-graphql.d.ts.map +0 -1
- package/dts/utils/loader-map.d.ts +0 -11
- package/dts/utils/loader-map.d.ts.map +0 -1
- package/dts/utils/usage.d.ts +0 -5
- package/dts/utils/usage.d.ts.map +0 -1
- package/esm/utils/deep-equal.d.ts +0 -2
- package/esm/utils/deep-equal.d.ts.map +0 -1
- package/esm/utils/deep-equal.js +0 -45
- package/esm/utils/deep-equal.js.map +0 -1
- package/esm/utils/drizzle-graphql.d.ts +0 -2
- package/esm/utils/drizzle-graphql.d.ts.map +0 -1
- package/esm/utils/drizzle-graphql.js +0 -232
- package/esm/utils/drizzle-graphql.js.map +0 -1
- package/esm/utils/loader-map.d.ts +0 -11
- package/esm/utils/loader-map.d.ts.map +0 -1
- package/esm/utils/loader-map.js +0 -35
- package/esm/utils/loader-map.js.map +0 -1
- package/esm/utils/usage.d.ts +0 -5
- package/esm/utils/usage.d.ts.map +0 -1
- package/esm/utils/usage.js +0 -59
- package/esm/utils/usage.js.map +0 -1
- package/lib/utils/deep-equal.js +0 -55
- package/lib/utils/deep-equal.js.map +0 -1
- package/lib/utils/drizzle-graphql.js +0 -236
- package/lib/utils/drizzle-graphql.js.map +0 -1
- package/lib/utils/loader-map.js +0 -56
- package/lib/utils/loader-map.js.map +0 -1
- package/lib/utils/usage.js +0 -83
- package/lib/utils/usage.js.map +0 -1
- package/src/utils/deep-equal.ts +0 -57
- package/src/utils/drizzle-graphql.ts +0 -274
- package/src/utils/loader-map.ts +0 -49
- package/src/utils/usage.ts +0 -62
package/src/model-loader.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { createContextCache, type SchemaTypes } from '@pothos/core';
|
|
1
|
+
import { createContextCache, isThenable, type MaybePromise, type SchemaTypes } from '@pothos/core';
|
|
2
|
+
import { cacheKey, Plan, setLoaderMappings, setRowFieldMapping } from '@pothos/selection-mapper';
|
|
2
3
|
import {
|
|
3
4
|
type AnyTable,
|
|
4
5
|
type Column,
|
|
@@ -9,22 +10,22 @@ import {
|
|
|
9
10
|
type TableRelationalConfig,
|
|
10
11
|
} from 'drizzle-orm';
|
|
11
12
|
import type { GraphQLResolveInfo } from 'graphql';
|
|
12
|
-
import { getClient, getSchemaConfig, type PothosDrizzleSchemaConfig } from './utils/config.js';
|
|
13
|
-
import { cacheKey, setLoaderMappings } from './utils/loader-map.js';
|
|
14
|
-
import { selectionStateFromInfo, stateFromInfo } from './utils/map-query.js';
|
|
15
13
|
import {
|
|
16
|
-
|
|
17
|
-
type
|
|
18
|
-
type
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from './utils/
|
|
14
|
+
type DrizzleAdapter,
|
|
15
|
+
type DrizzleNode,
|
|
16
|
+
type DrizzlePlan,
|
|
17
|
+
type DrizzlePlayedPlan,
|
|
18
|
+
drizzleAdapter,
|
|
19
|
+
} from './utils/adapter.js';
|
|
20
|
+
import { getClient, getSchemaConfig, type PothosDrizzleSchemaConfig } from './utils/config.js';
|
|
21
|
+
import { planFromInfo } from './utils/map-query.js';
|
|
22
22
|
|
|
23
23
|
interface ResolvablePromise<T> {
|
|
24
24
|
promise: Promise<T>;
|
|
25
25
|
resolve: (value: T) => void;
|
|
26
26
|
reject: (err: unknown) => void;
|
|
27
27
|
}
|
|
28
|
+
|
|
28
29
|
export class ModelLoader {
|
|
29
30
|
context: object;
|
|
30
31
|
|
|
@@ -32,14 +33,22 @@ export class ModelLoader {
|
|
|
32
33
|
|
|
33
34
|
modelName: string;
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
// One plan per `Type@path`, a promise while a select beneath the field is async. A parent-row
|
|
37
|
+
// plan is played where it is made, since it is never played behind another selection; a field's
|
|
38
|
+
// plan is played per load, so no two loads share a node.
|
|
39
|
+
rowCache = new Map<string, MaybePromise<DrizzlePlayedPlan>>();
|
|
36
40
|
|
|
41
|
+
planCache = new Map<string, MaybePromise<DrizzlePlan>>();
|
|
42
|
+
|
|
43
|
+
// Each batch owns the node it accumulates into, so nothing a cached plan or play holds is
|
|
44
|
+
// changed by a row joining the batch.
|
|
37
45
|
staged = new Set<{
|
|
38
|
-
|
|
46
|
+
root: DrizzleNode;
|
|
39
47
|
models: Map<object, ResolvablePromise<Record<string, unknown> | null>>;
|
|
40
48
|
}>();
|
|
41
49
|
|
|
42
50
|
config: PothosDrizzleSchemaConfig;
|
|
51
|
+
adapter: DrizzleAdapter;
|
|
43
52
|
table: TableRelationalConfig;
|
|
44
53
|
columns: Column[];
|
|
45
54
|
primaryKey: Column[];
|
|
@@ -55,6 +64,7 @@ export class ModelLoader {
|
|
|
55
64
|
this.builder = builder;
|
|
56
65
|
this.modelName = modelName;
|
|
57
66
|
this.config = getSchemaConfig(builder);
|
|
67
|
+
this.adapter = drizzleAdapter(this.config);
|
|
58
68
|
this.table = this.config.relations[modelName];
|
|
59
69
|
this.primaryKey = this.config.getPrimaryKey(modelName);
|
|
60
70
|
this.columns = columns ?? this.primaryKey;
|
|
@@ -93,68 +103,88 @@ export class ModelLoader {
|
|
|
93
103
|
|
|
94
104
|
getSelection(info: GraphQLResolveInfo) {
|
|
95
105
|
const key = cacheKey(info.parentType.name, info.path);
|
|
96
|
-
if (!this.
|
|
97
|
-
|
|
98
|
-
this.queryCache.set(key, {
|
|
99
|
-
selection,
|
|
100
|
-
query: selectionToQuery(this.config, selection),
|
|
101
|
-
});
|
|
106
|
+
if (!this.rowCache.has(key)) {
|
|
107
|
+
this.rowCache.set(key, Plan.forParentRow(drizzleAdapter(this.config), this.context, info));
|
|
102
108
|
}
|
|
103
109
|
|
|
104
|
-
return this.
|
|
110
|
+
return this.rowCache.get(key)!;
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
getSelectionForField(info: GraphQLResolveInfo, typeName: string) {
|
|
108
114
|
const key = cacheKey(typeName, info.path);
|
|
109
|
-
if (!this.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
info,
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
this.queryCache.set(key, {
|
|
118
|
-
selection,
|
|
119
|
-
query: selectionToQuery(this.config, selection),
|
|
120
|
-
});
|
|
115
|
+
if (!this.planCache.has(key)) {
|
|
116
|
+
this.planCache.set(
|
|
117
|
+
key,
|
|
118
|
+
// Walked without paths, so there is always a plan.
|
|
119
|
+
planFromInfo({ config: this.config, context: this.context, info, typeName })!,
|
|
120
|
+
);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
return this.
|
|
123
|
+
return this.planCache.get(key)!;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
/**
|
|
127
|
+
* `model` reloaded with the selection of the field `info` resolves. A synchronous selection
|
|
128
|
+
* stages synchronously, so every row resolved in a tick joins the same batch; only a selection
|
|
129
|
+
* with an async select beneath the field waits for it.
|
|
130
|
+
*/
|
|
131
|
+
loadSelection(info: GraphQLResolveInfo, model: object): Promise<Record<string, unknown> | null> {
|
|
132
|
+
const selection = this.getSelection(info);
|
|
133
|
+
|
|
134
|
+
return isThenable(selection)
|
|
135
|
+
? selection.then((settled) => this.loadWith(settled, info, model))
|
|
136
|
+
: this.loadWith(selection, info, model);
|
|
137
|
+
}
|
|
133
138
|
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
private loadWith(played: DrizzlePlayedPlan, info: GraphQLResolveInfo, model: object) {
|
|
140
|
+
return this.stageQuery(played, model).then((result) => {
|
|
141
|
+
if (result) {
|
|
142
|
+
const mapping = played.mappings[`${info.parentType.name}@${info.path.key}`];
|
|
143
|
+
|
|
144
|
+
if (mapping) {
|
|
145
|
+
// Recorded for the field itself too, so its resolver finds the pathInfo it was planned
|
|
146
|
+
// with, along with the mappings of the fields beneath it. Against `result` alone: this
|
|
147
|
+
// load fetched one row, so the field's own mapping is not the whole field's to claim.
|
|
148
|
+
// A sibling row that falls back on a later tick would otherwise read it as proof of
|
|
149
|
+
// having been loaded and resolve against a row that never carried the data.
|
|
150
|
+
setRowFieldMapping(this.context, info, mapping, result);
|
|
151
|
+
}
|
|
136
152
|
}
|
|
137
|
-
}
|
|
138
153
|
|
|
139
|
-
|
|
154
|
+
return result;
|
|
155
|
+
});
|
|
140
156
|
}
|
|
141
157
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
158
|
+
/** A node loaded by id with the selection beneath the field `info` resolves, as `returnType`. */
|
|
159
|
+
loadSelectionForField(
|
|
160
|
+
info: GraphQLResolveInfo,
|
|
161
|
+
model: object,
|
|
162
|
+
returnType: string,
|
|
163
|
+
): Promise<Record<string, unknown> | null> {
|
|
164
|
+
const selection = this.getSelectionForField(info, returnType);
|
|
165
|
+
|
|
166
|
+
return isThenable(selection)
|
|
167
|
+
? selection.then((settled) => this.loadFieldWith(settled.play(), info, model))
|
|
168
|
+
: this.loadFieldWith(selection.play(), info, model);
|
|
169
|
+
}
|
|
146
170
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
171
|
+
private loadFieldWith(played: DrizzlePlayedPlan, info: GraphQLResolveInfo, model: object) {
|
|
172
|
+
return this.stageQuery(played, model).then((result) => {
|
|
173
|
+
if (result) {
|
|
174
|
+
// Relay nodes of different types share this field path. Each node plan contributes
|
|
175
|
+
// its type-qualified mappings, as a queryFromInfo plan would.
|
|
176
|
+
setLoaderMappings(this.context, info, played.mappings);
|
|
177
|
+
}
|
|
150
178
|
|
|
151
|
-
|
|
179
|
+
return result;
|
|
180
|
+
});
|
|
152
181
|
}
|
|
153
182
|
|
|
154
|
-
stageQuery(
|
|
183
|
+
stageQuery(played: DrizzlePlayedPlan, model: object) {
|
|
155
184
|
for (const entry of this.staged) {
|
|
156
|
-
|
|
157
|
-
|
|
185
|
+
// Node to node: the batch takes the field's play whole, never through a query.
|
|
186
|
+
if (this.adapter.canMergeNode(entry.root, played.root)) {
|
|
187
|
+
this.adapter.mergeNode(entry.root, played.root);
|
|
158
188
|
|
|
159
189
|
if (!entry.models.has(model)) {
|
|
160
190
|
entry.models.set(model, createResolvablePromise<Record<string, unknown> | null>());
|
|
@@ -164,13 +194,17 @@ export class ModelLoader {
|
|
|
164
194
|
}
|
|
165
195
|
}
|
|
166
196
|
|
|
167
|
-
return this.initLoad(
|
|
197
|
+
return this.initLoad(played, model);
|
|
168
198
|
}
|
|
169
199
|
|
|
170
|
-
initLoad(
|
|
200
|
+
initLoad(played: DrizzlePlayedPlan, model: object) {
|
|
171
201
|
const promise = createResolvablePromise<Record<string, unknown> | null>();
|
|
202
|
+
const root = this.adapter.createNode(played.root.model);
|
|
203
|
+
|
|
204
|
+
this.adapter.mergeNode(root, played.root);
|
|
205
|
+
|
|
172
206
|
const entry = {
|
|
173
|
-
|
|
207
|
+
root,
|
|
174
208
|
models: new Map([[model, promise]]),
|
|
175
209
|
};
|
|
176
210
|
this.staged.add(entry);
|
|
@@ -181,15 +215,10 @@ export class ModelLoader {
|
|
|
181
215
|
nextTick.promise
|
|
182
216
|
.then(() => {
|
|
183
217
|
this.staged.delete(entry);
|
|
184
|
-
const api =
|
|
185
|
-
client.query as Record<
|
|
186
|
-
string,
|
|
187
|
-
{ findMany: (...args: unknown[]) => Promise<Record<string, unknown>[]> }
|
|
188
|
-
>
|
|
189
|
-
)[this.modelName];
|
|
218
|
+
const api = client.query[this.modelName];
|
|
190
219
|
|
|
191
220
|
const query = api.findMany({
|
|
192
|
-
...
|
|
221
|
+
...this.adapter.toQuery(entry.root),
|
|
193
222
|
where: {
|
|
194
223
|
RAW: (table: AnyTable<{}>) =>
|
|
195
224
|
inArray(
|
|
@@ -197,21 +226,31 @@ export class ModelLoader {
|
|
|
197
226
|
[...entry.models.keys()].map((model) => this.sqlForModel(model)),
|
|
198
227
|
),
|
|
199
228
|
},
|
|
200
|
-
});
|
|
229
|
+
} as never);
|
|
201
230
|
|
|
202
231
|
query.then(
|
|
203
232
|
(results) => {
|
|
204
233
|
for (const [model, promise] of entry.models.entries()) {
|
|
234
|
+
// Matched on the columns the batch was keyed by, which are the columns a row of
|
|
235
|
+
// `entry.models` carries: a node loaded by a column other than the primary key
|
|
236
|
+
// has only that one.
|
|
205
237
|
const result = results.find((row) =>
|
|
206
|
-
this.
|
|
207
|
-
(key)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
238
|
+
this.columns.every((key) => {
|
|
239
|
+
const name = this.config.columnToTsName(key);
|
|
240
|
+
const actual = row[name as keyof typeof row];
|
|
241
|
+
const expected = (model as Record<string, unknown>)[name];
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
actual === expected ||
|
|
245
|
+
(actual instanceof Date &&
|
|
246
|
+
expected instanceof Date &&
|
|
247
|
+
actual.getTime() === expected.getTime())
|
|
248
|
+
);
|
|
249
|
+
}),
|
|
211
250
|
);
|
|
212
251
|
|
|
213
252
|
if (result) {
|
|
214
|
-
promise.resolve(result
|
|
253
|
+
promise.resolve(result);
|
|
215
254
|
} else {
|
|
216
255
|
promise.reject(
|
|
217
256
|
new Error(`Model ${this.modelName}(${this.sqlForModel(model)}) not found`),
|
package/src/schema-builder.ts
CHANGED
|
@@ -8,7 +8,7 @@ import SchemaBuilder, {
|
|
|
8
8
|
PothosError,
|
|
9
9
|
type SchemaTypes,
|
|
10
10
|
} from '@pothos/core';
|
|
11
|
-
import type { Column } from 'drizzle-orm';
|
|
11
|
+
import type { Column, TableRelationalConfig } from 'drizzle-orm';
|
|
12
12
|
import type { GraphQLResolveInfo } from 'graphql';
|
|
13
13
|
import { DrizzleObjectFieldBuilder } from './drizzle-field-builder.js';
|
|
14
14
|
import { DrizzleInterfaceRef } from './interface-ref.js';
|
|
@@ -22,61 +22,70 @@ import { getRefFromModel } from './utils/refs.js';
|
|
|
22
22
|
|
|
23
23
|
const schemaBuilderProto = SchemaBuilder.prototype as PothosSchemaTypes.SchemaBuilder<SchemaTypes>;
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
...
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
name,
|
|
45
|
-
fields: fields ? () => fields(new DrizzleObjectFieldBuilder(ref.name, this, table)) : undefined,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
return ref as never;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
schemaBuilderProto.drizzleInterface = function drizzleInterface(
|
|
52
|
-
table,
|
|
53
|
-
{ select, fields, ...options },
|
|
25
|
+
/**
|
|
26
|
+
* The body of `drizzleObject` and `drizzleInterface`. The two build the same ref, extensions and
|
|
27
|
+
* field builder; only the ref class and which of `objectType`/`interfaceType` registers it differ.
|
|
28
|
+
*/
|
|
29
|
+
function defineDrizzleType(
|
|
30
|
+
builder: PothosSchemaTypes.SchemaBuilder<SchemaTypes>,
|
|
31
|
+
table: string,
|
|
32
|
+
{
|
|
33
|
+
select,
|
|
34
|
+
fields,
|
|
35
|
+
...options
|
|
36
|
+
}: {
|
|
37
|
+
select?: {} | boolean;
|
|
38
|
+
fields?: (t: DrizzleObjectFieldBuilder<SchemaTypes, TableRelationalConfig, {}>) => {};
|
|
39
|
+
variant?: string;
|
|
40
|
+
name?: string;
|
|
41
|
+
extensions?: {};
|
|
42
|
+
},
|
|
43
|
+
kind: 'Interface' | 'Object',
|
|
54
44
|
) {
|
|
45
|
+
const isInterface = kind === 'Interface';
|
|
55
46
|
const name = options.variant ?? options.name ?? table;
|
|
56
|
-
|
|
57
47
|
const ref = options.variant
|
|
58
|
-
?
|
|
59
|
-
|
|
48
|
+
? isInterface
|
|
49
|
+
? new DrizzleInterfaceRef(options.variant, table)
|
|
50
|
+
: new DrizzleObjectRef(options.variant, table)
|
|
51
|
+
: (getRefFromModel(table, builder, isInterface ? 'interface' : 'object') as ObjectRef<
|
|
52
|
+
SchemaTypes,
|
|
53
|
+
unknown
|
|
54
|
+
>);
|
|
60
55
|
|
|
61
56
|
ref.name = name;
|
|
62
57
|
|
|
63
|
-
|
|
64
|
-
...
|
|
58
|
+
const config = {
|
|
59
|
+
...options,
|
|
65
60
|
extensions: {
|
|
66
61
|
...options.extensions,
|
|
67
62
|
pothosDrizzleModel: table,
|
|
68
|
-
pothosDrizzleTable: getSchemaConfig(
|
|
63
|
+
pothosDrizzleTable: getSchemaConfig(builder).relations[table],
|
|
69
64
|
pothosDrizzleSelect:
|
|
70
65
|
typeof select === 'object' ? { columns: {}, ...select } : (select ?? true),
|
|
71
|
-
pothosDrizzleLoader: ModelLoader.forModel(table,
|
|
66
|
+
pothosDrizzleLoader: ModelLoader.forModel(table, builder),
|
|
72
67
|
},
|
|
73
68
|
name,
|
|
74
69
|
fields: fields
|
|
75
|
-
? () => fields(new DrizzleObjectFieldBuilder(
|
|
70
|
+
? () => fields(new DrizzleObjectFieldBuilder(name, builder, table, kind) as never)
|
|
76
71
|
: undefined,
|
|
77
|
-
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
if (isInterface) {
|
|
75
|
+
builder.interfaceType(ref as never, config as never);
|
|
76
|
+
} else {
|
|
77
|
+
builder.objectType(ref as never, config as never);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return ref;
|
|
81
|
+
}
|
|
78
82
|
|
|
79
|
-
|
|
83
|
+
schemaBuilderProto.drizzleObject = function drizzleObject(table, options) {
|
|
84
|
+
return defineDrizzleType(this, table, options as never, 'Object') as never;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
schemaBuilderProto.drizzleInterface = function drizzleInterface(table, options) {
|
|
88
|
+
return defineDrizzleType(this, table, options as never, 'Interface') as never;
|
|
80
89
|
};
|
|
81
90
|
|
|
82
91
|
schemaBuilderProto.drizzleNode = function drizzleNode(
|
|
@@ -104,7 +113,7 @@ schemaBuilderProto.drizzleNode = function drizzleNode(
|
|
|
104
113
|
const idColumns = Array.isArray(idColumn) ? idColumn : [idColumn];
|
|
105
114
|
const interfaceRef = this.nodeInterfaceRef?.();
|
|
106
115
|
const resolve = getIDSerializer(idColumns, schemaConfig);
|
|
107
|
-
const idParser = getIDParser(idColumns);
|
|
116
|
+
const idParser = getIDParser(idColumns, schemaConfig);
|
|
108
117
|
const typeName = variant ?? name ?? table;
|
|
109
118
|
const nodeRef = new DrizzleNodeRef(typeName, table, {
|
|
110
119
|
parseId: (id) => {
|
|
@@ -176,142 +185,40 @@ schemaBuilderProto.drizzleNode = function drizzleNode(
|
|
|
176
185
|
return nodeRef;
|
|
177
186
|
} as never;
|
|
178
187
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
188
|
+
/**
|
|
189
|
+
* The body of `drizzleObjectField(s)` and `drizzleInterfaceField(s)`: they differ only in kind.
|
|
190
|
+
* A table name names the interface registered under it, as `drizzleInterface` registers one.
|
|
191
|
+
*/
|
|
192
|
+
function addDrizzleFields(
|
|
193
|
+
builder: PothosSchemaTypes.SchemaBuilder<SchemaTypes>,
|
|
194
|
+
type: string | { tableName: string },
|
|
195
|
+
fields: (t: DrizzleObjectFieldBuilder<SchemaTypes, TableRelationalConfig, {}>) => {},
|
|
196
|
+
graphqlKind?: 'Interface',
|
|
197
|
+
) {
|
|
198
|
+
const ref =
|
|
199
|
+
typeof type === 'string'
|
|
200
|
+
? getRefFromModel(type, builder, graphqlKind ? 'interface' : 'object')
|
|
201
|
+
: (type as never);
|
|
202
|
+
|
|
203
|
+
builder.configStore.onTypeConfig(ref, ({ name }) => {
|
|
204
|
+
builder.configStore.addFields(ref, () =>
|
|
205
|
+
fields(new DrizzleObjectFieldBuilder(name, builder, ref.tableName, graphqlKind) as never),
|
|
206
|
+
);
|
|
185
207
|
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
schemaBuilderProto.drizzleObjectField = function drizzleObjectField(type, fieldName, field) {
|
|
211
|
+
addDrizzleFields(this, type as never, (t) => ({ [fieldName]: field(t as never) }));
|
|
186
212
|
};
|
|
187
213
|
|
|
188
214
|
schemaBuilderProto.drizzleInterfaceField = function drizzleInterfaceField(type, fieldName, field) {
|
|
189
|
-
|
|
190
|
-
this.configStore.onTypeConfig(ref, ({ name }) => {
|
|
191
|
-
this.configStore.addFields(ref, () => ({
|
|
192
|
-
[fieldName]: field(new DrizzleObjectFieldBuilder(name, this, ref.tableName, 'Interface')),
|
|
193
|
-
}));
|
|
194
|
-
});
|
|
215
|
+
addDrizzleFields(this, type as never, (t) => ({ [fieldName]: field(t as never) }), 'Interface');
|
|
195
216
|
};
|
|
196
217
|
|
|
197
218
|
schemaBuilderProto.drizzleObjectFields = function drizzleObjectFields(type, fields) {
|
|
198
|
-
|
|
199
|
-
this.configStore.onTypeConfig(ref, ({ name }) => {
|
|
200
|
-
this.configStore.addFields(ref, () =>
|
|
201
|
-
fields(new DrizzleObjectFieldBuilder(name, this, ref.tableName)),
|
|
202
|
-
);
|
|
203
|
-
});
|
|
219
|
+
addDrizzleFields(this, type as never, fields as never);
|
|
204
220
|
};
|
|
205
221
|
|
|
206
222
|
schemaBuilderProto.drizzleInterfaceFields = function drizzleInterfaceFields(type, fields) {
|
|
207
|
-
|
|
208
|
-
this.configStore.onTypeConfig(ref, ({ name }) => {
|
|
209
|
-
this.configStore.addFields(ref, () =>
|
|
210
|
-
fields(new DrizzleObjectFieldBuilder(name, this, ref.tableName, 'Interface')),
|
|
211
|
-
);
|
|
212
|
-
});
|
|
223
|
+
addDrizzleFields(this, type as never, fields as never, 'Interface');
|
|
213
224
|
};
|
|
214
|
-
|
|
215
|
-
// schemaBuilderProto.drizzleGraphQLOrderBy = function drizzleGraphQLOrderBy(
|
|
216
|
-
// this: PothosSchemaTypes.SchemaBuilder<SchemaTypes>,
|
|
217
|
-
// table: string,
|
|
218
|
-
// type: GraphQLInputObjectType,
|
|
219
|
-
// options?: { extensions?: object },
|
|
220
|
-
// ) {
|
|
221
|
-
// return (
|
|
222
|
-
// this as typeof this & {
|
|
223
|
-
// addGraphQLInput: (
|
|
224
|
-
// type: GraphQLInputObjectType,
|
|
225
|
-
// options: Record<string, unknown>,
|
|
226
|
-
// ) => InputObjectRef<SchemaTypes, {}>;
|
|
227
|
-
// }
|
|
228
|
-
// ).addGraphQLInput(type, {
|
|
229
|
-
// ...options,
|
|
230
|
-
// extensions: {
|
|
231
|
-
// ...options?.extensions,
|
|
232
|
-
// drizzleGraphQL: {
|
|
233
|
-
// inputType: 'orderBy',
|
|
234
|
-
// table,
|
|
235
|
-
// tableConfig: getSchemaConfig(this).relations[table],
|
|
236
|
-
// } satisfies DrizzleGraphQLInputExtensions,
|
|
237
|
-
// },
|
|
238
|
-
// });
|
|
239
|
-
// } as never;
|
|
240
|
-
|
|
241
|
-
// schemaBuilderProto.drizzleGraphQLFilters = function drizzleGraphQLFilters(
|
|
242
|
-
// this: PothosSchemaTypes.SchemaBuilder<SchemaTypes>,
|
|
243
|
-
// table: string,
|
|
244
|
-
// type: GraphQLInputObjectType,
|
|
245
|
-
// options?: { extensions?: object },
|
|
246
|
-
// ) {
|
|
247
|
-
// return (
|
|
248
|
-
// this as typeof this & {
|
|
249
|
-
// addGraphQLInput: (
|
|
250
|
-
// type: GraphQLInputObjectType,
|
|
251
|
-
// options: Record<string, unknown>,
|
|
252
|
-
// ) => InputObjectRef<SchemaTypes, {}>;
|
|
253
|
-
// }
|
|
254
|
-
// ).addGraphQLInput(type, {
|
|
255
|
-
// ...options,
|
|
256
|
-
// extensions: {
|
|
257
|
-
// ...options?.extensions,
|
|
258
|
-
// drizzleGraphQL: {
|
|
259
|
-
// inputType: 'filters',
|
|
260
|
-
// table,
|
|
261
|
-
// tableConfig: getSchemaConfig(this).relations[table],
|
|
262
|
-
// } satisfies DrizzleGraphQLInputExtensions,
|
|
263
|
-
// },
|
|
264
|
-
// });
|
|
265
|
-
// } as never;
|
|
266
|
-
|
|
267
|
-
// schemaBuilderProto.drizzleGraphQLInsert = function drizzleGraphQLInsert(
|
|
268
|
-
// this: PothosSchemaTypes.SchemaBuilder<SchemaTypes>,
|
|
269
|
-
// table: string,
|
|
270
|
-
// type: GraphQLInputObjectType,
|
|
271
|
-
// options?: { extensions?: object },
|
|
272
|
-
// ) {
|
|
273
|
-
// return (
|
|
274
|
-
// this as typeof this & {
|
|
275
|
-
// addGraphQLInput: (
|
|
276
|
-
// type: GraphQLInputObjectType,
|
|
277
|
-
// options: Record<string, unknown>,
|
|
278
|
-
// ) => InputObjectRef<SchemaTypes, {}>;
|
|
279
|
-
// }
|
|
280
|
-
// ).addGraphQLInput(type, {
|
|
281
|
-
// ...options,
|
|
282
|
-
// extensions: {
|
|
283
|
-
// ...options?.extensions,
|
|
284
|
-
// drizzleGraphQL: {
|
|
285
|
-
// inputType: 'insert',
|
|
286
|
-
// table,
|
|
287
|
-
// tableConfig: getSchemaConfig(this).relations[table],
|
|
288
|
-
// } satisfies DrizzleGraphQLInputExtensions,
|
|
289
|
-
// },
|
|
290
|
-
// });
|
|
291
|
-
// } as never;
|
|
292
|
-
|
|
293
|
-
// schemaBuilderProto.drizzleGraphQLUpdate = function drizzleGraphQLUpdate(
|
|
294
|
-
// this: PothosSchemaTypes.SchemaBuilder<SchemaTypes>,
|
|
295
|
-
// table: string,
|
|
296
|
-
// type: GraphQLInputObjectType,
|
|
297
|
-
// options?: { extensions?: object },
|
|
298
|
-
// ) {
|
|
299
|
-
// return (
|
|
300
|
-
// this as typeof this & {
|
|
301
|
-
// addGraphQLInput: (
|
|
302
|
-
// type: GraphQLInputObjectType,
|
|
303
|
-
// options: Record<string, unknown>,
|
|
304
|
-
// ) => InputObjectRef<SchemaTypes, {}>;
|
|
305
|
-
// }
|
|
306
|
-
// ).addGraphQLInput(type, {
|
|
307
|
-
// ...options,
|
|
308
|
-
// extensions: {
|
|
309
|
-
// ...options?.extensions,
|
|
310
|
-
// drizzleGraphQL: {
|
|
311
|
-
// inputType: 'update',
|
|
312
|
-
// table,
|
|
313
|
-
// tableConfig: getSchemaConfig(this).relations[table],
|
|
314
|
-
// } satisfies DrizzleGraphQLInputExtensions,
|
|
315
|
-
// },
|
|
316
|
-
// });
|
|
317
|
-
// } as never;
|