@vantreeseba/drizzle-graphql 5.1.0 → 5.2.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/dist/index.cjs CHANGED
@@ -411,6 +411,21 @@ var geoXyInputType = new import_graphql3.GraphQLInputObjectType({
411
411
  }
412
412
  });
413
413
  var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
414
+ const dimensions = column.dimensions;
415
+ if (dimensions !== void 0 && dimensions > 0) {
416
+ const inner = columnBaseToGraphQLCore(column, columnName, tableName, isInput);
417
+ const innerDesc = inner.description ?? inner.type.name;
418
+ let type = inner.type;
419
+ let description = innerDesc;
420
+ for (let i = 0; i < dimensions; i++) {
421
+ type = new import_graphql3.GraphQLList(new import_graphql3.GraphQLNonNull(type));
422
+ description = `Array<${description}>`;
423
+ }
424
+ return { type, description };
425
+ }
426
+ return columnBaseToGraphQLCore(column, columnName, tableName, isInput);
427
+ };
428
+ var columnBaseToGraphQLCore = (column, columnName, tableName, isInput) => {
414
429
  const { type: baseType, constraint } = (0, import_drizzle_orm2.extractExtendedColumnType)(column);
415
430
  switch (baseType) {
416
431
  case "boolean":
@@ -442,28 +457,10 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
442
457
  if (column instanceof import_pg_core.PgDateString) {
443
458
  return isInput ? { type: import_graphql3.GraphQLString, description: "Date" } : { type: import_graphql_scalars.GraphQLDate, description: "Date" };
444
459
  }
445
- {
446
- const dims = column.dimensions;
447
- if (dims !== void 0 && dims > 0) {
448
- return {
449
- type: new import_graphql3.GraphQLList(new import_graphql3.GraphQLNonNull(import_graphql3.GraphQLString)),
450
- description: "Array<String>"
451
- };
452
- }
453
- }
454
460
  return { type: import_graphql3.GraphQLString, description: "String" };
455
461
  case "bigint":
456
462
  return { type: GraphQLBigIntString, description: "BigInt" };
457
463
  case "number": {
458
- const dims = column.dimensions;
459
- if (dims !== void 0 && dims > 0) {
460
- const baseDesc = (0, import_drizzle_orm2.is)(column, import_pg_core.PgInteger) || (0, import_drizzle_orm2.is)(column, import_pg_core.PgSerial) ? "Integer" : "Float";
461
- const baseType2 = baseDesc === "Integer" ? import_graphql3.GraphQLInt : import_graphql3.GraphQLFloat;
462
- return {
463
- type: new import_graphql3.GraphQLList(new import_graphql3.GraphQLNonNull(baseType2)),
464
- description: `Array<${baseDesc}>`
465
- };
466
- }
467
464
  return (0, import_drizzle_orm2.is)(column, import_pg_core.PgInteger) || (0, import_drizzle_orm2.is)(column, import_pg_core.PgSerial) || (0, import_drizzle_orm2.is)(column, import_mysql_core.MySqlInt) || (0, import_drizzle_orm2.is)(column, import_mysql_core.MySqlSerial) || (0, import_drizzle_orm2.is)(column, import_sqlite_core.SQLiteInteger) ? { type: import_graphql3.GraphQLInt, description: "Integer" } : { type: import_graphql3.GraphQLFloat, description: "Float" };
468
465
  }
469
466
  case "array": {
@@ -808,52 +805,95 @@ var innerOrder = new import_graphql4.GraphQLInputObjectType({
808
805
  }
809
806
  }
810
807
  });
811
- var resolveGenericFilterName = (column, columnGraphQLType) => {
808
+ var columnDialect = (column) => {
809
+ const ct = column.columnType ?? "";
810
+ if (ct.startsWith("Pg")) {
811
+ return "pg";
812
+ }
813
+ if (ct.startsWith("MySql")) {
814
+ return "mysql";
815
+ }
816
+ if (ct.startsWith("SQLite")) {
817
+ return "sqlite";
818
+ }
819
+ return void 0;
820
+ };
821
+ var resolveGenericFilterDescriptor = (column, columnGraphQLType) => {
822
+ if (columnGraphQLType.type === import_graphql_scalars.GraphQLJSON) {
823
+ return { name: "JSON", kind: "json" };
824
+ }
825
+ if (columnGraphQLType.type instanceof import_graphql4.GraphQLList) {
826
+ let element = columnGraphQLType.type.ofType;
827
+ if (element instanceof import_graphql4.GraphQLNonNull) {
828
+ element = element.ofType;
829
+ }
830
+ return { name: `${element.name}Array`, kind: "array" };
831
+ }
812
832
  if (columnGraphQLType.type === import_graphql_scalars.GraphQLUUID) {
813
- return "Id";
833
+ return { name: "Id", kind: "scalar" };
814
834
  }
815
835
  if (columnGraphQLType.type === import_graphql4.GraphQLBoolean) {
816
- return "Boolean";
836
+ return { name: "Boolean", kind: "scalar" };
817
837
  }
818
838
  if (columnGraphQLType.type instanceof import_graphql4.GraphQLEnumType) {
819
- return columnGraphQLType.type.name;
839
+ return { name: columnGraphQLType.type.name, kind: "scalar" };
820
840
  }
821
841
  if (columnGraphQLType.type === GraphQLBigIntString) {
822
- return "BigInt";
842
+ return { name: "BigInt", kind: "scalar" };
823
843
  }
824
844
  if (columnGraphQLType.type === GraphQLDecimalString) {
825
- return "Decimal";
826
- }
827
- if (columnGraphQLType.type instanceof import_graphql4.GraphQLList) {
828
- const desc2 = columnGraphQLType.description ?? "";
829
- let inner = columnGraphQLType.type.ofType;
830
- if (inner instanceof import_graphql4.GraphQLNonNull) {
831
- inner = inner.ofType;
832
- }
833
- if (desc2.includes("Integer") || inner === import_graphql4.GraphQLInt) {
834
- return "IntArray";
835
- }
836
- if (desc2.includes("Float") || inner === import_graphql4.GraphQLFloat) {
837
- return "FloatArray";
838
- }
839
- return "StringArray";
845
+ return { name: "Decimal", kind: "scalar" };
840
846
  }
841
847
  const ct = column.columnType ?? "";
842
848
  if (ct === "PgTimestamp" || ct === "PgTimestampString" || ct === "PgDate") {
843
- return "DateTime";
849
+ return { name: "DateTime", kind: "scalar" };
844
850
  }
845
851
  if (columnGraphQLType.type === import_graphql4.GraphQLInt) {
846
- return "Int";
852
+ return { name: "Int", kind: "scalar" };
847
853
  }
848
854
  if (columnGraphQLType.type === import_graphql4.GraphQLFloat) {
849
- return "Float";
855
+ return { name: "Float", kind: "scalar" };
850
856
  }
851
- return "String";
857
+ return { name: "String", kind: "scalar" };
858
+ };
859
+ var jsonFilterFields = (column, colType) => {
860
+ const dialect = columnDialect(column);
861
+ return {
862
+ eq: { type: colType, description: "JSON equality on the whole value" },
863
+ ne: { type: colType, description: "JSON inequality on the whole value" },
864
+ ...dialect === "pg" || dialect === "mysql" ? {
865
+ contains: {
866
+ type: colType,
867
+ description: "Value structurally contains this JSON (Postgres `@>` / MySQL JSON_CONTAINS)"
868
+ }
869
+ } : {},
870
+ isNull: { type: import_graphql4.GraphQLBoolean },
871
+ isNotNull: { type: import_graphql4.GraphQLBoolean }
872
+ };
873
+ };
874
+ var arrayFilterFields = (colType, colArr, colDesc) => {
875
+ let element = colType.ofType;
876
+ if (element instanceof import_graphql4.GraphQLNonNull) {
877
+ element = element.ofType;
878
+ }
879
+ const elementList = new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(element));
880
+ return {
881
+ eq: { type: colType, description: colDesc },
882
+ ne: { type: colType, description: colDesc },
883
+ has: { type: element, description: "Array contains this element" },
884
+ hasSome: { type: elementList, description: "Array contains at least one of these elements (overlap, `&&`)" },
885
+ hasEvery: { type: elementList, description: "Array contains every one of these elements (containment, `@>`)" },
886
+ isEmpty: { type: import_graphql4.GraphQLBoolean, description: "When true, matches arrays with no elements" },
887
+ inArray: { type: colArr, description: `Array<${colDesc}>` },
888
+ notInArray: { type: colArr, description: `Array<${colDesc}>` },
889
+ isNull: { type: import_graphql4.GraphQLBoolean },
890
+ isNotNull: { type: import_graphql4.GraphQLBoolean }
891
+ };
852
892
  };
853
893
  var FILTERS_WITHOUT_STRING_OPS = /* @__PURE__ */ new Set(["Id", "Int", "Float", "BigInt", "Decimal"]);
854
894
  var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
855
895
  const columnGraphQLType = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, true);
