drizzle-graphql-plus 0.8.6 → 0.8.8

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.
@@ -1,517 +1,616 @@
1
- import { createTableRelationsHelpers, is, Relation, Relations, Table } from 'drizzle-orm';
2
- import { PgColumn, PgDatabase, PgTable } from 'drizzle-orm/pg-core';
3
1
  import {
4
- GraphQLError,
5
- GraphQLInputObjectType,
6
- GraphQLInt,
7
- GraphQLList,
8
- GraphQLNonNull,
9
- GraphQLObjectType,
10
- } from 'graphql';
2
+ createTableRelationsHelpers,
3
+ is,
4
+ Relation,
5
+ Relations,
6
+ Table,
7
+ } from "drizzle-orm";
8
+ import { PgColumn, PgDatabase, PgTable } from "drizzle-orm/pg-core";
9
+ import {
10
+ GraphQLError,
11
+ GraphQLInputObjectType,
12
+ GraphQLInt,
13
+ GraphQLInterfaceType,
14
+ GraphQLList,
15
+ GraphQLNonNull,
16
+ GraphQLObjectType,
17
+ } from "graphql";
11
18
 
12
19
  import {
13
- extractFilters,
14
- extractOrderBy,
15
- extractRelationsParams,
16
- extractSelectedColumnsFromTree,
17
- extractSelectedColumnsFromTreeSQLFormat,
18
- generateTableTypes,
19
- } from '@/util/builders/common';
20
- import { capitalize, uncapitalize } from '@/util/case-ops';
20
+ extractFilters,
21
+ extractOrderBy,
22
+ extractRelationsParams,
23
+ extractSelectedColumnsFromTree,
24
+ extractSelectedColumnsFromTreeSQLFormat,
25
+ generateTableTypes,
26
+ } from "@/util/builders/common";
27
+ import { capitalize, uncapitalize } from "@/util/case-ops";
21
28
  import {
22
- remapFromGraphQLArrayInput,
23
- remapFromGraphQLSingleInput,
24
- remapToGraphQLArrayOutput,
25
- remapToGraphQLSingleOutput,
26
- } from '@/util/data-mappers';
27
- import { parseResolveInfo } from 'graphql-parse-resolve-info';
28
-
29
- import type { GeneratedEntities } from '@/types';
30
- import type { RelationalQueryBuilder } from 'drizzle-orm/mysql-core/query-builders/query';
31
- import type { GraphQLFieldConfig, GraphQLFieldConfigArgumentMap, ThunkObjMap } from 'graphql';
32
- import type { ResolveTree } from 'graphql-parse-resolve-info';
33
- import type { CreatedResolver, Filters, TableNamedRelations, TableSelectArgs } from './types';
29
+ remapFromGraphQLArrayInput,
30
+ remapFromGraphQLSingleInput,
31
+ remapToGraphQLArrayOutput,
32
+ remapToGraphQLSingleOutput,
33
+ } from "@/util/data-mappers";
34
+ import { parseResolveInfo } from "graphql-parse-resolve-info";
35
+
36
+ import type { GeneratedEntities } from "@/types";
37
+ import type { RelationalQueryBuilder } from "drizzle-orm/mysql-core/query-builders/query";
38
+ import type {
39
+ GraphQLFieldConfig,
40
+ GraphQLFieldConfigArgumentMap,
41
+ ThunkObjMap,
42
+ } from "graphql";
43
+ import type { ResolveTree } from "graphql-parse-resolve-info";
44
+ import type {
45
+ CreatedResolver,
46
+ Filters,
47
+ TableNamedRelations,
48
+ TableSelectArgs,
49
+ } from "./types";
34
50
 
