@pothos/plugin-drizzle 0.14.0 → 0.16.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 +17 -0
- package/README.md +417 -49
- package/dts/drizzle-field-builder.d.ts +14 -3
- package/dts/drizzle-field-builder.d.ts.map +1 -1
- package/dts/types.d.ts +6 -0
- package/dts/types.d.ts.map +1 -1
- package/dts/utils/cursors.d.ts +6 -2
- package/dts/utils/cursors.d.ts.map +1 -1
- package/dts/utils/map-query.d.ts.map +1 -1
- package/esm/drizzle-field-builder.d.ts +16 -3
- package/esm/drizzle-field-builder.d.ts.map +1 -1
- package/esm/drizzle-field-builder.js +115 -7
- package/esm/drizzle-field-builder.js.map +1 -1
- package/esm/field-builder.js +33 -2
- package/esm/field-builder.js.map +1 -1
- package/esm/types.d.ts +6 -0
- package/esm/types.d.ts.map +1 -1
- package/esm/types.js.map +1 -1
- package/esm/utils/cursors.d.ts +6 -2
- package/esm/utils/cursors.d.ts.map +1 -1
- package/esm/utils/cursors.js +18 -2
- package/esm/utils/cursors.js.map +1 -1
- package/esm/utils/map-query.d.ts.map +1 -1
- package/esm/utils/map-query.js +25 -6
- package/esm/utils/map-query.js.map +1 -1
- package/lib/drizzle-field-builder.js +113 -5
- package/lib/drizzle-field-builder.js.map +1 -1
- package/lib/field-builder.js +33 -2
- package/lib/field-builder.js.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/cursors.js +18 -2
- package/lib/utils/cursors.js.map +1 -1
- package/lib/utils/map-query.js +24 -6
- package/lib/utils/map-query.js.map +1 -1
- package/package.json +4 -4
- package/src/drizzle-field-builder.ts +207 -3
- package/src/field-builder.ts +40 -1
- package/src/types.ts +20 -1
- package/src/utils/cursors.ts +24 -3
- package/src/utils/map-query.ts +26 -6
package/src/field-builder.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { FieldRef } from '@pothos/core';
|
|
1
|
+
import type { FieldRef, MaybePromise } from '@pothos/core';
|
|
2
2
|
import { type FieldKind, ObjectRef, RootFieldBuilder, type SchemaTypes } from '@pothos/core';
|
|
3
3
|
import type { TableRelationalConfig } from 'drizzle-orm';
|
|
4
4
|
import type { GraphQLResolveInfo } from 'graphql';
|
|
5
|
+
import { isInterfaceType, isObjectType, Kind } from 'graphql';
|
|
5
6
|
import type { DrizzleRef } from './interface-ref';
|
|
6
7
|
import type { DrizzleConnectionFieldOptions } from './types';
|
|
7
8
|
import { getSchemaConfig } from './utils/config';
|
|
@@ -101,6 +102,7 @@ fieldBuilderProto.drizzleConnection = function drizzleConnection<
|
|
|
101
102
|
maxSize = this.builder.options.drizzle?.maxConnectionSize,
|
|
102
103
|
defaultSize = this.builder.options.drizzle?.defaultConnectionSize,
|
|
103
104
|
resolve,
|
|
105
|
+
totalCount,
|
|
104
106
|
...options
|
|
105
107
|
}: DrizzleConnectionFieldOptions<
|
|
106
108
|
SchemaTypes,
|
|
@@ -133,6 +135,21 @@ fieldBuilderProto.drizzleConnection = function drizzleConnection<
|
|
|
133
135
|
context: {},
|
|
134
136
|
info: GraphQLResolveInfo,
|
|
135
137
|
) => {
|
|
138
|
+
const returnType = info.returnType;
|
|
139
|
+
const fields =
|
|
140
|
+
isObjectType(returnType) || isInterfaceType(returnType) ? returnType.getFields() : {};
|
|
141
|
+
|
|
142
|
+
const selections = info.fieldNodes;
|
|
143
|
+
|
|
144
|
+
const totalCountOnly = selections.every((selection) =>
|
|
145
|
+
selection.selectionSet?.selections.every(
|
|
146
|
+
(s) =>
|
|
147
|
+
s.kind === Kind.FIELD &&
|
|
148
|
+
(fields[s.name.value]?.extensions?.pothosDrizzleTotalCount ||
|
|
149
|
+
s.name.value === '__typename'),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
|
|
136
153
|
return resolveDrizzleCursorConnection(
|
|
137
154
|
tableName,
|
|
138
155
|
info,
|
|
@@ -143,8 +160,13 @@ fieldBuilderProto.drizzleConnection = function drizzleConnection<
|
|
|
143
160
|
maxSize,
|
|
144
161
|
defaultSize,
|
|
145
162
|
args,
|
|
163
|
+
totalCount: totalCount && (() => totalCount(parent, args as never, context, info)),
|
|
146
164
|
},
|
|
147
165
|
(q) => {
|
|
166
|
+
if (totalCountOnly) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
|
|
148
170
|
// return checkIfQueryIsUsed(
|
|
149
171
|
// this.builder,
|
|
150
172
|
// query,
|
|
@@ -160,6 +182,23 @@ fieldBuilderProto.drizzleConnection = function drizzleConnection<
|
|
|
160
182
|
? connectionOptions
|
|
161
183
|
: {
|
|
162
184
|
...connectionOptions,
|
|
185
|
+
fields: totalCount
|
|
186
|
+
? (
|
|
187
|
+
t: PothosSchemaTypes.ObjectFieldBuilder<
|
|
188
|
+
SchemaTypes,
|
|
189
|
+
{ totalCount?: () => MaybePromise<number> }
|
|
190
|
+
>,
|
|
191
|
+
) => ({
|
|
192
|
+
totalCount: t.int({
|
|
193
|
+
nullable: false,
|
|
194
|
+
extensions: {
|
|
195
|
+
pothosDrizzleTotalCount: true,
|
|
196
|
+
},
|
|
197
|
+
resolve: (parent) => parent.totalCount?.(),
|
|
198
|
+
}),
|
|
199
|
+
...(connectionOptions as { fields?: (t: unknown) => {} }).fields?.(t),
|
|
200
|
+
})
|
|
201
|
+
: (connectionOptions as { fields: undefined }).fields,
|
|
163
202
|
extensions: {
|
|
164
203
|
...(connectionOptions as Record<string, object> | undefined)?.extensions,
|
|
165
204
|
},
|
package/src/types.ts
CHANGED
|
@@ -51,6 +51,7 @@ export type DrizzleClient = {
|
|
|
51
51
|
readonly relations: AnyRelations;
|
|
52
52
|
};
|
|
53
53
|
query: {};
|
|
54
|
+
$count: (table: Table, filter?: SQL) => SQL<number>;
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
export type DrizzlePluginOptions<Types extends SchemaTypes> = {
|
|
@@ -428,6 +429,18 @@ export type RefForRelation<Types extends SchemaTypes, Rel extends Relation> = Re
|
|
|
428
429
|
? ObjectRef<Types, TypesForRelation<Types, Rel>>
|
|
429
430
|
: [ObjectRef<Types, TypesForRelation<Types, Rel>>];
|
|
430
431
|
|
|
432
|
+
export type RelatedCountOptions<
|
|
433
|
+
Types extends SchemaTypes,
|
|
434
|
+
Shape,
|
|
435
|
+
Args extends InputFieldMap,
|
|
436
|
+
Where,
|
|
437
|
+
> = Omit<
|
|
438
|
+
PothosSchemaTypes.ObjectFieldOptions<Types, Shape, 'Int', false, Args, number>,
|
|
439
|
+
'type' | InferredFieldOptionKeys
|
|
440
|
+
> & {
|
|
441
|
+
where?: Where | ((args: InputShapeFromFields<Args>, context: Types['Context']) => Where);
|
|
442
|
+
};
|
|
443
|
+
|
|
431
444
|
export type TypesForRelation<Types extends SchemaTypes, Rel extends Relation> = BuildQueryResult<
|
|
432
445
|
Types['DrizzleRelations'],
|
|
433
446
|
Types['DrizzleRelations'][Rel['targetTable']['_']['name']],
|
|
@@ -543,6 +556,12 @@ export type DrizzleConnectionFieldOptions<
|
|
|
543
556
|
type: Type;
|
|
544
557
|
defaultSize?: number | ((args: ConnectionArgs, ctx: Types['Context']) => number);
|
|
545
558
|
maxSize?: number | ((args: ConnectionArgs, ctx: Types['Context']) => number);
|
|
559
|
+
totalCount?: (
|
|
560
|
+
parent: ParentShape,
|
|
561
|
+
args: ConnectionArgs,
|
|
562
|
+
context: Types['Context'],
|
|
563
|
+
info: GraphQLResolveInfo,
|
|
564
|
+
) => MaybePromise<number>;
|
|
546
565
|
|
|
547
566
|
resolve: (
|
|
548
567
|
query: <T = {}>(
|
|
@@ -626,7 +645,7 @@ export type RelatedConnectionOptions<
|
|
|
626
645
|
|
|
627
646
|
defaultSize?: number | ((args: ConnectionArgs, ctx: Types['Context']) => number);
|
|
628
647
|
maxSize?: number | ((args: ConnectionArgs, ctx: Types['Context']) => number);
|
|
629
|
-
|
|
648
|
+
totalCount?: boolean;
|
|
630
649
|
}
|
|
631
650
|
: never);
|
|
632
651
|
|
package/src/utils/cursors.ts
CHANGED
|
@@ -462,6 +462,7 @@ export function wrapConnectionResult<T extends {}>(
|
|
|
462
462
|
cursor: (node: T) => string,
|
|
463
463
|
resolveNode?: (node: Record<string, unknown>) => unknown,
|
|
464
464
|
parent?: unknown,
|
|
465
|
+
totalCount?: number | (() => MaybePromise<number>) | null,
|
|
465
466
|
) {
|
|
466
467
|
const gotFullResults = results.length === Math.abs(limit);
|
|
467
468
|
const hasNextPage = args.before ? true : args.last ? false : gotFullResults;
|
|
@@ -471,6 +472,7 @@ export function wrapConnectionResult<T extends {}>(
|
|
|
471
472
|
const connection = {
|
|
472
473
|
parent,
|
|
473
474
|
args,
|
|
475
|
+
totalCount,
|
|
474
476
|
edges: [] as ({ cursor: string; node: unknown } | null)[],
|
|
475
477
|
pageInfo: {
|
|
476
478
|
startCursor: null as string | null,
|
|
@@ -513,14 +515,16 @@ export async function resolveDrizzleCursorConnection<T extends {}>(
|
|
|
513
515
|
info: GraphQLResolveInfo,
|
|
514
516
|
typeName: string,
|
|
515
517
|
config: PothosDrizzleSchemaConfig,
|
|
516
|
-
options: Omit<DrizzleCursorConnectionQueryOptions, 'orderBy' | 'config' | 'table'
|
|
518
|
+
options: Omit<DrizzleCursorConnectionQueryOptions, 'orderBy' | 'config' | 'table'> & {
|
|
519
|
+
totalCount?: () => MaybePromise<number>;
|
|
520
|
+
},
|
|
517
521
|
resolve: (
|
|
518
522
|
queryFn: (query: QueryForDrizzleConnection<SchemaTypes, TableRelationalConfig>) => SelectionMap,
|
|
519
523
|
) => MaybePromise<readonly T[]>,
|
|
520
524
|
parent: unknown,
|
|
521
525
|
) {
|
|
522
526
|
const table = config.relations[tableName];
|
|
523
|
-
let query: DBQueryConfig<'many'
|
|
527
|
+
let query: DBQueryConfig<'many'> | undefined;
|
|
524
528
|
let formatter: (node: Record<string, unknown>) => string;
|
|
525
529
|
const results = await resolve((q = {}) => {
|
|
526
530
|
const { cursorColumns, ...connectionQuery } = drizzleCursorConnectionQuery({
|
|
@@ -562,12 +566,29 @@ export async function resolveDrizzleCursorConnection<T extends {}>(
|
|
|
562
566
|
return results;
|
|
563
567
|
}
|
|
564
568
|
|
|
569
|
+
// Handle totalCountOnly case where resolve returns [] without calling query function
|
|
570
|
+
if (!query) {
|
|
571
|
+
return {
|
|
572
|
+
parent,
|
|
573
|
+
args: options.args,
|
|
574
|
+
totalCount: options.totalCount,
|
|
575
|
+
edges: [],
|
|
576
|
+
pageInfo: {
|
|
577
|
+
startCursor: null,
|
|
578
|
+
endCursor: null,
|
|
579
|
+
hasPreviousPage: false,
|
|
580
|
+
hasNextPage: false,
|
|
581
|
+
},
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
|
|
565
585
|
return wrapConnectionResult(
|
|
566
586
|
results,
|
|
567
587
|
options.args,
|
|
568
|
-
query
|
|
588
|
+
query.limit as number,
|
|
569
589
|
formatter!,
|
|
570
590
|
undefined,
|
|
571
591
|
parent,
|
|
592
|
+
options.totalCount,
|
|
572
593
|
);
|
|
573
594
|
}
|
package/src/utils/map-query.ts
CHANGED
|
@@ -401,15 +401,35 @@ function addFieldSelection(
|
|
|
401
401
|
|
|
402
402
|
if (fieldSelect && selectionCompatible(state, fieldSelectionMap, true)) {
|
|
403
403
|
mergeSelection(config, state, fieldSelectionMap);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
404
|
+
|
|
405
|
+
state.mappings = mergeMappings(state.mappings, {
|
|
406
|
+
[selection.alias?.value ?? selection.name.value]: {
|
|
407
|
+
field: selection.name.value,
|
|
408
|
+
type: type.name,
|
|
409
|
+
mappings,
|
|
410
|
+
indirectPath,
|
|
411
|
+
},
|
|
412
|
+
});
|
|
410
413
|
}
|
|
411
414
|
}
|
|
412
415
|
|
|
416
|
+
function mergeMappings(existing: LoaderMappings, incoming: LoaderMappings): LoaderMappings {
|
|
417
|
+
const result: LoaderMappings = { ...existing };
|
|
418
|
+
|
|
419
|
+
for (const [key, value] of Object.entries(incoming)) {
|
|
420
|
+
if (result[key]) {
|
|
421
|
+
result[key] = {
|
|
422
|
+
...result[key],
|
|
423
|
+
mappings: mergeMappings(result[key].mappings, value.mappings),
|
|
424
|
+
};
|
|
425
|
+
} else {
|
|
426
|
+
result[key] = value;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return result;
|
|
431
|
+
}
|
|
432
|
+
|
|
413
433
|
export interface QueryFromInfoOptions<T extends SelectionMap> {
|
|
414
434
|
config: PothosDrizzleSchemaConfig;
|
|
415
435
|
context: object;
|