@vantreeseba/drizzle-graphql 10.0.0 → 10.0.1

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
@@ -26,9 +26,9 @@ let drizzle_orm_mysql_core = require("drizzle-orm/mysql-core");
26
26
  let drizzle_orm_pg_core = require("drizzle-orm/pg-core");
27
27
  let drizzle_orm_sqlite_core = require("drizzle-orm/sqlite-core");
28
28
  let graphql = require("graphql");
29
+ let graphql_scalars = require("graphql-scalars");
29
30
  let pluralize = require("pluralize");
30
31
  pluralize = __toESM(pluralize, 1);
31
- let graphql_scalars = require("graphql-scalars");
32
32
  //#region src/util/builders/common/errors.ts
33
33
  /**
34
34
  * A `GraphQLError` carrying its context as data. The message says what went wrong, in prose
@@ -115,28 +115,6 @@ const applyErrorMapper = (entities, mapError) => {
115
115
  for (const tableResolvers of Object.values(entities.fieldResolvers ?? {})) for (const [relationName, resolve] of Object.entries(tableResolvers)) tableResolvers[relationName] = wrap(resolve);
116
116
  };
117
117
  //#endregion
118
- //#region src/util/case-ops/index.ts
119
- const uncapitalize = (input) => input?.length ? `${input[0].toLocaleLowerCase()}${input.length > 1 ? input.slice(1, input.length) : ""}` : input;
120
- const capitalize = (input) => input?.length ? `${input[0].toLocaleUpperCase()}${input.length > 1 ? input.slice(1, input.length) : ""}` : input;
121
- /**
122
- * The `typeNameMapper` preset behind `typeNameMapper: 'singularize'`.
123
- *
124
- * Derives the singular and plural forms of a table key with the library's own `pluralize`,
125
- * which is what nearly every consumer with plural table keys (`export const tasks =
126
- * pgTable('tasks', …)`) was writing by hand — and adding `pluralize` to their own
127
- * dependencies to write.
128
- *
129
- * `tasks` becomes type `Task`, queries `tasks` / `task`, mutations `createTasks` /
130
- * `createTask`. A key that is already singular is pluralized for the list side, so `task`
131
- * yields the same names, and a capitalized key (`Tasks`) yields them too — the field forms
132
- * are uncapitalized so the generated names follow GraphQL's camelCase convention whatever
133
- * the schema key looks like. The type name is capitalized by the generator either way.
134
- */
135
- const singularizeMapper = (tableName) => ({
136
- singular: uncapitalize(pluralize.default.singular(tableName)),
137
- plural: uncapitalize(pluralize.default.plural(tableName))
138
- });
139
- //#endregion
140
118
  //#region src/util/scalars/index.ts
141
119
  const INVALID_INPUT = "DRIZZLE_INVALID_INPUT_VALUE";
142
120
  const UNREPRESENTABLE = "DRIZZLE_UNREPRESENTABLE_VALUE";
@@ -207,6 +185,28 @@ const GraphQLDecimalString = new graphql.GraphQLScalarType({
207
185
  }
208
186
  });
209
187
  //#endregion
188
+ //#region src/util/case-ops/index.ts
189
+ const uncapitalize = (input) => input?.length ? `${input[0].toLocaleLowerCase()}${input.length > 1 ? input.slice(1, input.length) : ""}` : input;
190
+ const capitalize = (input) => input?.length ? `${input[0].toLocaleUpperCase()}${input.length > 1 ? input.slice(1, input.length) : ""}` : input;
191
+ /**
192
+ * The `typeNameMapper` preset behind `typeNameMapper: 'singularize'`.
193
+ *
194
+ * Derives the singular and plural forms of a table key with the library's own `pluralize`,
195
+ * which is what nearly every consumer with plural table keys (`export const tasks =
196
+ * pgTable('tasks', …)`) was writing by hand — and adding `pluralize` to their own
197
+ * dependencies to write.
198
+ *
199
+ * `tasks` becomes type `Task`, queries `tasks` / `task`, mutations `createTasks` /
200
+ * `createTask`. A key that is already singular is pluralized for the list side, so `task`
201
+ * yields the same names, and a capitalized key (`Tasks`) yields them too — the field forms
202
+ * are uncapitalized so the generated names follow GraphQL's camelCase convention whatever
203
+ * the schema key looks like. The type name is capitalized by the generator either way.
204
+ */
205
+ const singularizeMapper = (tableName) => ({
206
+ singular: uncapitalize(pluralize.default.singular(tableName)),
207
+ plural: uncapitalize(pluralize.default.plural(tableName))
208
+ });
209
+ //#endregion
210
210
  //#region src/util/type-converter/index.ts
211
211
  const allowedNameChars = /^[a-zA-Z0-9_]+$/;
212
212
  /**
@@ -436,7 +436,7 @@ const normalizeScalarOverride = (override, tableName, columnName) => {
436
436
  * leaves the column on built-in detection.
437
437
  */