35
51
  const generateSelectArray = (
36
- db: PgDatabase<any, any, any>,
37
- tableName: string,
38
- tables: Record<string, Table>,
39
- relationMap: Record<string, Record<string, TableNamedRelations>>,
40
- orderArgs: GraphQLInputObjectType,
41
- filterArgs: GraphQLInputObjectType,
52
+ db: PgDatabase<any, any, any>,
53
+ tableName: string,
54
+ tables: Record<string, Table>,
55
+ relationMap: Record<string, Record<string, TableNamedRelations>>,
56
+ orderArgs: GraphQLInputObjectType,
57
+ filterArgs: GraphQLInputObjectType
42
58
  ): CreatedResolver => {
43
- const queryName = `${uncapitalize(tableName)}`;
44
- const queryBase = db.query[tableName as keyof typeof db.query] as unknown as
45
- | RelationalQueryBuilder<any, any, any>
46
- | undefined;
47
- if (!queryBase) {
48
- throw new Error(
49
- `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`,
50
- );
51
- }
52
-
53
- const queryArgs = {
54
- offset: {
55
- type: GraphQLInt,
56
- },
57
- limit: {
58
- type: GraphQLInt,
59
- },
60
- orderBy: {
61
- type: orderArgs,
62
- },
63
- where: {
64
- type: filterArgs,
65
- },
66
- } as GraphQLFieldConfigArgumentMap;
67
-
68
- const typeName = `${capitalize(tableName)}SelectItem`;
69
- const table = tables[tableName]!;
70
-
71
- return {
72
- name: queryName,
73
- resolver: async (source, args: Partial<TableSelectArgs>, context, info) => {
74
- try {
75
- const { offset, limit, orderBy, where } = args;
76
-
77
- const parsedInfo = parseResolveInfo(info, {
78
- deep: true,
79
- }) as ResolveTree;
80
-
81
- const query = queryBase.findMany({
82
- columns: extractSelectedColumnsFromTree(
83
- parsedInfo.fieldsByTypeName[typeName]!,
84
- table,
85
- ), /*extractSelectedColumnsFromNode(tableSelection, info.fragments, table) */
86
- offset,
87
- limit,
88
- orderBy: orderBy ? extractOrderBy(table, orderBy) : undefined,
89
- where: where ? extractFilters(table, tableName, where) : undefined,
90
- with: relationMap[tableName]
91
- ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName)
92
- : undefined,
93
- });
94
-
95
- const result = await query;
96
-
97
- return remapToGraphQLArrayOutput(result, tableName, table, relationMap);
98
- } catch (e) {
99
- if (typeof e === 'object' && typeof (<any> e).message === 'string') {
100
- throw new GraphQLError((<any> e).message);
101
- }
102
-
103
- throw e;
104
- }
105
- },
106
- args: queryArgs,
107
- };
59
+ const queryName = `${uncapitalize(tableName)}`;
60
+ const queryBase = db.query[tableName as keyof typeof db.query] as unknown as
61
+ | RelationalQueryBuilder<any, any, any>
62
+ | undefined;
63
+ if (!queryBase) {
64
+ throw new Error(
65
+ `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
66
+ );
67
+ }
68
+
69
+ const queryArgs = {
70
+ offset: {
71
+ type: GraphQLInt,
72
+ },
73
+ limit: {
74
+ type: GraphQLInt,
75
+ },
76
+ orderBy: {
77
+ type: orderArgs,
78
+ },
79
+ where: {
80
+ type: filterArgs,
81
+ },
82
+ } as GraphQLFieldConfigArgumentMap;
83
+
84
+ const typeName = `${capitalize(tableName)}SelectItem`;
85
+ const table = tables[tableName]!;
86
+
87
+ return {
88
+ name: queryName,
89
+ resolver: async (source, args: Partial<TableSelectArgs>, context, info) => {
90
+ try {
91
+ const { offset, limit, orderBy, where } = args;
92
+
93
+ const parsedInfo = parseResolveInfo(info, {
94
+ deep: true,
95
+ }) as ResolveTree;
96
+
97
+ const query = queryBase.findMany({
98
+ columns: extractSelectedColumnsFromTree(
99
+ parsedInfo.fieldsByTypeName[typeName]!,
100
+ table
101
+ ) /*extractSelectedColumnsFromNode(tableSelection, info.fragments, table) */,
102
+ offset,
103
+ limit,
104
+ orderBy: orderBy ? extractOrderBy(table, orderBy) : undefined,
105
+ where: where ? extractFilters(table, tableName, where) : undefined,
106
+ with: relationMap[tableName]
107
+ ? extractRelationsParams(
108
+ relationMap,
109
+ tables,
110
+ tableName,
111
+ parsedInfo,
112
+ typeName
113
+ )
114
+ : undefined,
115
+ });
116
+
117
+ const result = await query;
118
+
119
+ return remapToGraphQLArrayOutput(result, tableName, table, relationMap);
120
+ } catch (e) {
121
+ if (typeof e === "object" && typeof (<any>e).message === "string") {
122
+ throw new GraphQLError((<any>e).message);
123
+ }
124
+
125
+ throw e;
126
+ }
127
+ },
128
+ args: queryArgs,
129
+ };
108
130
  };
109
131
 
110
132
  const generateSelectSingle = (
111
- db: PgDatabase<any, any, any>,
112
- tableName: string,
113
- tables: Record<string, Table>,
114
- relationMap: Record<string, Record<string, TableNamedRelations>>,
115
- orderArgs: GraphQLInputObjectType,
116
- filterArgs: GraphQLInputObjectType,
133
+ db: PgDatabase<any, any, any>,
134
+ tableName: string,
135
+ tables: Record<string, Table>,
136
+ relationMap: Record<string, Record<string, TableNamedRelations>>,
137
+ orderArgs: GraphQLInputObjectType,
138
+ filterArgs: GraphQLInputObjectType
117
139
  ): CreatedResolver => {
118
- const queryName = `${uncapitalize(tableName)}Single`;
119
- const queryBase = db.query[tableName as keyof typeof db.query] as unknown as
120
- | RelationalQueryBuilder<any, any, any>
121
- | undefined;
122
- if (!queryBase) {
123
- throw new Error(
124
- `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`,
125
- );
126
- }
127
-
128
- const queryArgs = {
129
- offset: {
130
- type: GraphQLInt,
131
- },
132
- orderBy: {
133
- type: orderArgs,
134
- },
135
- where: {
136
- type: filterArgs,
137
- },
138
- } as GraphQLFieldConfigArgumentMap;
139
-
140
- const typeName = `${capitalize(tableName)}SelectItem`;
141
- const table = tables[tableName]!;
142
-
143
- return {
144
- name: queryName,
145
- resolver: async (source, args: Partial<TableSelectArgs>, context, info) => {
146
- try {
147
- const { offset, orderBy, where } = args;
148
-
149
- const parsedInfo = parseResolveInfo(info, {
150
- deep: true,
151
- }) as ResolveTree;
152
-
153
- const query = queryBase.findFirst({
154
- columns: extractSelectedColumnsFromTree(
155
- parsedInfo.fieldsByTypeName[typeName]!,
156
- table,
157
- ),
158
- offset,
159
- orderBy: orderBy ? extractOrderBy(table, orderBy) : undefined,
160
- where: where ? extractFilters(table, tableName, where) : undefined,
161
- with: relationMap[tableName]
162
- ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName)
163
- : undefined,
164
- });
165
-
166
- const result = await query;
167
- if (!result) return undefined;
168
-
169
- return remapToGraphQLSingleOutput(result, tableName, table, relationMap);
170
- } catch (e) {
171
- if (typeof e === 'object' && typeof (<any> e).message === 'string') {
172
- throw new GraphQLError((<any> e).message);
173
- }
174
-
175
- throw e;
176
- }
177
- },
178
- args: queryArgs,
179
- };
140
+ const queryName = `${uncapitalize(tableName)}Single`;
141
+ const queryBase = db.query[tableName as keyof typeof db.query] as unknown as
142
+ | RelationalQueryBuilder<any, any, any>
143
+ | undefined;
144
+ if (!queryBase) {
145
+ throw new Error(
146
+ `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
147
+ );
148
+ }
149
+
150
+ const queryArgs = {
151
+ offset: {
152
+ type: GraphQLInt,
153
+ },
154
+ orderBy: {
155
+ type: orderArgs,
156
+ },
157
+ where: {
158
+ type: filterArgs,
159
+ },
160
+ } as GraphQLFieldConfigArgumentMap;
161
+
162
+ const typeName = `${capitalize(tableName)}SelectItem`;
163
+ const table = tables[tableName]!;
164
+
165
+ return {
166
+ name: queryName,
167
+ resolver: async (source, args: Partial<TableSelectArgs>, context, info) => {
168
+ try {
169
+ const { offset, orderBy, where } = args;
170
+
171
+ const parsedInfo = parseResolveInfo(info, {
172
+ deep: true,
173
+ }) as ResolveTree;
174
+
175
+ const query = queryBase.findFirst({
176
+ columns: extractSelectedColumnsFromTree(
177
+ parsedInfo.fieldsByTypeName[typeName]!,
178
+ table
179
+ ),
180
+ offset,
181
+ orderBy: orderBy ? extractOrderBy(table, orderBy) : undefined,
182
+ where: where ? extractFilters(table, tableName, where) : undefined,
183
+ with: relationMap[tableName]
184
+ ? extractRelationsParams(
185
+ relationMap,
186
+ tables,
187
+ tableName,
188
+ parsedInfo,
189
+ typeName
190
+ )
191
+ : undefined,
192
+ });
193
+
194
+ const result = await query;
195
+ if (!result) return undefined;
196
+
197
+ return remapToGraphQLSingleOutput(
198
+ result,
199
+ tableName,
200
+ table,
201
+ relationMap
202
+ );
203
+ } catch (e) {
204
+ if (typeof e === "object" && typeof (<any>e).message === "string") {
205
+ throw new GraphQLError((<any>e).message);
206
+ }
207
+
208
+ throw e;
209
+ }
210
+ },
211
+ args: queryArgs,
212
+ };
180
213
  };
