pothos-drizzle-generator 0.0.1
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/LICENSE +21 -0
- package/README.md +127 -0
- package/dist/cjs/PothosDrizzleGeneratorPlugin.d.ts +7 -0
- package/dist/cjs/PothosDrizzleGeneratorPlugin.js +399 -0
- package/dist/cjs/generator.d.ts +63 -0
- package/dist/cjs/generator.js +231 -0
- package/dist/cjs/global-types.d.ts +80 -0
- package/dist/cjs/global-types.js +2 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +28 -0
- package/dist/cjs/libs/operations.d.ts +11 -0
- package/dist/cjs/libs/operations.js +45 -0
- package/dist/cjs/libs/utils.d.ts +58 -0
- package/dist/cjs/libs/utils.js +149 -0
- package/dist/esm/PothosDrizzleGeneratorPlugin.d.ts +7 -0
- package/dist/esm/PothosDrizzleGeneratorPlugin.js +395 -0
- package/dist/esm/generator.d.ts +63 -0
- package/dist/esm/generator.js +227 -0
- package/dist/esm/global-types.d.ts +80 -0
- package/dist/esm/global-types.js +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/libs/operations.d.ts +11 -0
- package/dist/esm/libs/operations.js +40 -0
- package/dist/esm/libs/utils.d.ts +58 -0
- package/dist/esm/libs/utils.js +108 -0
- package/dist/esm/package.json +3 -0
- package/eslint.config.mjs +43 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 SoraKumo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# pothos-drizzle-generator
|
|
2
|
+
|
|
3
|
+
A Pothos plugin that automatically generates GraphQL schemas based on Drizzle schema information.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
# usage
|
|
8
|
+
|
|
9
|
+
To use this service, you must have version `drizzle-orm@1.0.0-beta.2` or later.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import "dotenv/config";
|
|
13
|
+
import SchemaBuilder from "@pothos/core";
|
|
14
|
+
import DrizzlePlugin from "@pothos/plugin-drizzle";
|
|
15
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
16
|
+
import { getTableConfig } from "drizzle-orm/pg-core";
|
|
17
|
+
import { relations } from "./db/relations";
|
|
18
|
+
import PothosDrizzleGeneratorPlugin from "pothos-drizzle-generator";
|
|
19
|
+
|
|
20
|
+
const db = drizzle({
|
|
21
|
+
connection: process.env.DATABASE_URL!,
|
|
22
|
+
relations,
|
|
23
|
+
logger: true,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export interface PothosTypes {
|
|
27
|
+
DrizzleRelations: typeof relations;
|
|
28
|
+
Context: { userId?: string };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const builder = new SchemaBuilder<PothosTypes>({
|
|
32
|
+
plugins: [
|
|
33
|
+
DrizzlePlugin,
|
|
34
|
+
PothosDrizzleGeneratorPlugin, // Set plugin
|
|
35
|
+
],
|
|
36
|
+
drizzle: {
|
|
37
|
+
client: () => db,
|
|
38
|
+
relations,
|
|
39
|
+
getTableConfig,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const schema = builder.toSchema();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
# Options
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const builder = new SchemaBuilder<PothosTypes>({
|
|
50
|
+
plugins: [
|
|
51
|
+
DrizzlePlugin,
|
|
52
|
+
PothosDrizzleGeneratorPlugin, // Set plugin
|
|
53
|
+
],
|
|
54
|
+
drizzle: {
|
|
55
|
+
client: () => db,
|
|
56
|
+
relations,
|
|
57
|
+
getTableConfig,
|
|
58
|
+
},
|
|
59
|
+
pothosDrizzleGenerator: {
|
|
60
|
+
// Specifying the Maximum Query Depth
|
|
61
|
+
depthLimit: ({ ctx, modelName, operation }) => $limit$,
|
|
62
|
+
// Specifying the model to use
|
|
63
|
+
use: { include: [...$modelNames$], exclude: [...$modelNames$] },
|
|
64
|
+
models: {
|
|
65
|
+
[$modelName$]: {
|
|
66
|
+
// Specifying fields to use in queries
|
|
67
|
+
fields: { include: [...$fields$], exclude: [...$fields$] },
|
|
68
|
+
// Specifying the method of operation for the model
|
|
69
|
+
operations: { include: [...$operation$], exclude: [...$operation$] },
|
|
70
|
+
// Runtime Permission Check
|
|
71
|
+
executable: ({ ctx, modelName, operation }) => $permission$,
|
|
72
|
+
// Specify the maximum value for the query's limit
|
|
73
|
+
limit: ({ ctx, modelName, operation }) => $limit$,
|
|
74
|
+
// Override the query's orderBy
|
|
75
|
+
orderBy: ({ ctx, modelName, operation }) => $orderBy$,
|
|
76
|
+
// Add query conditions
|
|
77
|
+
where: ({ ctx, modelName, operation }) => $where$,
|
|
78
|
+
// Specifying input fields
|
|
79
|
+
inputFields: { include: [$fields$], exclude: [$fields$] },
|
|
80
|
+
// Overwriting input data
|
|
81
|
+
inputData: ({ ctx, modelName, operation }) => $inputData$,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
# Current implementation status
|
|
89
|
+
|
|
90
|
+
## Operations
|
|
91
|
+
|
|
92
|
+
- findMany
|
|
93
|
+
- findFirst
|
|
94
|
+
- count
|
|
95
|
+
- create
|
|
96
|
+
- update
|
|
97
|
+
- delete
|
|
98
|
+
|
|
99
|
+
## Parameters
|
|
100
|
+
|
|
101
|
+
- where
|
|
102
|
+
- orderBy
|
|
103
|
+
- offset
|
|
104
|
+
- limit
|
|
105
|
+
|
|
106
|
+
## operators
|
|
107
|
+
|
|
108
|
+
- AND
|
|
109
|
+
- OR
|
|
110
|
+
- NOT
|
|
111
|
+
- eq
|
|
112
|
+
- ne
|
|
113
|
+
- gt
|
|
114
|
+
- gte
|
|
115
|
+
- lt
|
|
116
|
+
- lte
|
|
117
|
+
- like
|
|
118
|
+
- notLike
|
|
119
|
+
- ilike
|
|
120
|
+
- notIlike
|
|
121
|
+
- isNull
|
|
122
|
+
- isNotNull,
|
|
123
|
+
- in,
|
|
124
|
+
- notIn
|
|
125
|
+
- arrayContained
|
|
126
|
+
- arrayOverlaps
|
|
127
|
+
- arrayContains
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BasePlugin, type BuildCache, type SchemaTypes } from "@pothos/core";
|
|
2
|
+
import { PothosDrizzleGenerator } from "./generator.js";
|
|
3
|
+
export declare class PothosDrizzleGeneratorPlugin<Types extends SchemaTypes, T extends object = object> extends BasePlugin<Types, T> {
|
|
4
|
+
generator: PothosDrizzleGenerator;
|
|
5
|
+
constructor(buildCache: BuildCache<Types>, name: keyof PothosSchemaTypes.Plugins<Types>);
|
|
6
|
+
beforeBuild(): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PothosDrizzleGeneratorPlugin = void 0;
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
+
const core_1 = require("@pothos/core");
|
|
6
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
7
|
+
const generator_js_1 = require("./generator.js");
|
|
8
|
+
const utils_js_1 = require("./libs/utils.js");
|
|
9
|
+
class PothosDrizzleGeneratorPlugin extends core_1.BasePlugin {
|
|
10
|
+
generator;
|
|
11
|
+
constructor(buildCache, name) {
|
|
12
|
+
super(buildCache, name);
|
|
13
|
+
this.generator = new generator_js_1.PothosDrizzleGenerator(this.builder);
|
|
14
|
+
}
|
|
15
|
+
beforeBuild() {
|
|
16
|
+
const generator = this.generator;
|
|
17
|
+
const builder = this.builder;
|
|
18
|
+
const depthLimit = generator.getDepthLimit();
|
|
19
|
+
const tables = generator.getTables();
|
|
20
|
+
for (const [modelName, { table, tableInfo, relations, columns, operations, executable, limit, where, orderBy, inputData, },] of Object.entries(tables)) {
|
|
21
|
+
const objectRef = builder.objectRef(modelName);
|
|
22
|
+
objectRef.implement({
|
|
23
|
+
fields: (t) => Object.fromEntries(columns.map((c) => {
|
|
24
|
+
return [
|
|
25
|
+
c.name,
|
|
26
|
+
t.expose(c.name, {
|
|
27
|
+
type: generator.getDataType(c),
|
|
28
|
+
nullable: !c.notNull,
|
|
29
|
+
}),
|
|
30
|
+
];
|
|
31
|
+
})),
|
|
32
|
+
});
|
|
33
|
+
const filterRelations = Object.entries(relations).filter(([, relay]) => tables[relay.targetTableName]);
|
|
34
|
+
builder.drizzleObject(modelName, {
|
|
35
|
+
name: tableInfo.name,
|
|
36
|
+
fields: (t) => {
|
|
37
|
+
const relayList = filterRelations.map(([relayName, relay]) => {
|
|
38
|
+
const modelName = relay.targetTableName;
|
|
39
|
+
const { executable, where, orderBy, limit, operations } = tables[modelName];
|
|
40
|
+
const operation = relay.relationType === "one" ? "findFirst" : "findMany";
|
|
41
|
+
if (!operations.includes(operation))
|
|
42
|
+
return [];
|
|
43
|
+
const inputWhere = generator.getInputWhere(modelName);
|
|
44
|
+
const inputOrderBy = generator.getInputOrderBy(modelName);
|
|
45
|
+
return [
|
|
46
|
+
relayName,
|
|
47
|
+
t.relation(relayName, {
|
|
48
|
+
columns: { id: true },
|
|
49
|
+
args: {
|
|
50
|
+
offset: t.arg({ type: "Int" }),
|
|
51
|
+
limit: t.arg({ type: "Int" }),
|
|
52
|
+
where: t.arg({ type: inputWhere }),
|
|
53
|
+
orderBy: t.arg({ type: inputOrderBy }),
|
|
54
|
+
},
|
|
55
|
+
query: (args, ctx) => {
|
|
56
|
+
if (executable?.({
|
|
57
|
+
modelName,
|
|
58
|
+
ctx,
|
|
59
|
+
operation,
|
|
60
|
+
}) === false) {
|
|
61
|
+
throw new Error("No permission");
|
|
62
|
+
}
|
|
63
|
+
const p = {
|
|
64
|
+
limit: limit?.({ modelName, ctx, operation }),
|
|
65
|
+
where: where?.({ modelName, ctx, operation }),
|
|
66
|
+
orderBy: orderBy?.({ modelName, ctx, operation }),
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
...args,
|
|
70
|
+
limit: p.limit && args.limit
|
|
71
|
+
? Math.min(p.limit, args.limit)
|
|
72
|
+
: p.limit ?? args.limit,
|
|
73
|
+
where: { AND: [args.where, p.where].filter((v) => v) },
|
|
74
|
+
orderBy: args.orderBy && Object.keys(args.orderBy).length
|
|
75
|
+
? args.orderBy
|
|
76
|
+
: p.orderBy,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
}),
|
|
80
|
+
];
|
|
81
|
+
});
|
|
82
|
+
const relayCount = filterRelations.map(([relayName, relay]) => {
|
|
83
|
+
const modelName = relay.targetTableName;
|
|
84
|
+
const operation = "count";
|
|
85
|
+
const { executable, where, operations } = tables[modelName];
|
|
86
|
+
if (!operations.includes(operation))
|
|
87
|
+
return [];
|
|
88
|
+
const inputWhere = generator.getInputWhere(modelName);
|
|
89
|
+
return [
|
|
90
|
+
`${relayName}Count`,
|
|
91
|
+
t.relatedCount(relayName, {
|
|
92
|
+
args: { where: t.arg({ type: inputWhere }) },
|
|
93
|
+
where: (args, ctx) => {
|
|
94
|
+
if (executable?.({
|
|
95
|
+
modelName,
|
|
96
|
+
ctx,
|
|
97
|
+
operation,
|
|
98
|
+
}) === false) {
|
|
99
|
+
throw new Error("No permission");
|
|
100
|
+
}
|
|
101
|
+
const p = {
|
|
102
|
+
where: where?.({ modelName, ctx, operation }),
|
|
103
|
+
};
|
|
104
|
+
return (0, utils_js_1.createWhereQuery)(relay.targetTable, {
|
|
105
|
+
AND: [args.where, p.where].filter((v) => v),
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
];
|
|
110
|
+
});
|
|
111
|
+
return Object.fromEntries([
|
|
112
|
+
...relayCount,
|
|
113
|
+
...relayList,
|
|
114
|
+
...columns.map((c) => {
|
|
115
|
+
return [
|
|
116
|
+
c.name,
|
|
117
|
+
t.expose(c.name, {
|
|
118
|
+
type: generator.getDataType(c),
|
|
119
|
+
nullable: !c.notNull,
|
|
120
|
+
}),
|
|
121
|
+
];
|
|
122
|
+
}),
|
|
123
|
+
]);
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
const inputWhere = generator.getInputWhere(modelName);
|
|
127
|
+
const inputOrderBy = generator.getInputOrderBy(modelName);
|
|
128
|
+
const inputCreate = generator.getInputCreate(modelName);
|
|
129
|
+
const inputUpdate = generator.getInputUpdate(modelName);
|
|
130
|
+
if (operations.includes("findMany")) {
|
|
131
|
+
builder.queryType({
|
|
132
|
+
fields: (t) => ({
|
|
133
|
+
[`findMany${tableInfo.name}`]: t.drizzleField({
|
|
134
|
+
type: [modelName],
|
|
135
|
+
nullable: false,
|
|
136
|
+
args: {
|
|
137
|
+
offset: t.arg({ type: "Int" }),
|
|
138
|
+
limit: t.arg({ type: "Int" }),
|
|
139
|
+
where: t.arg({ type: inputWhere }),
|
|
140
|
+
orderBy: t.arg({ type: inputOrderBy }),
|
|
141
|
+
},
|
|
142
|
+
resolve: async (query, _parent, args, ctx, info) => {
|
|
143
|
+
const operation = "findMany";
|
|
144
|
+
if (executable?.({
|
|
145
|
+
modelName,
|
|
146
|
+
ctx,
|
|
147
|
+
operation,
|
|
148
|
+
}) === false) {
|
|
149
|
+
throw new Error("No permission");
|
|
150
|
+
}
|
|
151
|
+
const p = {
|
|
152
|
+
depthLimit: depthLimit?.({ modelName, ctx, operation }),
|
|
153
|
+
limit: limit?.({ modelName, ctx, operation }),
|
|
154
|
+
where: where?.({ modelName, ctx, operation }),
|
|
155
|
+
orderBy: orderBy?.({ modelName, ctx, operation }),
|
|
156
|
+
};
|
|
157
|
+
if (p.depthLimit !== undefined &&
|
|
158
|
+
(0, utils_js_1.getQueryDepth)(info) > p.depthLimit)
|
|
159
|
+
throw new Error("Depth limit exceeded");
|
|
160
|
+
return generator.getClient(ctx).query[modelName].findMany(query({
|
|
161
|
+
...args,
|
|
162
|
+
limit: p.limit && args.limit
|
|
163
|
+
? Math.min(p.limit, args.limit)
|
|
164
|
+
: p.limit ?? args.limit,
|
|
165
|
+
where: { AND: [args.where, p.where].filter((v) => v) },
|
|
166
|
+
orderBy: args.orderBy && Object.keys(args.orderBy).length
|
|
167
|
+
? args.orderBy
|
|
168
|
+
: p.orderBy,
|
|
169
|
+
}));
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
}),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
if (operations.includes("findFirst")) {
|
|
176
|
+
builder.queryType({
|
|
177
|
+
fields: (t) => ({
|
|
178
|
+
[`findFirst${tableInfo.name}`]: t.drizzleField({
|
|
179
|
+
type: modelName,
|
|
180
|
+
args: {
|
|
181
|
+
offset: t.arg({ type: "Int" }),
|
|
182
|
+
where: t.arg({ type: inputWhere }),
|
|
183
|
+
orderBy: t.arg({ type: inputOrderBy }),
|
|
184
|
+
},
|
|
185
|
+
resolve: async (query, _parent, args, ctx, info) => {
|
|
186
|
+
const operation = "findFirst";
|
|
187
|
+
if (executable?.({
|
|
188
|
+
modelName,
|
|
189
|
+
ctx,
|
|
190
|
+
operation,
|
|
191
|
+
}) === false) {
|
|
192
|
+
throw new Error("No permission");
|
|
193
|
+
}
|
|
194
|
+
const p = {
|
|
195
|
+
depthLimit: depthLimit?.({ modelName, ctx, operation }),
|
|
196
|
+
where: where?.({ modelName, ctx, operation }),
|
|
197
|
+
orderBy: orderBy?.({ modelName, ctx, operation }),
|
|
198
|
+
};
|
|
199
|
+
if (p.depthLimit !== undefined &&
|
|
200
|
+
(0, utils_js_1.getQueryDepth)(info) > p.depthLimit)
|
|
201
|
+
throw new Error("Depth limit exceeded");
|
|
202
|
+
return generator.getClient(ctx).query[modelName].findFirst(query({
|
|
203
|
+
...args,
|
|
204
|
+
where: { AND: [args.where, p.where].filter((v) => v) },
|
|
205
|
+
orderBy: args.orderBy && Object.keys(args.orderBy).length
|
|
206
|
+
? args.orderBy
|
|
207
|
+
: p.orderBy,
|
|
208
|
+
}));
|
|
209
|
+
},
|
|
210
|
+
}),
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (operations.includes("count")) {
|
|
215
|
+
builder.queryType({
|
|
216
|
+
fields: (t) => ({
|
|
217
|
+
[`count${tableInfo.name}`]: t.field({
|
|
218
|
+
type: "Int",
|
|
219
|
+
nullable: false,
|
|
220
|
+
args: {
|
|
221
|
+
limit: t.arg({ type: "Int" }),
|
|
222
|
+
where: t.arg({ type: inputWhere }),
|
|
223
|
+
},
|
|
224
|
+
resolve: async (_query, _parent, args, ctx, info) => {
|
|
225
|
+
const operation = "count";
|
|
226
|
+
if (executable?.({
|
|
227
|
+
modelName,
|
|
228
|
+
ctx,
|
|
229
|
+
operation,
|
|
230
|
+
}) === false) {
|
|
231
|
+
throw new Error("No permission");
|
|
232
|
+
}
|
|
233
|
+
const p = {
|
|
234
|
+
depthLimit: depthLimit?.({ modelName, ctx, operation }),
|
|
235
|
+
limit: limit?.({ modelName, ctx, operation }),
|
|
236
|
+
where: where?.({ modelName, ctx, operation }),
|
|
237
|
+
};
|
|
238
|
+
if (p.depthLimit !== undefined &&
|
|
239
|
+
(0, utils_js_1.getQueryDepth)(info) > p.depthLimit)
|
|
240
|
+
throw new Error("Depth limit exceeded");
|
|
241
|
+
return generator.getClient(ctx).query[modelName]
|
|
242
|
+
.findFirst({
|
|
243
|
+
columns: {},
|
|
244
|
+
extras: { _count: () => (0, drizzle_orm_1.sql) `count(*)` },
|
|
245
|
+
...args,
|
|
246
|
+
limit: p.limit && args.limit
|
|
247
|
+
? Math.min(p.limit, args.limit)
|
|
248
|
+
: p.limit ?? args.limit,
|
|
249
|
+
where: { AND: [args.where, p.where].filter((v) => v) },
|
|
250
|
+
})
|
|
251
|
+
.then((v) => v._count);
|
|
252
|
+
},
|
|
253
|
+
}),
|
|
254
|
+
}),
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (operations.includes("createOne")) {
|
|
258
|
+
builder.mutationType({
|
|
259
|
+
fields: (t) => ({
|
|
260
|
+
[`createOne${tableInfo.name}`]: t.drizzleField({
|
|
261
|
+
type: modelName,
|
|
262
|
+
nullable: false,
|
|
263
|
+
args: { input: t.arg({ type: inputCreate, required: true }) },
|
|
264
|
+
resolve: async (_query, _parent, args, ctx, info) => {
|
|
265
|
+
const operation = "createOne";
|
|
266
|
+
if (executable?.({
|
|
267
|
+
modelName,
|
|
268
|
+
ctx,
|
|
269
|
+
operation,
|
|
270
|
+
}) === false) {
|
|
271
|
+
throw new Error("No permission");
|
|
272
|
+
}
|
|
273
|
+
const p = {
|
|
274
|
+
depthLimit: depthLimit?.({ modelName, ctx, operation }),
|
|
275
|
+
input: inputData?.({ modelName, ctx, operation }),
|
|
276
|
+
};
|
|
277
|
+
if (p.depthLimit !== undefined &&
|
|
278
|
+
(0, utils_js_1.getQueryDepth)(info) > p.depthLimit)
|
|
279
|
+
throw new Error("Depth limit exceeded");
|
|
280
|
+
return generator.getClient(ctx)
|
|
281
|
+
.insert(table)
|
|
282
|
+
.values({ ...args.input, ...p.input })
|
|
283
|
+
.returning()
|
|
284
|
+
.then((v) => v[0]);
|
|
285
|
+
},
|
|
286
|
+
}),
|
|
287
|
+
}),
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
if (operations.includes("createMany")) {
|
|
291
|
+
builder.mutationType({
|
|
292
|
+
fields: (t) => ({
|
|
293
|
+
[`createMany${tableInfo.name}`]: t.drizzleField({
|
|
294
|
+
type: [modelName],
|
|
295
|
+
nullable: false,
|
|
296
|
+
args: { input: t.arg({ type: [inputCreate], required: true }) },
|
|
297
|
+
resolve: async (_query, _parent, args, ctx, info) => {
|
|
298
|
+
const operation = "createMany";
|
|
299
|
+
if (executable?.({
|
|
300
|
+
modelName,
|
|
301
|
+
ctx,
|
|
302
|
+
operation,
|
|
303
|
+
}) === false) {
|
|
304
|
+
throw new Error("No permission");
|
|
305
|
+
}
|
|
306
|
+
const p = {
|
|
307
|
+
depthLimit: depthLimit?.({ modelName, ctx, operation }),
|
|
308
|
+
args: inputData?.({ modelName, ctx, operation }),
|
|
309
|
+
};
|
|
310
|
+
if (p.depthLimit !== undefined &&
|
|
311
|
+
(0, utils_js_1.getQueryDepth)(info) > p.depthLimit)
|
|
312
|
+
throw new Error("Depth limit exceeded");
|
|
313
|
+
return generator.getClient(ctx)
|
|
314
|
+
.insert(table)
|
|
315
|
+
.values(args.input.map((v) => ({ ...v, ...p.args })))
|
|
316
|
+
.returning();
|
|
317
|
+
},
|
|
318
|
+
}),
|
|
319
|
+
}),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
if (operations.includes("update")) {
|
|
323
|
+
builder.mutationType({
|
|
324
|
+
fields: (t) => ({
|
|
325
|
+
[`update${tableInfo.name}`]: t.drizzleField({
|
|
326
|
+
type: [modelName],
|
|
327
|
+
nullable: false,
|
|
328
|
+
args: {
|
|
329
|
+
input: t.arg({ type: inputUpdate, required: true }),
|
|
330
|
+
where: t.arg({ type: inputWhere }),
|
|
331
|
+
},
|
|
332
|
+
resolve: async (_query, _parent, args, ctx, info) => {
|
|
333
|
+
const operation = "update";
|
|
334
|
+
if (executable?.({
|
|
335
|
+
modelName,
|
|
336
|
+
ctx,
|
|
337
|
+
operation,
|
|
338
|
+
}) === false) {
|
|
339
|
+
throw new Error("No permission");
|
|
340
|
+
}
|
|
341
|
+
const p = {
|
|
342
|
+
depthLimit: depthLimit?.({ modelName, ctx, operation }),
|
|
343
|
+
where: where?.({ modelName, ctx, operation }),
|
|
344
|
+
};
|
|
345
|
+
if (p.depthLimit !== undefined &&
|
|
346
|
+
(0, utils_js_1.getQueryDepth)(info) > p.depthLimit)
|
|
347
|
+
throw new Error("Depth limit exceeded");
|
|
348
|
+
return generator.getClient(ctx)
|
|
349
|
+
.update(table)
|
|
350
|
+
.set(args.input)
|
|
351
|
+
.where((0, utils_js_1.createWhereQuery)(table, {
|
|
352
|
+
AND: [args.where, p.where].filter((v) => v),
|
|
353
|
+
}))
|
|
354
|
+
.returning();
|
|
355
|
+
},
|
|
356
|
+
}),
|
|
357
|
+
}),
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (operations.includes("delete")) {
|
|
361
|
+
builder.mutationType({
|
|
362
|
+
fields: (t) => ({
|
|
363
|
+
[`delete${tableInfo.name}`]: t.field({
|
|
364
|
+
type: [modelName],
|
|
365
|
+
nullable: false,
|
|
366
|
+
args: {
|
|
367
|
+
where: t.arg({ type: inputWhere }),
|
|
368
|
+
},
|
|
369
|
+
resolve: async (_parent, args, ctx, info) => {
|
|
370
|
+
const operation = "delete";
|
|
371
|
+
if (executable?.({
|
|
372
|
+
modelName,
|
|
373
|
+
ctx,
|
|
374
|
+
operation,
|
|
375
|
+
}) === false) {
|
|
376
|
+
throw new Error("No permission");
|
|
377
|
+
}
|
|
378
|
+
const p = {
|
|
379
|
+
depthLimit: depthLimit?.({ modelName, ctx, operation }),
|
|
380
|
+
where: where?.({ modelName, ctx, operation }),
|
|
381
|
+
};
|
|
382
|
+
if (p.depthLimit !== undefined &&
|
|
383
|
+
(0, utils_js_1.getQueryDepth)(info) > p.depthLimit)
|
|
384
|
+
throw new Error("Depth limit exceeded");
|
|
385
|
+
return generator.getClient(ctx)
|
|
386
|
+
.delete(table)
|
|
387
|
+
.where((0, utils_js_1.createWhereQuery)(table, {
|
|
388
|
+
AND: [args.where, p.where].filter((v) => v),
|
|
389
|
+
}))
|
|
390
|
+
.returning();
|
|
391
|
+
},
|
|
392
|
+
}),
|
|
393
|
+
}),
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
exports.PothosDrizzleGeneratorPlugin = PothosDrizzleGeneratorPlugin;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type AnyRelations, type RelationsRecord, type SchemaEntry } from "drizzle-orm";
|
|
2
|
+
import { OperationBasic } from "./libs/operations.js";
|
|
3
|
+
import type { DrizzleClient } from "@pothos/plugin-drizzle";
|
|
4
|
+
import type { PgColumn, getTableConfig } from "drizzle-orm/pg-core";
|
|
5
|
+
type ModelData = {
|
|
6
|
+
table: SchemaEntry;
|
|
7
|
+
operations: (typeof OperationBasic)[number][];
|
|
8
|
+
columns: PgColumn<any, object>[];
|
|
9
|
+
inputColumns: PgColumn<any, object>[];
|
|
10
|
+
tableInfo: ReturnType<typeof getTableConfig>;
|
|
11
|
+
relations: RelationsRecord;
|
|
12
|
+
executable?: (params: {
|
|
13
|
+
ctx: any;
|
|
14
|
+
modelName: string;
|
|
15
|
+
operation: (typeof OperationBasic)[number];
|
|
16
|
+
}) => boolean | undefined;
|
|
17
|
+
limit?: (params: {
|
|
18
|
+
ctx: any;
|
|
19
|
+
modelName: string;
|
|
20
|
+
operation: (typeof OperationBasic)[number];
|
|
21
|
+
}) => number | undefined;
|
|
22
|
+
orderBy?: (params: {
|
|
23
|
+
ctx: any;
|
|
24
|
+
modelName: string;
|
|
25
|
+
operation: (typeof OperationBasic)[number];
|
|
26
|
+
}) => object | undefined;
|
|
27
|
+
where?: (params: {
|
|
28
|
+
ctx: any;
|
|
29
|
+
modelName: string;
|
|
30
|
+
operation: (typeof OperationBasic)[number];
|
|
31
|
+
}) => object | undefined;
|
|
32
|
+
inputData?: (params: {
|
|
33
|
+
ctx: any;
|
|
34
|
+
modelName: string;
|
|
35
|
+
operation: (typeof OperationBasic)[number];
|
|
36
|
+
}) => object | undefined;
|
|
37
|
+
};
|
|
38
|
+
export declare class PothosDrizzleGenerator {
|
|
39
|
+
enums: Record<string, PothosSchemaTypes.EnumRef<any, any>>;
|
|
40
|
+
inputOperators: Record<string, PothosSchemaTypes.InputObjectRef<any, any>>;
|
|
41
|
+
inputType: Record<string, Record<string, PothosSchemaTypes.InputObjectRef<any, any>>>;
|
|
42
|
+
tables?: Record<string, ModelData>;
|
|
43
|
+
builder: PothosSchemaTypes.SchemaBuilder<any>;
|
|
44
|
+
constructor(builder: PothosSchemaTypes.SchemaBuilder<any>);
|
|
45
|
+
createTableInfo(): Record<string, ModelData>;
|
|
46
|
+
getClient(ctx: any): DrizzleClient;
|
|
47
|
+
getRelations(): AnyRelations;
|
|
48
|
+
getTables(): Record<string, ModelData>;
|
|
49
|
+
getDepthLimit(): ((params: {
|
|
50
|
+
ctx: any;
|
|
51
|
+
modelName: string | number | symbol;
|
|
52
|
+
operation: (typeof OperationBasic)[number];
|
|
53
|
+
}) => number | undefined) | undefined;
|
|
54
|
+
getInputType(modelName: string, type: string, options: PothosSchemaTypes.InputObjectTypeOptions<any, any>): PothosSchemaTypes.InputObjectRef<any, any>;
|
|
55
|
+
getInputCreate(modelName: string): PothosSchemaTypes.InputObjectRef<any, any>;
|
|
56
|
+
getInputUpdate(modelName: string): PothosSchemaTypes.InputObjectRef<any, any>;
|
|
57
|
+
getInputWhere(modelName: string): PothosSchemaTypes.InputObjectRef<any, any>;
|
|
58
|
+
getInputOrderBy(modelName: string): PothosSchemaTypes.InputObjectRef<any, any>;
|
|
59
|
+
getInputOperator(type: string | [string]): PothosSchemaTypes.InputObjectRef<any, any>;
|
|
60
|
+
createInputType(): void;
|
|
61
|
+
getDataType(column: PgColumn): string | [string];
|
|
62
|
+
}
|
|
63
|
+
export {};
|