438
438
  const registerScalarOverrides = (tables, config) => {
439
- for (const [tableName, table] of Object.entries(tables)) for (const [columnName, column] of Object.entries((0, drizzle_orm.getTableColumns)(table))) {
439
+ for (const [tableName, table] of Object.entries(tables)) for (const [columnName, column] of Object.entries((0, drizzle_orm.getColumns)(table))) {
440
440
  const declared = config.scalars?.[tableName]?.[columnName];
441
441
  let resolved;
442
442
  if (declared !== void 0) resolved = normalizeScalarOverride(declared, tableName, columnName);
@@ -475,137 +475,6 @@ const drizzleColumnToGraphQLType = (column, columnName, tableName, forceNullable
475
475
  return typeDesc;
476
476
  };
477
477
  //#endregion
478
- //#region src/util/data-mappers/index.ts
479
- const isJsonColumn$1 = (column) => (column.dataType ?? "").includes("json") && column.columnType !== "PgGeometryObject";
480
- const remapToGraphQLCore = (key, value, tableName, column, relationMap) => {
481
- if (Array.isArray(value)) {
482
- const relations = relationMap?.[tableName];
483
- if (relations?.[key]) {
484
- const rel = relations[key];
485
- return remapToGraphQLArrayOutput(value, rel.targetTableName, rel.relation?.targetTable ?? rel.relation?.referencedTable, relationMap);
486
- }
487
- }
488
- if (typeof value === "object" && value !== null) {
489
- const relations = relationMap?.[tableName];
490
- if (relations?.[key]) {
491
- const rel = relations[key];
492
- return remapToGraphQLSingleOutput(value, rel.targetTableName, rel.relation?.targetTable ?? rel.relation?.referencedTable, relationMap);
493
- }
494
- }
495
- if (!column) return value;
496
- if (getColumnScalarOverride(column, false)) return value;
497
- if (isJsonColumn$1(column)) return value;
498
- if (value instanceof Date) return value.toISOString();
499
- if (value instanceof Buffer) return Array.from(value);
500
- if (typeof value === "bigint") return value.toString();
501
- if (Array.isArray(value)) {
502
- if (column.columnType === "PgGeometry" || column.columnType === "PgVector") return value;
503
- return value.map((arrVal) => remapToGraphQLCore(key, arrVal, tableName, column, relationMap));
504
- }
505
- if (typeof value === "object" && value !== null) {
506
- if (column.columnType === "PgGeometryObject") return value;
507
- return JSON.stringify(value);
508
- }
509
- return value;
510
- };
511
- const remapToGraphQLSingleOutput = (queryOutput, tableName, table, relationMap) => {
512
- const columns = (0, drizzle_orm.getTableColumns)(table);
513
- for (const [key, value] of Object.entries(queryOutput)) {
514
- if (value === void 0 || value === null) {
515
- const relEntry = value === null ? relationMap?.[tableName]?.[key] : void 0;
516
- if (relEntry && (0, drizzle_orm.is)(relEntry.relation, drizzle_orm.One)) {
517
- queryOutput[key] = null;
518
- continue;
519
- }
520
- delete queryOutput[key];
521
- continue;
522
- }
523
- const column = columns[key];
524
- if (value === 0n && column && column.columnType === "SQLiteBigInt" && !column.notNull) {
525
- delete queryOutput[key];
526
- continue;
527
- }
528
- queryOutput[key] = remapToGraphQLCore(key, value, tableName, column, relationMap);
529
- }
530
- return queryOutput;
531
- };
532
- const remapToGraphQLArrayOutput = (queryOutput, tableName, table, relationMap) => {
533
- for (const entry of queryOutput) remapToGraphQLSingleOutput(entry, tableName, table, relationMap);
534
- return queryOutput;
535
- };
536
- const remapFromGraphQLCore = (value, column, columnName) => {
537
- if (getColumnScalarOverride(column, true)) {
538
- if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) return Object.assign({}, value);
539
- return value;
540
- }
541
- const dataType = column.dataType ?? "";
542
- const columnType = column.columnType ?? "";
543
- if (columnType === "SQLiteTimestamp" || columnType === "SQLiteTimestampMs" || columnType === "MySqlTimestamp" || columnType === "MySqlDateTime" || columnType === "PgTimestamp" || columnType === "PgTimestampString") {
544
- const formatted = new Date(value);
545
- if (Number.isNaN(formatted.getTime())) throw drizzleError(`Field '${columnName}' is not a valid date!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
546
- return formatted;
547
- }
548
- if ((columnType === "MySqlDate" || columnType === "PgDate") && typeof value === "string") {
549
- const dateOnly = value.includes("T") ? value.split("T")[0] : value;
550
- const check = new Date(dateOnly);
551
- if (Number.isNaN(check.getTime())) throw drizzleError(`Field '${columnName}' is not a valid date!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
552
- return dateOnly;
553
- }
554
- if (dataType.includes("bigint")) try {
555
- return BigInt(value);
556
- } catch {
557
- throw drizzleError(`Field '${columnName}' is not a BigInt!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
558
- }
559
- if (dataType.includes("json") && column.columnType !== "PgGeometryObject") return value;
560
- switch (dataType) {
561
- case "date": {
562
- const formatted = new Date(value);
563
- if (Number.isNaN(formatted.getTime())) throw drizzleError(`Field '${columnName}' is not a valid date!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
564
- return formatted;
565
- }
566
- case "buffer":
567
- if (!Array.isArray(value)) throw drizzleError(`Field '${columnName}' is not an array!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
568
- return Buffer.from(value);
569
- case "json":
570
- if (column.columnType === "PgGeometryObject") return value;
571
- try {
572
- return JSON.parse(value);
573
- } catch (e) {
574
- throw drizzleError(`Invalid JSON in field '${columnName}':\n${e instanceof Error ? e.message : "Unknown error"}`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
575
- }
576
- case "array":
577
- if (!Array.isArray(value)) throw drizzleError(`Field '${columnName}' is not an array!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
578
- if (column.columnType === "PgGeometry" && value.length !== 2) throw drizzleError(`Invalid float tuple in field '${columnName}': expected array with length of 2, received ${value.length}`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
579
- return value;
580
- case "bigint": try {
581
- return BigInt(value);
582
- } catch (_error) {
583
- throw drizzleError(`Field '${columnName}' is not a BigInt!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
584
- }
585
- default:
586
- if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) return Object.assign({}, value);
587
- return value;
588
- }
589
- };
590
- const remapFromGraphQLSingleInput = (queryInput, table, operation = "insert") => {
591
- for (const [key, value] of Object.entries(queryInput)) if (value === void 0) delete queryInput[key];
592
- else {
593
- const column = (0, drizzle_orm.getTableColumns)(table)[key];
594
- if (!column) throw drizzleError(`Unknown column: ${key}`, { code: "DRIZZLE_UNKNOWN_COLUMN" });
595
- if (value === null && column.notNull) {
596
- if (operation === "update") throw drizzleError(`Column '${key}' cannot be set to null.`, { code: "DRIZZLE_NOT_NULL" });
597
- delete queryInput[key];
598
- continue;
599
- }
600
- queryInput[key] = remapFromGraphQLCore(value, column, key);
601
- }
602
- return queryInput;
603
- };
604
- const remapFromGraphQLArrayInput = (queryInput, table, operation = "insert") => {
605
- for (const entry of queryInput) remapFromGraphQLSingleInput(entry, table, operation);
606
- return queryInput;
607
- };
608
- //#endregion
609
478
  //#region src/util/builders/common/type-names.ts
610
479
  /**
611
480
  * The build's naming rule: the mapper's answer where it has one, otherwise the default name
@@ -648,6 +517,23 @@ const columnDialect = (column) => {
648
517
  if (ct.startsWith("SQLite")) return "sqlite";
649
518
  };
650
519
  /**
520
+ * Whether the column stores JSON.
521
+ *
522
+ * Decided on drizzle's `dataType`, its semantic marker, rather than on `columnType`, which
523
+ * names the implementing class. drizzle-orm v1 uses compound dataType strings (`"object
524
+ * json"` for every json/jsonb column across the three dialects), hence the inclusion test.
525
+ *
526
+ * `PgGeometryObject` is excluded explicitly. That is currently redundant — it reports
527
+ * `"object geometry"` — but it is stored as json, has its own object type in the generated
528
+ * schema, and must not be reclassified if drizzle ever spells its dataType differently.
529
+ *
530
+ * One predicate for two callers that must agree: the filter builder, whose `path` and
531
+ * `contains` operators mean structural JSON containment rather than the string operators,
532
+ * and the data mappers, which transport a JSON value as-is instead of remapping it. They
533
+ * previously had a copy each, asking different questions of the column.
534
+ */
535
+ const isJsonColumn = (column) => (column.dataType ?? "").includes("json") && column.columnType !== "PgGeometryObject";
536
+ /**
651
537
  * Maps a Drizzle column to the generic filter type to use.
652
538
  *
653
539
  * Selection is keyed on the column's data type, never its name: a text column named
@@ -1078,6 +964,137 @@ const generateColumnFilterValues = (column, tableName, columnName, cacheCtx) =>
1078
964
  return mainType;
1079
965
  };
1080
966
  //#endregion
967
+ //#region src/util/data-mappers/index.ts
968
+ const remapToGraphQLCore = (key, value, tableName, column, relationMap) => {
969
+ if (Array.isArray(value)) {
970
+ const relations = relationMap?.[tableName];
971
+ if (relations?.[key]) {
972
+ const rel = relations[key];
973
+ return remapToGraphQLArrayOutput(value, rel.targetTableName, rel.relation?.targetTable ?? rel.relation?.referencedTable, relationMap);
974
+ }
975
+ }
976
+ if (typeof value === "object" && value !== null) {
977
+ const relations = relationMap?.[tableName];
978
+ if (relations?.[key]) {
979
+ const rel = relations[key];
980
+ return remapToGraphQLSingleOutput(value, rel.targetTableName, rel.relation?.targetTable ?? rel.relation?.referencedTable, relationMap);
981
+ }
982
+ }
983
+ if (!column) return value;
984
+ if (getColumnScalarOverride(column, false)) return value;
985
+ if (isJsonColumn(column)) return value;
986
+ if (value instanceof Date) return value.toISOString();
987
+ if (value instanceof Buffer) return Array.from(value);
988
+ if (typeof value === "bigint") return value.toString();
989
+ if (Array.isArray(value)) {
990
+ if (column.columnType === "PgGeometry" || column.columnType === "PgVector") return value;
991
+ return value.map((arrVal) => remapToGraphQLCore(key, arrVal, tableName, column, relationMap));
992
+ }
993
+ if (typeof value === "object" && value !== null) {
994
+ if (column.columnType === "PgGeometryObject") return value;
995
+ return JSON.stringify(value);
996
+ }
997
+ return value;
998
+ };
999
+ const remapToGraphQLSingleOutput = (queryOutput, tableName, table, relationMap) => {
1000
+ const columns = (0, drizzle_orm.getColumns)(table);
1001
+ for (const [key, value] of Object.entries(queryOutput)) {
1002
+ if (value === void 0 || value === null) {
1003
+ const relEntry = value === null ? relationMap?.[tableName]?.[key] : void 0;
1004
+ if (relEntry && (0, drizzle_orm.is)(relEntry.relation, drizzle_orm.One)) {
1005
+ queryOutput[key] = null;
1006
+ continue;
1007
+ }
1008
+ delete queryOutput[key];
1009
+ continue;
1010
+ }
1011
+ const column = columns[key];
1012
+ if (value === 0n && column && column.columnType === "SQLiteBigInt" && !column.notNull) {
1013
+ delete queryOutput[key];
1014
+ continue;
1015
+ }
1016
+ queryOutput[key] = remapToGraphQLCore(key, value, tableName, column, relationMap);
1017
+ }
1018
+ return queryOutput;
1019
+ };
1020
+ const remapToGraphQLArrayOutput = (queryOutput, tableName, table, relationMap) => {
1021
+ for (const entry of queryOutput) remapToGraphQLSingleOutput(entry, tableName, table, relationMap);
1022
+ return queryOutput;
1023
+ };
1024
+ const remapFromGraphQLCore = (value, column, columnName) => {
1025
+ if (getColumnScalarOverride(column, true)) {
1026
+ if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) return Object.assign({}, value);
1027
+ return value;
1028
+ }
1029
+ const dataType = column.dataType ?? "";
1030
+ const columnType = column.columnType ?? "";
1031
+ if (columnType === "SQLiteTimestamp" || columnType === "SQLiteTimestampMs" || columnType === "MySqlTimestamp" || columnType === "MySqlDateTime" || columnType === "PgTimestamp" || columnType === "PgTimestampString") {
1032
+ const formatted = new Date(value);
1033
+ if (Number.isNaN(formatted.getTime())) throw drizzleError(`Field '${columnName}' is not a valid date!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1034
+ return formatted;
1035
+ }
1036
+ if ((columnType === "MySqlDate" || columnType === "PgDate") && typeof value === "string") {
1037
+ const dateOnly = value.includes("T") ? value.split("T")[0] : value;
1038
+ const check = new Date(dateOnly);
1039
+ if (Number.isNaN(check.getTime())) throw drizzleError(`Field '${columnName}' is not a valid date!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1040
+ return dateOnly;
1041
+ }
1042
+ if (dataType.includes("bigint")) try {
1043
+ return BigInt(value);
1044
+ } catch {
1045
+ throw drizzleError(`Field '${columnName}' is not a BigInt!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1046
+ }
1047
+ if (dataType.includes("json") && column.columnType !== "PgGeometryObject") return value;
1048
+ switch (dataType) {
1049
+ case "date": {
1050
+ const formatted = new Date(value);
1051
+ if (Number.isNaN(formatted.getTime())) throw drizzleError(`Field '${columnName}' is not a valid date!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1052
+ return formatted;
1053
+ }
1054
+ case "buffer":
1055
+ if (!Array.isArray(value)) throw drizzleError(`Field '${columnName}' is not an array!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1056
+ return Buffer.from(value);
1057
+ case "json":
1058
+ if (column.columnType === "PgGeometryObject") return value;
1059
+ try {
1060
+ return JSON.parse(value);
1061
+ } catch (e) {
1062
+ throw drizzleError(`Invalid JSON in field '${columnName}':\n${e instanceof Error ? e.message : "Unknown error"}`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1063
+ }
1064
+ case "array":
1065
+ if (!Array.isArray(value)) throw drizzleError(`Field '${columnName}' is not an array!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1066
+ if (column.columnType === "PgGeometry" && value.length !== 2) throw drizzleError(`Invalid float tuple in field '${columnName}': expected array with length of 2, received ${value.length}`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1067
+ return value;
1068
+ case "bigint": try {
1069
+ return BigInt(value);
1070
+ } catch (_error) {
1071
+ throw drizzleError(`Field '${columnName}' is not a BigInt!`, { code: "DRIZZLE_INVALID_INPUT_VALUE" });
1072
+ }
1073
+ default:
1074
+ if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) return Object.assign({}, value);
1075
+ return value;
1076
+ }
1077
+ };
1078
+ const remapFromGraphQLSingleInput = (queryInput, table, operation = "insert") => {
1079
+ const columns = (0, drizzle_orm.getColumns)(table);
1080
+ for (const [key, value] of Object.entries(queryInput)) if (value === void 0) delete queryInput[key];
1081
+ else {
1082
+ const column = columns[key];
1083
+ if (!column) throw drizzleError(`Unknown column: ${key}`, { code: "DRIZZLE_UNKNOWN_COLUMN" });
1084
+ if (value === null && column.notNull) {
1085
+ if (operation === "update") throw drizzleError(`Column '${key}' cannot be set to null.`, { code: "DRIZZLE_NOT_NULL" });
1086
+ delete queryInput[key];
1087
+ continue;
1088
+ }
1089
+ queryInput[key] = remapFromGraphQLCore(value, column, key);
1090
+ }
1091
+ return queryInput;
1092
+ };
1093
+ const remapFromGraphQLArrayInput = (queryInput, table, operation = "insert") => {
1094
+ for (const entry of queryInput) remapFromGraphQLSingleInput(entry, table, operation);
1095
+ return queryInput;
1096
+ };
1097
+ //#endregion
1081
1098
  //#region src/util/builders/common/filters.ts
1082
1099
  /**
1083
1100
  * Escape character pinned via `ESCAPE` on every generated safe-LIKE predicate. Bound as a
@@ -1166,11 +1183,6 @@ const lowerMembership = (column, values, negated) => {
1166
1183
  return negated ? drizzle_orm.sql`lower(${column}) not in (${lowered})` : drizzle_orm.sql`lower(${column}) in (${lowered})`;
1167
1184
  };
1168
1185
  /**
1169
- * Whether the column stores JSON — its `contains` operator is structural containment,
1170
- * not the safe substring operator string columns get.
1171
- */
1172
- const isJsonColumn = (column) => (column.columnType ?? "").includes("Json");
1173
- /**
1174
1186
  * Structural JSON containment for the `contains` operator on json/jsonb columns.
1175
1187
  * The value is serialized and bound as a parameter (never interpolated into the SQL text):
1176
1188
  * - Postgres: `col @> $1::jsonb` (a plain `json` column is cast through jsonb — `json` has
@@ -1309,36 +1321,37 @@ const jsonPathCondition = (column, columnName, filter) => {
1309
1321
  }
1310
1322
  return variants.length ? variants.length > 1 ? (0, drizzle_orm.and)(...variants) : variants[0] : void 0;
1311
1323
  };
1324
+ const singleValueOps = {
1325
+ eq: drizzle_orm.eq,
1326
+ ne: drizzle_orm.ne,
1327
+ gt: drizzle_orm.gt,
1328
+ gte: drizzle_orm.gte,
1329
+ lt: drizzle_orm.lt,
1330
+ lte: drizzle_orm.lte
1331
+ };
1332
+ const stringValueOps = {
1333
+ like: drizzle_orm.like,
1334
+ notLike: drizzle_orm.notLike,
1335
+ ilike: drizzle_orm.ilike,
1336
+ notIlike: drizzle_orm.notIlike
1337
+ };
1338
+ const arrayValueOps = {
1339
+ inArray: drizzle_orm.inArray,
1340
+ notInArray: drizzle_orm.notInArray
1341
+ };
1342
+ /** Membership operators for array columns: element list → SQL. Empty lists are rejected below. */
1343
+ const arrayMembershipOps = {
1344
+ hasSome: drizzle_orm.arrayOverlaps,
1345
+ hasEvery: drizzle_orm.arrayContains
1346
+ };
1347
+ const nullableOps = {
1348
+ isNull: drizzle_orm.isNull,
1349
+ isNotNull: drizzle_orm.isNotNull
1350
+ };
1312
1351
  const extractFiltersColumn = (column, columnName, operators) => {
1313
1352
  const { OR, AND, NOT, insensitive, ...restOperators } = operators;
1314
1353
  const foldCase = insensitive === true;
1315
1354
  const entries = Object.entries(restOperators);
1316
- const singleValueOps = {
1317
- eq: drizzle_orm.eq,
1318
- ne: drizzle_orm.ne,
1319
- gt: drizzle_orm.gt,
1320
- gte: drizzle_orm.gte,
1321
- lt: drizzle_orm.lt,
1322
- lte: drizzle_orm.lte
1323
- };
1324
- const stringValueOps = {
1325
- like: drizzle_orm.like,
1326
- notLike: drizzle_orm.notLike,
1327
- ilike: drizzle_orm.ilike,
1328
- notIlike: drizzle_orm.notIlike
1329
- };
1330
- const arrayValueOps = {
1331
- inArray: drizzle_orm.inArray,
1332
- notInArray: drizzle_orm.notInArray
1333
- };
1334
- const arrayMembershipOps = {
1335
- hasSome: drizzle_orm.arrayOverlaps,
1336
- hasEvery: drizzle_orm.arrayContains
1337
- };
1338
- const nullableOps = {
1339
- isNull: drizzle_orm.isNull,
1340
- isNotNull: drizzle_orm.isNotNull
1341
- };
1342
1355
  const variants = [];
1343
1356
  for (const [operatorName, operatorValue] of entries) {
1344
1357
  if (operatorValue === null || operatorValue === false) continue;
@@ -2169,7 +2182,7 @@ const isFilterableRelation = (relation) => !relation.through;
2169
2182
  * (an object without a `direction`) is rejected with a clear error instead of being
2170
2183
  * silently dropped.
2171
2184
  */
2172
- const orderByEntries = (orderArgs) => Object.entries(orderArgs).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).filter(([, config]) => config).map(([column, config]) => {
2185
+ const orderByEntries = (orderArgs) => Object.entries(orderArgs).filter(([, config]) => config).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).map(([column, config]) => {
2173
2186
  if (typeof config === "object" && config.direction === void 0) throw drizzleError(`ORDER BY ${column}: ordering through a relation is not supported in this query`, { code: "DRIZZLE_INVALID_ORDER_BY" });
2174
2187
  if (config.matchFilterOrder) throw drizzleError(`ORDER BY ${column}: 'matchFilterOrder' is not supported in this query`, { code: "DRIZZLE_INVALID_ORDER_BY" });
2175
2188
  return [
@@ -2355,16 +2368,20 @@ const decodeCursorValue = (value) => {
2355
2368
  return value;
2356
2369
  };
2357
2370
  /**
2358
- * Encodes a row's position in the given total order as an opaque cursor: base64url of a JSON
2359
- * payload holding the ordering spec (`o`) and the row's values for it (`v`). The spec rides
2360
- * along so a later request can verify the cursor was issued for the same ordering it is using.
2361
- */
2362
- const encodeCursor = (entries, row) => {
2363
- const payload = {
2364
- o: entries,
2365
- v: entries.map(([column]) => encodeCursorValue(row[column] ?? null))
2371
+ * `encodeCursor` bound to one ordering, for encoding a whole page.
2372
+ *
2373
+ * The ordering spec is the same for every row of a page, so it is serialized once here and
2374
+ * spliced into each row's payload rather than re-serialized per row. The bytes are identical
2375
+ * to what building the payload object and stringifying it produces — same keys, same order —
2376
+ * so cursors stay interchangeable with ones issued before this was split out.
2377
+ */
2378
+ const cursorEncoder = (entries) => {
2379
+ const spec = JSON.stringify(entries);
2380
+ const columns = entries.map(([column]) => column);
2381
+ return (row) => {
2382
+ const values = JSON.stringify(columns.map((column) => encodeCursorValue(row[column] ?? null)));
2383
+ return Buffer.from(`{"o":${spec},"v":${values}}`, "utf8").toString("base64url");
2366
2384
  };
2367
- return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
2368
2385
  };
2369
2386
  /**
2370
2387
  * Decodes an `after` cursor and validates it against the ordering the current request pages
@@ -2454,7 +2471,8 @@ const selectsCursorField = (info, table) => {
2454
2471
  * dates and bigints into their transport forms.
2455
2472
  */
2456
2473
  const attachRowCursors = (rows, entries) => {
2457
- for (const row of rows) row[ROW_CURSOR_PROP] = encodeCursor(entries, row);
2474
+ const encode = cursorEncoder(entries);
2475
+ for (const row of rows) row[ROW_CURSOR_PROP] = encode(row);
2458
2476
  };
2459
2477
  /** Resolver for the `cursor` meta field: reads the value a list resolver attached, if any. */
2460
2478
  const rowCursorResolver = (source) => source?.[ROW_CURSOR_PROP] ?? null;
@@ -2498,6 +2516,31 @@ const withPrimaryKeyColumns = (columns, table, pkNames) => {
2498
2516
  return columns;
2499
2517
  };
2500
2518
  /**
2519
+ * Wraps a dialect's `getTableConfig` in a per-table cache.
2520
+ *
2521
+ * The dialect implementations are not lookups: each call re-runs the table's
2522
+ * `extraConfigBuilder` and rebuilds every index, check, unique constraint, primary key and
2523
+ * foreign key it declares. Nothing about a table changes after it is defined, so the result
2524
+ * is the same every time — but a build asks for it many times per table (primary-key names,
2525
+ * unique column sets, conflict targets, one per relation that keys off the target's PK), and
2526
+ * an overriding resolver asks again at request time.
2527
+ *
2528
+ * The cache is a `WeakMap` on the table object, so it costs nothing once the table is gone.
2529
+ * Bind it once per dialect module, at module scope, so the cache outlives a single
2530
+ * `buildSchema` call.
2531
+ */
2532
+ const memoizeTableConfig = (getTableConfig) => {
2533
+ const cache = /* @__PURE__ */ new WeakMap();
2534
+ return (table) => {
2535
+ let config = cache.get(table);
2536
+ if (config === void 0) {
2537
+ config = getTableConfig(table);
2538
+ cache.set(table, config);
2539
+ }
2540
+ return config;
2541
+ };
2542
+ };
2543
+ /**
2501
2544
  * Resolves a table's primary-key property names using a dialect's `getTableConfig` to
2502
2545
  * surface table-level composite keys (whose member columns aren't flagged `.primary`).
2503
2546
  * Each dialect builder binds this with its own getTableConfig and reuses the binding for
@@ -3054,48 +3097,55 @@ const relationJoinColumns = (tree, table, selectionCtx) => {
3054
3097
  }
3055
3098
  return needed;
3056
3099
  };
3057
- const extractSelectedColumnsFromTree = (tree, table, selectionCtx) => {
3100
+ /**
3101
+ * The column the extractors fall back to when a selection names none of its own — a query that
3102
+ * asked only for `__typename`, or only for relation fields. The relational query builder still
3103
+ * needs at least one column, and some SQLite column types crash it when they are the only one
3104
+ * selected, so a column of any other type is preferred and the first column is the last resort.
3105
+ */
3106
+ const fallbackColumnName = (tableColumns) => {
3107
+ const columnKeys = Object.entries(tableColumns);
3108
+ return columnKeys.find(([, column]) => !rqbCrashTypes.includes(column.columnType))?.[0] ?? columnKeys[0][0];
3109
+ };
3110
+ /**
3111
+ * Property names of the columns a selection reads: the ones it names itself, plus the join
3112
+ * columns its relation fields correlate on, plus the fallback when that leaves nothing.
3113
+ */
3114
+ const selectedColumnNames = (tree, table, selectionCtx) => {
3058
3115
  const tableColumns = (0, drizzle_orm.getColumns)(table);
3059
- const treeEntries = Object.entries(tree);
3060
- const selectedColumns = [];
3061
- for (const [_fieldName, fieldData] of treeEntries) {
3116
+ const names = [];
3117
+ for (const fieldData of Object.values(tree)) {
3062
3118
  if (!tableColumns[fieldData.name]) continue;
3063
- selectedColumns.push([fieldData.name, true]);
3064
- }
3065
- for (const columnName of relationJoinColumns(tree, table, selectionCtx)) selectedColumns.push([columnName, true]);
3066
- if (!selectedColumns.length) {
3067
- const columnKeys = Object.entries(tableColumns);
3068
- const columnName = columnKeys.find((e) => rqbCrashTypes.find((haram) => e[1].columnType !== haram))?.[0] ?? columnKeys[0][0];
3069
- selectedColumns.push([columnName, true]);
3119
+ names.push(fieldData.name);
3070
3120
  }
3121
+ names.push(...relationJoinColumns(tree, table, selectionCtx));
3122
+ if (!names.length) names.push(fallbackColumnName(tableColumns));
3123
+ return names;
3124
+ };
3125
+ /** The requested columns as the relational query builder's `columns` map. */
3126
+ const extractSelectedColumnsFromTree = (tree, table, selectionCtx) => {
3127
+ const selectedColumns = selectedColumnNames(tree, table, selectionCtx).map((columnName) => [columnName, true]);
3071
3128
  return Object.fromEntries(selectedColumns);
3072
3129
  };
3073
3130
  /**
3131
+ * The same columns as a SQL select list.
3132
+ *
3074
3133
  * Can't automatically determine column type on type level
3075
3134
  * Since drizzle table types extend eachother
3076
3135
  */
3077
3136
  const extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
3078
3137
  const tableColumns = (0, drizzle_orm.getColumns)(table);
3079
- const treeEntries = Object.entries(tree);
3080
- const selectedColumns = [];
3081
- for (const [_fieldName, fieldData] of treeEntries) {
3082
- if (!tableColumns[fieldData.name]) continue;
3083
- selectedColumns.push([fieldData.name, tableColumns[fieldData.name]]);
3084
- }
3085
- for (const columnName of relationJoinColumns(tree, table, selectionCtx)) selectedColumns.push([columnName, tableColumns[columnName]]);
3086
- if (!selectedColumns.length) {
3087
- const columnKeys = Object.entries(tableColumns);
3088
- const columnName = columnKeys.find((e) => rqbCrashTypes.find((haram) => e[1].columnType !== haram))?.[0] ?? columnKeys[0][0];
3089
- selectedColumns.push([columnName, tableColumns[columnName]]);
3090
- }
3138
+ const selectedColumns = selectedColumnNames(tree, table, selectionCtx).map((columnName) => [columnName, tableColumns[columnName]]);
3091
3139
  return Object.fromEntries(selectedColumns);
3092
3140
  };
3093
3141
  //#endregion
3094
3142
  //#region src/util/builders/common/relation-params.ts
3095
- const extractRelationsParamsInner = (relationMap, tables, tableName, typeName, originField, typeNameMapper, _isInitial = false, filterCtx, limits, scope, defaultOrderBy, resolveName) => {
3143
+ const extractRelationsParams = (relationMap, tables, tableName, info, typeName, options = {}) => {
3144
+ const { typeNameMapper, filterCtx, limits, scope, defaultOrderBy, resolveName } = options;
3145
+ if (!info) return;
3096
3146
  const relationsForTable = relationMap[tableName];
3097
3147
  if (!relationsForTable) return;
3098
- const baseField = Object.entries(originField.fieldsByTypeName).find(([key, _value]) => key === typeName)?.[1];
3148
+ const baseField = Object.entries(info.fieldsByTypeName).find(([key, _value]) => key === typeName)?.[1];
3099
3149
  if (!baseField) return;
3100
3150
  const args = {};
3101
3151
  for (const [relName, relEntry] of Object.entries(relationsForTable)) {
@@ -3132,15 +3182,11 @@ const extractRelationsParamsInner = (relationMap, tables, tableName, typeName, o
3132
3182
  thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable) => extractOrderBy(aliasedTable, relationArgs.orderBy, relationFilterCtx(filterCtx, targetTableName), relWhere) : hasPagination && pkNames.length ? (aliasedTable) => primaryKeyOrderExprs(aliasedTable, pkNames) : void 0;
3133
3183
  thisRecord.offset = offset;
3134
3184
  thisRecord.limit = limit;
3135
- thisRecord.with = relationField ? extractRelationsParamsInner(relationMap, tables, targetTableName, relTypeName, relationField, typeNameMapper, false, filterCtx, limits, scope, defaultOrderBy, resolveName) : void 0;
3185
+ thisRecord.with = extractRelationsParams(relationMap, tables, targetTableName, relationField, relTypeName, options);
3136
3186
  args[relName] = thisRecord;
3137
3187
  }
3138
3188
  return args;
3139
3189
  };
3140
- const extractRelationsParams = (relationMap, tables, tableName, info, typeName, typeNameMapper, filterCtx, limits, scope, defaultOrderBy, resolveName) => {
3141
- if (!info) return;
3142
- return extractRelationsParamsInner(relationMap, tables, tableName, typeName, info, typeNameMapper, true, filterCtx, limits, scope, defaultOrderBy, resolveName);
3143
- };
3144
3190
  /**
3145
3191
  * Returns a copy of `relationMap` containing only the relations that should be eagerly
3146
3192
  * pre-fetched (per the `shouldEagerLoad` predicate). Pass the result wherever a query or
@@ -3341,7 +3387,13 @@ const hardDeleteArg = {
3341
3387
  const prepareMutationRelationColumns = (params) => {
3342
3388
  const { relationMap, tables, tableName, typeNameMapper, table, pkNames, parsedInfo, resolveName } = params;
3343
3389
  const typeName = resolveObjectTypeName(tableName, typeNameMapper, resolveName);
3344
- const withParams = relationMap[tableName] ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName, typeNameMapper, void 0, params.limits, params.scope, params.defaultOrderBy, resolveName) : void 0;
3390
+ const withParams = relationMap[tableName] ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName, {
3391
+ typeNameMapper,
3392
+ limits: params.limits,
3393
+ scope: params.scope,
3394
+ defaultOrderBy: params.defaultOrderBy,
3395
+ resolveName
3396
+ }) : void 0;
3345
3397
  const hasRelations = !!(withParams && Object.keys(withParams).length);
3346
3398
  const baseColumns = extractSelectedColumnsFromTreeSQLFormat(parsedInfo.fieldsByTypeName[typeName], table, {
3347
3399
  tableName,
@@ -3920,7 +3972,14 @@ const runRelationalSelect = async (opts) => {
3920
3972
  offset: distinctKeys ? void 0 : offset,
3921
3973
  orderBy: distinctKeys ? (aliasedTable) => [...orderBy ? extractOrderBy(aliasedTable, orderBy, relationFilterCtx(filterCtx, tableName), where) : [], ...primaryKeyOrderExprs(aliasedTable, pkNames)] : cursorEntries ? (aliasedTable) => cursorOrderExprs(aliasedTable, cursorEntries) : orderBy ? (aliasedTable) => extractOrderBy(aliasedTable, orderBy, relationFilterCtx(filterCtx, tableName), where) : needsDefaultOrder && pkNames?.length ? (aliasedTable) => primaryKeyOrderExprs(aliasedTable, pkNames) : void 0,
3922
3974
  where: distinctKeys ? { RAW: (aliasedTable) => primaryKeyRestriction(aliasedTable, pkNames, distinctKeys) } : where || cursorValues || scope?.has(tableName, deleted) ? { RAW: (aliasedTable) => withScope(scope, tableName, aliasedTable, (0, drizzle_orm.and)(where ? extractFilters(aliasedTable, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0, cursorValues ? buildCursorCondition(aliasedTable, cursorEntries, cursorValues, opts.nullOrdering ?? "nulls-smallest") : void 0), deleted) } : void 0,
3923
- with: relationMap[tableName] ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName, typeNameMapper, filterCtx, opts.limits, scope, opts.defaultOrderBy, opts.resolveName) : void 0
3975
+ with: relationMap[tableName] ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName, {
3976
+ typeNameMapper,
3977
+ filterCtx,
3978
+ limits: opts.limits,
3979
+ scope,
3980
+ defaultOrderBy: opts.defaultOrderBy,
3981
+ resolveName: opts.resolveName
3982
+ }) : void 0
3924
3983
  };
3925
3984
  if (single) {
3926
3985
  const result = await queryBase.findFirst(params);
@@ -4841,12 +4900,13 @@ const collectSelections = (selections, info, tree, parentType, deep, activeFragm
4841
4900
  fields = {};
4842
4901
  tree[parentTypeName] = fields;
4843
4902
  }
4903
+ const parentFields = fieldsOf(parentType);
4844
4904
  for (const selection of selections) {
4845
4905
  if (isExcluded(info, selection)) continue;
4846
4906
  if (selection.kind === graphql.Kind.FIELD) {
4847
4907
  const name = selection.name.value;
4848
4908
  if (isMetaField(name)) continue;
4849
- const fieldDef = fieldsOf(parentType)?.[name];
4909
+ const fieldDef = parentFields?.[name];
4850
4910
  if (!fieldDef) continue;
4851
4911
  const fieldType = namedTypeOf(fieldDef.type);
4852
4912
  if (!fieldType) continue;
@@ -4889,7 +4949,10 @@ const collectSelections = (selections, info, tree, parentType, deep, activeFragm
4889
4949
  }
4890
4950
  return tree;
4891
4951
  };
4892
- const firstKey = (object) => Object.keys(object)[0];
4952
+ /** The first key of an object, without materializing the whole key array to discard it. */
4953
+ const firstKey = (object) => {
4954
+ for (const key in object) return key;
4955
+ };
4893
4956
  /**
4894
4957
  * Reads the selection under a resolver's own field out of its `info`, as a tree of
4895
4958
  * {@link ResolveTree} nodes.
@@ -4940,7 +5003,30 @@ const SEP = "__";
4940
5003
  * arrays (including array-typed number columns), JSON, buffers, and object-shaped columns
4941
5004
  * (e.g. geometry) are excluded entirely.
4942
5005
  */
5006
+ /**
5007
+ * Cache for {@link classifyAggregateColumns}. Keyed on the table object, then on the name it
5008
+ * was classified under — the name only reaches `drizzleColumnToGraphQLType` for enum naming,
5009
+ * but a table registered under two names would name its enums differently, so it is part of
5010
+ * the key rather than assumed irrelevant.
5011
+ *
5012
+ * The entries hold this build's GraphQL types and this build's column exclusions, so the
5013
+ * cache lives exactly as long as a build: {@link resetAggregateColumnCache} runs at the start
5014
+ * of every one, alongside the other per-build registries. Kept across builds it would hand a
5015
+ * second build the first build's enum instances, which is a schema with two types of one name.
5016
+ */
5017
+ let aggregateColumnSetsCache = /* @__PURE__ */ new WeakMap();
5018
+ /** Drops the classifications cached for the previous build. Called once per `generateSchemaData`. */
5019
+ const resetAggregateColumnCache = () => {
5020
+ aggregateColumnSetsCache = /* @__PURE__ */ new WeakMap();
5021
+ };
4943
5022
  const classifyAggregateColumns = (table, tableName) => {
5023
+ let byName = aggregateColumnSetsCache.get(table);
5024
+ if (!byName) {
5025
+ byName = /* @__PURE__ */ new Map();
5026
+ aggregateColumnSetsCache.set(table, byName);
5027
+ }
5028
+ const cached = byName.get(tableName);
5029
+ if (cached) return cached;
4944
5030
  const numeric = {};
4945
5031
  const orderable = {};
4946
5032
  const all = {};
@@ -4958,11 +5044,13 @@ const classifyAggregateColumns = (table, tableName) => {
4958
5044
  };
4959
5045
  if (dataType === "number") numeric[columnName] = column;
4960
5046
  }
4961
- return {
5047
+ const sets = {
4962
5048
  numeric,
4963
5049
  orderable,
4964
5050
  all
4965
5051
  };
5052
+ byName.set(tableName, sets);
5053
+ return sets;
4966
5054
  };
4967
5055
  /**
4968
5056
  * Builds the `${typeName}Aggregate` output type for a table:
@@ -6086,6 +6174,7 @@ const createSchemaBuilder = (adapter) => {
6086
6174
  registerScalarOverrides(tables, options);
6087
6175
  registerEnumConfig(options);
6088
6176
  registerColumnExclusions(tables, options.exclude);
6177
+ resetAggregateColumnCache();
6089
6178
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
6090
6179
  for (const excluded of excludedTables) delete namedRelations[excluded];
6091
6180
  attachTargetPrimaryKeys(namedRelations, tables, (table) => primaryKeyPropNames(table));
@@ -6475,11 +6564,13 @@ const generateDelete = (db, tableName, table, filterArgs, fieldName, single, req
6475
6564
  }
6476
6565
  });
6477
6566
  };
6567
+ /** The dialect's table config, cached per table — see {@link memoizeTableConfig}. */
6568
+ const getTableConfig$2 = memoizeTableConfig(drizzle_orm_mysql_core.getTableConfig);
6478
6569
  /** Primary-key property names for a MySQL table, including table-level composite keys. */
6479
- const mysqlPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, drizzle_orm_mysql_core.getTableConfig);
6570
+ const mysqlPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig$2);
6480
6571
  const { prepareBuild, addReadFields, finalizeBuild } = createSchemaBuilder({
6481
6572
  tableClass: drizzle_orm_mysql_core.MySqlTable,
6482
- getTableConfig: drizzle_orm_mysql_core.getTableConfig,
6573
+ getTableConfig: getTableConfig$2,
6483
6574
  primaryKeyPropNames: mysqlPrimaryKeyPropNames,
6484
6575
  nullOrdering: "nulls-smallest",
6485
6576
  returnsRows: false,
@@ -7360,12 +7451,14 @@ const createUpdateManyGenerator = (primaryKeyPropNames, runBatch = runUpdateMany
7360
7451
  };
7361
7452
  //#endregion
7362
7453
  //#region src/util/builders/pg.ts
7454
+ /** The dialect's table config, cached per table — see {@link memoizeTableConfig}. */
7455
+ const getTableConfig$1 = memoizeTableConfig(drizzle_orm_pg_core.getTableConfig);
7363
7456
  /** Primary-key property names for a PG table, including table-level composite keys. */
7364
- const pgPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, drizzle_orm_pg_core.getTableConfig);
7457
+ const pgPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig$1);
7365
7458
  const generateUpdateMany$1 = createUpdateManyGenerator(pgPrimaryKeyPropNames);
7366
7459
  const pgSchemaData = createSchemaDataGenerator({
7367
7460
  tableClass: drizzle_orm_pg_core.PgTable,
7368
- getTableConfig: drizzle_orm_pg_core.getTableConfig,
7461
+ getTableConfig: getTableConfig$1,
7369
7462
  primaryKeyPropNames: pgPrimaryKeyPropNames,
7370
7463
  nullOrdering: "nulls-largest",
7371
7464
  returnsRows: true,
@@ -7374,8 +7467,10 @@ const pgSchemaData = createSchemaDataGenerator({
7374
7467
  const generateSchemaData$1 = (db, schema, relations, options) => pgSchemaData(db, schema, relations, options);
7375
7468
  //#endregion
7376
7469
  //#region src/util/builders/sqlite.ts
7470
+ /** The dialect's table config, cached per table — see {@link memoizeTableConfig}. */
7471
+ const getTableConfig = memoizeTableConfig(drizzle_orm_sqlite_core.getTableConfig);
7377
7472
  /** Primary-key property names for a SQLite table, including table-level composite keys. */
7378
- const sqlitePrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, drizzle_orm_sqlite_core.getTableConfig);
7473
+ const sqlitePrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig);
7379
7474
  /**
7380
7475
  * SQLite's batch runner. A synchronous driver (better-sqlite3) commits the moment its
7381
7476
  * transaction callback returns, so that callback must not be async — an awaited statement
@@ -7420,7 +7515,7 @@ const runSqliteUpdateManyBatch = ({ executor, entries, table, returning, anyNest
7420
7515
  const generateUpdateMany = createUpdateManyGenerator(sqlitePrimaryKeyPropNames, runSqliteUpdateManyBatch);
7421
7516
  const sqliteSchemaData = createSchemaDataGenerator({
7422
7517
  tableClass: drizzle_orm_sqlite_core.SQLiteTable,
7423
- getTableConfig: drizzle_orm_sqlite_core.getTableConfig,
7518
+ getTableConfig,
7424
7519
  primaryKeyPropNames: sqlitePrimaryKeyPropNames,
7425
7520
  nullOrdering: "nulls-smallest",
7426
7521
  returnsRows: true,
@@ -7434,11 +7529,14 @@ const generateSchemaData = (db, schema, relations, options) => sqliteSchemaData(
7434
7529
  //#endregion
7435
7530
  //#region src/util/selection.ts
7436
7531
  const contextCache = /* @__PURE__ */ new WeakMap();
7532
+ const getMySqlTableConfig = memoizeTableConfig(drizzle_orm_mysql_core.getTableConfig);
7533
+ const getPgTableConfig = memoizeTableConfig(drizzle_orm_pg_core.getTableConfig);
7534
+ const getSQLiteTableConfig = memoizeTableConfig(drizzle_orm_sqlite_core.getTableConfig);
7437
7535
  /** The dialect's `getTableConfig`, which is the only place a composite primary key shows up. */
7438
7536
  const tableConfigFor = (db) => {
7439
- if ((0, drizzle_orm.is)(db, drizzle_orm_mysql_core.MySqlAsyncDatabase)) return drizzle_orm_mysql_core.getTableConfig;
7440
- if ((0, drizzle_orm.is)(db, drizzle_orm_pg_core.PgAsyncDatabase)) return drizzle_orm_pg_core.getTableConfig;
7441
- if ((0, drizzle_orm.is)(db, drizzle_orm_sqlite_core.SQLiteAsyncDatabase)) return drizzle_orm_sqlite_core.getTableConfig;
7537
+ if ((0, drizzle_orm.is)(db, drizzle_orm_mysql_core.MySqlAsyncDatabase)) return getMySqlTableConfig;
7538
+ if ((0, drizzle_orm.is)(db, drizzle_orm_pg_core.PgAsyncDatabase)) return getPgTableConfig;
7539
+ if ((0, drizzle_orm.is)(db, drizzle_orm_sqlite_core.SQLiteAsyncDatabase)) return getSQLiteTableConfig;
7442
7540
  throw new Error("Drizzle-GraphQL Error: unsupported database instance — expected a PostgreSQL, MySQL or SQLite one.");
7443
7541
  };
7444
7542
  const contextFor = (db) => {
@@ -7519,7 +7617,11 @@ const selectionToWith = (info, options) => {
7519
7617
  if (!tables[table]) throw new Error(`Drizzle-GraphQL Error: '${table}' is not a table in the Drizzle schema.`);
7520
7618
  if (!relationMap[table]) return;
7521
7619
  const parsed = parseInfo(info);
7522
- const params = extractRelationsParams(relationMap, tables, table, parsed, resolveObjectTypeName(table, typeNameMapper, resolveName), typeNameMapper, filterCtx, void 0, void 0, void 0, resolveName);
7620
+ const params = extractRelationsParams(relationMap, tables, table, parsed, resolveObjectTypeName(table, typeNameMapper, resolveName), {
7621
+ typeNameMapper,
7622
+ filterCtx,
7623
+ resolveName
7624
+ });
7523
7625
  return params && Object.keys(params).length ? params : void 0;
7524
7626
  };
7525
7627
  /**