181
214
 
182
215
  const generateInsertArray = (
183
- db: PgDatabase<any, any, any>,
184
- tableName: string,
185
- table: PgTable,
186
- baseType: GraphQLInputObjectType,
216
+ db: PgDatabase<any, any, any>,
217
+ tableName: string,
218
+ table: PgTable,
219
+ baseType: GraphQLInputObjectType
187
220
  ): CreatedResolver => {
188
- const queryName = `insertInto${capitalize(tableName)}`;
189
- const typeName = `${capitalize(tableName)}Item`;
190
-
191
- const queryArgs: GraphQLFieldConfigArgumentMap = {
192
- values: {
193
- type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(baseType))),
194
- },
195
- };
196
-
197
- return {
198
- name: queryName,
199
- resolver: async (source, args: { values: Record<string, any>[] }, context, info) => {
200
- try {
201
- const input = remapFromGraphQLArrayInput(args.values, table);
202
- if (!input.length) throw new GraphQLError('No values were provided!');
203
-
204
- const parsedInfo = parseResolveInfo(info, {
205
- deep: true,
206
- }) as ResolveTree;
207
-
208
- const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
209
- parsedInfo.fieldsByTypeName[typeName]!,
210
- table,
211
- );
212
-
213
- const result = await db.insert(table).values(input).returning(columns)
214
- .onConflictDoNothing();
215
-
216
- return remapToGraphQLArrayOutput(result, tableName, table);
217
- } catch (e) {
218
- if (typeof e === 'object' && typeof (<any> e).message === 'string') {
219
- throw new GraphQLError((<any> e).message);
220
- }
221
-
222
- throw e;
223
- }
224
- },
225
- args: queryArgs,
226
- };
221
+ const queryName = `insertInto${capitalize(tableName)}`;
222
+ const typeName = `${capitalize(tableName)}Item`;
223
+
224
+ const queryArgs: GraphQLFieldConfigArgumentMap = {
225
+ values: {
226
+ type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(baseType))),
227
+ },
228
+ };
229
+
230
+ return {
231
+ name: queryName,
232
+ resolver: async (
233
+ source,
234
+ args: { values: Record<string, any>[] },
235
+ context,
236
+ info
237
+ ) => {
238
+ try {
239
+ const input = remapFromGraphQLArrayInput(args.values, table);
240
+ if (!input.length) throw new GraphQLError("No values were provided!");
241
+
242
+ const parsedInfo = parseResolveInfo(info, {
243
+ deep: true,
244
+ }) as ResolveTree;
245
+
246
+ const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
247
+ parsedInfo.fieldsByTypeName[typeName]!,
248
+ table
249
+ );
250
+
251
+ const result = await db
252
+ .insert(table)
253
+ .values(input)
254
+ .returning(columns)
255
+ .onConflictDoNothing();
256
+
257
+ return remapToGraphQLArrayOutput(result, tableName, table);
258
+ } catch (e) {
259
+ if (typeof e === "object" && typeof (<any>e).message === "string") {
260
+ throw new GraphQLError((<any>e).message);
261
+ }
262
+
263
+ throw e;
264
+ }
265
+ },
266
+ args: queryArgs,
267
+ };
227
268
  };
