@pothos/plugin-drizzle 0.8.1 → 0.10.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 +102 -0
- package/TODO.md +25 -4
- package/dts/connection-helpers.d.ts +34 -0
- package/dts/connection-helpers.d.ts.map +1 -0
- package/dts/drizzle-field-builder.d.ts +18 -53
- package/dts/drizzle-field-builder.d.ts.map +1 -1
- package/dts/global-types.d.ts +22 -41
- package/dts/global-types.d.ts.map +1 -1
- package/dts/index.d.ts +5 -2
- package/dts/index.d.ts.map +1 -1
- package/dts/interface-ref.d.ts +3 -2
- package/dts/interface-ref.d.ts.map +1 -1
- package/dts/model-loader.d.ts +3 -2
- package/dts/model-loader.d.ts.map +1 -1
- package/dts/node-ref.d.ts +1 -1
- package/dts/node-ref.d.ts.map +1 -1
- package/dts/object-ref.d.ts +2 -2
- package/dts/object-ref.d.ts.map +1 -1
- package/dts/types.d.ts +61 -41
- package/dts/types.d.ts.map +1 -1
- package/dts/utils/config.d.ts +4 -3
- package/dts/utils/config.d.ts.map +1 -1
- package/dts/utils/cursors.d.ts +13 -7
- package/dts/utils/cursors.d.ts.map +1 -1
- package/dts/utils/drizzle-graphql.d.ts +0 -17
- package/dts/utils/drizzle-graphql.d.ts.map +1 -1
- package/dts/utils/map-query.d.ts.map +1 -1
- package/dts/utils/selections.d.ts +5 -5
- package/dts/utils/selections.d.ts.map +1 -1
- package/esm/connection-helpers.d.ts +36 -0
- package/esm/connection-helpers.d.ts.map +1 -0
- package/esm/connection-helpers.js +82 -0
- package/esm/connection-helpers.js.map +1 -0
- package/esm/drizzle-field-builder.d.ts +18 -73
- package/esm/drizzle-field-builder.d.ts.map +1 -1
- package/esm/drizzle-field-builder.js +25 -14
- package/esm/drizzle-field-builder.js.map +1 -1
- package/esm/field-builder.js +2 -3
- package/esm/field-builder.js.map +1 -1
- package/esm/global-types.d.ts +35 -60
- package/esm/global-types.d.ts.map +1 -1
- package/esm/global-types.js.map +1 -1
- package/esm/index.d.ts +5 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +71 -61
- package/esm/index.js.map +1 -1
- package/esm/interface-ref.d.ts +3 -2
- package/esm/interface-ref.d.ts.map +1 -1
- package/esm/interface-ref.js.map +1 -1
- package/esm/model-loader.d.ts +3 -2
- package/esm/model-loader.d.ts.map +1 -1
- package/esm/model-loader.js +17 -10
- package/esm/model-loader.js.map +1 -1
- package/esm/node-ref.d.ts +1 -1
- package/esm/node-ref.d.ts.map +1 -1
- package/esm/object-ref.d.ts +2 -2
- package/esm/object-ref.d.ts.map +1 -1
- package/esm/schema-builder.js +113 -67
- package/esm/schema-builder.js.map +1 -1
- package/esm/types.d.ts +61 -41
- package/esm/types.d.ts.map +1 -1
- package/esm/types.js.map +1 -1
- package/esm/utils/config.d.ts +4 -3
- package/esm/utils/config.d.ts.map +1 -1
- package/esm/utils/config.js +32 -15
- package/esm/utils/config.js.map +1 -1
- package/esm/utils/cursors.d.ts +13 -7
- package/esm/utils/cursors.d.ts.map +1 -1
- package/esm/utils/cursors.js +137 -63
- package/esm/utils/cursors.js.map +1 -1
- package/esm/utils/drizzle-graphql.d.ts +0 -17
- package/esm/utils/drizzle-graphql.d.ts.map +1 -1
- package/esm/utils/drizzle-graphql.js +230 -198
- package/esm/utils/drizzle-graphql.js.map +1 -1
- package/esm/utils/map-query.d.ts.map +1 -1
- package/esm/utils/map-query.js +10 -6
- package/esm/utils/map-query.js.map +1 -1
- package/esm/utils/selections.d.ts +5 -5
- package/esm/utils/selections.d.ts.map +1 -1
- package/esm/utils/selections.js +19 -18
- package/esm/utils/selections.js.map +1 -1
- package/lib/connection-helpers.js +93 -0
- package/lib/connection-helpers.js.map +1 -0
- package/lib/drizzle-field-builder.js +24 -13
- package/lib/drizzle-field-builder.js.map +1 -1
- package/lib/field-builder.js +2 -3
- package/lib/field-builder.js.map +1 -1
- package/lib/index.js +79 -60
- package/lib/index.js.map +1 -1
- package/lib/interface-ref.js.map +1 -1
- package/lib/model-loader.js +17 -10
- package/lib/model-loader.js.map +1 -1
- package/lib/schema-builder.js +113 -67
- package/lib/schema-builder.js.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/config.js +31 -14
- package/lib/utils/config.js.map +1 -1
- package/lib/utils/cursors.js +135 -63
- package/lib/utils/cursors.js.map +1 -1
- package/lib/utils/drizzle-graphql.js +230 -221
- package/lib/utils/drizzle-graphql.js.map +1 -1
- package/lib/utils/map-query.js +10 -6
- package/lib/utils/map-query.js.map +1 -1
- package/lib/utils/selections.js +18 -17
- package/lib/utils/selections.js.map +1 -1
- package/package.json +14 -14
- package/src/connection-helpers.ts +206 -0
- package/src/drizzle-field-builder.ts +30 -26
- package/src/field-builder.ts +4 -7
- package/src/global-types.ts +112 -119
- package/src/index.ts +91 -70
- package/src/interface-ref.ts +7 -3
- package/src/model-loader.ts +32 -17
- package/src/node-ref.ts +1 -1
- package/src/object-ref.ts +2 -2
- package/src/schema-builder.ts +116 -113
- package/src/types.ts +95 -62
- package/src/utils/config.ts +39 -30
- package/src/utils/cursors.ts +134 -101
- package/src/utils/drizzle-graphql.ts +273 -274
- package/src/utils/map-query.ts +20 -8
- package/src/utils/selections.ts +34 -28
package/src/utils/cursors.ts
CHANGED
|
@@ -5,13 +5,14 @@ import {
|
|
|
5
5
|
decodeBase64,
|
|
6
6
|
encodeBase64,
|
|
7
7
|
} from '@pothos/core';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
import type {
|
|
9
|
+
Column,
|
|
10
|
+
DBQueryConfig,
|
|
11
|
+
OrderByOperators,
|
|
12
|
+
SQL,
|
|
13
|
+
Table,
|
|
14
|
+
TableConfig,
|
|
15
|
+
TableRelationalConfig,
|
|
15
16
|
} from 'drizzle-orm';
|
|
16
17
|
import type { GraphQLResolveInfo } from 'graphql';
|
|
17
18
|
import type { ConnectionOrderBy, QueryForDrizzleConnection } from '../types';
|
|
@@ -73,6 +74,7 @@ export function getIDSerializer(fields: Column[], config: PothosDrizzleSchemaCon
|
|
|
73
74
|
|
|
74
75
|
return (value: Record<string, unknown>) => {
|
|
75
76
|
if (fields.length > 1) {
|
|
77
|
+
fields.map((field) => field.keyAsName);
|
|
76
78
|
return `${JSON.stringify(fields.map((col) => value[config.columnToTsName(col)]))}`;
|
|
77
79
|
}
|
|
78
80
|
|
|
@@ -286,49 +288,58 @@ export interface DrizzleCursorConnectionQueryOptions {
|
|
|
286
288
|
ctx: {};
|
|
287
289
|
defaultSize?: number | ((args: {}, ctx: {}) => number);
|
|
288
290
|
maxSize?: number | ((args: {}, ctx: {}) => number);
|
|
289
|
-
orderBy: ConnectionOrderBy
|
|
291
|
+
orderBy: ConnectionOrderBy<TableRelationalConfig>;
|
|
290
292
|
where?: SQL;
|
|
293
|
+
config: PothosDrizzleSchemaConfig;
|
|
294
|
+
table: TableRelationalConfig | TableConfig;
|
|
291
295
|
}
|
|
292
296
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
297
|
+
function parseOrderBy(
|
|
298
|
+
config: PothosDrizzleSchemaConfig,
|
|
299
|
+
table: TableRelationalConfig | TableConfig,
|
|
300
|
+
orderBy: ConnectionOrderBy<TableRelationalConfig>,
|
|
301
|
+
invert: boolean,
|
|
302
|
+
) {
|
|
303
|
+
const entries: [name: string, direction: 'asc' | 'desc'][] = [];
|
|
304
|
+
const columns: Column[] = [];
|
|
305
|
+
const normalized: { direction: 'asc' | 'desc'; column: Column }[] = [];
|
|
299
306
|
|
|
300
307
|
const asc = invert ? 'desc' : 'asc';
|
|
301
308
|
const desc = invert ? 'asc' : 'desc';
|
|
302
309
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
if ('table' in orderBy && orderBy.table && typeof orderBy.table === 'object') {
|
|
311
|
+
entries.push([config.columnToTsName(orderBy as Column), asc]);
|
|
312
|
+
columns.push(orderBy as Column);
|
|
313
|
+
normalized.push({ direction: 'asc', column: orderBy as Column });
|
|
314
|
+
} else if (Array.isArray(orderBy)) {
|
|
315
|
+
for (const field of orderBy) {
|
|
316
|
+
entries.push([config.columnToTsName(field), asc]);
|
|
317
|
+
columns.push(field);
|
|
318
|
+
normalized.push({ direction: 'asc', column: field });
|
|
309
319
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
320
|
+
} else {
|
|
321
|
+
// biome-ignore lint/complexity/noForEach: <explanation>
|
|
322
|
+
Object.entries(
|
|
323
|
+
orderBy as {
|
|
324
|
+
[k: string]: 'asc' | 'desc' | undefined;
|
|
325
|
+
},
|
|
326
|
+
).forEach(([name, direction]) => {
|
|
327
|
+
if (direction) {
|
|
328
|
+
const column = table.columns[name] as Column;
|
|
329
|
+
columns.push(column);
|
|
330
|
+
entries.push([name, direction === 'asc' ? asc : desc]);
|
|
331
|
+
normalized.push({ direction: direction, column });
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
322
335
|
|
|
323
336
|
return {
|
|
324
337
|
normalized,
|
|
325
|
-
columns
|
|
326
|
-
|
|
338
|
+
columns,
|
|
339
|
+
orderBy: Object.fromEntries(entries),
|
|
327
340
|
};
|
|
328
341
|
}
|
|
329
342
|
|
|
330
|
-
const ops = getOperators();
|
|
331
|
-
|
|
332
343
|
export function drizzleCursorConnectionQuery({
|
|
333
344
|
args,
|
|
334
345
|
ctx,
|
|
@@ -336,6 +347,8 @@ export function drizzleCursorConnectionQuery({
|
|
|
336
347
|
defaultSize = DEFAULT_SIZE,
|
|
337
348
|
orderBy,
|
|
338
349
|
where,
|
|
350
|
+
config,
|
|
351
|
+
table,
|
|
339
352
|
}: DrizzleCursorConnectionQueryOptions) {
|
|
340
353
|
const { before, after, first, last } = args;
|
|
341
354
|
if (first != null && first < 0) {
|
|
@@ -346,79 +359,95 @@ export function drizzleCursorConnectionQuery({
|
|
|
346
359
|
throw new PothosValidationError('Argument "last" must be a non-negative integer');
|
|
347
360
|
}
|
|
348
361
|
|
|
349
|
-
if (
|
|
362
|
+
if (first != null && last != null) {
|
|
350
363
|
throw new PothosValidationError(
|
|
351
|
-
'Arguments "
|
|
364
|
+
'Arguments "first" and "last" are not supported at the same time',
|
|
352
365
|
);
|
|
353
366
|
}
|
|
354
367
|
|
|
355
|
-
if (before != null && first != null) {
|
|
356
|
-
throw new PothosValidationError(
|
|
357
|
-
'Arguments "before" and "first" are not supported at the same time',
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (after != null && last != null) {
|
|
362
|
-
throw new PothosValidationError(
|
|
363
|
-
'Arguments "after" and "last" are not supported at the same time',
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const cursor = before ?? after;
|
|
368
|
-
|
|
369
368
|
const maxSizeForConnection = typeof maxSize === 'function' ? maxSize(args, ctx) : maxSize;
|
|
370
369
|
const defaultSizeForConnection =
|
|
371
370
|
typeof defaultSize === 'function' ? defaultSize(args, ctx) : defaultSize;
|
|
372
371
|
|
|
373
|
-
|
|
372
|
+
const limit = Math.min(first ?? last ?? defaultSizeForConnection, maxSizeForConnection) + 1;
|
|
373
|
+
const inverted = !first && !!last;
|
|
374
374
|
|
|
375
|
-
|
|
376
|
-
limit = -limit;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
const parsedOrderBy = parseOrderBy(orderBy, limit < 0);
|
|
375
|
+
const parsedOrderBy = parseOrderBy(config, table, orderBy, inverted);
|
|
380
376
|
|
|
381
377
|
const columns: Record<string, boolean> = {};
|
|
382
378
|
|
|
383
379
|
for (const column of parsedOrderBy.columns) {
|
|
384
|
-
columns[column
|
|
380
|
+
columns[config.columnToTsName(column)] = true;
|
|
385
381
|
}
|
|
386
382
|
|
|
387
|
-
const whereClauses:
|
|
383
|
+
const whereClauses: {}[] = [];
|
|
384
|
+
|
|
385
|
+
if (where) {
|
|
386
|
+
whereClauses.push(where);
|
|
387
|
+
}
|
|
388
388
|
|
|
389
|
-
if (
|
|
389
|
+
if (after) {
|
|
390
390
|
const cursorParser = getCursorParser(parsedOrderBy.columns);
|
|
391
|
-
const parsedCursor = cursorParser(
|
|
392
|
-
|
|
393
|
-
whereClauses.push(
|
|
394
|
-
ops.or(
|
|
395
|
-
...parsedOrderBy.normalized.map(({ direction, column }, index) => {
|
|
396
|
-
const compare =
|
|
397
|
-
direction === 'asc'
|
|
398
|
-
? ops.gt(column, parsedCursor[column.name])
|
|
399
|
-
: ops.lt(column, parsedCursor[column.name]);
|
|
400
|
-
|
|
401
|
-
if (index === 0) {
|
|
402
|
-
return compare;
|
|
403
|
-
}
|
|
391
|
+
const parsedCursor = cursorParser(after);
|
|
404
392
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
)
|
|
413
|
-
|
|
393
|
+
const parts = parsedOrderBy.normalized.map(({ direction, column }, index) => {
|
|
394
|
+
const columnName = config.columnToTsName(column);
|
|
395
|
+
const compare =
|
|
396
|
+
direction === 'asc'
|
|
397
|
+
? { [columnName]: { gt: parsedCursor[column.name] } }
|
|
398
|
+
: { [columnName]: { lt: parsedCursor[column.name] } };
|
|
399
|
+
|
|
400
|
+
if (index === 0) {
|
|
401
|
+
return compare;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return {
|
|
405
|
+
AND: [
|
|
406
|
+
...parsedOrderBy.normalized.slice(0, index).map(({ column: c }) => {
|
|
407
|
+
return { [config.columnToTsName(c)]: parsedCursor[c.name] };
|
|
408
|
+
}),
|
|
409
|
+
compare,
|
|
410
|
+
],
|
|
411
|
+
};
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
whereClauses.push(parts.length > 1 ? { OR: parts } : parts[0]);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (before) {
|
|
418
|
+
const cursorParser = getCursorParser(parsedOrderBy.columns);
|
|
419
|
+
const parsedCursor = cursorParser(before);
|
|
420
|
+
|
|
421
|
+
const parts = parsedOrderBy.normalized.map(({ direction, column }, index) => {
|
|
422
|
+
const columnName = config.columnToTsName(column);
|
|
423
|
+
const compare =
|
|
424
|
+
direction === 'desc'
|
|
425
|
+
? { [columnName]: { gt: parsedCursor[column.name] } }
|
|
426
|
+
: { [columnName]: { lt: parsedCursor[column.name] } };
|
|
427
|
+
|
|
428
|
+
if (index === 0) {
|
|
429
|
+
return compare;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return {
|
|
433
|
+
AND: [
|
|
434
|
+
...parsedOrderBy.normalized.slice(0, index).map(({ column: c }) => {
|
|
435
|
+
return { [config.columnToTsName(c)]: parsedCursor[c.name] };
|
|
436
|
+
}),
|
|
437
|
+
compare,
|
|
438
|
+
],
|
|
439
|
+
};
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
whereClauses.push(parts.length > 1 ? { OR: parts } : parts[0]);
|
|
414
443
|
}
|
|
415
444
|
|
|
416
445
|
return {
|
|
417
446
|
cursorColumns: parsedOrderBy.columns,
|
|
418
447
|
columns,
|
|
419
|
-
orderBy: parsedOrderBy.
|
|
448
|
+
orderBy: parsedOrderBy.orderBy,
|
|
420
449
|
limit,
|
|
421
|
-
where:
|
|
450
|
+
where: whereClauses.length > 1 ? { AND: whereClauses } : whereClauses[0],
|
|
422
451
|
};
|
|
423
452
|
}
|
|
424
453
|
|
|
@@ -428,15 +457,15 @@ export function wrapConnectionResult<T extends {}>(
|
|
|
428
457
|
limit: number,
|
|
429
458
|
cursor: (node: T) => string,
|
|
430
459
|
resolveNode?: (node: Record<string, unknown>) => unknown,
|
|
460
|
+
parent?: unknown,
|
|
431
461
|
) {
|
|
432
462
|
const gotFullResults = results.length === Math.abs(limit);
|
|
433
463
|
const hasNextPage = args.before ? true : args.last ? false : gotFullResults;
|
|
434
|
-
const hasPreviousPage = args.after ? true :
|
|
435
|
-
const nodes = gotFullResults
|
|
436
|
-
? results.slice(limit < 0 ? 1 : 0, limit < 0 ? results.length : -1)
|
|
437
|
-
: results;
|
|
464
|
+
const hasPreviousPage = args.after ? true : !args.first && !!args.last ? gotFullResults : false;
|
|
465
|
+
const nodes = gotFullResults ? results.slice(0, -1) : results;
|
|
438
466
|
|
|
439
467
|
const connection = {
|
|
468
|
+
parent,
|
|
440
469
|
args,
|
|
441
470
|
edges: [] as ({ cursor: string; node: unknown } | null)[],
|
|
442
471
|
pageInfo: {
|
|
@@ -476,30 +505,29 @@ export function wrapConnectionResult<T extends {}>(
|
|
|
476
505
|
}
|
|
477
506
|
|
|
478
507
|
export async function resolveDrizzleCursorConnection<T extends {}>(
|
|
479
|
-
|
|
508
|
+
tableName: string,
|
|
480
509
|
info: GraphQLResolveInfo,
|
|
481
510
|
typeName: string,
|
|
482
511
|
config: PothosDrizzleSchemaConfig,
|
|
483
|
-
options: Omit<DrizzleCursorConnectionQueryOptions, 'orderBy'>,
|
|
512
|
+
options: Omit<DrizzleCursorConnectionQueryOptions, 'orderBy' | 'config' | 'table'>,
|
|
484
513
|
resolve: (
|
|
485
514
|
queryFn: (query: QueryForDrizzleConnection<SchemaTypes, TableRelationalConfig>) => SelectionMap,
|
|
486
515
|
) => MaybePromise<readonly T[]>,
|
|
487
516
|
) {
|
|
488
|
-
|
|
517
|
+
const table = config.relations.tablesConfig[tableName];
|
|
518
|
+
let query: DBQueryConfig<'many'>;
|
|
489
519
|
let formatter: (node: Record<string, unknown>) => string;
|
|
490
520
|
const results = await resolve((q = {}) => {
|
|
491
521
|
const { cursorColumns, ...connectionQuery } = drizzleCursorConnectionQuery({
|
|
492
522
|
...options,
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
523
|
+
config,
|
|
524
|
+
orderBy:
|
|
525
|
+
(typeof q.orderBy === 'function' ? q.orderBy(table.columns) : q.orderBy) ??
|
|
526
|
+
config.getPrimaryKey(table.tsName),
|
|
527
|
+
table,
|
|
498
528
|
});
|
|
499
529
|
formatter = getCursorFormatter(cursorColumns, config);
|
|
500
530
|
|
|
501
|
-
const where = typeof q.where === 'function' ? q.where(table.columns, getOperators()) : q.where;
|
|
502
|
-
|
|
503
531
|
query = queryFromInfo({
|
|
504
532
|
context: options.ctx,
|
|
505
533
|
info,
|
|
@@ -509,8 +537,13 @@ export async function resolveDrizzleCursorConnection<T extends {}>(
|
|
|
509
537
|
...q.columns,
|
|
510
538
|
...connectionQuery.columns,
|
|
511
539
|
},
|
|
512
|
-
where:
|
|
513
|
-
|
|
540
|
+
where:
|
|
541
|
+
connectionQuery.where && q.where
|
|
542
|
+
? {
|
|
543
|
+
AND: [q.where, connectionQuery.where],
|
|
544
|
+
}
|
|
545
|
+
: q.where || connectionQuery.where,
|
|
546
|
+
} as never,
|
|
514
547
|
paths: [['nodes'], ['edges', 'node']],
|
|
515
548
|
typeName,
|
|
516
549
|
config,
|