@vantreeseba/drizzle-graphql 4.1.0 → 5.0.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/README.md +130 -6
- package/dist/README.md +130 -6
- package/dist/index.cjs +909 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -5
- package/dist/index.d.ts +99 -5
- package/dist/index.js +941 -148
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
GraphQLBoolean as GraphQLBoolean2,
|
|
42
42
|
GraphQLEnumType as GraphQLEnumType2,
|
|
43
43
|
GraphQLError as GraphQLError3,
|
|
44
|
+
GraphQLFloat as GraphQLFloat2,
|
|
44
45
|
GraphQLInputObjectType as GraphQLInputObjectType2,
|
|
45
46
|
GraphQLInt as GraphQLInt2,
|
|
46
47
|
GraphQLList as GraphQLList2,
|
|
@@ -293,23 +294,6 @@ var remapFromGraphQLArrayInput = (queryInput, table) => {
|
|
|
293
294
|
return queryInput;
|
|
294
295
|
};
|
|
295
296
|
|
|
296
|
-
// src/util/type-converter/index.ts
|
|
297
|
-
import { extractExtendedColumnType, is as is2 } from "drizzle-orm";
|
|
298
|
-
import { MySqlInt, MySqlSerial } from "drizzle-orm/mysql-core";
|
|
299
|
-
import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString, PgUUID } from "drizzle-orm/pg-core";
|
|
300
|
-
import { SQLiteInteger } from "drizzle-orm/sqlite-core";
|
|
301
|
-
import {
|
|
302
|
-
GraphQLBoolean,
|
|
303
|
-
GraphQLEnumType,
|
|
304
|
-
GraphQLFloat,
|
|
305
|
-
GraphQLInputObjectType,
|
|
306
|
-
GraphQLInt,
|
|
307
|
-
GraphQLList,
|
|
308
|
-
GraphQLNonNull,
|
|
309
|
-
GraphQLObjectType,
|
|
310
|
-
GraphQLString
|
|
311
|
-
} from "graphql";
|
|
312
|
-
|
|
313
297
|
// src/util/scalars/index.ts
|
|
314
298
|
import { GraphQLError as GraphQLError2, GraphQLScalarType, Kind } from "graphql";
|
|
315
299
|
import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
|
|
@@ -348,8 +332,54 @@ var GraphQLBigIntString = new GraphQLScalarType({
|
|
|
348
332
|
return asDecimalString(ast.value);
|
|
349
333
|
}
|
|
350
334
|
});
|
|
335
|
+
var numericStringPattern = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
|
|
336
|
+
var asNumericString = (value) => {
|
|
337
|
+
if (typeof value === "bigint") {
|
|
338
|
+
return value.toString();
|
|
339
|
+
}
|
|
340
|
+
if (typeof value === "number") {
|
|
341
|
+
if (!Number.isFinite(value)) {
|
|
342
|
+
throw new GraphQLError2(`Decimal cannot represent non-finite value: ${value}`);
|
|
343
|
+
}
|
|
344
|
+
return String(value);
|
|
345
|
+
}
|
|
346
|
+
if (typeof value === "string") {
|
|
347
|
+
if (!numericStringPattern.test(value)) {
|
|
348
|
+
throw new GraphQLError2(`Decimal cannot represent non-numeric value: "${value}"`);
|
|
349
|
+
}
|
|
350
|
+
return value;
|
|
351
|
+
}
|
|
352
|
+
throw new GraphQLError2(`Decimal cannot represent value: ${JSON.stringify(value)}`);
|
|
353
|
+
};
|
|
354
|
+
var GraphQLDecimalString = new GraphQLScalarType({
|
|
355
|
+
name: "Decimal",
|
|
356
|
+
description: "An arbitrary-precision decimal, transported as a numeric string so that values beyond JavaScript's double-precision range survive the round-trip intact.",
|
|
357
|
+
serialize: asNumericString,
|
|
358
|
+
parseValue: asNumericString,
|
|
359
|
+
parseLiteral: (ast) => {
|
|
360
|
+
if (ast.kind !== Kind.STRING && ast.kind !== Kind.INT && ast.kind !== Kind.FLOAT) {
|
|
361
|
+
throw new GraphQLError2(`Decimal cannot represent a ${ast.kind}`, { nodes: ast });
|
|
362
|
+
}
|
|
363
|
+
return asNumericString(ast.value);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
351
366
|
|
|
352
367
|
// src/util/type-converter/index.ts
|
|
368
|
+
import { extractExtendedColumnType, is as is2 } from "drizzle-orm";
|
|
369
|
+
import { MySqlInt, MySqlSerial } from "drizzle-orm/mysql-core";
|
|
370
|
+
import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString, PgUUID } from "drizzle-orm/pg-core";
|
|
371
|
+
import { SQLiteInteger } from "drizzle-orm/sqlite-core";
|
|
372
|
+
import {
|
|
373
|
+
GraphQLBoolean,
|
|
374
|
+
GraphQLEnumType,
|
|
375
|
+
GraphQLFloat,
|
|
376
|
+
GraphQLInputObjectType,
|
|
377
|
+
GraphQLInt,
|
|
378
|
+
GraphQLList,
|
|
379
|
+
GraphQLNonNull,
|
|
380
|
+
GraphQLObjectType,
|
|
381
|
+
GraphQLString
|
|
382
|
+
} from "graphql";
|
|
353
383
|
var allowedNameChars = /^[a-zA-Z0-9_]+$/;
|
|
354
384
|
var enumMap = /* @__PURE__ */ new WeakMap();
|
|
355
385
|
var generateEnumCached = (column, columnName, tableName) => {
|
|
@@ -386,7 +416,7 @@ var geoXyInputType = new GraphQLInputObjectType({
|
|
|
386
416
|
}
|
|
387
417
|
});
|
|
388
418
|
var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
|
|
389
|
-
const { type: baseType } = extractExtendedColumnType(column);
|
|
419
|
+
const { type: baseType, constraint } = extractExtendedColumnType(column);
|
|
390
420
|
switch (baseType) {
|
|
391
421
|
case "boolean":
|
|
392
422
|
return { type: GraphQLBoolean, description: "Boolean" };
|
|
@@ -405,6 +435,9 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
|
|
|
405
435
|
if (column.enumValues?.length) {
|
|
406
436
|
return { type: generateEnumCached(column, columnName, tableName) };
|
|
407
437
|
}
|
|
438
|
+
if (constraint === "numeric" && !column.dimensions) {
|
|
439
|
+
return { type: GraphQLDecimalString, description: "Decimal" };
|
|
440
|
+
}
|
|
408
441
|
if (column instanceof PgTimestamp || column instanceof PgTimestampString) {
|
|
409
442
|
return { type: GraphQLDateTime, description: "DateTime" };
|
|
410
443
|
}
|
|
@@ -414,6 +447,15 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
|
|
|
414
447
|
if (column instanceof PgDateString) {
|
|
415
448
|
return isInput ? { type: GraphQLString, description: "Date" } : { type: GraphQLDate, description: "Date" };
|
|
416
449
|
}
|
|
450
|
+
{
|
|
451
|
+
const dims = column.dimensions;
|
|
452
|
+
if (dims !== void 0 && dims > 0) {
|
|
453
|
+
return {
|
|
454
|
+
type: new GraphQLList(new GraphQLNonNull(GraphQLString)),
|
|
455
|
+
description: "Array<String>"
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
}
|
|
417
459
|
return { type: GraphQLString, description: "String" };
|
|
418
460
|
case "bigint":
|
|
419
461
|
return { type: GraphQLBigIntString, description: "BigInt" };
|
|
@@ -564,10 +606,10 @@ var resolveQueryExecutor = (db, context, tableName, buildTimeQueryBase) => {
|
|
|
564
606
|
queryBase: buildTimeQueryBase ? executor?.query?.[tableName] ?? buildTimeQueryBase : buildTimeQueryBase
|
|
565
607
|
};
|
|
566
608
|
};
|
|
567
|
-
var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCondition, orderByArg, limit, offset, pkNames) => {
|
|
609
|
+
var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCondition, orderByArg, limit, offset, pkNames, orderCtx) => {
|
|
568
610
|
const cols = getColumns(targetTable);
|
|
569
611
|
const orderExprs = [
|
|
570
|
-
...orderByArg ? extractOrderBy(targetTable, orderByArg) : [],
|
|
612
|
+
...orderByArg ? extractOrderBy(targetTable, orderByArg, orderCtx) : [],
|
|
571
613
|
...primaryKeyOrderExprs(targetTable, pkNames)
|
|
572
614
|
];
|
|
573
615
|
const orderClause = orderExprs.length ? sql` order by ${sql.join(orderExprs, sql`, `)}` : sql``;
|
|
@@ -631,12 +673,13 @@ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, rel
|
|
|
631
673
|
orderByArg,
|
|
632
674
|
limit ?? null,
|
|
633
675
|
offset ?? null,
|
|
634
|
-
targetPkNames
|
|
676
|
+
targetPkNames,
|
|
677
|
+
relationFilterCtx(filterCtx, targetTableName)
|
|
635
678
|
);
|
|
636
679
|
} else {
|
|
637
680
|
let q = executor.select().from(targetTable).where(whereCondition);
|
|
638
681
|
if (orderByArg) {
|
|
639
|
-
q = q.orderBy(...extractOrderBy(targetTable, orderByArg));
|
|
682
|
+
q = q.orderBy(...extractOrderBy(targetTable, orderByArg, relationFilterCtx(filterCtx, targetTableName)));
|
|
640
683
|
}
|
|
641
684
|
rows = await q;
|
|
642
685
|
}
|
|
@@ -725,6 +768,20 @@ var extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
|
|
|
725
768
|
}
|
|
726
769
|
return Object.fromEntries(selectedColumns);
|
|
727
770
|
};
|
|
771
|
+
var orderNulls = new GraphQLEnumType2({
|
|
772
|
+
name: "OrderNulls",
|
|
773
|
+
description: "Where NULL values sort relative to non-NULL values",
|
|
774
|
+
values: {
|
|
775
|
+
first: {
|
|
776
|
+
value: "first",
|
|
777
|
+
description: "NULL values sort before all non-NULL values"
|
|
778
|
+
},
|
|
779
|
+
last: {
|
|
780
|
+
value: "last",
|
|
781
|
+
description: "NULL values sort after all non-NULL values"
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
});
|
|
728
785
|
var innerOrder = new GraphQLInputObjectType2({
|
|
729
786
|
name: "InnerOrder",
|
|
730
787
|
fields: {
|
|
@@ -749,6 +806,10 @@ var innerOrder = new GraphQLInputObjectType2({
|
|
|
749
806
|
priority: {
|
|
750
807
|
type: new GraphQLNonNull2(GraphQLInt2),
|
|
751
808
|
description: "Priority of current field"
|
|
809
|
+
},
|
|
810
|
+
nulls: {
|
|
811
|
+
type: orderNulls,
|
|
812
|
+
description: "Where NULL values sort. Defaults to the database's own rule (PostgreSQL: last on asc, first on desc; MySQL/SQLite: first on asc, last on desc)"
|
|
752
813
|
}
|
|
753
814
|
}
|
|
754
815
|
});
|
|
@@ -762,9 +823,25 @@ var resolveGenericFilterName = (column, columnName, columnGraphQLType) => {
|
|
|
762
823
|
if (columnGraphQLType.type instanceof GraphQLEnumType2) {
|
|
763
824
|
return columnGraphQLType.type.name;
|
|
764
825
|
}
|
|
826
|
+
if (columnGraphQLType.type === GraphQLBigIntString) {
|
|
827
|
+
return "BigInt";
|
|
828
|
+
}
|
|
829
|
+
if (columnGraphQLType.type === GraphQLDecimalString) {
|
|
830
|
+
return "Decimal";
|
|
831
|
+
}
|
|
765
832
|
if (columnGraphQLType.type instanceof GraphQLList2) {
|
|
766
833
|
const desc2 = columnGraphQLType.description ?? "";
|
|
767
|
-
|
|
834
|
+
let inner = columnGraphQLType.type.ofType;
|
|
835
|
+
if (inner instanceof GraphQLNonNull2) {
|
|
836
|
+
inner = inner.ofType;
|
|
837
|
+
}
|
|
838
|
+
if (desc2.includes("Integer") || inner === GraphQLInt2) {
|
|
839
|
+
return "IntArray";
|
|
840
|
+
}
|
|
841
|
+
if (desc2.includes("Float") || inner === GraphQLFloat2) {
|
|
842
|
+
return "FloatArray";
|
|
843
|
+
}
|
|
844
|
+
return "StringArray";
|
|
768
845
|
}
|
|
769
846
|
const ct = column.columnType ?? "";
|
|
770
847
|
if (ct === "PgTimestamp" || ct === "PgTimestampString" || ct === "PgDate") {
|
|
@@ -777,12 +854,12 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
|
|
|
777
854
|
const genericName = resolveGenericFilterName(column, columnName, columnGraphQLType);
|
|
778
855
|
const cached = cacheCtx.genericFilterCache.get(genericName);
|
|
779
856
|
if (cached) {
|
|
780
|
-
return cached
|
|
857
|
+
return cached;
|
|
781
858
|
}
|
|
782
859
|
const colType = columnGraphQLType.type;
|
|
783
860
|
const colDesc = columnGraphQLType.description;
|
|
784
861
|
const colArr = new GraphQLList2(new GraphQLNonNull2(colType));
|
|
785
|
-
const
|
|
862
|
+
const omitStringOps = genericName === "Id" || genericName === "BigInt" || genericName === "Decimal";
|
|
786
863
|
const baseFields = {
|
|
787
864
|
eq: { type: colType, description: colDesc },
|
|
788
865
|
ne: { type: colType, description: colDesc },
|
|
@@ -790,31 +867,60 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
|
|
|
790
867
|
lte: { type: colType, description: colDesc },
|
|
791
868
|
gt: { type: colType, description: colDesc },
|
|
792
869
|
gte: { type: colType, description: colDesc },
|
|
793
|
-
...
|
|
870
|
+
...omitStringOps ? {} : {
|
|
794
871
|
like: { type: GraphQLString2 },
|
|
795
872
|
notLike: { type: GraphQLString2 },
|
|
796
873
|
ilike: { type: GraphQLString2 },
|
|
797
|
-
notIlike: { type: GraphQLString2 }
|
|
874
|
+
notIlike: { type: GraphQLString2 },
|
|
875
|
+
startsWith: {
|
|
876
|
+
type: GraphQLString2,
|
|
877
|
+
description: "Matches values starting with the given string. `%`, `_` and `\\` are matched literally."
|
|
878
|
+
},
|
|
879
|
+
endsWith: {
|
|
880
|
+
type: GraphQLString2,
|
|
881
|
+
description: "Matches values ending with the given string. `%`, `_` and `\\` are matched literally."
|
|
882
|
+
},
|
|
883
|
+
contains: {
|
|
884
|
+
type: GraphQLString2,
|
|
885
|
+
description: "Matches values containing the given string. `%`, `_` and `\\` are matched literally."
|
|
886
|
+
},
|
|
887
|
+
iStartsWith: {
|
|
888
|
+
type: GraphQLString2,
|
|
889
|
+
description: "Case-insensitive `startsWith`."
|
|
890
|
+
},
|
|
891
|
+
iEndsWith: {
|
|
892
|
+
type: GraphQLString2,
|
|
893
|
+
description: "Case-insensitive `endsWith`."
|
|
894
|
+
},
|
|
895
|
+
iContains: {
|
|
896
|
+
type: GraphQLString2,
|
|
897
|
+
description: "Case-insensitive `contains`."
|
|
898
|
+
}
|
|
798
899
|
},
|
|
799
900
|
inArray: { type: colArr, description: `Array<${colDesc}>` },
|
|
800
901
|
notInArray: { type: colArr, description: `Array<${colDesc}>` },
|
|
801
902
|
isNull: { type: GraphQLBoolean2 },
|
|
802
903
|
isNotNull: { type: GraphQLBoolean2 }
|
|
803
904
|
};
|
|
804
|
-
const orType = new GraphQLInputObjectType2({
|
|
805
|
-
name: `${genericName}FilterOr`,
|
|
806
|
-
fields: { ...baseFields }
|
|
807
|
-
});
|
|
808
905
|
const mainType = new GraphQLInputObjectType2({
|
|
809
906
|
name: `${genericName}Filter`,
|
|
810
|
-
fields: {
|
|
907
|
+
fields: () => ({
|
|
811
908
|
...baseFields,
|
|
812
909
|
OR: {
|
|
813
|
-
type: new GraphQLList2(new GraphQLNonNull2(
|
|
910
|
+
type: new GraphQLList2(new GraphQLNonNull2(mainType)),
|
|
911
|
+
description: "At least one branch matches; ANDed with any sibling operators"
|
|
912
|
+
},
|
|
913
|
+
AND: {
|
|
914
|
+
type: new GraphQLList2(new GraphQLNonNull2(mainType)),
|
|
915
|
+
description: "Every branch matches"
|
|
916
|
+
},
|
|
917
|
+
NOT: {
|
|
918
|
+
type: mainType,
|
|
919
|
+
description: "Negates the nested operators"
|
|
814
920
|
}
|
|
815
|
-
}
|
|
921
|
+
})
|
|
816
922
|
});
|
|
817
|
-
cacheCtx.genericFilterCache.set(genericName,
|
|
923
|
+
cacheCtx.genericFilterCache.set(genericName, mainType);
|
|
818
924
|
return mainType;
|
|
819
925
|
};
|
|
820
926
|
var orderMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -868,19 +974,53 @@ var generateTableSelectTypeFieldsCached = (table, tableName) => {
|
|
|
868
974
|
fieldMap.set(table, remapped);
|
|
869
975
|
return remapped;
|
|
870
976
|
};
|
|
871
|
-
var
|
|
977
|
+
var isFilterableRelation = (relation) => !relation.through;
|
|
978
|
+
var generateRelationOrderFields = (tableName, cacheCtx, typeNameMapper, columnFields, relationMap, tables) => {
|
|
979
|
+
const relations = relationMap?.[tableName];
|
|
980
|
+
if (!relations || !tables) {
|
|
981
|
+
return {};
|
|
982
|
+
}
|
|
983
|
+
const fields = {};
|
|
984
|
+
for (const [relationName, relEntry] of Object.entries(relations)) {
|
|
985
|
+
if (relationName in columnFields) {
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
const targetTable = tables[relEntry.targetTableName];
|
|
989
|
+
const relation = relEntry.relation ?? relEntry;
|
|
990
|
+
if (!targetTable || !is3(relation, One2) || !isFilterableRelation(relation)) {
|
|
991
|
+
continue;
|
|
992
|
+
}
|
|
993
|
+
fields[relationName] = {
|
|
994
|
+
type: generateTableOrderTypeCached(
|
|
995
|
+
targetTable,
|
|
996
|
+
relEntry.targetTableName,
|
|
997
|
+
typeNameMapper,
|
|
998
|
+
cacheCtx,
|
|
999
|
+
relationMap,
|
|
1000
|
+
tables
|
|
1001
|
+
),
|
|
1002
|
+
description: `Order by columns of the related ${relationName} row`
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
return fields;
|
|
1006
|
+
};
|
|
1007
|
+
var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx, relationMap, tables) => {
|
|
872
1008
|
if (cacheCtx.orderTypeCache.has(table)) {
|
|
873
1009
|
return cacheCtx.orderTypeCache.get(table);
|
|
874
1010
|
}
|
|
875
|
-
const orderColumns = generateTableOrderCached(table);
|
|
876
1011
|
const order = new GraphQLInputObjectType2({
|
|
877
1012
|
name: `${resolveTypeName(tableName, typeNameMapper)}OrderBy`,
|
|
878
|
-
fields:
|
|
1013
|
+
fields: () => {
|
|
1014
|
+
const orderColumns = generateTableOrderCached(table);
|
|
1015
|
+
return {
|
|
1016
|
+
...orderColumns,
|
|
1017
|
+
...generateRelationOrderFields(tableName, cacheCtx, typeNameMapper, orderColumns, relationMap, tables)
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
879
1020
|
});
|
|
880
1021
|
cacheCtx.orderTypeCache.set(table, order);
|
|
881
1022
|
return order;
|
|
882
1023
|
};
|
|
883
|
-
var isFilterableRelation = (relation) => !relation.through;
|
|
884
1024
|
var generateListRelationFilterCached = (targetTable, targetTableName, cacheCtx, typeNameMapper, relationMap, tables) => {
|
|
885
1025
|
const cached = cacheCtx.listRelationFilterCache.get(targetTableName);
|
|
886
1026
|
if (cached) {
|
|
@@ -919,7 +1059,7 @@ var generateRelationFilterFields = (tableName, cacheCtx, typeNameMapper, columnF
|
|
|
919
1059
|
}
|
|
920
1060
|
const targetTable = tables[relEntry.targetTableName];
|
|
921
1061
|
const relation = relEntry.relation ?? relEntry;
|
|
922
|
-
if (!targetTable
|
|
1062
|
+
if (!targetTable) {
|
|
923
1063
|
continue;
|
|
924
1064
|
}
|
|
925
1065
|
fields[relationName] = is3(relation, One2) ? {
|
|
@@ -956,16 +1096,21 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
|
|
|
956
1096
|
...generateRelationFilterFields(tableName, cacheCtx, typeNameMapper, filterColumns, relationMap, tables)
|
|
957
1097
|
};
|
|
958
1098
|
};
|
|
959
|
-
const orFilters = new GraphQLInputObjectType2({
|
|
960
|
-
name: `${resolveTypeName(tableName, typeNameMapper)}FiltersOr`,
|
|
961
|
-
fields: buildFields
|
|
962
|
-
});
|
|
963
1099
|
const filters = new GraphQLInputObjectType2({
|
|
964
1100
|
name: `${resolveTypeName(tableName, typeNameMapper)}Filters`,
|
|
965
1101
|
fields: () => ({
|
|
966
1102
|
...buildFields(),
|
|
967
1103
|
OR: {
|
|
968
|
-
type: new GraphQLList2(new GraphQLNonNull2(
|
|
1104
|
+
type: new GraphQLList2(new GraphQLNonNull2(filters)),
|
|
1105
|
+
description: "At least one branch matches; ANDed with any sibling fields"
|
|
1106
|
+
},
|
|
1107
|
+
AND: {
|
|
1108
|
+
type: new GraphQLList2(new GraphQLNonNull2(filters)),
|
|
1109
|
+
description: "Every branch matches"
|
|
1110
|
+
},
|
|
1111
|
+
NOT: {
|
|
1112
|
+
type: filters,
|
|
1113
|
+
description: "Negates the nested filters"
|
|
969
1114
|
}
|
|
970
1115
|
})
|
|
971
1116
|
});
|
|
@@ -974,7 +1119,7 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
|
|
|
974
1119
|
};
|
|
975
1120
|
var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromRelationName, withOrder, relationsDepthLimit, cacheCtx, typeNameMapper, usedTables = /* @__PURE__ */ new Set(), resolverFactory, currentDepth = 0, relationAggregateFactory) => {
|
|
976
1121
|
const table = tables[tableName];
|
|
977
|
-
const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx) : void 0;
|
|
1122
|
+
const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx, relationMap, tables) : void 0;
|
|
978
1123
|
const filters = generateTableFilterTypeCached(table, tableName, cacheCtx, typeNameMapper, relationMap, tables);
|
|
979
1124
|
const tableFields = generateTableSelectTypeFieldsCached(table, tableName);
|
|
980
1125
|
const relationsForTable = relationMap[tableName];
|
|
@@ -1060,10 +1205,11 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
|
|
|
1060
1205
|
}
|
|
1061
1206
|
const resolve = resolverFactory?.({ tableName, relationName, relEntry, isOne });
|
|
1062
1207
|
if (isOne) {
|
|
1208
|
+
const isRequired = relation.optional === false;
|
|
1063
1209
|
rawRelationFields.push([
|
|
1064
1210
|
relationName,
|
|
1065
1211
|
{
|
|
1066
|
-
type: relType,
|
|
1212
|
+
type: isRequired ? new GraphQLNonNull2(relType) : relType,
|
|
1067
1213
|
args: {
|
|
1068
1214
|
where: { type: relSelectData.filters }
|
|
1069
1215
|
},
|
|
@@ -1201,28 +1347,95 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
|
|
|
1201
1347
|
outputs
|
|
1202
1348
|
};
|
|
1203
1349
|
};
|
|
1204
|
-
var orderByEntries = (orderArgs) => Object.entries(orderArgs).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).filter(([, config]) => config).map(([column, config]) =>
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1350
|
+
var orderByEntries = (orderArgs) => Object.entries(orderArgs).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).filter(([, config]) => config).map(([column, config]) => {
|
|
1351
|
+
if (typeof config === "object" && config.direction === void 0) {
|
|
1352
|
+
throw new GraphQLError3(`ORDER BY ${column}: ordering through a relation is not supported in this query`);
|
|
1353
|
+
}
|
|
1354
|
+
return [column, config.direction, config.nulls ?? void 0];
|
|
1355
|
+
});
|
|
1356
|
+
var orderExpressions = (expr, direction, nulls, dialectColumn) => {
|
|
1357
|
+
const directed = direction === "asc" ? asc(expr) : desc(expr);
|
|
1358
|
+
if (!nulls) {
|
|
1359
|
+
return [directed];
|
|
1360
|
+
}
|
|
1361
|
+
const isMySql = (dialectColumn.columnType ?? "").startsWith("MySql");
|
|
1362
|
+
if (isMySql) {
|
|
1363
|
+
const nullsKey = nulls === "first" ? desc(sql`(${expr} is null)`) : asc(sql`(${expr} is null)`);
|
|
1364
|
+
return [nullsKey, directed];
|
|
1365
|
+
}
|
|
1366
|
+
return [nulls === "first" ? sql`${directed} nulls first` : sql`${directed} nulls last`];
|
|
1367
|
+
};
|
|
1368
|
+
var extendRelationOrderChain = (parentTable, relationName, relEntry, ctx, chain) => {
|
|
1369
|
+
const targetTable = ctx.tables[relEntry.targetTableName];
|
|
1370
|
+
const relation = relEntry.relation ?? relEntry;
|
|
1371
|
+
if (!targetTable || !is3(relation, One2) || !isFilterableRelation(relation)) {
|
|
1372
|
+
throw new GraphQLError3(`ORDER BY ${relationName}: Relation cannot be used for ordering`);
|
|
1211
1373
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1374
|
+
ctx.aliases ??= { n: 0 };
|
|
1375
|
+
const aliasedTarget = aliasedTable(targetTable, `dgql_ord_${ctx.aliases.n++}`);
|
|
1376
|
+
const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
|
|
1377
|
+
const relationWhere = relation.where ? relationsFilterToSQL(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
|
|
1378
|
+
return {
|
|
1379
|
+
fromParts: [...chain?.fromParts ?? [], getTableAsAliasSQL(aliasedTarget)],
|
|
1380
|
+
conditions: [
|
|
1381
|
+
...chain?.conditions ?? [],
|
|
1382
|
+
...joinCondition ? [joinCondition] : [],
|
|
1383
|
+
...relationWhere ? [relationWhere] : []
|
|
1384
|
+
],
|
|
1385
|
+
table: aliasedTarget
|
|
1386
|
+
};
|
|
1387
|
+
};
|
|
1388
|
+
var collectOrderEntries = (table, tableKey, orderArgs, ctx, chain, out) => {
|
|
1389
|
+
const columns = getColumns(table);
|
|
1390
|
+
const relations = ctx?.relationMap[tableKey];
|
|
1391
|
+
for (const [key, config] of Object.entries(orderArgs)) {
|
|
1392
|
+
if (config === null || config === void 0) {
|
|
1393
|
+
continue;
|
|
1216
1394
|
}
|
|
1217
|
-
const
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1395
|
+
const column = columns[key];
|
|
1396
|
+
if (column) {
|
|
1397
|
+
out.push({
|
|
1398
|
+
expression: chain ? sql`(select ${column} from ${sql.join(chain.fromParts, sql`, `)} where ${and(...chain.conditions)})` : column,
|
|
1399
|
+
column,
|
|
1400
|
+
direction: config.direction,
|
|
1401
|
+
nulls: config.nulls ?? void 0,
|
|
1402
|
+
priority: config.priority ?? 0
|
|
1403
|
+
});
|
|
1404
|
+
continue;
|
|
1405
|
+
}
|
|
1406
|
+
const relEntry = relations?.[key];
|
|
1407
|
+
if (!relEntry || !ctx) {
|
|
1408
|
+
throw new GraphQLError3(`ORDER BY ${key}: Unknown column or relation`);
|
|
1223
1409
|
}
|
|
1224
|
-
|
|
1410
|
+
const nextChain = extendRelationOrderChain(chain?.table ?? table, key, relEntry, ctx, chain);
|
|
1411
|
+
collectOrderEntries(nextChain.table, relEntry.targetTableName, config, ctx, nextChain, out);
|
|
1412
|
+
}
|
|
1413
|
+
};
|
|
1414
|
+
var extractOrderBy = (table, orderArgs, ctx) => {
|
|
1415
|
+
const entries = [];
|
|
1416
|
+
collectOrderEntries(table, ctx?.tableKey ?? "", orderArgs, ctx, void 0, entries);
|
|
1417
|
+
return entries.sort((a, b) => b.priority - a.priority).flatMap((entry) => orderExpressions(entry.expression, entry.direction, entry.nulls, entry.column));
|
|
1418
|
+
};
|
|
1419
|
+
var LIKE_ESCAPE_CHAR = "\\";
|
|
1420
|
+
var escapeLikeValue = (value) => value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
1421
|
+
var safeLikeOps = {
|
|
1422
|
+
startsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: false },
|
|
1423
|
+
endsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: false },
|
|
1424
|
+
contains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: false },
|
|
1425
|
+
iStartsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: true },
|
|
1426
|
+
iEndsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: true },
|
|
1427
|
+
iContains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: true }
|
|
1428
|
+
};
|
|
1429
|
+
var safeLikeCondition = (column, pattern, insensitive) => {
|
|
1430
|
+
if (!insensitive) {
|
|
1431
|
+
return sql`${column} like ${pattern} escape ${LIKE_ESCAPE_CHAR}`;
|
|
1225
1432
|
}
|
|
1433
|
+
const isPg = (column.columnType ?? "").startsWith("Pg");
|
|
1434
|
+
return isPg ? sql`${column} ilike ${pattern} escape ${LIKE_ESCAPE_CHAR}` : sql`lower(${column}) like ${pattern.toLowerCase()} escape ${LIKE_ESCAPE_CHAR}`;
|
|
1435
|
+
};
|
|
1436
|
+
var extractFiltersColumn = (column, columnName, operators) => {
|
|
1437
|
+
const { OR, AND, NOT, ...restOperators } = operators;
|
|
1438
|
+
const entries = Object.entries(restOperators);
|
|
1226
1439
|
const singleValueOps = { eq, ne, gt, gte, lt, lte };
|
|
1227
1440
|
const stringValueOps = { like, notLike, ilike, notIlike };
|
|
1228
1441
|
const arrayValueOps = { inArray, notInArray };
|
|
@@ -1237,6 +1450,9 @@ var extractFiltersColumn = (column, columnName, operators) => {
|
|
|
1237
1450
|
variants.push(singleValueOps[operatorName](column, singleValue));
|
|
1238
1451
|
} else if (operatorName in stringValueOps) {
|
|
1239
1452
|
variants.push(stringValueOps[operatorName](column, operatorValue));
|
|
1453
|
+
} else if (operatorName in safeLikeOps) {
|
|
1454
|
+
const { buildPattern, insensitive } = safeLikeOps[operatorName];
|
|
1455
|
+
variants.push(safeLikeCondition(column, buildPattern(operatorValue), insensitive));
|
|
1240
1456
|
} else if (operatorName in arrayValueOps) {
|
|
1241
1457
|
if (!operatorValue.length) {
|
|
1242
1458
|
throw new GraphQLError3(`WHERE ${columnName}: Unable to use operator ${operatorName} with an empty array!`);
|
|
@@ -1245,6 +1461,34 @@ var extractFiltersColumn = (column, columnName, operators) => {
|
|
|
1245
1461
|
variants.push(arrayValueOps[operatorName](column, arrayValue));
|
|
1246
1462
|
} else if (operatorName in nullableOps) {
|
|
1247
1463
|
variants.push(nullableOps[operatorName](column));
|
|
1464
|
+
} else {
|
|
1465
|
+
throw new GraphQLError3(`WHERE ${columnName}: Unknown operator: ${operatorName}`);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
if (AND?.length) {
|
|
1469
|
+
for (const variant of AND) {
|
|
1470
|
+
const extracted = extractFiltersColumn(column, columnName, variant);
|
|
1471
|
+
if (extracted) {
|
|
1472
|
+
variants.push(extracted);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
if (NOT) {
|
|
1477
|
+
const extracted = extractFiltersColumn(column, columnName, NOT);
|
|
1478
|
+
if (extracted) {
|
|
1479
|
+
variants.push(not(extracted));
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
if (OR?.length) {
|
|
1483
|
+
const orVariants = [];
|
|
1484
|
+
for (const variant of OR) {
|
|
1485
|
+
const extracted = extractFiltersColumn(column, columnName, variant);
|
|
1486
|
+
if (extracted) {
|
|
1487
|
+
orVariants.push(extracted);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
if (orVariants.length) {
|
|
1491
|
+
variants.push(orVariants.length > 1 ? or(...orVariants) : orVariants[0]);
|
|
1248
1492
|
}
|
|
1249
1493
|
}
|
|
1250
1494
|
return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
|
|
@@ -1269,39 +1513,105 @@ var buildRelationJoinCondition = (parentTable, relation, aliasedTarget, relation
|
|
|
1269
1513
|
}
|
|
1270
1514
|
return conditions.length > 1 ? and(...conditions) : conditions[0];
|
|
1271
1515
|
};
|
|
1516
|
+
var resolveJunctionColumn = (aliasedThrough, junctionRef, relationName) => {
|
|
1517
|
+
const throughColumns = getColumns(aliasedThrough);
|
|
1518
|
+
const key = junctionRef?._?.key;
|
|
1519
|
+
const byKey = key ? throughColumns[key] : void 0;
|
|
1520
|
+
if (byKey) {
|
|
1521
|
+
return byKey;
|
|
1522
|
+
}
|
|
1523
|
+
const columnName = junctionRef?._?.column?.name;
|
|
1524
|
+
const byName = columnName ? Object.values(throughColumns).find((c) => c.name === columnName) : void 0;
|
|
1525
|
+
if (!byName) {
|
|
1526
|
+
throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
|
|
1527
|
+
}
|
|
1528
|
+
return byName;
|
|
1529
|
+
};
|
|
1530
|
+
var buildThroughJoinConditions = (parentTable, relation, aliasedThrough, aliasedTarget, relationName) => {
|
|
1531
|
+
const sourceColumns = relation.sourceColumns;
|
|
1532
|
+
const targetColumns = relation.targetColumns;
|
|
1533
|
+
const through = relation.through;
|
|
1534
|
+
if (!sourceColumns?.length || !targetColumns?.length || through?.source.length !== sourceColumns.length || through.target.length !== targetColumns.length) {
|
|
1535
|
+
throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
|
|
1536
|
+
}
|
|
1537
|
+
const parentColumns = Object.values(getColumns(parentTable));
|
|
1538
|
+
const targetTableColumns = Object.values(getColumns(aliasedTarget));
|
|
1539
|
+
const correlationConditions = [];
|
|
1540
|
+
for (let i = 0; i < sourceColumns.length; i++) {
|
|
1541
|
+
const localColumn = parentColumns.find((c) => c.name === sourceColumns[i].name);
|
|
1542
|
+
if (!localColumn) {
|
|
1543
|
+
throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
|
|
1544
|
+
}
|
|
1545
|
+
correlationConditions.push(eq(localColumn, resolveJunctionColumn(aliasedThrough, through.source[i], relationName)));
|
|
1546
|
+
}
|
|
1547
|
+
const junctionJoinConditions = [];
|
|
1548
|
+
for (let i = 0; i < targetColumns.length; i++) {
|
|
1549
|
+
const foreignColumn = targetTableColumns.find((c) => c.name === targetColumns[i].name);
|
|
1550
|
+
if (!foreignColumn) {
|
|
1551
|
+
throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
|
|
1552
|
+
}
|
|
1553
|
+
junctionJoinConditions.push(
|
|
1554
|
+
eq(resolveJunctionColumn(aliasedThrough, through.target[i], relationName), foreignColumn)
|
|
1555
|
+
);
|
|
1556
|
+
}
|
|
1557
|
+
return {
|
|
1558
|
+
correlation: correlationConditions.length > 1 ? and(...correlationConditions) : correlationConditions[0],
|
|
1559
|
+
junctionJoin: junctionJoinConditions.length > 1 ? and(...junctionJoinConditions) : junctionJoinConditions[0]
|
|
1560
|
+
};
|
|
1561
|
+
};
|
|
1272
1562
|
var buildRelationExists = (parentTable, relationName, relEntry, innerFilters, mode, ctx) => {
|
|
1273
1563
|
const { targetTableName } = relEntry;
|
|
1274
1564
|
const targetTable = ctx.tables[targetTableName];
|
|
1275
1565
|
const relation = relEntry.relation ?? relEntry;
|
|
1276
|
-
if (!targetTable
|
|
1566
|
+
if (!targetTable) {
|
|
1277
1567
|
throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
|
|
1278
1568
|
}
|
|
1279
1569
|
ctx.aliases ??= { n: 0 };
|
|
1280
1570
|
const aliases = ctx.aliases;
|
|
1281
1571
|
const aliasedTarget = aliasedTable(targetTable, `dgql_rel_${aliases.n++}`);
|
|
1282
|
-
const
|
|
1572
|
+
const throughTable = relation.throughTable;
|
|
1573
|
+
let fromClause;
|
|
1574
|
+
let joinCondition;
|
|
1575
|
+
if (throughTable) {
|
|
1576
|
+
const aliasedThrough = aliasedTable(throughTable, `dgql_rel_${aliases.n++}`);
|
|
1577
|
+
const { correlation, junctionJoin } = buildThroughJoinConditions(
|
|
1578
|
+
parentTable,
|
|
1579
|
+
relation,
|
|
1580
|
+
aliasedThrough,
|
|
1581
|
+
aliasedTarget,
|
|
1582
|
+
relationName
|
|
1583
|
+
);
|
|
1584
|
+
fromClause = sql`${getTableAsAliasSQL(aliasedTarget)} inner join ${getTableAsAliasSQL(aliasedThrough)} on ${junctionJoin}`;
|
|
1585
|
+
joinCondition = correlation;
|
|
1586
|
+
} else {
|
|
1587
|
+
fromClause = getTableAsAliasSQL(aliasedTarget);
|
|
1588
|
+
joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
|
|
1589
|
+
}
|
|
1283
1590
|
const relationWhere = relation.where ? relationsFilterToSQL(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
|
|
1284
1591
|
const inner = innerFilters ? extractFilters(aliasedTarget, targetTableName, innerFilters, { ...ctx, tableKey: targetTableName, aliases }) : void 0;
|
|
1285
1592
|
if (mode === "every") {
|
|
1286
1593
|
if (!inner) {
|
|
1287
1594
|
return void 0;
|
|
1288
1595
|
}
|
|
1289
|
-
return sql`not exists (select 1 from ${
|
|
1596
|
+
return sql`not exists (select 1 from ${fromClause} where ${and(joinCondition, relationWhere, not(inner))})`;
|
|
1290
1597
|
}
|
|
1291
1598
|
const condition = and(joinCondition, relationWhere, inner);
|
|
1292
|
-
return mode === "none" ? sql`not exists (select 1 from ${
|
|
1599
|
+
return mode === "none" ? sql`not exists (select 1 from ${fromClause} where ${condition})` : sql`exists (select 1 from ${fromClause} where ${condition})`;
|
|
1293
1600
|
};
|
|
1294
1601
|
var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) => {
|
|
1295
1602
|
const relation = relEntry.relation ?? relEntry;
|
|
1296
1603
|
if (is3(relation, One2)) {
|
|
1297
1604
|
return buildRelationExists(parentTable, relationName, relEntry, value, "some", ctx);
|
|
1298
1605
|
}
|
|
1606
|
+
const relationMatchModes = ["some", "none", "every"];
|
|
1299
1607
|
const variants = [];
|
|
1300
|
-
for (const mode of
|
|
1301
|
-
const inner = value[mode];
|
|
1608
|
+
for (const [mode, inner] of Object.entries(value)) {
|
|
1302
1609
|
if (inner === void 0 || inner === null) {
|
|
1303
1610
|
continue;
|
|
1304
1611
|
}
|
|
1612
|
+
if (!relationMatchModes.includes(mode)) {
|
|
1613
|
+
throw new GraphQLError3(`WHERE ${relationName}: Unknown relation filter key: ${mode}`);
|
|
1614
|
+
}
|
|
1305
1615
|
const extracted = buildRelationExists(parentTable, relationName, relEntry, inner, mode, ctx);
|
|
1306
1616
|
if (extracted) {
|
|
1307
1617
|
variants.push(extracted);
|
|
@@ -1310,26 +1620,8 @@ var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) =>
|
|
|
1310
1620
|
return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
|
|
1311
1621
|
};
|
|
1312
1622
|
var extractFilters = (table, tableName, filters, relationCtx) => {
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
}
|
|
1316
|
-
const entries = Object.entries(filters);
|
|
1317
|
-
if (!entries.length) {
|
|
1318
|
-
return;
|
|
1319
|
-
}
|
|
1320
|
-
if (filters.OR) {
|
|
1321
|
-
if (entries.length > 1) {
|
|
1322
|
-
throw new GraphQLError3(`WHERE ${tableName}: Cannot specify both fields and 'OR' in table filters!`);
|
|
1323
|
-
}
|
|
1324
|
-
const variants2 = [];
|
|
1325
|
-
for (const variant of filters.OR) {
|
|
1326
|
-
const extracted = extractFilters(table, tableName, variant, relationCtx);
|
|
1327
|
-
if (extracted) {
|
|
1328
|
-
variants2.push(extracted);
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
return variants2.length ? variants2.length > 1 ? or(...variants2) : variants2[0] : void 0;
|
|
1332
|
-
}
|
|
1623
|
+
const { OR, AND, NOT, ...fieldFilters } = filters;
|
|
1624
|
+
const entries = Object.entries(fieldFilters);
|
|
1333
1625
|
const columns = getColumns(table);
|
|
1334
1626
|
const relations = relationCtx?.relationMap[relationCtx.tableKey];
|
|
1335
1627
|
const variants = [];
|
|
@@ -1338,11 +1630,40 @@ var extractFilters = (table, tableName, filters, relationCtx) => {
|
|
|
1338
1630
|
continue;
|
|
1339
1631
|
}
|
|
1340
1632
|
const column = columns[fieldName];
|
|
1341
|
-
|
|
1633
|
+
if (!column && !(relations?.[fieldName] && relationCtx)) {
|
|
1634
|
+
throw new GraphQLError3(`WHERE ${tableName}: Unknown filter key: ${fieldName}`);
|
|
1635
|
+
}
|
|
1636
|
+
const extracted = column ? extractFiltersColumn(column, fieldName, operators) : extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx);
|
|
1342
1637
|
if (extracted) {
|
|
1343
1638
|
variants.push(extracted);
|
|
1344
1639
|
}
|
|
1345
1640
|
}
|
|
1641
|
+
if (AND?.length) {
|
|
1642
|
+
for (const variant of AND) {
|
|
1643
|
+
const extracted = extractFilters(table, tableName, variant, relationCtx);
|
|
1644
|
+
if (extracted) {
|
|
1645
|
+
variants.push(extracted);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
if (NOT) {
|
|
1650
|
+
const extracted = extractFilters(table, tableName, NOT, relationCtx);
|
|
1651
|
+
if (extracted) {
|
|
1652
|
+
variants.push(not(extracted));
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
if (OR?.length) {
|
|
1656
|
+
const orVariants = [];
|
|
1657
|
+
for (const variant of OR) {
|
|
1658
|
+
const extracted = extractFilters(table, tableName, variant, relationCtx);
|
|
1659
|
+
if (extracted) {
|
|
1660
|
+
orVariants.push(extracted);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
if (orVariants.length) {
|
|
1664
|
+
variants.push(orVariants.length > 1 ? or(...orVariants) : orVariants[0]);
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1346
1667
|
return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
|
|
1347
1668
|
};
|
|
1348
1669
|
var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, originField, typeNameMapper, _isInitial = false, filterCtx) => {
|
|
@@ -1384,7 +1705,7 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
|
|
|
1384
1705
|
} : void 0;
|
|
1385
1706
|
const hasPagination = offset != null || limit != null;
|
|
1386
1707
|
const pkNames = targetPkNames ?? [];
|
|
1387
|
-
thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
|
|
1708
|
+
thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy, relationFilterCtx(filterCtx, targetTableName)) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
|
|
1388
1709
|
thisRecord.offset = offset;
|
|
1389
1710
|
thisRecord.limit = limit;
|
|
1390
1711
|
const relWith = relationField ? extractRelationsParamsInner(
|
|
@@ -1625,7 +1946,9 @@ var selectDistinctKeys = async (params) => {
|
|
|
1625
1946
|
}
|
|
1626
1947
|
const orderEntries = orderBy ? orderByEntries(orderBy) : [];
|
|
1627
1948
|
const windowOrder = [
|
|
1628
|
-
...orderEntries.
|
|
1949
|
+
...orderEntries.flatMap(
|
|
1950
|
+
([column, direction, nulls]) => orderExpressions(cols[column], direction, nulls, cols[column])
|
|
1951
|
+
),
|
|
1629
1952
|
...primaryKeyOrderExprs(table, pkNames)
|
|
1630
1953
|
];
|
|
1631
1954
|
const rowNumber = sql`row_number() over (partition by ${sql.join(partitionCols, sql`, `)} order by ${sql.join(
|
|
@@ -1634,7 +1957,9 @@ var selectDistinctKeys = async (params) => {
|
|
|
1634
1957
|
)})`.as(DISTINCT_RN);
|
|
1635
1958
|
const sub = db.select({ ...cols, [DISTINCT_RN]: rowNumber }).from(table).where(where).as("__dgql_distinct");
|
|
1636
1959
|
const outerOrder = [
|
|
1637
|
-
...orderEntries.
|
|
1960
|
+
...orderEntries.flatMap(
|
|
1961
|
+
([column, direction, nulls]) => orderExpressions(sub[column], direction, nulls, cols[column])
|
|
1962
|
+
),
|
|
1638
1963
|
...pkNames.filter((name) => sub[name]).map((name) => asc(sub[name]))
|
|
1639
1964
|
];
|
|
1640
1965
|
let query = db.select(Object.fromEntries(pkNames.map((name) => [name, sub[name]]))).from(sub).where(eq(sub[DISTINCT_RN], 1)).orderBy(...outerOrder);
|
|
@@ -1725,6 +2050,7 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
|
|
|
1725
2050
|
const listFieldName = (mapped?.plural ?? uncapitalize(tableName)) + suffixes.list;
|
|
1726
2051
|
const singleFieldName = mapped?.singular ?? uncapitalize(tableName) + suffixes.single;
|
|
1727
2052
|
const aggregateFieldName = `${mapped?.plural ?? uncapitalize(tableName)}Aggregate`;
|
|
2053
|
+
const groupByFieldName = `${mapped?.plural ?? uncapitalize(tableName)}GroupBy`;
|
|
1728
2054
|
const createArrayFieldName = `${prefixes.insert}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}`;
|
|
1729
2055
|
const createSingleFieldName = mapped ? `${prefixes.insert}${capitalize(mapped.singular)}` : `${prefixes.insert}${capitalize(tableName)}${suffixes.single}`;
|
|
1730
2056
|
const upsertPrefix = prefixes.upsert ?? "upsert";
|
|
@@ -1732,19 +2058,38 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
|
|
|
1732
2058
|
const upsertSingleFieldName = mapped ? `${upsertPrefix}${capitalize(mapped.singular)}` : `${upsertPrefix}${capitalize(tableName)}${suffixes.single}`;
|
|
1733
2059
|
const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
|
|
1734
2060
|
const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
|
|
2061
|
+
const writeSingleSuffix = suffixes.single === "" ? "Single" : suffixes.single;
|
|
2062
|
+
const updateSingleFieldName = `${updateFieldName}${writeSingleSuffix}`;
|
|
2063
|
+
const deleteSingleFieldName = `${deleteFieldName}${writeSingleSuffix}`;
|
|
1735
2064
|
return {
|
|
1736
2065
|
typeName,
|
|
1737
2066
|
listFieldName,
|
|
1738
2067
|
singleFieldName,
|
|
1739
2068
|
aggregateFieldName,
|
|
2069
|
+
groupByFieldName,
|
|
1740
2070
|
createArrayFieldName,
|
|
1741
2071
|
createSingleFieldName,
|
|
1742
2072
|
upsertArrayFieldName,
|
|
1743
2073
|
upsertSingleFieldName,
|
|
1744
2074
|
updateFieldName,
|
|
1745
|
-
|
|
2075
|
+
updateSingleFieldName,
|
|
2076
|
+
deleteFieldName,
|
|
2077
|
+
deleteSingleFieldName
|
|
1746
2078
|
};
|
|
1747
2079
|
};
|
|
2080
|
+
var extractRequiredFilters = (table, tableName, where, fieldName, relationCtx) => {
|
|
2081
|
+
const filters = where ? extractFilters(table, tableName, where, relationCtx) : void 0;
|
|
2082
|
+
if (!filters) {
|
|
2083
|
+
throw new GraphQLError3(`${fieldName} requires a 'where' argument with at least one filter!`);
|
|
2084
|
+
}
|
|
2085
|
+
return filters;
|
|
2086
|
+
};
|
|
2087
|
+
var assertSingleMatch = async (executor, table, filters, fieldName) => {
|
|
2088
|
+
const matched = await executor.select({ found: sql`1` }).from(table).where(filters).limit(2);
|
|
2089
|
+
if (matched.length > 1) {
|
|
2090
|
+
throw new GraphQLError3(`${fieldName}: 'where' matched more than one row \u2014 nothing was written!`);
|
|
2091
|
+
}
|
|
2092
|
+
};
|
|
1748
2093
|
var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
|
|
1749
2094
|
offset: { type: GraphQLInt2 },
|
|
1750
2095
|
limit: { type: GraphQLInt2 },
|
|
@@ -1803,9 +2148,9 @@ var runRelationalSelect = async (opts) => {
|
|
|
1803
2148
|
// drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
|
|
1804
2149
|
// directly so column refs match the CTE alias.
|
|
1805
2150
|
orderBy: distinctKeys ? (aliasedTable2) => [
|
|
1806
|
-
...orderBy ? extractOrderBy(aliasedTable2, orderBy) : [],
|
|
2151
|
+
...orderBy ? extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : [],
|
|
1807
2152
|
...primaryKeyOrderExprs(aliasedTable2, pkNames)
|
|
1808
|
-
] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
|
|
2153
|
+
] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
|
|
1809
2154
|
where: distinctKeys ? { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) } : where ? {
|
|
1810
2155
|
RAW: (aliasedTable2) => extractFilters(aliasedTable2, tableName, where, relationFilterCtx(filterCtx, tableName))
|
|
1811
2156
|
} : void 0,
|
|
@@ -1892,7 +2237,7 @@ import { is as is4, One as One3 } from "drizzle-orm";
|
|
|
1892
2237
|
import { getTableConfig, MySqlTable } from "drizzle-orm/mysql-core";
|
|
1893
2238
|
import {
|
|
1894
2239
|
GraphQLBoolean as GraphQLBoolean3,
|
|
1895
|
-
GraphQLError as
|
|
2240
|
+
GraphQLError as GraphQLError5,
|
|
1896
2241
|
GraphQLList as GraphQLList4,
|
|
1897
2242
|
GraphQLNonNull as GraphQLNonNull4,
|
|
1898
2243
|
GraphQLObjectType as GraphQLObjectType4
|
|
@@ -1905,15 +2250,23 @@ import {
|
|
|
1905
2250
|
avg,
|
|
1906
2251
|
count,
|
|
1907
2252
|
countDistinct,
|
|
2253
|
+
eq as eq2,
|
|
1908
2254
|
extractExtendedColumnType as extractExtendedColumnType2,
|
|
1909
2255
|
getColumns as getColumns2,
|
|
2256
|
+
gt as gt2,
|
|
2257
|
+
gte as gte2,
|
|
1910
2258
|
inArray as inArray2,
|
|
2259
|
+
lt as lt2,
|
|
2260
|
+
lte as lte2,
|
|
1911
2261
|
max,
|
|
1912
2262
|
min,
|
|
2263
|
+
ne as ne2,
|
|
1913
2264
|
sum
|
|
1914
2265
|
} from "drizzle-orm";
|
|
1915
2266
|
import {
|
|
1916
|
-
|
|
2267
|
+
GraphQLError as GraphQLError4,
|
|
2268
|
+
GraphQLFloat as GraphQLFloat3,
|
|
2269
|
+
GraphQLInputObjectType as GraphQLInputObjectType3,
|
|
1917
2270
|
GraphQLInt as GraphQLInt3,
|
|
1918
2271
|
GraphQLList as GraphQLList3,
|
|
1919
2272
|
GraphQLNonNull as GraphQLNonNull3,
|
|
@@ -1970,7 +2323,7 @@ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
|
|
|
1970
2323
|
fields[op] = {
|
|
1971
2324
|
type: new GraphQLObjectType3({
|
|
1972
2325
|
name: `${typeName}${capitalize(op)}Aggregate`,
|
|
1973
|
-
fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type:
|
|
2326
|
+
fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type: GraphQLFloat3 }]))
|
|
1974
2327
|
})
|
|
1975
2328
|
};
|
|
1976
2329
|
}
|
|
@@ -2034,9 +2387,9 @@ var aggregateTarget = (table, tableName, typeName) => {
|
|
|
2034
2387
|
)
|
|
2035
2388
|
};
|
|
2036
2389
|
};
|
|
2037
|
-
var parseAggregateRequest = (info, target) => {
|
|
2390
|
+
var parseAggregateRequest = (info, target, rootTypeName = `${target.typeName}Aggregate`) => {
|
|
2038
2391
|
const parsedInfo = parseResolveInfo(info, { deep: true });
|
|
2039
|
-
const selectionTree = parsedInfo.fieldsByTypeName[
|
|
2392
|
+
const selectionTree = parsedInfo.fieldsByTypeName[rootTypeName] ?? {};
|
|
2040
2393
|
const request = {
|
|
2041
2394
|
count: false,
|
|
2042
2395
|
ops: { avg: [], sum: [], min: [], max: [], countNonNull: [], countDistinct: [] },
|
|
@@ -2174,6 +2527,184 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
|
|
|
2174
2527
|
return { type, resolve };
|
|
2175
2528
|
};
|
|
2176
2529
|
};
|
|
2530
|
+
var GROUP_COL = `group${SEP}`;
|
|
2531
|
+
var HAVING_OPS = { eq: eq2, ne: ne2, gt: gt2, gte: gte2, lt: lt2, lte: lte2 };
|
|
2532
|
+
var groupableColumns = (table, tableName) => {
|
|
2533
|
+
const { orderable } = classifyAggregateColumns(table, tableName);
|
|
2534
|
+
const groupable = { ...orderable };
|
|
2535
|
+
for (const [columnName, column] of Object.entries(getColumns2(table))) {
|
|
2536
|
+
if (groupable[columnName]) {
|
|
2537
|
+
continue;
|
|
2538
|
+
}
|
|
2539
|
+
const { type: dataType } = extractExtendedColumnType2(column);
|
|
2540
|
+
if (dataType !== "boolean") {
|
|
2541
|
+
continue;
|
|
2542
|
+
}
|
|
2543
|
+
groupable[columnName] = {
|
|
2544
|
+
column,
|
|
2545
|
+
converted: drizzleColumnToGraphQLType(column, columnName, tableName, true, false, false)
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
return groupable;
|
|
2549
|
+
};
|
|
2550
|
+
var generateGroupByEnum = (table, tableName, typeName) => {
|
|
2551
|
+
const groupable = groupableColumns(table, tableName);
|
|
2552
|
+
return generateColumnEnum(
|
|
2553
|
+
table,
|
|
2554
|
+
`${typeName}GroupByColumn`,
|
|
2555
|
+
`Columns of ${typeName} that a query can group by`,
|
|
2556
|
+
(_column, columnName) => Boolean(groupable[columnName])
|
|
2557
|
+
);
|
|
2558
|
+
};
|
|
2559
|
+
var aggregateNumberFilter = new GraphQLInputObjectType3({
|
|
2560
|
+
name: "AggregateNumberFilter",
|
|
2561
|
+
description: "Compares an aggregated value. Several operators in one filter are ANDed together.",
|
|
2562
|
+
fields: Object.fromEntries(Object.keys(HAVING_OPS).map((op) => [op, { type: GraphQLFloat3 }]))
|
|
2563
|
+
});
|
|
2564
|
+
var generateHavingInput = (table, tableName, typeName) => {
|
|
2565
|
+
const { numeric, orderable, all } = classifyAggregateColumns(table, tableName);
|
|
2566
|
+
const fields = {
|
|
2567
|
+
count: { type: aggregateNumberFilter, description: "Filters groups by how many rows they contain" }
|
|
2568
|
+
};
|
|
2569
|
+
const opColumns = {
|
|
2570
|
+
avg: numeric,
|
|
2571
|
+
sum: numeric,
|
|
2572
|
+
min: numeric,
|
|
2573
|
+
max: numeric,
|
|
2574
|
+
countNonNull: all,
|
|
2575
|
+
countDistinct: orderable
|
|
2576
|
+
};
|
|
2577
|
+
for (const [op, columns] of Object.entries(opColumns)) {
|
|
2578
|
+
const columnNames = Object.keys(columns);
|
|
2579
|
+
if (!columnNames.length) {
|
|
2580
|
+
continue;
|
|
2581
|
+
}
|
|
2582
|
+
fields[op] = {
|
|
2583
|
+
type: new GraphQLInputObjectType3({
|
|
2584
|
+
name: `${typeName}${capitalize(op)}Having`,
|
|
2585
|
+
fields: Object.fromEntries(columnNames.map((columnName) => [columnName, { type: aggregateNumberFilter }]))
|
|
2586
|
+
})
|
|
2587
|
+
};
|
|
2588
|
+
}
|
|
2589
|
+
return new GraphQLInputObjectType3({
|
|
2590
|
+
name: `${typeName}Having`,
|
|
2591
|
+
description: `Filters ${typeName} groups by their aggregated values`,
|
|
2592
|
+
fields
|
|
2593
|
+
});
|
|
2594
|
+
};
|
|
2595
|
+
var generateGroupByType = (table, tableName, typeName, cacheCtx) => {
|
|
2596
|
+
const groupable = groupableColumns(table, tableName);
|
|
2597
|
+
if (!Object.keys(groupable).length) {
|
|
2598
|
+
return void 0;
|
|
2599
|
+
}
|
|
2600
|
+
const keysType = new GraphQLObjectType3({
|
|
2601
|
+
name: `${typeName}GroupKeys`,
|
|
2602
|
+
description: `The grouped column values of one ${typeName} group. A column the query did not group by is null.`,
|
|
2603
|
+
fields: Object.fromEntries(
|
|
2604
|
+
Object.entries(groupable).map(([columnName, { converted }]) => [
|
|
2605
|
+
columnName,
|
|
2606
|
+
{ type: converted.type, description: converted.description }
|
|
2607
|
+
])
|
|
2608
|
+
)
|
|
2609
|
+
});
|
|
2610
|
+
const aggregateType = generateAggregateTypes(table, tableName, typeName, cacheCtx);
|
|
2611
|
+
const aggregateFields = Object.fromEntries(
|
|
2612
|
+
Object.values(aggregateType.getFields()).map((field) => [
|
|
2613
|
+
field.name,
|
|
2614
|
+
{ type: field.type, description: field.description ?? void 0 }
|
|
2615
|
+
])
|
|
2616
|
+
);
|
|
2617
|
+
return new GraphQLObjectType3({
|
|
2618
|
+
name: `${typeName}GroupBy`,
|
|
2619
|
+
fields: { group: { type: new GraphQLNonNull3(keysType) }, ...aggregateFields }
|
|
2620
|
+
});
|
|
2621
|
+
};
|
|
2622
|
+
var havingComparisons = (expression, filter) => Object.entries(filter).filter(([op, value]) => value != null && op in HAVING_OPS).map(([op, value]) => HAVING_OPS[op](expression, value));
|
|
2623
|
+
var buildHavingCondition = (having, columns) => {
|
|
2624
|
+
if (!having) {
|
|
2625
|
+
return void 0;
|
|
2626
|
+
}
|
|
2627
|
+
const conditions = [];
|
|
2628
|
+
for (const [key, value] of Object.entries(having)) {
|
|
2629
|
+
if (value == null) {
|
|
2630
|
+
continue;
|
|
2631
|
+
}
|
|
2632
|
+
if (key === "count") {
|
|
2633
|
+
conditions.push(...havingComparisons(count(), value));
|
|
2634
|
+
continue;
|
|
2635
|
+
}
|
|
2636
|
+
if (!AGGREGATE_OPS.includes(key)) {
|
|
2637
|
+
continue;
|
|
2638
|
+
}
|
|
2639
|
+
for (const [columnName, filter] of Object.entries(value)) {
|
|
2640
|
+
const column = columns[columnName];
|
|
2641
|
+
if (!column || filter == null) {
|
|
2642
|
+
continue;
|
|
2643
|
+
}
|
|
2644
|
+
conditions.push(...havingComparisons(OP_FNS[key](column), filter));
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
return conditions.length ? and2(...conditions) : void 0;
|
|
2648
|
+
};
|
|
2649
|
+
var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, groupByEnum, havingInput, filterCtx) => {
|
|
2650
|
+
const target = aggregateTarget(table, tableName, typeName);
|
|
2651
|
+
const groupable = groupableColumns(table, tableName);
|
|
2652
|
+
const columns = getColumns2(table);
|
|
2653
|
+
const rootTypeName = `${typeName}GroupBy`;
|
|
2654
|
+
const queryArgs = {
|
|
2655
|
+
groupBy: {
|
|
2656
|
+
type: new GraphQLNonNull3(new GraphQLList3(new GraphQLNonNull3(groupByEnum))),
|
|
2657
|
+
description: "Columns to group by. One result row per distinct combination of their values."
|
|
2658
|
+
},
|
|
2659
|
+
where: { type: filterArgs, description: "Filters the rows before they are grouped." },
|
|
2660
|
+
having: { type: havingInput, description: "Filters the groups after they are aggregated." }
|
|
2661
|
+
};
|
|
2662
|
+
return {
|
|
2663
|
+
name: fieldName,
|
|
2664
|
+
resolver: async (_source, args, context, info) => {
|
|
2665
|
+
try {
|
|
2666
|
+
const requestedKeys = [...new Set(args.groupBy ?? [])];
|
|
2667
|
+
if (!requestedKeys.length) {
|
|
2668
|
+
throw new GraphQLError4("At least one column to group by is required!");
|
|
2669
|
+
}
|
|
2670
|
+
const keyColumns = requestedKeys.map((columnName) => {
|
|
2671
|
+
const groupableColumn = groupable[columnName];
|
|
2672
|
+
if (!groupableColumn) {
|
|
2673
|
+
throw new GraphQLError4(`Cannot group ${typeName} by ${columnName}!`);
|
|
2674
|
+
}
|
|
2675
|
+
return [columnName, groupableColumn.column];
|
|
2676
|
+
});
|
|
2677
|
+
const request = parseAggregateRequest(info, target, rootTypeName);
|
|
2678
|
+
const selection = {
|
|
2679
|
+
...Object.fromEntries(keyColumns.map(([columnName, column]) => [`${GROUP_COL}${columnName}`, column])),
|
|
2680
|
+
...request.selection
|
|
2681
|
+
};
|
|
2682
|
+
let query = resolveExecutor(db, context).select(selection).from(table);
|
|
2683
|
+
if (args.where) {
|
|
2684
|
+
query = query.where(extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)));
|
|
2685
|
+
}
|
|
2686
|
+
query = query.groupBy(...keyColumns.map(([, column]) => column));
|
|
2687
|
+
const havingCondition = buildHavingCondition(args.having, columns);
|
|
2688
|
+
if (havingCondition) {
|
|
2689
|
+
query = query.having(havingCondition);
|
|
2690
|
+
}
|
|
2691
|
+
const rows = await query;
|
|
2692
|
+
return rows.map((row) => {
|
|
2693
|
+
const group = {};
|
|
2694
|
+
for (const [columnName, column] of keyColumns) {
|
|
2695
|
+
const value = row[`${GROUP_COL}${columnName}`];
|
|
2696
|
+
const decoded = typeof value === "string" && target.dateTimeColumns.has(columnName) ? parseDriverDateTime(value) : value;
|
|
2697
|
+
group[columnName] = value == null ? null : remapToGraphQLCore(columnName, decoded, tableName, column);
|
|
2698
|
+
}
|
|
2699
|
+
return { group, ...assembleAggregateRow(row, request, target) };
|
|
2700
|
+
});
|
|
2701
|
+
} catch (e) {
|
|
2702
|
+
throw toGraphQLError(e);
|
|
2703
|
+
}
|
|
2704
|
+
},
|
|
2705
|
+
args: queryArgs
|
|
2706
|
+
};
|
|
2707
|
+
};
|
|
2177
2708
|
|
|
2178
2709
|
// src/util/builders/mysql.ts
|
|
2179
2710
|
var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
|
|
@@ -2268,7 +2799,7 @@ var generateInsertArray = (db, _tableName, table, baseType, fieldName) => {
|
|
|
2268
2799
|
try {
|
|
2269
2800
|
const input = remapFromGraphQLArrayInput(args.values, table);
|
|
2270
2801
|
if (!input.length) {
|
|
2271
|
-
throw new
|
|
2802
|
+
throw new GraphQLError5("No values were provided!");
|
|
2272
2803
|
}
|
|
2273
2804
|
await resolveExecutor(db, context).insert(table).values(input);
|
|
2274
2805
|
return { isSuccess: true };
|
|
@@ -2316,7 +2847,7 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
|
|
|
2316
2847
|
try {
|
|
2317
2848
|
const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
|
|
2318
2849
|
if (!input.length) {
|
|
2319
|
-
throw new
|
|
2850
|
+
throw new GraphQLError5("No values were provided!");
|
|
2320
2851
|
}
|
|
2321
2852
|
const plan = resolveConflictPlan({
|
|
2322
2853
|
table,
|
|
@@ -2341,13 +2872,13 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
|
|
|
2341
2872
|
args: queryArgs
|
|
2342
2873
|
};
|
|
2343
2874
|
};
|
|
2344
|
-
var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filterCtx) => {
|
|
2875
|
+
var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, single, requireWhere, filterCtx) => {
|
|
2345
2876
|
const queryArgs = {
|
|
2346
2877
|
set: {
|
|
2347
2878
|
type: new GraphQLNonNull4(setArgs)
|
|
2348
2879
|
},
|
|
2349
2880
|
where: {
|
|
2350
|
-
type: filterArgs
|
|
2881
|
+
type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
|
|
2351
2882
|
}
|
|
2352
2883
|
};
|
|
2353
2884
|
return {
|
|
@@ -2357,12 +2888,16 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
|
|
|
2357
2888
|
const { where, set } = args;
|
|
2358
2889
|
const input = remapFromGraphQLSingleInput(set, table);
|
|
2359
2890
|
if (!Object.keys(input).length) {
|
|
2360
|
-
throw new
|
|
2891
|
+
throw new GraphQLError5("Unable to update with no values specified!");
|
|
2361
2892
|
}
|
|
2893
|
+
const relationCtx = relationFilterCtx(filterCtx, tableName);
|
|
2894
|
+
const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
|
|
2362
2895
|
const executor = resolveExecutor(db, context);
|
|
2896
|
+
if (single) {
|
|
2897
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
2898
|
+
}
|
|
2363
2899
|
let query = executor.update(table).set(input);
|
|
2364
|
-
if (
|
|
2365
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
2900
|
+
if (filters) {
|
|
2366
2901
|
query = query.where(filters);
|
|
2367
2902
|
}
|
|
2368
2903
|
await query;
|
|
@@ -2374,10 +2909,10 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
|
|
|
2374
2909
|
args: queryArgs
|
|
2375
2910
|
};
|
|
2376
2911
|
};
|
|
2377
|
-
var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) => {
|
|
2912
|
+
var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx) => {
|
|
2378
2913
|
const queryArgs = {
|
|
2379
2914
|
where: {
|
|
2380
|
-
type: filterArgs
|
|
2915
|
+
type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
|
|
2381
2916
|
}
|
|
2382
2917
|
};
|
|
2383
2918
|
return {
|
|
@@ -2385,10 +2920,14 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) =>
|
|
|
2385
2920
|
resolver: async (_source, args, context, _info) => {
|
|
2386
2921
|
try {
|
|
2387
2922
|
const { where } = args;
|
|
2923
|
+
const relationCtx = relationFilterCtx(filterCtx, tableName);
|
|
2924
|
+
const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
|
|
2388
2925
|
const executor = resolveExecutor(db, context);
|
|
2926
|
+
if (single) {
|
|
2927
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
2928
|
+
}
|
|
2389
2929
|
let query = executor.delete(table);
|
|
2390
|
-
if (
|
|
2391
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
2930
|
+
if (filters) {
|
|
2392
2931
|
query = query.where(filters);
|
|
2393
2932
|
}
|
|
2394
2933
|
await query;
|
|
@@ -2471,12 +3010,15 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2471
3010
|
listFieldName,
|
|
2472
3011
|
singleFieldName,
|
|
2473
3012
|
aggregateFieldName,
|
|
3013
|
+
groupByFieldName,
|
|
2474
3014
|
createArrayFieldName,
|
|
2475
3015
|
createSingleFieldName,
|
|
2476
3016
|
upsertArrayFieldName,
|
|
2477
3017
|
upsertSingleFieldName,
|
|
2478
3018
|
updateFieldName,
|
|
2479
|
-
|
|
3019
|
+
updateSingleFieldName,
|
|
3020
|
+
deleteFieldName,
|
|
3021
|
+
deleteSingleFieldName
|
|
2480
3022
|
} = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
|
|
2481
3023
|
const selectArrGenerated = generateSelectArray(
|
|
2482
3024
|
db,
|
|
@@ -2521,9 +3063,41 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2521
3063
|
updateInput,
|
|
2522
3064
|
tableFilters,
|
|
2523
3065
|
updateFieldName,
|
|
3066
|
+
false,
|
|
3067
|
+
features.requireWhere,
|
|
3068
|
+
filterCtx
|
|
3069
|
+
) : void 0;
|
|
3070
|
+
const updateSingleGenerated = features.update ? generateUpdate(
|
|
3071
|
+
db,
|
|
3072
|
+
tableName,
|
|
3073
|
+
schema[tableName],
|
|
3074
|
+
updateInput,
|
|
3075
|
+
tableFilters,
|
|
3076
|
+
updateSingleFieldName,
|
|
3077
|
+
true,
|
|
3078
|
+
features.requireWhere,
|
|
3079
|
+
filterCtx
|
|
3080
|
+
) : void 0;
|
|
3081
|
+
const deleteGenerated = features.delete ? generateDelete(
|
|
3082
|
+
db,
|
|
3083
|
+
tableName,
|
|
3084
|
+
schema[tableName],
|
|
3085
|
+
tableFilters,
|
|
3086
|
+
deleteFieldName,
|
|
3087
|
+
false,
|
|
3088
|
+
features.requireWhere,
|
|
3089
|
+
filterCtx
|
|
3090
|
+
) : void 0;
|
|
3091
|
+
const deleteSingleGenerated = features.delete ? generateDelete(
|
|
3092
|
+
db,
|
|
3093
|
+
tableName,
|
|
3094
|
+
schema[tableName],
|
|
3095
|
+
tableFilters,
|
|
3096
|
+
deleteSingleFieldName,
|
|
3097
|
+
true,
|
|
3098
|
+
features.requireWhere,
|
|
2524
3099
|
filterCtx
|
|
2525
3100
|
) : void 0;
|
|
2526
|
-
const deleteGenerated = features.delete ? generateDelete(db, tableName, schema[tableName], tableFilters, deleteFieldName, filterCtx) : void 0;
|
|
2527
3101
|
const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
|
|
2528
3102
|
const aggregateGenerated = features.aggregates ? generateAggregate(
|
|
2529
3103
|
db,
|
|
@@ -2534,6 +3108,20 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2534
3108
|
tableFilters,
|
|
2535
3109
|
filterCtx
|
|
2536
3110
|
) : void 0;
|
|
3111
|
+
const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
|
|
3112
|
+
const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
|
|
3113
|
+
const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
|
|
3114
|
+
const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
|
|
3115
|
+
db,
|
|
3116
|
+
tableName,
|
|
3117
|
+
schema[tableName],
|
|
3118
|
+
typeName,
|
|
3119
|
+
groupByFieldName,
|
|
3120
|
+
tableFilters,
|
|
3121
|
+
groupByEnum,
|
|
3122
|
+
havingInput,
|
|
3123
|
+
filterCtx
|
|
3124
|
+
) : void 0;
|
|
2537
3125
|
queries[selectArrGenerated.name] = {
|
|
2538
3126
|
type: selectArrOutput,
|
|
2539
3127
|
args: selectArrGenerated.args,
|
|
@@ -2553,13 +3141,23 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2553
3141
|
...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
|
|
2554
3142
|
};
|
|
2555
3143
|
}
|
|
3144
|
+
if (groupByGenerated && groupByType) {
|
|
3145
|
+
queries[groupByGenerated.name] = {
|
|
3146
|
+
type: new GraphQLNonNull4(new GraphQLList4(new GraphQLNonNull4(groupByType))),
|
|
3147
|
+
args: groupByGenerated.args,
|
|
3148
|
+
resolve: groupByGenerated.resolver,
|
|
3149
|
+
...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
|
|
3150
|
+
};
|
|
3151
|
+
}
|
|
2556
3152
|
for (const generated of [
|
|
2557
3153
|
insertArrGenerated,
|
|
2558
3154
|
insertSingleGenerated,
|
|
2559
3155
|
upsertArrGenerated,
|
|
2560
3156
|
upsertSingleGenerated,
|
|
2561
3157
|
updateGenerated,
|
|
2562
|
-
|
|
3158
|
+
updateSingleGenerated,
|
|
3159
|
+
deleteGenerated,
|
|
3160
|
+
deleteSingleGenerated
|
|
2563
3161
|
]) {
|
|
2564
3162
|
if (generated) {
|
|
2565
3163
|
mutations[generated.name] = {
|
|
@@ -2584,6 +3182,10 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2584
3182
|
if (aggregateType) {
|
|
2585
3183
|
outputs[aggregateType.name] = aggregateType;
|
|
2586
3184
|
}
|
|
3185
|
+
if (groupByType && havingInput) {
|
|
3186
|
+
outputs[groupByType.name] = groupByType;
|
|
3187
|
+
inputs[havingInput.name] = havingInput;
|
|
3188
|
+
}
|
|
2587
3189
|
}
|
|
2588
3190
|
const fieldResolvers = {};
|
|
2589
3191
|
for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
|
|
@@ -2606,7 +3208,7 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2606
3208
|
import { is as is5, One as One4 } from "drizzle-orm";
|
|
2607
3209
|
import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
|
|
2608
3210
|
import {
|
|
2609
|
-
GraphQLError as
|
|
3211
|
+
GraphQLError as GraphQLError6,
|
|
2610
3212
|
GraphQLList as GraphQLList5,
|
|
2611
3213
|
GraphQLNonNull as GraphQLNonNull5
|
|
2612
3214
|
} from "graphql";
|
|
@@ -2675,7 +3277,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
|
|
|
2675
3277
|
}
|
|
2676
3278
|
if (orderBy) {
|
|
2677
3279
|
q = q.orderBy(
|
|
2678
|
-
...extractOrderBy(table, orderBy),
|
|
3280
|
+
...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)),
|
|
2679
3281
|
...distinctKeys ? primaryKeyOrderExprs(table, pkNames) : []
|
|
2680
3282
|
);
|
|
2681
3283
|
} else if ((distinctKeys || offset != null || limit != null) && pkNames.length) {
|
|
@@ -2736,7 +3338,7 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
|
|
|
2736
3338
|
q = q.where(extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)));
|
|
2737
3339
|
}
|
|
2738
3340
|
if (orderBy) {
|
|
2739
|
-
q = q.orderBy(...extractOrderBy(table, orderBy));
|
|
3341
|
+
q = q.orderBy(...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)));
|
|
2740
3342
|
} else if (pkNames.length) {
|
|
2741
3343
|
q = q.orderBy(...primaryKeyOrderExprs(table, pkNames));
|
|
2742
3344
|
}
|
|
@@ -2767,7 +3369,7 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
|
|
|
2767
3369
|
try {
|
|
2768
3370
|
const input = remapFromGraphQLArrayInput(args.values, table);
|
|
2769
3371
|
if (!input.length) {
|
|
2770
|
-
throw new
|
|
3372
|
+
throw new GraphQLError6("No values were provided!");
|
|
2771
3373
|
}
|
|
2772
3374
|
const parsedInfo = parseResolveInfo3(info, {
|
|
2773
3375
|
deep: true
|
|
@@ -2857,7 +3459,7 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
|
|
|
2857
3459
|
try {
|
|
2858
3460
|
const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
|
|
2859
3461
|
if (!input.length) {
|
|
2860
|
-
throw new
|
|
3462
|
+
throw new GraphQLError6("No values were provided!");
|
|
2861
3463
|
}
|
|
2862
3464
|
const parsedInfo = parseResolveInfo3(info, { deep: true });
|
|
2863
3465
|
const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
|
|
@@ -2896,13 +3498,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
|
|
|
2896
3498
|
args: queryArgs
|
|
2897
3499
|
};
|
|
2898
3500
|
};
|
|
2899
|
-
var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
|
|
3501
|
+
var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
|
|
2900
3502
|
const queryArgs = {
|
|
2901
3503
|
set: {
|
|
2902
3504
|
type: new GraphQLNonNull5(setArgs)
|
|
2903
3505
|
},
|
|
2904
3506
|
where: {
|
|
2905
|
-
type: filterArgs
|
|
3507
|
+
type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
|
|
2906
3508
|
}
|
|
2907
3509
|
};
|
|
2908
3510
|
const pkNames = pgPrimaryKeyPropNames(table);
|
|
@@ -2926,18 +3528,28 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
2926
3528
|
});
|
|
2927
3529
|
const input = remapFromGraphQLSingleInput(set, table);
|
|
2928
3530
|
if (!Object.keys(input).length) {
|
|
2929
|
-
throw new
|
|
3531
|
+
throw new GraphQLError6("Unable to update with no values specified!");
|
|
2930
3532
|
}
|
|
3533
|
+
const relationCtx = relationFilterCtx(filterCtx, tableName);
|
|
3534
|
+
const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
|
|
2931
3535
|
const executor = resolveExecutor(db, context);
|
|
3536
|
+
if (single) {
|
|
3537
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
3538
|
+
}
|
|
2932
3539
|
let query = executor.update(table).set(input);
|
|
2933
|
-
if (
|
|
2934
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
3540
|
+
if (filters) {
|
|
2935
3541
|
query = query.where(filters);
|
|
2936
3542
|
}
|
|
2937
3543
|
query = query.returning(columns);
|
|
2938
3544
|
const result = await query;
|
|
3545
|
+
if (single && result.length > 1) {
|
|
3546
|
+
throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
|
|
3547
|
+
}
|
|
3548
|
+
if (single && !result[0]) {
|
|
3549
|
+
return void 0;
|
|
3550
|
+
}
|
|
2939
3551
|
const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
|
|
2940
|
-
return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
3552
|
+
return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
2941
3553
|
} catch (e) {
|
|
2942
3554
|
throw toGraphQLError(e);
|
|
2943
3555
|
}
|
|
@@ -2945,10 +3557,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
2945
3557
|
args: queryArgs
|
|
2946
3558
|
};
|
|
2947
3559
|
};
|
|
2948
|
-
var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
|
|
3560
|
+
var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
|
|
2949
3561
|
const queryArgs = {
|
|
2950
3562
|
where: {
|
|
2951
|
-
type: filterArgs
|
|
3563
|
+
type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
|
|
2952
3564
|
}
|
|
2953
3565
|
};
|
|
2954
3566
|
return {
|
|
@@ -2964,14 +3576,24 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, fi
|
|
|
2964
3576
|
table,
|
|
2965
3577
|
selectionCtx
|
|
2966
3578
|
);
|
|
3579
|
+
const relationCtx = relationFilterCtx(filterCtx, tableName);
|
|
3580
|
+
const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
|
|
2967
3581
|
const executor = resolveExecutor(db, context);
|
|
3582
|
+
if (single) {
|
|
3583
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
3584
|
+
}
|
|
2968
3585
|
let query = executor.delete(table);
|
|
2969
|
-
if (
|
|
2970
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
3586
|
+
if (filters) {
|
|
2971
3587
|
query = query.where(filters);
|
|
2972
3588
|
}
|
|
2973
3589
|
query = query.returning(columns);
|
|
2974
3590
|
const result = await query;
|
|
3591
|
+
if (single && result.length > 1) {
|
|
3592
|
+
throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
|
|
3593
|
+
}
|
|
3594
|
+
if (single) {
|
|
3595
|
+
return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
|
|
3596
|
+
}
|
|
2975
3597
|
return remapToGraphQLArrayOutput(result, tableName, table);
|
|
2976
3598
|
} catch (e) {
|
|
2977
3599
|
throw toGraphQLError(e);
|
|
@@ -3047,12 +3669,15 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3047
3669
|
listFieldName,
|
|
3048
3670
|
singleFieldName,
|
|
3049
3671
|
aggregateFieldName,
|
|
3672
|
+
groupByFieldName,
|
|
3050
3673
|
createArrayFieldName,
|
|
3051
3674
|
createSingleFieldName,
|
|
3052
3675
|
upsertArrayFieldName,
|
|
3053
3676
|
upsertSingleFieldName,
|
|
3054
3677
|
updateFieldName,
|
|
3055
|
-
|
|
3678
|
+
updateSingleFieldName,
|
|
3679
|
+
deleteFieldName,
|
|
3680
|
+
deleteSingleFieldName
|
|
3056
3681
|
} = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
|
|
3057
3682
|
const selectArrGenerated = generateSelectArray2(
|
|
3058
3683
|
db,
|
|
@@ -3151,6 +3776,23 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3151
3776
|
tableFilters,
|
|
3152
3777
|
updateFieldName,
|
|
3153
3778
|
typeName,
|
|
3779
|
+
false,
|
|
3780
|
+
features.requireWhere,
|
|
3781
|
+
typeNameMapper,
|
|
3782
|
+
filterCtx
|
|
3783
|
+
) : void 0;
|
|
3784
|
+
const updateSingleGenerated = features.update ? generateUpdate2(
|
|
3785
|
+
db,
|
|
3786
|
+
tableName,
|
|
3787
|
+
schema[tableName],
|
|
3788
|
+
tables,
|
|
3789
|
+
eagerRelations,
|
|
3790
|
+
updateInput,
|
|
3791
|
+
tableFilters,
|
|
3792
|
+
updateSingleFieldName,
|
|
3793
|
+
typeName,
|
|
3794
|
+
true,
|
|
3795
|
+
features.requireWhere,
|
|
3154
3796
|
typeNameMapper,
|
|
3155
3797
|
filterCtx
|
|
3156
3798
|
) : void 0;
|
|
@@ -3161,6 +3803,20 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3161
3803
|
tableFilters,
|
|
3162
3804
|
deleteFieldName,
|
|
3163
3805
|
typeName,
|
|
3806
|
+
false,
|
|
3807
|
+
features.requireWhere,
|
|
3808
|
+
filterCtx,
|
|
3809
|
+
{ tableName, relationMap: namedRelations, tables }
|
|
3810
|
+
) : void 0;
|
|
3811
|
+
const deleteSingleGenerated = features.delete ? generateDelete2(
|
|
3812
|
+
db,
|
|
3813
|
+
tableName,
|
|
3814
|
+
schema[tableName],
|
|
3815
|
+
tableFilters,
|
|
3816
|
+
deleteSingleFieldName,
|
|
3817
|
+
typeName,
|
|
3818
|
+
true,
|
|
3819
|
+
features.requireWhere,
|
|
3164
3820
|
filterCtx,
|
|
3165
3821
|
{ tableName, relationMap: namedRelations, tables }
|
|
3166
3822
|
) : void 0;
|
|
@@ -3174,6 +3830,20 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3174
3830
|
tableFilters,
|
|
3175
3831
|
filterCtx
|
|
3176
3832
|
) : void 0;
|
|
3833
|
+
const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
|
|
3834
|
+
const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
|
|
3835
|
+
const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
|
|
3836
|
+
const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
|
|
3837
|
+
db,
|
|
3838
|
+
tableName,
|
|
3839
|
+
schema[tableName],
|
|
3840
|
+
typeName,
|
|
3841
|
+
groupByFieldName,
|
|
3842
|
+
tableFilters,
|
|
3843
|
+
groupByEnum,
|
|
3844
|
+
havingInput,
|
|
3845
|
+
filterCtx
|
|
3846
|
+
) : void 0;
|
|
3177
3847
|
queries[selectArrGenerated.name] = {
|
|
3178
3848
|
type: selectArrOutput,
|
|
3179
3849
|
args: selectArrGenerated.args,
|
|
@@ -3193,6 +3863,14 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3193
3863
|
...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
|
|
3194
3864
|
};
|
|
3195
3865
|
}
|
|
3866
|
+
if (groupByGenerated && groupByType) {
|
|
3867
|
+
queries[groupByGenerated.name] = {
|
|
3868
|
+
type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(groupByType))),
|
|
3869
|
+
args: groupByGenerated.args,
|
|
3870
|
+
resolve: groupByGenerated.resolver,
|
|
3871
|
+
...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
|
|
3872
|
+
};
|
|
3873
|
+
}
|
|
3196
3874
|
if (insertArrGenerated) {
|
|
3197
3875
|
mutations[insertArrGenerated.name] = {
|
|
3198
3876
|
type: arrTableItemOutput,
|
|
@@ -3228,6 +3906,13 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3228
3906
|
resolve: updateGenerated.resolver
|
|
3229
3907
|
};
|
|
3230
3908
|
}
|
|
3909
|
+
if (updateSingleGenerated) {
|
|
3910
|
+
mutations[updateSingleGenerated.name] = {
|
|
3911
|
+
type: singleTableItemOutput,
|
|
3912
|
+
args: updateSingleGenerated.args,
|
|
3913
|
+
resolve: updateSingleGenerated.resolver
|
|
3914
|
+
};
|
|
3915
|
+
}
|
|
3231
3916
|
if (deleteGenerated) {
|
|
3232
3917
|
mutations[deleteGenerated.name] = {
|
|
3233
3918
|
type: arrTableItemOutput,
|
|
@@ -3235,6 +3920,13 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3235
3920
|
resolve: deleteGenerated.resolver
|
|
3236
3921
|
};
|
|
3237
3922
|
}
|
|
3923
|
+
if (deleteSingleGenerated) {
|
|
3924
|
+
mutations[deleteSingleGenerated.name] = {
|
|
3925
|
+
type: singleTableItemOutput,
|
|
3926
|
+
args: deleteSingleGenerated.args,
|
|
3927
|
+
resolve: deleteSingleGenerated.resolver
|
|
3928
|
+
};
|
|
3929
|
+
}
|
|
3238
3930
|
const activeInputs = [
|
|
3239
3931
|
// The insert input types the upsert mutations too, so either feature keeps it.
|
|
3240
3932
|
...features.insert || onConflictInput ? [insertInput] : [],
|
|
@@ -3251,6 +3943,10 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3251
3943
|
if (aggregateType) {
|
|
3252
3944
|
outputs[aggregateType.name] = aggregateType;
|
|
3253
3945
|
}
|
|
3946
|
+
if (groupByType && havingInput) {
|
|
3947
|
+
outputs[groupByType.name] = groupByType;
|
|
3948
|
+
inputs[havingInput.name] = havingInput;
|
|
3949
|
+
}
|
|
3254
3950
|
}
|
|
3255
3951
|
const fieldResolvers = {};
|
|
3256
3952
|
for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
|
|
@@ -3273,7 +3969,7 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3273
3969
|
import { is as is6, One as One5 } from "drizzle-orm";
|
|
3274
3970
|
import { getTableConfig as getTableConfig3, SQLiteTable } from "drizzle-orm/sqlite-core";
|
|
3275
3971
|
import {
|
|
3276
|
-
GraphQLError as
|
|
3972
|
+
GraphQLError as GraphQLError7,
|
|
3277
3973
|
GraphQLList as GraphQLList6,
|
|
3278
3974
|
GraphQLNonNull as GraphQLNonNull6
|
|
3279
3975
|
} from "graphql";
|
|
@@ -3372,7 +4068,7 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
|
|
|
3372
4068
|
try {
|
|
3373
4069
|
const input = remapFromGraphQLArrayInput(args.values, table);
|
|
3374
4070
|
if (!input.length) {
|
|
3375
|
-
throw new
|
|
4071
|
+
throw new GraphQLError7("No values were provided!");
|
|
3376
4072
|
}
|
|
3377
4073
|
const parsedInfo = parseResolveInfo4(info, {
|
|
3378
4074
|
deep: true
|
|
@@ -3462,7 +4158,7 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
|
|
|
3462
4158
|
try {
|
|
3463
4159
|
const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
|
|
3464
4160
|
if (!input.length) {
|
|
3465
|
-
throw new
|
|
4161
|
+
throw new GraphQLError7("No values were provided!");
|
|
3466
4162
|
}
|
|
3467
4163
|
const parsedInfo = parseResolveInfo4(info, { deep: true });
|
|
3468
4164
|
const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
|
|
@@ -3501,13 +4197,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
|
|
|
3501
4197
|
args: queryArgs
|
|
3502
4198
|
};
|
|
3503
4199
|
};
|
|
3504
|
-
var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
|
|
4200
|
+
var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
|
|
3505
4201
|
const queryArgs = {
|
|
3506
4202
|
set: {
|
|
3507
4203
|
type: new GraphQLNonNull6(setArgs)
|
|
3508
4204
|
},
|
|
3509
4205
|
where: {
|
|
3510
|
-
type: filterArgs
|
|
4206
|
+
type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
|
|
3511
4207
|
}
|
|
3512
4208
|
};
|
|
3513
4209
|
const pkNames = sqlitePrimaryKeyPropNames(table);
|
|
@@ -3531,18 +4227,28 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
3531
4227
|
});
|
|
3532
4228
|
const input = remapFromGraphQLSingleInput(set, table);
|
|
3533
4229
|
if (!Object.keys(input).length) {
|
|
3534
|
-
throw new
|
|
4230
|
+
throw new GraphQLError7("Unable to update with no values specified!");
|
|
3535
4231
|
}
|
|
4232
|
+
const relationCtx = relationFilterCtx(filterCtx, tableName);
|
|
4233
|
+
const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
|
|
3536
4234
|
const executor = resolveExecutor(db, context);
|
|
4235
|
+
if (single) {
|
|
4236
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
4237
|
+
}
|
|
3537
4238
|
let query = executor.update(table).set(input);
|
|
3538
|
-
if (
|
|
3539
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
4239
|
+
if (filters) {
|
|
3540
4240
|
query = query.where(filters);
|
|
3541
4241
|
}
|
|
3542
4242
|
query = query.returning(columns);
|
|
3543
4243
|
const result = await query;
|
|
4244
|
+
if (single && result.length > 1) {
|
|
4245
|
+
throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
|
|
4246
|
+
}
|
|
4247
|
+
if (single && !result[0]) {
|
|
4248
|
+
return void 0;
|
|
4249
|
+
}
|
|
3544
4250
|
const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
|
|
3545
|
-
return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
4251
|
+
return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
3546
4252
|
} catch (e) {
|
|
3547
4253
|
throw toGraphQLError(e);
|
|
3548
4254
|
}
|
|
@@ -3550,10 +4256,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
3550
4256
|
args: queryArgs
|
|
3551
4257
|
};
|
|
3552
4258
|
};
|
|
3553
|
-
var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
|
|
4259
|
+
var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
|
|
3554
4260
|
const queryArgs = {
|
|
3555
4261
|
where: {
|
|
3556
|
-
type: filterArgs
|
|
4262
|
+
type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
|
|
3557
4263
|
}
|
|
3558
4264
|
};
|
|
3559
4265
|
return {
|
|
@@ -3569,14 +4275,24 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, fi
|
|
|
3569
4275
|
table,
|
|
3570
4276
|
selectionCtx
|
|
3571
4277
|
);
|
|
4278
|
+
const relationCtx = relationFilterCtx(filterCtx, tableName);
|
|
4279
|
+
const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
|
|
3572
4280
|
const executor = resolveExecutor(db, context);
|
|
4281
|
+
if (single) {
|
|
4282
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
4283
|
+
}
|
|
3573
4284
|
let query = executor.delete(table);
|
|
3574
|
-
if (
|
|
3575
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
4285
|
+
if (filters) {
|
|
3576
4286
|
query = query.where(filters);
|
|
3577
4287
|
}
|
|
3578
4288
|
query = query.returning(columns);
|
|
3579
4289
|
const result = await query;
|
|
4290
|
+
if (single && result.length > 1) {
|
|
4291
|
+
throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
|
|
4292
|
+
}
|
|
4293
|
+
if (single) {
|
|
4294
|
+
return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
|
|
4295
|
+
}
|
|
3580
4296
|
return remapToGraphQLArrayOutput(result, tableName, table);
|
|
3581
4297
|
} catch (e) {
|
|
3582
4298
|
throw toGraphQLError(e);
|
|
@@ -3653,12 +4369,15 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3653
4369
|
listFieldName,
|
|
3654
4370
|
singleFieldName,
|
|
3655
4371
|
aggregateFieldName,
|
|
4372
|
+
groupByFieldName,
|
|
3656
4373
|
createArrayFieldName,
|
|
3657
4374
|
createSingleFieldName,
|
|
3658
4375
|
upsertArrayFieldName,
|
|
3659
4376
|
upsertSingleFieldName,
|
|
3660
4377
|
updateFieldName,
|
|
3661
|
-
|
|
4378
|
+
updateSingleFieldName,
|
|
4379
|
+
deleteFieldName,
|
|
4380
|
+
deleteSingleFieldName
|
|
3662
4381
|
} = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
|
|
3663
4382
|
const selectArrGenerated = generateSelectArray3(
|
|
3664
4383
|
db,
|
|
@@ -3757,6 +4476,23 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3757
4476
|
tableFilters,
|
|
3758
4477
|
updateFieldName,
|
|
3759
4478
|
typeName,
|
|
4479
|
+
false,
|
|
4480
|
+
features.requireWhere,
|
|
4481
|
+
typeNameMapper,
|
|
4482
|
+
filterCtx
|
|
4483
|
+
) : void 0;
|
|
4484
|
+
const updateSingleGenerated = features.update ? generateUpdate3(
|
|
4485
|
+
db,
|
|
4486
|
+
tableName,
|
|
4487
|
+
schema[tableName],
|
|
4488
|
+
tables,
|
|
4489
|
+
eagerRelations,
|
|
4490
|
+
updateInput,
|
|
4491
|
+
tableFilters,
|
|
4492
|
+
updateSingleFieldName,
|
|
4493
|
+
typeName,
|
|
4494
|
+
true,
|
|
4495
|
+
features.requireWhere,
|
|
3760
4496
|
typeNameMapper,
|
|
3761
4497
|
filterCtx
|
|
3762
4498
|
) : void 0;
|
|
@@ -3767,6 +4503,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3767
4503
|
tableFilters,
|
|
3768
4504
|
deleteFieldName,
|
|
3769
4505
|
typeName,
|
|
4506
|
+
false,
|
|
4507
|
+
features.requireWhere,
|
|
4508
|
+
filterCtx,
|
|
4509
|
+
{ tableName, relationMap: namedRelations, tables }
|
|
4510
|
+
) : void 0;
|
|
4511
|
+
const deleteSingleGenerated = features.delete ? generateDelete3(
|
|
4512
|
+
db,
|
|
4513
|
+
tableName,
|
|
4514
|
+
schema[tableName],
|
|
4515
|
+
tableFilters,
|
|
4516
|
+
deleteSingleFieldName,
|
|
4517
|
+
typeName,
|
|
4518
|
+
true,
|
|
4519
|
+
features.requireWhere,
|
|
3770
4520
|
filterCtx,
|
|
3771
4521
|
{ tableName, relationMap: namedRelations, tables }
|
|
3772
4522
|
) : void 0;
|
|
@@ -3780,6 +4530,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3780
4530
|
tableFilters,
|
|
3781
4531
|
filterCtx
|
|
3782
4532
|
) : void 0;
|
|
4533
|
+
const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
|
|
4534
|
+
const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
|
|
4535
|
+
const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
|
|
4536
|
+
const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
|
|
4537
|
+
db,
|
|
4538
|
+
tableName,
|
|
4539
|
+
schema[tableName],
|
|
4540
|
+
typeName,
|
|
4541
|
+
groupByFieldName,
|
|
4542
|
+
tableFilters,
|
|
4543
|
+
groupByEnum,
|
|
4544
|
+
havingInput,
|
|
4545
|
+
filterCtx
|
|
4546
|
+
) : void 0;
|
|
3783
4547
|
queries[selectArrGenerated.name] = {
|
|
3784
4548
|
type: selectArrOutput,
|
|
3785
4549
|
args: selectArrGenerated.args,
|
|
@@ -3799,6 +4563,14 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3799
4563
|
...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
|
|
3800
4564
|
};
|
|
3801
4565
|
}
|
|
4566
|
+
if (groupByGenerated && groupByType) {
|
|
4567
|
+
queries[groupByGenerated.name] = {
|
|
4568
|
+
type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(groupByType))),
|
|
4569
|
+
args: groupByGenerated.args,
|
|
4570
|
+
resolve: groupByGenerated.resolver,
|
|
4571
|
+
...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
|
|
4572
|
+
};
|
|
4573
|
+
}
|
|
3802
4574
|
if (insertArrGenerated) {
|
|
3803
4575
|
mutations[insertArrGenerated.name] = {
|
|
3804
4576
|
type: arrTableItemOutput,
|
|
@@ -3834,6 +4606,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3834
4606
|
resolve: updateGenerated.resolver
|
|
3835
4607
|
};
|
|
3836
4608
|
}
|
|
4609
|
+
if (updateSingleGenerated) {
|
|
4610
|
+
mutations[updateSingleGenerated.name] = {
|
|
4611
|
+
type: singleTableItemOutput,
|
|
4612
|
+
args: updateSingleGenerated.args,
|
|
4613
|
+
resolve: updateSingleGenerated.resolver
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
3837
4616
|
if (deleteGenerated) {
|
|
3838
4617
|
mutations[deleteGenerated.name] = {
|
|
3839
4618
|
type: arrTableItemOutput,
|
|
@@ -3841,6 +4620,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3841
4620
|
resolve: deleteGenerated.resolver
|
|
3842
4621
|
};
|
|
3843
4622
|
}
|
|
4623
|
+
if (deleteSingleGenerated) {
|
|
4624
|
+
mutations[deleteSingleGenerated.name] = {
|
|
4625
|
+
type: singleTableItemOutput,
|
|
4626
|
+
args: deleteSingleGenerated.args,
|
|
4627
|
+
resolve: deleteSingleGenerated.resolver
|
|
4628
|
+
};
|
|
4629
|
+
}
|
|
3844
4630
|
const activeInputs = [
|
|
3845
4631
|
// The insert input types the upsert mutations too, so either feature keeps it.
|
|
3846
4632
|
...features.insert || onConflictInput ? [insertInput] : [],
|
|
@@ -3857,6 +4643,10 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3857
4643
|
if (aggregateType) {
|
|
3858
4644
|
outputs[aggregateType.name] = aggregateType;
|
|
3859
4645
|
}
|
|
4646
|
+
if (groupByType && havingInput) {
|
|
4647
|
+
outputs[groupByType.name] = groupByType;
|
|
4648
|
+
inputs[havingInput.name] = havingInput;
|
|
4649
|
+
}
|
|
3860
4650
|
}
|
|
3861
4651
|
const fieldResolvers = {};
|
|
3862
4652
|
for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
|
|
@@ -3899,12 +4689,14 @@ var buildSchema = (db, config) => {
|
|
|
3899
4689
|
const typeNameMapper = config?.typeNameMapper;
|
|
3900
4690
|
const features = {
|
|
3901
4691
|
aggregates: config?.features?.aggregates ?? true,
|
|
4692
|
+
groupBy: config?.features?.groupBy ?? true,
|
|
3902
4693
|
relationAggregates: config?.features?.relationAggregates ?? true,
|
|
3903
4694
|
distinct: config?.features?.distinct ?? true,
|
|
3904
4695
|
insert: config?.features?.insert ?? true,
|
|
3905
4696
|
update: config?.features?.update ?? true,
|
|
3906
4697
|
delete: config?.features?.delete ?? true,
|
|
3907
|
-
upsert: config?.features?.upsert ?? false
|
|
4698
|
+
upsert: config?.features?.upsert ?? false,
|
|
4699
|
+
requireWhere: config?.features?.requireWhere ?? false
|
|
3908
4700
|
};
|
|
3909
4701
|
const complexityConfig = config?.complexity ?? true;
|
|
3910
4702
|
const complexity = complexityConfig === false ? void 0 : {
|
|
@@ -3977,6 +4769,7 @@ export {
|
|
|
3977
4769
|
GraphQLBigIntString,
|
|
3978
4770
|
GraphQLDate,
|
|
3979
4771
|
GraphQLDateTime,
|
|
4772
|
+
GraphQLDecimalString,
|
|
3980
4773
|
GraphQLJSON,
|
|
3981
4774
|
GraphQLUUID,
|
|
3982
4775
|
buildSchema,
|