228
269
 
229
270
  const generateInsertSingle = (
230
- db: PgDatabase<any, any, any>,
231
- tableName: string,
232
- table: PgTable,
233
- baseType: GraphQLInputObjectType,
271
+ db: PgDatabase<any, any, any>,
272
+ tableName: string,
273
+ table: PgTable,
274
+ baseType: GraphQLInputObjectType
234
275
  ): CreatedResolver => {
235
- const queryName = `insertInto${capitalize(tableName)}Single`;
236
- const typeName = `${capitalize(tableName)}Item`;
237
-
238
- const queryArgs: GraphQLFieldConfigArgumentMap = {
239
- values: {
240
- type: new GraphQLNonNull(baseType),
241
- },
242
- };
243
-
244
- return {
245
- name: queryName,
246
- resolver: async (source, args: { values: Record<string, any> }, context, info) => {
247
- try {
248
- const input = remapFromGraphQLSingleInput(args.values, table);
249
-
250
- const parsedInfo = parseResolveInfo(info, {
251
- deep: true,
252
- }) as ResolveTree;
253
-
254
- const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
255
- parsedInfo.fieldsByTypeName[typeName]!,
256
- table,
257
- );
258
-
259
- const result = await db.insert(table).values(input).returning(columns)
260
- .onConflictDoNothing();
261
-
262
- if (!result[0]) return undefined;
263
-
264
- return remapToGraphQLSingleOutput(result[0], tableName, table);
265
- } catch (e) {
266
- if (typeof e === 'object' && typeof (<any> e).message === 'string') {
267
- throw new GraphQLError((<any> e).message);
268
- }
269
-
270
- throw e;
271
- }
272
- },
273
- args: queryArgs,
274
- };
276
+ const queryName = `insertInto${capitalize(tableName)}Single`;
277
+ const typeName = `${capitalize(tableName)}Item`;
278
+
279
+ const queryArgs: GraphQLFieldConfigArgumentMap = {
280
+ values: {
281
+ type: new GraphQLNonNull(baseType),
282
+ },
283
+ };
284
+
285
+ return {
286
+ name: queryName,
287
+ resolver: async (
288
+ source,
289
+ args: { values: Record<string, any> },
290
+ context,
291
+ info
292
+ ) => {
293
+ try {
294
+ const input = remapFromGraphQLSingleInput(args.values, table);
295
+
296
+ const parsedInfo = parseResolveInfo(info, {
297
+ deep: true,
298
+ }) as ResolveTree;
299
+
300
+ const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
301
+ parsedInfo.fieldsByTypeName[typeName]!,
302
+ table
303
+ );
304
+
305
+ const result = await db
306
+ .insert(table)
307
+ .values(input)
308
+ .returning(columns)
309
+ .onConflictDoNothing();
310
+
311
+ if (!result[0]) return undefined;
312
+
313
+ return remapToGraphQLSingleOutput(result[0], tableName, table);
314
+ } catch (e) {
315
+ if (typeof e === "object" && typeof (<any>e).message === "string") {
316
+ throw new GraphQLError((<any>e).message);
317
+ }
318
+
319
+ throw e;
320
+ }
321
+ },
322
+ args: queryArgs,
323
+ };
275
324
  };
