@vantreeseba/drizzle-graphql 4.2.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 +60 -4
- package/dist/README.md +60 -4
- package/dist/index.cjs +645 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -5
- package/dist/index.d.ts +92 -5
- package/dist/index.js +658 -135
- 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];
|
|
1211
1360
|
}
|
|
1212
|
-
const
|
|
1213
|
-
if (
|
|
1214
|
-
|
|
1215
|
-
|
|
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`);
|
|
1373
|
+
}
|
|
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;
|
|
1223
1405
|
}
|
|
1224
|
-
|
|
1406
|
+
const relEntry = relations?.[key];
|
|
1407
|
+
if (!relEntry || !ctx) {
|
|
1408
|
+
throw new GraphQLError3(`ORDER BY ${key}: Unknown column or relation`);
|
|
1409
|
+
}
|
|
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);
|
|
@@ -1733,6 +2058,9 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
|
|
|
1733
2058
|
const upsertSingleFieldName = mapped ? `${upsertPrefix}${capitalize(mapped.singular)}` : `${upsertPrefix}${capitalize(tableName)}${suffixes.single}`;
|
|
1734
2059
|
const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
|
|
1735
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}`;
|
|
1736
2064
|
return {
|
|
1737
2065
|
typeName,
|
|
1738
2066
|
listFieldName,
|
|
@@ -1744,9 +2072,24 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
|
|
|
1744
2072
|
upsertArrayFieldName,
|
|
1745
2073
|
upsertSingleFieldName,
|
|
1746
2074
|
updateFieldName,
|
|
1747
|
-
|
|
2075
|
+
updateSingleFieldName,
|
|
2076
|
+
deleteFieldName,
|
|
2077
|
+
deleteSingleFieldName
|
|
1748
2078
|
};
|
|
1749
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
|
+
};
|
|
1750
2093
|
var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
|
|
1751
2094
|
offset: { type: GraphQLInt2 },
|
|
1752
2095
|
limit: { type: GraphQLInt2 },
|
|
@@ -1805,9 +2148,9 @@ var runRelationalSelect = async (opts) => {
|
|
|
1805
2148
|
// drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
|
|
1806
2149
|
// directly so column refs match the CTE alias.
|
|
1807
2150
|
orderBy: distinctKeys ? (aliasedTable2) => [
|
|
1808
|
-
...orderBy ? extractOrderBy(aliasedTable2, orderBy) : [],
|
|
2151
|
+
...orderBy ? extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : [],
|
|
1809
2152
|
...primaryKeyOrderExprs(aliasedTable2, pkNames)
|
|
1810
|
-
] : 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,
|
|
1811
2154
|
where: distinctKeys ? { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) } : where ? {
|
|
1812
2155
|
RAW: (aliasedTable2) => extractFilters(aliasedTable2, tableName, where, relationFilterCtx(filterCtx, tableName))
|
|
1813
2156
|
} : void 0,
|
|
@@ -1922,7 +2265,7 @@ import {
|
|
|
1922
2265
|
} from "drizzle-orm";
|
|
1923
2266
|
import {
|
|
1924
2267
|
GraphQLError as GraphQLError4,
|
|
1925
|
-
GraphQLFloat as
|
|
2268
|
+
GraphQLFloat as GraphQLFloat3,
|
|
1926
2269
|
GraphQLInputObjectType as GraphQLInputObjectType3,
|
|
1927
2270
|
GraphQLInt as GraphQLInt3,
|
|
1928
2271
|
GraphQLList as GraphQLList3,
|
|
@@ -1980,7 +2323,7 @@ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
|
|
|
1980
2323
|
fields[op] = {
|
|
1981
2324
|
type: new GraphQLObjectType3({
|
|
1982
2325
|
name: `${typeName}${capitalize(op)}Aggregate`,
|
|
1983
|
-
fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type:
|
|
2326
|
+
fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type: GraphQLFloat3 }]))
|
|
1984
2327
|
})
|
|
1985
2328
|
};
|
|
1986
2329
|
}
|
|
@@ -2216,7 +2559,7 @@ var generateGroupByEnum = (table, tableName, typeName) => {
|
|
|
2216
2559
|
var aggregateNumberFilter = new GraphQLInputObjectType3({
|
|
2217
2560
|
name: "AggregateNumberFilter",
|
|
2218
2561
|
description: "Compares an aggregated value. Several operators in one filter are ANDed together.",
|
|
2219
|
-
fields: Object.fromEntries(Object.keys(HAVING_OPS).map((op) => [op, { type:
|
|
2562
|
+
fields: Object.fromEntries(Object.keys(HAVING_OPS).map((op) => [op, { type: GraphQLFloat3 }]))
|
|
2220
2563
|
});
|
|
2221
2564
|
var generateHavingInput = (table, tableName, typeName) => {
|
|
2222
2565
|
const { numeric, orderable, all } = classifyAggregateColumns(table, tableName);
|
|
@@ -2529,13 +2872,13 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
|
|
|
2529
2872
|
args: queryArgs
|
|
2530
2873
|
};
|
|
2531
2874
|
};
|
|
2532
|
-
var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filterCtx) => {
|
|
2875
|
+
var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, single, requireWhere, filterCtx) => {
|
|
2533
2876
|
const queryArgs = {
|
|
2534
2877
|
set: {
|
|
2535
2878
|
type: new GraphQLNonNull4(setArgs)
|
|
2536
2879
|
},
|
|
2537
2880
|
where: {
|
|
2538
|
-
type: filterArgs
|
|
2881
|
+
type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
|
|
2539
2882
|
}
|
|
2540
2883
|
};
|
|
2541
2884
|
return {
|
|
@@ -2547,10 +2890,14 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
|
|
|
2547
2890
|
if (!Object.keys(input).length) {
|
|
2548
2891
|
throw new GraphQLError5("Unable to update with no values specified!");
|
|
2549
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;
|
|
2550
2895
|
const executor = resolveExecutor(db, context);
|
|
2896
|
+
if (single) {
|
|
2897
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
2898
|
+
}
|
|
2551
2899
|
let query = executor.update(table).set(input);
|
|
2552
|
-
if (
|
|
2553
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
2900
|
+
if (filters) {
|
|
2554
2901
|
query = query.where(filters);
|
|
2555
2902
|
}
|
|
2556
2903
|
await query;
|
|
@@ -2562,10 +2909,10 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
|
|
|
2562
2909
|
args: queryArgs
|
|
2563
2910
|
};
|
|
2564
2911
|
};
|
|
2565
|
-
var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) => {
|
|
2912
|
+
var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx) => {
|
|
2566
2913
|
const queryArgs = {
|
|
2567
2914
|
where: {
|
|
2568
|
-
type: filterArgs
|
|
2915
|
+
type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
|
|
2569
2916
|
}
|
|
2570
2917
|
};
|
|
2571
2918
|
return {
|
|
@@ -2573,10 +2920,14 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) =>
|
|
|
2573
2920
|
resolver: async (_source, args, context, _info) => {
|
|
2574
2921
|
try {
|
|
2575
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;
|
|
2576
2925
|
const executor = resolveExecutor(db, context);
|
|
2926
|
+
if (single) {
|
|
2927
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
2928
|
+
}
|
|
2577
2929
|
let query = executor.delete(table);
|
|
2578
|
-
if (
|
|
2579
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
2930
|
+
if (filters) {
|
|
2580
2931
|
query = query.where(filters);
|
|
2581
2932
|
}
|
|
2582
2933
|
await query;
|
|
@@ -2665,7 +3016,9 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2665
3016
|
upsertArrayFieldName,
|
|
2666
3017
|
upsertSingleFieldName,
|
|
2667
3018
|
updateFieldName,
|
|
2668
|
-
|
|
3019
|
+
updateSingleFieldName,
|
|
3020
|
+
deleteFieldName,
|
|
3021
|
+
deleteSingleFieldName
|
|
2669
3022
|
} = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
|
|
2670
3023
|
const selectArrGenerated = generateSelectArray(
|
|
2671
3024
|
db,
|
|
@@ -2710,9 +3063,41 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2710
3063
|
updateInput,
|
|
2711
3064
|
tableFilters,
|
|
2712
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,
|
|
2713
3099
|
filterCtx
|
|
2714
3100
|
) : void 0;
|
|
2715
|
-
const deleteGenerated = features.delete ? generateDelete(db, tableName, schema[tableName], tableFilters, deleteFieldName, filterCtx) : void 0;
|
|
2716
3101
|
const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
|
|
2717
3102
|
const aggregateGenerated = features.aggregates ? generateAggregate(
|
|
2718
3103
|
db,
|
|
@@ -2770,7 +3155,9 @@ var generateSchemaData = (db, schema, relations, options) => {
|
|
|
2770
3155
|
upsertArrGenerated,
|
|
2771
3156
|
upsertSingleGenerated,
|
|
2772
3157
|
updateGenerated,
|
|
2773
|
-
|
|
3158
|
+
updateSingleGenerated,
|
|
3159
|
+
deleteGenerated,
|
|
3160
|
+
deleteSingleGenerated
|
|
2774
3161
|
]) {
|
|
2775
3162
|
if (generated) {
|
|
2776
3163
|
mutations[generated.name] = {
|
|
@@ -2890,7 +3277,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
|
|
|
2890
3277
|
}
|
|
2891
3278
|
if (orderBy) {
|
|
2892
3279
|
q = q.orderBy(
|
|
2893
|
-
...extractOrderBy(table, orderBy),
|
|
3280
|
+
...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)),
|
|
2894
3281
|
...distinctKeys ? primaryKeyOrderExprs(table, pkNames) : []
|
|
2895
3282
|
);
|
|
2896
3283
|
} else if ((distinctKeys || offset != null || limit != null) && pkNames.length) {
|
|
@@ -2951,7 +3338,7 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
|
|
|
2951
3338
|
q = q.where(extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)));
|
|
2952
3339
|
}
|
|
2953
3340
|
if (orderBy) {
|
|
2954
|
-
q = q.orderBy(...extractOrderBy(table, orderBy));
|
|
3341
|
+
q = q.orderBy(...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)));
|
|
2955
3342
|
} else if (pkNames.length) {
|
|
2956
3343
|
q = q.orderBy(...primaryKeyOrderExprs(table, pkNames));
|
|
2957
3344
|
}
|
|
@@ -3111,13 +3498,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
|
|
|
3111
3498
|
args: queryArgs
|
|
3112
3499
|
};
|
|
3113
3500
|
};
|
|
3114
|
-
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) => {
|
|
3115
3502
|
const queryArgs = {
|
|
3116
3503
|
set: {
|
|
3117
3504
|
type: new GraphQLNonNull5(setArgs)
|
|
3118
3505
|
},
|
|
3119
3506
|
where: {
|
|
3120
|
-
type: filterArgs
|
|
3507
|
+
type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
|
|
3121
3508
|
}
|
|
3122
3509
|
};
|
|
3123
3510
|
const pkNames = pgPrimaryKeyPropNames(table);
|
|
@@ -3143,16 +3530,26 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
3143
3530
|
if (!Object.keys(input).length) {
|
|
3144
3531
|
throw new GraphQLError6("Unable to update with no values specified!");
|
|
3145
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;
|
|
3146
3535
|
const executor = resolveExecutor(db, context);
|
|
3536
|
+
if (single) {
|
|
3537
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
3538
|
+
}
|
|
3147
3539
|
let query = executor.update(table).set(input);
|
|
3148
|
-
if (
|
|
3149
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
3540
|
+
if (filters) {
|
|
3150
3541
|
query = query.where(filters);
|
|
3151
3542
|
}
|
|
3152
3543
|
query = query.returning(columns);
|
|
3153
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
|
+
}
|
|
3154
3551
|
const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
|
|
3155
|
-
return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
3552
|
+
return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
3156
3553
|
} catch (e) {
|
|
3157
3554
|
throw toGraphQLError(e);
|
|
3158
3555
|
}
|
|
@@ -3160,10 +3557,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
3160
3557
|
args: queryArgs
|
|
3161
3558
|
};
|
|
3162
3559
|
};
|
|
3163
|
-
var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
|
|
3560
|
+
var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
|
|
3164
3561
|
const queryArgs = {
|
|
3165
3562
|
where: {
|
|
3166
|
-
type: filterArgs
|
|
3563
|
+
type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
|
|
3167
3564
|
}
|
|
3168
3565
|
};
|
|
3169
3566
|
return {
|
|
@@ -3179,14 +3576,24 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, fi
|
|
|
3179
3576
|
table,
|
|
3180
3577
|
selectionCtx
|
|
3181
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;
|
|
3182
3581
|
const executor = resolveExecutor(db, context);
|
|
3582
|
+
if (single) {
|
|
3583
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
3584
|
+
}
|
|
3183
3585
|
let query = executor.delete(table);
|
|
3184
|
-
if (
|
|
3185
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
3586
|
+
if (filters) {
|
|
3186
3587
|
query = query.where(filters);
|
|
3187
3588
|
}
|
|
3188
3589
|
query = query.returning(columns);
|
|
3189
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
|
+
}
|
|
3190
3597
|
return remapToGraphQLArrayOutput(result, tableName, table);
|
|
3191
3598
|
} catch (e) {
|
|
3192
3599
|
throw toGraphQLError(e);
|
|
@@ -3268,7 +3675,9 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3268
3675
|
upsertArrayFieldName,
|
|
3269
3676
|
upsertSingleFieldName,
|
|
3270
3677
|
updateFieldName,
|
|
3271
|
-
|
|
3678
|
+
updateSingleFieldName,
|
|
3679
|
+
deleteFieldName,
|
|
3680
|
+
deleteSingleFieldName
|
|
3272
3681
|
} = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
|
|
3273
3682
|
const selectArrGenerated = generateSelectArray2(
|
|
3274
3683
|
db,
|
|
@@ -3367,6 +3776,23 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3367
3776
|
tableFilters,
|
|
3368
3777
|
updateFieldName,
|
|
3369
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,
|
|
3370
3796
|
typeNameMapper,
|
|
3371
3797
|
filterCtx
|
|
3372
3798
|
) : void 0;
|
|
@@ -3377,6 +3803,20 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3377
3803
|
tableFilters,
|
|
3378
3804
|
deleteFieldName,
|
|
3379
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,
|
|
3380
3820
|
filterCtx,
|
|
3381
3821
|
{ tableName, relationMap: namedRelations, tables }
|
|
3382
3822
|
) : void 0;
|
|
@@ -3466,6 +3906,13 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3466
3906
|
resolve: updateGenerated.resolver
|
|
3467
3907
|
};
|
|
3468
3908
|
}
|
|
3909
|
+
if (updateSingleGenerated) {
|
|
3910
|
+
mutations[updateSingleGenerated.name] = {
|
|
3911
|
+
type: singleTableItemOutput,
|
|
3912
|
+
args: updateSingleGenerated.args,
|
|
3913
|
+
resolve: updateSingleGenerated.resolver
|
|
3914
|
+
};
|
|
3915
|
+
}
|
|
3469
3916
|
if (deleteGenerated) {
|
|
3470
3917
|
mutations[deleteGenerated.name] = {
|
|
3471
3918
|
type: arrTableItemOutput,
|
|
@@ -3473,6 +3920,13 @@ function generateSchemaData2(db, schema, relations, options) {
|
|
|
3473
3920
|
resolve: deleteGenerated.resolver
|
|
3474
3921
|
};
|
|
3475
3922
|
}
|
|
3923
|
+
if (deleteSingleGenerated) {
|
|
3924
|
+
mutations[deleteSingleGenerated.name] = {
|
|
3925
|
+
type: singleTableItemOutput,
|
|
3926
|
+
args: deleteSingleGenerated.args,
|
|
3927
|
+
resolve: deleteSingleGenerated.resolver
|
|
3928
|
+
};
|
|
3929
|
+
}
|
|
3476
3930
|
const activeInputs = [
|
|
3477
3931
|
// The insert input types the upsert mutations too, so either feature keeps it.
|
|
3478
3932
|
...features.insert || onConflictInput ? [insertInput] : [],
|
|
@@ -3743,13 +4197,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
|
|
|
3743
4197
|
args: queryArgs
|
|
3744
4198
|
};
|
|
3745
4199
|
};
|
|
3746
|
-
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) => {
|
|
3747
4201
|
const queryArgs = {
|
|
3748
4202
|
set: {
|
|
3749
4203
|
type: new GraphQLNonNull6(setArgs)
|
|
3750
4204
|
},
|
|
3751
4205
|
where: {
|
|
3752
|
-
type: filterArgs
|
|
4206
|
+
type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
|
|
3753
4207
|
}
|
|
3754
4208
|
};
|
|
3755
4209
|
const pkNames = sqlitePrimaryKeyPropNames(table);
|
|
@@ -3775,16 +4229,26 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
3775
4229
|
if (!Object.keys(input).length) {
|
|
3776
4230
|
throw new GraphQLError7("Unable to update with no values specified!");
|
|
3777
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;
|
|
3778
4234
|
const executor = resolveExecutor(db, context);
|
|
4235
|
+
if (single) {
|
|
4236
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
4237
|
+
}
|
|
3779
4238
|
let query = executor.update(table).set(input);
|
|
3780
|
-
if (
|
|
3781
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
4239
|
+
if (filters) {
|
|
3782
4240
|
query = query.where(filters);
|
|
3783
4241
|
}
|
|
3784
4242
|
query = query.returning(columns);
|
|
3785
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
|
+
}
|
|
3786
4250
|
const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
|
|
3787
|
-
return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
4251
|
+
return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
3788
4252
|
} catch (e) {
|
|
3789
4253
|
throw toGraphQLError(e);
|
|
3790
4254
|
}
|
|
@@ -3792,10 +4256,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
|
|
|
3792
4256
|
args: queryArgs
|
|
3793
4257
|
};
|
|
3794
4258
|
};
|
|
3795
|
-
var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
|
|
4259
|
+
var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
|
|
3796
4260
|
const queryArgs = {
|
|
3797
4261
|
where: {
|
|
3798
|
-
type: filterArgs
|
|
4262
|
+
type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
|
|
3799
4263
|
}
|
|
3800
4264
|
};
|
|
3801
4265
|
return {
|
|
@@ -3811,14 +4275,24 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, fi
|
|
|
3811
4275
|
table,
|
|
3812
4276
|
selectionCtx
|
|
3813
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;
|
|
3814
4280
|
const executor = resolveExecutor(db, context);
|
|
4281
|
+
if (single) {
|
|
4282
|
+
await assertSingleMatch(executor, table, filters, fieldName);
|
|
4283
|
+
}
|
|
3815
4284
|
let query = executor.delete(table);
|
|
3816
|
-
if (
|
|
3817
|
-
const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
|
|
4285
|
+
if (filters) {
|
|
3818
4286
|
query = query.where(filters);
|
|
3819
4287
|
}
|
|
3820
4288
|
query = query.returning(columns);
|
|
3821
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
|
+
}
|
|
3822
4296
|
return remapToGraphQLArrayOutput(result, tableName, table);
|
|
3823
4297
|
} catch (e) {
|
|
3824
4298
|
throw toGraphQLError(e);
|
|
@@ -3901,7 +4375,9 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
3901
4375
|
upsertArrayFieldName,
|
|
3902
4376
|
upsertSingleFieldName,
|
|
3903
4377
|
updateFieldName,
|
|
3904
|
-
|
|
4378
|
+
updateSingleFieldName,
|
|
4379
|
+
deleteFieldName,
|
|
4380
|
+
deleteSingleFieldName
|
|
3905
4381
|
} = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
|
|
3906
4382
|
const selectArrGenerated = generateSelectArray3(
|
|
3907
4383
|
db,
|
|
@@ -4000,6 +4476,23 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
4000
4476
|
tableFilters,
|
|
4001
4477
|
updateFieldName,
|
|
4002
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,
|
|
4003
4496
|
typeNameMapper,
|
|
4004
4497
|
filterCtx
|
|
4005
4498
|
) : void 0;
|
|
@@ -4010,6 +4503,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
4010
4503
|
tableFilters,
|
|
4011
4504
|
deleteFieldName,
|
|
4012
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,
|
|
4013
4520
|
filterCtx,
|
|
4014
4521
|
{ tableName, relationMap: namedRelations, tables }
|
|
4015
4522
|
) : void 0;
|
|
@@ -4099,6 +4606,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
4099
4606
|
resolve: updateGenerated.resolver
|
|
4100
4607
|
};
|
|
4101
4608
|
}
|
|
4609
|
+
if (updateSingleGenerated) {
|
|
4610
|
+
mutations[updateSingleGenerated.name] = {
|
|
4611
|
+
type: singleTableItemOutput,
|
|
4612
|
+
args: updateSingleGenerated.args,
|
|
4613
|
+
resolve: updateSingleGenerated.resolver
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
4102
4616
|
if (deleteGenerated) {
|
|
4103
4617
|
mutations[deleteGenerated.name] = {
|
|
4104
4618
|
type: arrTableItemOutput,
|
|
@@ -4106,6 +4620,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
|
|
|
4106
4620
|
resolve: deleteGenerated.resolver
|
|
4107
4621
|
};
|
|
4108
4622
|
}
|
|
4623
|
+
if (deleteSingleGenerated) {
|
|
4624
|
+
mutations[deleteSingleGenerated.name] = {
|
|
4625
|
+
type: singleTableItemOutput,
|
|
4626
|
+
args: deleteSingleGenerated.args,
|
|
4627
|
+
resolve: deleteSingleGenerated.resolver
|
|
4628
|
+
};
|
|
4629
|
+
}
|
|
4109
4630
|
const activeInputs = [
|
|
4110
4631
|
// The insert input types the upsert mutations too, so either feature keeps it.
|
|
4111
4632
|
...features.insert || onConflictInput ? [insertInput] : [],
|
|
@@ -4174,7 +4695,8 @@ var buildSchema = (db, config) => {
|
|
|
4174
4695
|
insert: config?.features?.insert ?? true,
|
|
4175
4696
|
update: config?.features?.update ?? true,
|
|
4176
4697
|
delete: config?.features?.delete ?? true,
|
|
4177
|
-
upsert: config?.features?.upsert ?? false
|
|
4698
|
+
upsert: config?.features?.upsert ?? false,
|
|
4699
|
+
requireWhere: config?.features?.requireWhere ?? false
|
|
4178
4700
|
};
|
|
4179
4701
|
const complexityConfig = config?.complexity ?? true;
|
|
4180
4702
|
const complexity = complexityConfig === false ? void 0 : {
|
|
@@ -4247,6 +4769,7 @@ export {
|
|
|
4247
4769
|
GraphQLBigIntString,
|
|
4248
4770
|
GraphQLDate,
|
|
4249
4771
|
GraphQLDateTime,
|
|
4772
|
+
GraphQLDecimalString,
|
|
4250
4773
|
GraphQLJSON,
|
|
4251
4774
|
GraphQLUUID,
|
|
4252
4775
|
buildSchema,
|