856
- const genericName = resolveGenericFilterName(column, columnGraphQLType);
896
+ const { name: genericName, kind } = resolveGenericFilterDescriptor(column, columnGraphQLType);
857
897
  const cached = cacheCtx.genericFilterCache.get(genericName);
858
898
  if (cached) {
859
899
  return cached;
@@ -862,7 +902,7 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
862
902
  const colDesc = columnGraphQLType.description;
863
903
  const colArr = new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(colType));
864
904
  const omitStringOps = FILTERS_WITHOUT_STRING_OPS.has(genericName);
865
- const baseFields = {
905
+ const baseFields = kind === "json" ? jsonFilterFields(column, colType) : kind === "array" ? arrayFilterFields(colType, colArr, colDesc) : {
866
906
  eq: { type: colType, description: colDesc },
867
907
  ne: { type: colType, description: colDesc },
868
908
  lt: { type: colType, description: colDesc },
@@ -1435,12 +1475,28 @@ var safeLikeCondition = (column, pattern, insensitive) => {
1435
1475
  const isPg = (column.columnType ?? "").startsWith("Pg");
1436
1476
  return isPg ? import_drizzle_orm3.sql`${column} ilike ${pattern} escape ${LIKE_ESCAPE_CHAR}` : import_drizzle_orm3.sql`lower(${column}) like ${pattern.toLowerCase()} escape ${LIKE_ESCAPE_CHAR}`;
1437
1477
  };
1478
+ var isJsonColumn2 = (column) => (column.columnType ?? "").includes("Json");
1479
+ var jsonContains = (column, columnName, value) => {
1480
+ const serialized = JSON.stringify(value);
1481
+ switch (columnDialect(column)) {
1482
+ case "pg":
1483
+ return column.columnType === "PgJson" ? import_drizzle_orm3.sql`${column}::jsonb @> ${serialized}::jsonb` : import_drizzle_orm3.sql`${column} @> ${serialized}::jsonb`;
1484
+ case "mysql":
1485
+ return import_drizzle_orm3.sql`json_contains(${column}, ${serialized})`;
1486
+ default:
1487
+ throw new import_graphql4.GraphQLError(`WHERE ${columnName}: Operator 'contains' is not supported for this dialect!`);
1488
+ }
1489
+ };
1438
1490
  var extractFiltersColumn = (column, columnName, operators) => {
1439
1491
  const { OR, AND, NOT, ...restOperators } = operators;
1440
1492
  const entries = Object.entries(restOperators);
1441
1493
  const singleValueOps = { eq: import_drizzle_orm3.eq, ne: import_drizzle_orm3.ne, gt: import_drizzle_orm3.gt, gte: import_drizzle_orm3.gte, lt: import_drizzle_orm3.lt, lte: import_drizzle_orm3.lte };
1442
1494
  const stringValueOps = { like: import_drizzle_orm3.like, notLike: import_drizzle_orm3.notLike, ilike: import_drizzle_orm3.ilike, notIlike: import_drizzle_orm3.notIlike };
1443
1495
  const arrayValueOps = { inArray: import_drizzle_orm3.inArray, notInArray: import_drizzle_orm3.notInArray };
1496
+ const arrayMembershipOps = {
1497
+ hasSome: import_drizzle_orm3.arrayOverlaps,
1498
+ hasEvery: import_drizzle_orm3.arrayContains
1499
+ };
1444
1500
  const nullableOps = { isNull: import_drizzle_orm3.isNull, isNotNull: import_drizzle_orm3.isNotNull };
1445
1501
  const variants = [];
1446
1502
  for (const [operatorName, operatorValue] of entries) {
@@ -1452,6 +1508,8 @@ var extractFiltersColumn = (column, columnName, operators) => {
1452
1508
  variants.push(singleValueOps[operatorName](column, singleValue));
1453
1509
  } else if (operatorName in stringValueOps) {
1454
1510
  variants.push(stringValueOps[operatorName](column, operatorValue));
1511
+ } else if (operatorName === "contains" && isJsonColumn2(column)) {
1512
+ variants.push(jsonContains(column, columnName, operatorValue));
1455
1513
  } else if (operatorName in safeLikeOps) {
1456
1514
  const { buildPattern, insensitive } = safeLikeOps[operatorName];
1457
1515
  variants.push(safeLikeCondition(column, buildPattern(operatorValue), insensitive));
@@ -1461,6 +1519,15 @@ var extractFiltersColumn = (column, columnName, operators) => {
1461
1519
  }
1462
1520
  const arrayValue = operatorValue.map((val) => remapFromGraphQLCore(val, column, columnName));
1463
1521
  variants.push(arrayValueOps[operatorName](column, arrayValue));
1522
+ } else if (operatorName === "has") {
1523
+ variants.push((0, import_drizzle_orm3.arrayContains)(column, [operatorValue]));
1524
+ } else if (operatorName in arrayMembershipOps) {
1525
+ if (!operatorValue.length) {
1526
+ throw new import_graphql4.GraphQLError(`WHERE ${columnName}: Unable to use operator ${operatorName} with an empty array!`);
1527
+ }
1528
+ variants.push(arrayMembershipOps[operatorName](column, operatorValue));
1529
+ } else if (operatorName === "isEmpty") {
1530
+ variants.push(import_drizzle_orm3.sql`cardinality(${column}) = 0`);
1464
1531
  } else if (operatorName in nullableOps) {
1465
1532
  variants.push(nullableOps[operatorName](column));
1466
1533
  } else {