276
325
 
277
326
  const generateUpdate = (
278
- db: PgDatabase<any, any, any>,
279
- tableName: string,
280
- table: PgTable,
281
- setArgs: GraphQLInputObjectType,
282
- filterArgs: GraphQLInputObjectType,
327
+ db: PgDatabase<any, any, any>,
328
+ tableName: string,
329
+ table: PgTable,
330
+ setArgs: GraphQLInputObjectType,
331
+ filterArgs: GraphQLInputObjectType
283
332
  ): CreatedResolver => {
284
- const queryName = `update${capitalize(tableName)}`;
285
- const typeName = `${capitalize(tableName)}Item`;
286
-
287
- const queryArgs = {
288
- set: {
289
- type: new GraphQLNonNull(setArgs),
290
- },
291
- where: {
292
- type: filterArgs,
293
- },
294
- } as const satisfies GraphQLFieldConfigArgumentMap;
295
-
296
- return {
297
- name: queryName,
298
- resolver: async (source, args: { where?: Filters<Table>; set: Record<string, any> }, context, info) => {
299
- try {
300
- const { where, set } = args;
301
-
302
- const parsedInfo = parseResolveInfo(info, {
303
- deep: true,
304
- }) as ResolveTree;
305
-
306
- const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
307
- parsedInfo.fieldsByTypeName[typeName]!,
308
- table,
309
- );
310
-
311
- const input = remapFromGraphQLSingleInput(set, table);
312
- if (!Object.keys(input).length) throw new GraphQLError('Unable to update with no values specified!');
313
-
314
- let query = db.update(table).set(input);
315
- if (where) {
316
- const filters = extractFilters(table, tableName, where);
317
- query = query.where(filters) as any;
318
- }
319
-
320
- query = query.returning(columns) as any;
321
-
322
- const result = await query;
323
-
324
- return remapToGraphQLArrayOutput(result, tableName, table);
325
- } catch (e) {
326
- if (typeof e === 'object' && typeof (<any> e).message === 'string') {
327
- throw new GraphQLError((<any> e).message);
328
- }
329
-
330
- throw e;
331
- }
332
- },
333
- args: queryArgs,
334
- };
333
+ const queryName = `update${capitalize(tableName)}`;
334
+ const typeName = `${capitalize(tableName)}Item`;
335
+
336
+ const queryArgs = {
337
+ set: {
338
+ type: new GraphQLNonNull(setArgs),
339
+ },
340
+ where: {
341
+ type: filterArgs,
342
+ },
343
+ } as const satisfies GraphQLFieldConfigArgumentMap;
344
+
345
+ return {
346
+ name: queryName,
347
+ resolver: async (
348
+ source,
349
+ args: { where?: Filters<Table>; set: Record<string, any> },
350
+ context,
351
+ info
352
+ ) => {
353
+ try {
354
+ const { where, set } = args;
355
+
356
+ const parsedInfo = parseResolveInfo(info, {
357
+ deep: true,
358
+ }) as ResolveTree;
359
+
360
+ const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
361
+ parsedInfo.fieldsByTypeName[typeName]!,
362
+ table
363
+ );
364
+
365
+ const input = remapFromGraphQLSingleInput(set, table);
366
+ if (!Object.keys(input).length)
367
+ throw new GraphQLError("Unable to update with no values specified!");
368
+
369
+ let query = db.update(table).set(input);
370
+ if (where) {
371
+ const filters = extractFilters(table, tableName, where);
372
+ query = query.where(filters) as any;
373
+ }
374
+
375
+ query = query.returning(columns) as any;
376
+
377
+ const result = await query;
378
+
379
+ return remapToGraphQLArrayOutput(result, tableName, table);
380
+ } catch (e) {
381
+ if (typeof e === "object" && typeof (<any>e).message === "string") {
382
+ throw new GraphQLError((<any>e).message);
383
+ }
384
+
385
+ throw e;
386
+ }
387
+ },
388
+ args: queryArgs,
389
+ };
335
390
  };
336
391
 
337
392
  const generateDelete = (
338
- db: PgDatabase<any, any, any>,
339
- tableName: string,
340
- table: PgTable,
341
- filterArgs: GraphQLInputObjectType,
393
+ db: PgDatabase<any, any, any>,
394
+ tableName: string,
395
+ table: PgTable,
396
+ filterArgs: GraphQLInputObjectType
342
397
  ): CreatedResolver => {
343
- const queryName = `deleteFrom${capitalize(tableName)}`;
344
- const typeName = `${capitalize(tableName)}Item`;
345
-
346
- const queryArgs = {
347
- where: {
348
- type: filterArgs,
349
- },
350
- } as const satisfies GraphQLFieldConfigArgumentMap;
351
-
352
- return {
353
- name: queryName,
354
- resolver: async (source, args: { where?: Filters<Table> }, context, info) => {
355
- try {
356
- const { where } = args;
357
-
358
- const parsedInfo = parseResolveInfo(info, {
359
- deep: true,
360
- }) as ResolveTree;
361
-
362
- const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
363
- parsedInfo.fieldsByTypeName[typeName]!,
364
- table,
365
- );
366
-
367
- let query = db.delete(table);
368
- if (where) {
369
- const filters = extractFilters(table, tableName, where);
370
- query = query.where(filters) as any;
371
- }
372
-
373
- query = query.returning(columns) as any;
374
-
375
- const result = await query;
376
-
377
- return remapToGraphQLArrayOutput(result, tableName, table);
378
- } catch (e) {
379
- if (typeof e === 'object' && typeof (<any> e).message === 'string') {
380
- throw new GraphQLError((<any> e).message);
381
- }
382
-
383
- throw e;
384
- }
385
- },
386
- args: queryArgs,
387
- };
398
+ const queryName = `deleteFrom${capitalize(tableName)}`;
399
+ const typeName = `${capitalize(tableName)}Item`;
400
+
401
+ const queryArgs = {
402
+ where: {
403
+ type: filterArgs,
404
+ },
405
+ } as const satisfies GraphQLFieldConfigArgumentMap;
406
+
407
+ return {
408
+ name: queryName,
409
+ resolver: async (
410
+ source,
411
+ args: { where?: Filters<Table> },
412
+ context,
413
+ info
414
+ ) => {
415
+ try {
416
+ const { where } = args;
417
+
418
+ const parsedInfo = parseResolveInfo(info, {
419
+ deep: true,
420
+ }) as ResolveTree;
421
+
422
+ const columns = extractSelectedColumnsFromTreeSQLFormat<PgColumn>(
423
+ parsedInfo.fieldsByTypeName[typeName]!,
424
+ table
425
+ );
426
+
427
+ let query = db.delete(table);
428
+ if (where) {
429
+ const filters = extractFilters(table, tableName, where);
430
+ query = query.where(filters) as any;
431
+ }
432
+
433
+ query = query.returning(columns) as any;
434
+
435
+ const result = await query;
436
+
437
+ return remapToGraphQLArrayOutput(result, tableName, table);
438
+ } catch (e) {
439
+ if (typeof e === "object" && typeof (<any>e).message === "string") {
440
+ throw new GraphQLError((<any>e).message);
441
+ }
442
+
443
+ throw e;
444
+ }
445
+ },
446
+ args: queryArgs,
447
+ };
388
448
  };
389
449
 
390
450
  export const generateSchemaData = <
391
- TDrizzleInstance extends PgDatabase<any, any, any>,
392
- TSchema extends Record<string, Table | unknown>,
451
+ TDrizzleInstance extends PgDatabase<any, any, any>,
452
+ TSchema extends Record<string, Table | unknown>
393
453
  >(
394
- db: TDrizzleInstance,
395
- schema: TSchema,
396
- relationsDepthLimit: number | undefined,
454
+ db: TDrizzleInstance,
455
+ schema: TSchema,
456
+ relationsDepthLimit: number | undefined
397
457
  ): GeneratedEntities<TDrizzleInstance, TSchema> => {
398
- const rawSchema = schema;
399
- const schemaEntries = Object.entries(rawSchema);
400
-
401
- const tableEntries = schemaEntries.filter(([key, value]) => is(value, PgTable)) as [string, PgTable][];
402
- const tables = Object.fromEntries(tableEntries) as Record<
403
- string,
404
- PgTable
405
- >;
406
-
407
- if (!tableEntries.length) {
408
- throw new Error(
409
- "Drizzle-GraphQL Error: No tables detected in Drizzle-ORM's database instance. Did you forget to pass schema to drizzle constructor?",
410
- );
411
- }
412
-
413
- const rawRelations = schemaEntries
414
- .filter(([key, value]) => is(value, Relations))
415
- .map<[string, Relations]>(([key, value]) => [
416
- tableEntries.find(
417
- ([tableName, tableValue]) => tableValue === (value as Relations).table,
418
- )![0] as string,
419
- value as Relations,
420
- ]).map<[string, Record<string, Relation>]>(([tableName, relValue]) => [
421
- tableName,
422
- relValue.config(createTableRelationsHelpers(tables[tableName]!)),
423
- ]);
424
-
425
- const namedRelations = Object.fromEntries(
426
- rawRelations
427
- .map(([relName, config]) => {
428
- const namedConfig: Record<string, TableNamedRelations> = Object.fromEntries(
429
- Object.entries(config).map(([innerRelName, innerRelValue]) => [innerRelName, {
430
- relation: innerRelValue,
431
- targetTableName: tableEntries.find(([tableName, tableValue]) =>
432
- tableValue === innerRelValue.referencedTable
433
- )![0],
434
- }]),
435
- );
436
-
437
- return [
438
- relName,
439
- namedConfig,
440
- ];
441
- }),
442
- );
443
-
444
- const queries: ThunkObjMap<GraphQLFieldConfig<any, any>> = {};
445
- const mutations: ThunkObjMap<GraphQLFieldConfig<any, any>> = {};
446
- const gqlSchemaTypes = Object.fromEntries(
447
- Object.entries(tables).map(([tableName, table]) => [
448
- tableName,
449
- generateTableTypes(tableName, tables, namedRelations, true, relationsDepthLimit),
450
- ]),
451
- );
452
-
453
- const inputs: Record<string, GraphQLInputObjectType> = {};
454
- const outputs: Record<string, GraphQLObjectType> = {};
455
-
456
- for (const [tableName, tableTypes] of Object.entries(gqlSchemaTypes)) {
457
- const { insertInput, updateInput, tableFilters, tableOrder } = tableTypes.inputs;
458
- const { selectSingleOutput, selectArrOutput, singleTableItemOutput, arrTableItemOutput } = tableTypes.outputs;
459
-
460
- const selectArrGenerated = generateSelectArray(
461
- db,
462
- tableName,
463
- tables,
464
- namedRelations,
465
- tableOrder,
466
- tableFilters,
467
- );
468
- const selectSingleGenerated = generateSelectSingle(
469
- db,
470
- tableName,
471
- tables,
472
- namedRelations,
473
- tableOrder,
474
- tableFilters,
475
- );
476
- const insertArrGenerated = generateInsertArray(db, tableName, schema[tableName] as PgTable, insertInput);
477
- const insertSingleGenerated = generateInsertSingle(db, tableName, schema[tableName] as PgTable, insertInput);
478
- const updateGenerated = generateUpdate(db, tableName, schema[tableName] as PgTable, updateInput, tableFilters);
479
- const deleteGenerated = generateDelete(db, tableName, schema[tableName] as PgTable, tableFilters);
480
-
481
- queries[selectArrGenerated.name] = {
482
- type: selectArrOutput,
483
- args: selectArrGenerated.args,
484
- resolve: selectArrGenerated.resolver,
485
- };
486
- queries[selectSingleGenerated.name] = {
487
- type: selectSingleOutput,
488
- args: selectSingleGenerated.args,
489
- resolve: selectSingleGenerated.resolver,
490
- };
491
- mutations[insertArrGenerated.name] = {
492
- type: arrTableItemOutput,
493
- args: insertArrGenerated.args,
494
- resolve: insertArrGenerated.resolver,
495
- };
496
- mutations[insertSingleGenerated.name] = {
497
- type: singleTableItemOutput,
498
- args: insertSingleGenerated.args,
499
- resolve: insertSingleGenerated.resolver,
500
- };
501
- mutations[updateGenerated.name] = {
502
- type: arrTableItemOutput,
503
- args: updateGenerated.args,
504
- resolve: updateGenerated.resolver,
505
- };
506
- mutations[deleteGenerated.name] = {
507
- type: arrTableItemOutput,
508
- args: deleteGenerated.args,
509
- resolve: deleteGenerated.resolver,
510
- };
511
- [insertInput, updateInput, tableFilters, tableOrder].forEach((e) => (inputs[e.name] = e));
512
- outputs[selectSingleOutput.name] = selectSingleOutput;
513
- outputs[singleTableItemOutput.name] = singleTableItemOutput;
514
- }
515
-
516
- return { queries, mutations, inputs, types: outputs } as any;
458
+ const rawSchema = schema;
459
+ const schemaEntries = Object.entries(rawSchema);
460
+
461
+ const tableEntries = schemaEntries.filter(([key, value]) =>
462
+ is(value, PgTable)
463
+ ) as [string, PgTable][];
464
+ const tables = Object.fromEntries(tableEntries) as Record<string, PgTable>;
465
+
466
+ if (!tableEntries.length) {
467
+ throw new Error(
468
+ "Drizzle-GraphQL Error: No tables detected in Drizzle-ORM's database instance. Did you forget to pass schema to drizzle constructor?"
469
+ );
470
+ }
471
+
472
+ const rawRelations = schemaEntries
473
+ .filter(([key, value]) => is(value, Relations))
474
+ .map<[string, Relations]>(([key, value]) => [
475
+ tableEntries.find(
476
+ ([tableName, tableValue]) => tableValue === (value as Relations).table
477
+ )![0] as string,
478
+ value as Relations,
479
+ ])
480
+ .map<[string, Record<string, Relation>]>(([tableName, relValue]) => [
481
+ tableName,
482
+ relValue.config(createTableRelationsHelpers(tables[tableName]!)),
483
+ ]);
484
+
485
+ const namedRelations = Object.fromEntries(
486
+ rawRelations.map(([relName, config]) => {
487
+ const namedConfig: Record<string, TableNamedRelations> =
488
+ Object.fromEntries(
489
+ Object.entries(config).map(([innerRelName, innerRelValue]) => [
490
+ innerRelName,
491
+ {
492
+ relation: innerRelValue,
493
+ targetTableName: tableEntries.find(
494
+ ([tableName, tableValue]) =>
495
+ tableValue === innerRelValue.referencedTable
496
+ )![0],
497
+ },
498
+ ])
499
+ );
500
+
501
+ return [relName, namedConfig];
502
+ })
503
+ );
504
+
505
+ const queries: ThunkObjMap<GraphQLFieldConfig<any, any>> = {};
506
+ const mutations: ThunkObjMap<GraphQLFieldConfig<any, any>> = {};
507
+ const gqlSchemaTypes = Object.fromEntries(
508
+ Object.entries(tables).map(([tableName, table]) => [
509
+ tableName,
510
+ generateTableTypes(
511
+ tableName,
512
+ tables,
513
+ namedRelations,
514
+ true,
515
+ relationsDepthLimit
516
+ ),
517
+ ])
518
+ );
519
+
520
+ const inputs: Record<string, GraphQLInputObjectType> = {};
521
+ const interfaces: Record<string, GraphQLInterfaceType> = {};
522
+ const outputs: Record<string, GraphQLObjectType> = {};
523
+
524
+ for (const [tableName, tableTypes] of Object.entries(gqlSchemaTypes)) {
525
+ const { insertInput, updateInput, tableFilters, tableOrder } =
526
+ tableTypes.inputs;
527
+ const {
528
+ selectSingleOutput,
529
+ selectArrOutput,
530
+ singleTableItemOutput,
531
+ arrTableItemOutput,
532
+ tableFieldsInterface,
533
+ } = tableTypes.outputs;
534
+
535
+ const selectArrGenerated = generateSelectArray(
536
+ db,
537
+ tableName,
538
+ tables,
539
+ namedRelations,
540
+ tableOrder,
541
+ tableFilters
542
+ );
543
+ const selectSingleGenerated = generateSelectSingle(
544
+ db,
545
+ tableName,
546
+ tables,
547
+ namedRelations,
548
+ tableOrder,
549
+ tableFilters
550
+ );
551
+ const insertArrGenerated = generateInsertArray(
552
+ db,
553
+ tableName,
554
+ schema[tableName] as PgTable,
555
+ insertInput
556
+ );
557
+ const insertSingleGenerated = generateInsertSingle(
558
+ db,
559
+ tableName,
560
+ schema[tableName] as PgTable,
561
+ insertInput
562
+ );
563
+ const updateGenerated = generateUpdate(
564
+ db,
565
+ tableName,
566
+ schema[tableName] as PgTable,
567
+ updateInput,
568
+ tableFilters
569
+ );
570
+ const deleteGenerated = generateDelete(
571
+ db,
572
+ tableName,
573
+ schema[tableName] as PgTable,
574
+ tableFilters
575
+ );
576
+
577
+ queries[selectArrGenerated.name] = {
578
+ type: selectArrOutput,
579
+ args: selectArrGenerated.args,
580
+ resolve: selectArrGenerated.resolver,
581
+ };
582
+ queries[selectSingleGenerated.name] = {
583
+ type: selectSingleOutput,
584
+ args: selectSingleGenerated.args,
585
+ resolve: selectSingleGenerated.resolver,
586
+ };
587
+ mutations[insertArrGenerated.name] = {
588
+ type: arrTableItemOutput,
589
+ args: insertArrGenerated.args,
590
+ resolve: insertArrGenerated.resolver,
591
+ };
592
+ mutations[insertSingleGenerated.name] = {
593
+ type: singleTableItemOutput,
594
+ args: insertSingleGenerated.args,
595
+ resolve: insertSingleGenerated.resolver,
596
+ };
597
+ mutations[updateGenerated.name] = {
598
+ type: arrTableItemOutput,
599
+ args: updateGenerated.args,
600
+ resolve: updateGenerated.resolver,
601
+ };
602
+ mutations[deleteGenerated.name] = {
603
+ type: arrTableItemOutput,
604
+ args: deleteGenerated.args,
605
+ resolve: deleteGenerated.resolver,
606
+ };
607
+ [insertInput, updateInput, tableFilters, tableOrder].forEach(
608
+ (e) => (inputs[e.name] = e)
609
+ );
610
+ outputs[selectSingleOutput.name] = selectSingleOutput;
611
+ outputs[singleTableItemOutput.name] = singleTableItemOutput;
612
+ interfaces[tableFieldsInterface.name] = tableFieldsInterface;
613
+ }
614
+
615
+ return { queries, mutations, inputs, interfaces, types: outputs } as any;
517
616
  };