@vsrepo/drizzle-adapter 0.1.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 ADDED
@@ -0,0 +1,1531 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc2) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DrizzleAdapter: () => DrizzleAdapter
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/drizzle.adapter.ts
28
+ var import_drizzle_orm9 = require("drizzle-orm");
29
+ var import_vsrepo10 = require("vsrepo");
30
+
31
+ // src/resolvers/fields-config.resolver.ts
32
+ var import_vsrepo = require("vsrepo");
33
+ var import_drizzle_orm = require("drizzle-orm");
34
+ function resolveFieldsConfig(table) {
35
+ let pk;
36
+ for (const column of Object.values((0, import_drizzle_orm.getColumns)(table))) {
37
+ if (column.primary) {
38
+ pk = column.name;
39
+ break;
40
+ }
41
+ }
42
+ if (!pk) {
43
+ throw new import_vsrepo.VSRepoAdapterError(
44
+ `Table '${(0, import_drizzle_orm.getTableName)(table)}' has no primary key defined. VSRepoDrizzleAdapter requires every table to declare a primary key.`,
45
+ import_vsrepo.AdapterErrorCode.INVALID_ADAPTER_CONFIG,
46
+ null
47
+ );
48
+ }
49
+ return { pk };
50
+ }
51
+
52
+ // src/resolvers/isolation-level.resolver.ts
53
+ var isolationRecord = {
54
+ ReadCommitted: "read committed",
55
+ ReadUncommitted: "read uncommitted",
56
+ RepeatableRead: "repeatable read",
57
+ Serializable: "serializable"
58
+ };
59
+ function resolveIsolationLevel(vsrepoIsolation) {
60
+ return isolationRecord[vsrepoIsolation];
61
+ }
62
+
63
+ // src/resolvers/raw-sql.resolver.ts
64
+ var import_drizzle_orm2 = require("drizzle-orm");
65
+ var PLACEHOLDER_PATTERNS = {
66
+ postgresql: /\$(\d+)/g,
67
+ cockroach: /\$(\d+)/g,
68
+ sqlite: /\?/g
69
+ };
70
+ var NUMBERED_DIALECTS = /* @__PURE__ */ new Set(["postgresql", "cockroach"]);
71
+ function resolveRawSql(dialect, query, args = []) {
72
+ const pattern = PLACEHOLDER_PATTERNS[dialect];
73
+ const isNumbered = NUMBERED_DIALECTS.has(dialect);
74
+ const chunks = [];
75
+ let lastIndex = 0;
76
+ let positionalIndex = 0;
77
+ for (const match of query.matchAll(pattern)) {
78
+ chunks.push(new import_drizzle_orm2.StringChunk(query.slice(lastIndex, match.index)));
79
+ const argIndex = isNumbered ? Number(match[1]) - 1 : positionalIndex++;
80
+ chunks.push(new import_drizzle_orm2.Param(args[argIndex]));
81
+ lastIndex = match.index + match[0].length;
82
+ }
83
+ chunks.push(new import_drizzle_orm2.StringChunk(query.slice(lastIndex)));
84
+ return new import_drizzle_orm2.SQL(chunks);
85
+ }
86
+
87
+ // src/resolvers/raw-result.resolver.ts
88
+ function resolveRawResult(dialect, result, modifying) {
89
+ switch (dialect) {
90
+ case "postgresql":
91
+ case "cockroach":
92
+ return modifying ? result.rowCount ?? 0 : result.rows;
93
+ // assume node-postgres
94
+ case "sqlite":
95
+ return modifying ? result.changes ?? 0 : result;
96
+ }
97
+ }
98
+
99
+ // src/resolvers/map-drizzle-error.resolver.ts
100
+ var import_vsrepo2 = require("vsrepo");
101
+ var import_drizzle_orm3 = require("drizzle-orm");
102
+ var POSTGRES_SQLSTATE_MAP = {
103
+ "23505": import_vsrepo2.AdapterErrorCode.UNIQUE_CONSTRAINT_VIOLATION,
104
+ "23503": import_vsrepo2.AdapterErrorCode.FOREIGN_KEY_VIOLATION,
105
+ "23502": import_vsrepo2.AdapterErrorCode.NOT_NULL_VIOLATION,
106
+ "23514": import_vsrepo2.AdapterErrorCode.CHECK_VIOLATION,
107
+ "23000": import_vsrepo2.AdapterErrorCode.CONSTRAINT_VIOLATION,
108
+ "22001": import_vsrepo2.AdapterErrorCode.VALUE_TOO_LONG,
109
+ "22P02": import_vsrepo2.AdapterErrorCode.CONVERSION_ERROR,
110
+ "42601": import_vsrepo2.AdapterErrorCode.INVALID_QUERY,
111
+ "42703": import_vsrepo2.AdapterErrorCode.TABLE_OR_COLUMN_NOT_FOUND,
112
+ "42P01": import_vsrepo2.AdapterErrorCode.TABLE_OR_COLUMN_NOT_FOUND,
113
+ "40P01": import_vsrepo2.AdapterErrorCode.DEADLOCK,
114
+ "40001": import_vsrepo2.AdapterErrorCode.TRANSACTION_CONFLICT,
115
+ "55P03": import_vsrepo2.AdapterErrorCode.LOCK_TIMEOUT,
116
+ "57014": import_vsrepo2.AdapterErrorCode.TIMEOUT,
117
+ "28000": import_vsrepo2.AdapterErrorCode.INVALID_CREDENTIALS,
118
+ "28P01": import_vsrepo2.AdapterErrorCode.INVALID_CREDENTIALS,
119
+ "3D000": import_vsrepo2.AdapterErrorCode.CONNECTION_FAILED
120
+ };
121
+ var SQLITE_CODE_MAP = {
122
+ SQLITE_CONSTRAINT_UNIQUE: import_vsrepo2.AdapterErrorCode.UNIQUE_CONSTRAINT_VIOLATION,
123
+ SQLITE_CONSTRAINT_PRIMARYKEY: import_vsrepo2.AdapterErrorCode.UNIQUE_CONSTRAINT_VIOLATION,
124
+ SQLITE_CONSTRAINT_FOREIGNKEY: import_vsrepo2.AdapterErrorCode.FOREIGN_KEY_VIOLATION,
125
+ SQLITE_CONSTRAINT_NOTNULL: import_vsrepo2.AdapterErrorCode.NOT_NULL_VIOLATION,
126
+ SQLITE_CONSTRAINT_CHECK: import_vsrepo2.AdapterErrorCode.CHECK_VIOLATION,
127
+ SQLITE_CONSTRAINT: import_vsrepo2.AdapterErrorCode.CONSTRAINT_VIOLATION,
128
+ SQLITE_BUSY: import_vsrepo2.AdapterErrorCode.LOCK_TIMEOUT,
129
+ SQLITE_LOCKED: import_vsrepo2.AdapterErrorCode.LOCKED,
130
+ SQLITE_MISUSE: import_vsrepo2.AdapterErrorCode.INVALID_QUERY,
131
+ SQLITE_CANTOPEN: import_vsrepo2.AdapterErrorCode.CONNECTION_FAILED
132
+ };
133
+ function resolveCodeFromDriverError(dialect, error) {
134
+ switch (dialect) {
135
+ case "postgresql":
136
+ case "cockroach":
137
+ return typeof error.code === "string" ? POSTGRES_SQLSTATE_MAP[error.code] : void 0;
138
+ case "sqlite":
139
+ return typeof error.code === "string" ? SQLITE_CODE_MAP[error.code] : void 0;
140
+ }
141
+ }
142
+ function mapDrizzleError(error, operation, dialect) {
143
+ if (error instanceof import_vsrepo2.VSRepoAdapterError) return error;
144
+ if (error instanceof import_drizzle_orm3.TransactionRollbackError) {
145
+ return new import_vsrepo2.VSRepoAdapterError(
146
+ `'${operation}' was rolled back intentionally via 'tx.rollback()'`,
147
+ import_vsrepo2.AdapterErrorCode.UNKNOWN,
148
+ error
149
+ );
150
+ }
151
+ const driverError = error instanceof import_drizzle_orm3.DrizzleQueryError && error.cause ? error.cause : error;
152
+ const code = resolveCodeFromDriverError(dialect, driverError);
153
+ return new import_vsrepo2.VSRepoAdapterError(
154
+ `'${operation}' failed: ${driverError?.message ?? "unknown error"}`,
155
+ code ?? import_vsrepo2.AdapterErrorCode.UNKNOWN,
156
+ error
157
+ );
158
+ }
159
+
160
+ // src/validators/validate-adapter-config.validator.ts
161
+ var import_drizzle_orm4 = require("drizzle-orm");
162
+ var import_vsrepo3 = require("vsrepo");
163
+ var SUPPORTED_DIALECTS = /* @__PURE__ */ new Set(["postgresql", "sqlite", "cockroach"]);
164
+ function validateDrizzleAdapterConfig(db, config) {
165
+ if (db === null || db === void 0) {
166
+ throw new import_vsrepo3.VSRepoAdapterError(
167
+ "Missing Drizzle client: the first constructor argument (db) is null/undefined.",
168
+ import_vsrepo3.AdapterErrorCode.MISSING_DB_CLIENT,
169
+ null
170
+ );
171
+ }
172
+ const dbLike = db;
173
+ if (typeof dbLike.query !== "object" || dbLike.query === null) {
174
+ throw new import_vsrepo3.VSRepoAdapterError(
175
+ "Invalid Drizzle client: 'db.query' is undefined \u2014 the client must be created with the 'relations' config (e.g. 'drizzle(connection, { relations })') for DrizzleAdapter to run relational queries.",
176
+ import_vsrepo3.AdapterErrorCode.MISSING_DB_CLIENT,
177
+ null
178
+ );
179
+ }
180
+ if (config === null || config === void 0) {
181
+ throw new import_vsrepo3.VSRepoAdapterError(
182
+ "Invalid constructor config: the second constructor argument (config) is null/undefined.",
183
+ import_vsrepo3.AdapterErrorCode.INVALID_ADAPTER_CONFIG,
184
+ null
185
+ );
186
+ }
187
+ const { table, dialect, queryKey } = config;
188
+ if (!(0, import_drizzle_orm4.is)(table, import_drizzle_orm4.Table)) {
189
+ throw new import_vsrepo3.VSRepoAdapterError(
190
+ "Invalid constructor config (table): expected a Drizzle 'Table' instance (the object exported by your schema, e.g. 'userTable').",
191
+ import_vsrepo3.AdapterErrorCode.INVALID_ADAPTER_CONFIG,
192
+ null
193
+ );
194
+ }
195
+ if (dialect !== void 0 && !SUPPORTED_DIALECTS.has(dialect)) {
196
+ throw new import_vsrepo3.VSRepoAdapterError(
197
+ `Invalid constructor config (dialect): '${String(dialect)}' is not supported. Expected one of: ${[...SUPPORTED_DIALECTS].join(", ")}.`,
198
+ import_vsrepo3.AdapterErrorCode.INVALID_ADAPTER_CONFIG,
199
+ null
200
+ );
201
+ }
202
+ if (typeof queryKey !== "string" || queryKey.length === 0) {
203
+ throw new import_vsrepo3.VSRepoAdapterError(
204
+ "Invalid constructor config (queryKey): expected a non-empty string matching a key of 'db.query' (the name your schema exports the table under, e.g. 'userTable').",
205
+ import_vsrepo3.AdapterErrorCode.INVALID_ADAPTER_CONFIG,
206
+ null
207
+ );
208
+ }
209
+ const queryEntry = dbLike.query[queryKey];
210
+ if (typeof queryEntry !== "object" || queryEntry === null || typeof queryEntry.findFirst !== "function" || typeof queryEntry.findMany !== "function") {
211
+ throw new import_vsrepo3.VSRepoAdapterError(
212
+ `Invalid constructor config (queryKey): no relational query builder found for '${queryKey}' on 'db.query' (expected 'db.query.${queryKey}' to exist \u2014 check that '${queryKey}' matches the name your schema exports the table under, and that the table is included in the 'relations' config).`,
213
+ import_vsrepo3.AdapterErrorCode.MODEL_NOT_FOUND,
214
+ null
215
+ );
216
+ }
217
+ return { db, config };
218
+ }
219
+
220
+ // src/validators/validate-relations.validator.ts
221
+ var import_drizzle_orm5 = require("drizzle-orm");
222
+ var import_vsrepo4 = require("vsrepo");
223
+
224
+ // src/validators/is-plain-object.validator.ts
225
+ function isPlainObject(value) {
226
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date);
227
+ }
228
+
229
+ // src/validators/validate-relations.validator.ts
230
+ var MODES = /* @__PURE__ */ new Set(["otm", "mto", "oto"]);
231
+ var RESTRICTIONS = /* @__PURE__ */ new Set(["set", "add"]);
232
+ function fail(message) {
233
+ throw new import_vsrepo4.VSRepoAdapterError(message, import_vsrepo4.AdapterErrorCode.INVALID_ADAPTER_CONFIG, null);
234
+ }
235
+ function validateRelations(table, dialect, relations) {
236
+ if (relations === void 0) return void 0;
237
+ if (!isPlainObject(relations)) {
238
+ fail(
239
+ "Invalid constructor config (relations): expected an object mapping relation field names to their config."
240
+ );
241
+ }
242
+ const hereColumns = new Set(Object.keys((0, import_drizzle_orm5.getColumns)(table)));
243
+ const resolved = /* @__PURE__ */ new Map();
244
+ for (const [key, rawRelation] of Object.entries(relations)) {
245
+ if (rawRelation === void 0) continue;
246
+ if (!isPlainObject(rawRelation)) {
247
+ fail(`Invalid constructor config (relations.${key}): expected an object (an 'AdapterRelation').`);
248
+ }
249
+ const { mode, restriction, table: relatedTable, fkHere, fkThere, nullable } = rawRelation;
250
+ if (!(0, import_drizzle_orm5.is)(relatedTable, import_drizzle_orm5.Table)) {
251
+ fail(
252
+ `Invalid constructor config (relations.${key}.table): expected a Drizzle 'Table' instance (the object exported by your schema).`
253
+ );
254
+ }
255
+ if (!MODES.has(mode)) {
256
+ fail(
257
+ `Invalid constructor config (relations.${key}.mode): expected one of 'otm' | 'mto' | 'oto', got '${String(mode)}'.`
258
+ );
259
+ }
260
+ if (!RESTRICTIONS.has(restriction)) {
261
+ fail(
262
+ `Invalid constructor config (relations.${key}.restriction): expected one of 'set' | 'add', got '${String(restriction)}'.`
263
+ );
264
+ }
265
+ const thereColumns = new Set(Object.keys((0, import_drizzle_orm5.getColumns)(relatedTable)));
266
+ if (mode === "otm") {
267
+ if (fkHere !== void 0) {
268
+ fail(`Invalid constructor config (relations.${key}): mode 'otm' doesn't accept 'fkHere'.`);
269
+ }
270
+ if (typeof fkThere !== "string" || fkThere.length === 0) {
271
+ fail(
272
+ `Invalid constructor config (relations.${key}): mode 'otm' requires 'fkThere' (a column of the related table).`
273
+ );
274
+ }
275
+ if (!thereColumns.has(fkThere)) {
276
+ fail(
277
+ `Invalid constructor config (relations.${key}.fkThere): '${fkThere}' is not a column of table '${(0, import_drizzle_orm5.getTableName)(relatedTable)}'.`
278
+ );
279
+ }
280
+ } else if (mode === "mto") {
281
+ if (fkThere !== void 0) {
282
+ fail(`Invalid constructor config (relations.${key}): mode 'mto' doesn't accept 'fkThere'.`);
283
+ }
284
+ if (typeof fkHere !== "string" || fkHere.length === 0) {
285
+ fail(
286
+ `Invalid constructor config (relations.${key}): mode 'mto' requires 'fkHere' (a column of this adapter's table).`
287
+ );
288
+ }
289
+ if (!hereColumns.has(fkHere)) {
290
+ fail(
291
+ `Invalid constructor config (relations.${key}.fkHere): '${fkHere}' is not a column of table '${(0, import_drizzle_orm5.getTableName)(table)}'.`
292
+ );
293
+ }
294
+ if (nullable !== void 0 && typeof nullable !== "boolean") {
295
+ fail(`Invalid constructor config (relations.${key}.nullable): expected a boolean.`);
296
+ }
297
+ } else {
298
+ const hasHere = fkHere !== void 0;
299
+ const hasThere = fkThere !== void 0;
300
+ if (hasHere === hasThere) {
301
+ fail(
302
+ `Invalid constructor config (relations.${key}): mode 'oto' requires exactly one of 'fkHere' / 'fkThere'.`
303
+ );
304
+ }
305
+ if (hasHere) {
306
+ if (typeof fkHere !== "string" || !hereColumns.has(fkHere)) {
307
+ fail(
308
+ `Invalid constructor config (relations.${key}.fkHere): '${String(fkHere)}' is not a column of table '${(0, import_drizzle_orm5.getTableName)(table)}'.`
309
+ );
310
+ }
311
+ } else {
312
+ if (typeof fkThere !== "string" || !thereColumns.has(fkThere)) {
313
+ fail(
314
+ `Invalid constructor config (relations.${key}.fkThere): '${String(fkThere)}' is not a column of table '${(0, import_drizzle_orm5.getTableName)(relatedTable)}'.`
315
+ );
316
+ }
317
+ }
318
+ }
319
+ const relatedFieldsConfig = resolveFieldsConfig(relatedTable);
320
+ resolved.set(key, {
321
+ mode,
322
+ restriction,
323
+ table: relatedTable,
324
+ fkHere,
325
+ fkThere,
326
+ nullable,
327
+ relatedPk: relatedFieldsConfig.pk
328
+ });
329
+ }
330
+ return resolved;
331
+ }
332
+
333
+ // src/parsers/columns.parser.ts
334
+ function parseColumns(select) {
335
+ const columns = {};
336
+ let withResult;
337
+ for (const [key, value] of Object.entries(select)) {
338
+ if (value === void 0) continue;
339
+ if (isPlainObject(value)) {
340
+ withResult ??= {};
341
+ const nested = parseColumns(value);
342
+ withResult[key] = nested.with ? { columns: nested.columns, with: nested.with } : { columns: nested.columns };
343
+ } else {
344
+ columns[key] = value;
345
+ }
346
+ }
347
+ return { columns, with: withResult };
348
+ }
349
+
350
+ // src/parsers/with.parser.ts
351
+ function parseWith(relations) {
352
+ const result = {};
353
+ for (const [key, value] of Object.entries(relations)) {
354
+ if (value === void 0) continue;
355
+ result[key] = isPlainObject(value) ? { with: parseWith(value) } : value;
356
+ }
357
+ return result;
358
+ }
359
+
360
+ // src/parsers/where.parser.ts
361
+ var import_vsrepo5 = require("vsrepo");
362
+ var FIELD_OPERATOR_KEYS = /* @__PURE__ */ new Set([
363
+ "equals",
364
+ "not",
365
+ "in",
366
+ "notIn",
367
+ "gt",
368
+ "gte",
369
+ "lt",
370
+ "lte",
371
+ "between",
372
+ "contains",
373
+ "startsWith",
374
+ "endsWith",
375
+ "ignoreCase"
376
+ ]);
377
+ function isFieldOperatorObject(value) {
378
+ return Object.keys(value).some((key) => FIELD_OPERATOR_KEYS.has(key));
379
+ }
380
+ function isArrayRelationFilter(value) {
381
+ return "_some" in value || "_every" in value || "_none" in value;
382
+ }
383
+ function isObjectRelationFilter(value) {
384
+ return "_with" in value || "_without" in value;
385
+ }
386
+ function parseFieldOperators(value, dialect) {
387
+ const result = {};
388
+ const likeKey = value.ignoreCase === true && dialect !== "sqlite" ? "ilike" : "like";
389
+ for (const [key, val] of Object.entries(value)) {
390
+ if (val === void 0) continue;
391
+ switch (key) {
392
+ case "ignoreCase":
393
+ break;
394
+ case "equals":
395
+ result.eq = val;
396
+ break;
397
+ case "between": {
398
+ const [min, max] = val;
399
+ if (min !== void 0) result.gte = min;
400
+ if (max !== void 0) result.lte = max;
401
+ break;
402
+ }
403
+ case "contains":
404
+ result[likeKey] = `%${val}%`;
405
+ break;
406
+ case "startsWith":
407
+ result[likeKey] = `${val}%`;
408
+ break;
409
+ case "endsWith":
410
+ result[likeKey] = `%${val}`;
411
+ break;
412
+ case "not":
413
+ result.NOT = isPlainObject(val) && isFieldOperatorObject(val) ? parseFieldOperators(val, dialect) : val;
414
+ break;
415
+ default:
416
+ result[key] = val;
417
+ }
418
+ }
419
+ return result;
420
+ }
421
+ function parseArrayRelationFilter(value, dialect) {
422
+ if (value._every !== void 0 || value._none !== void 0) {
423
+ throw new import_vsrepo5.VSRepoAdapterError(
424
+ "Drizzle's relational query API has no native 'every'/'none' filter for to-many relations (only an implicit 'some'/exists filter, via '_some') \u2014 rewrite the filter using '_some', or fall back to 'query()' with raw SQL.",
425
+ import_vsrepo5.AdapterErrorCode.NOT_SUPPORTED,
426
+ null
427
+ );
428
+ }
429
+ return parsePlainWhere(value._some, dialect) ?? {};
430
+ }
431
+ function parseObjectRelationFilter(value, dialect) {
432
+ if (value._with !== void 0) {
433
+ return parsePlainWhere(value._with, dialect) ?? {};
434
+ }
435
+ if (value._without !== void 0) {
436
+ return { NOT: parsePlainWhere(value._without, dialect) };
437
+ }
438
+ return {};
439
+ }
440
+ function parseFieldValue(value, dialect) {
441
+ if (value === null || typeof value !== "object" || value instanceof Date) {
442
+ return value;
443
+ }
444
+ if (Array.isArray(value)) {
445
+ return { in: value };
446
+ }
447
+ const obj = value;
448
+ if (isArrayRelationFilter(obj)) return parseArrayRelationFilter(obj, dialect);
449
+ if (isObjectRelationFilter(obj)) return parseObjectRelationFilter(obj, dialect);
450
+ if (isFieldOperatorObject(obj)) return parseFieldOperators(obj, dialect);
451
+ return parsePlainWhere(obj, dialect);
452
+ }
453
+ function parsePlainWhere(where, dialect) {
454
+ if (where === void 0 || where === null) return void 0;
455
+ const result = {};
456
+ for (const [key, value] of Object.entries(where)) {
457
+ if (value === void 0) continue;
458
+ result[key] = parseFieldValue(value, dialect);
459
+ }
460
+ return result;
461
+ }
462
+ function parseWhere(where, dialect) {
463
+ if (where === void 0 || where === null) return void 0;
464
+ const result = {};
465
+ let andList;
466
+ for (const [key, value] of Object.entries(where)) {
467
+ if (value === void 0) continue;
468
+ if (key === "AND") {
469
+ const list = Array.isArray(value) ? value : [value];
470
+ andList = [...andList ?? [], ...list.map((v) => parseWhere(v, dialect))];
471
+ continue;
472
+ }
473
+ if (key === "OR") {
474
+ const list = Array.isArray(value) ? value : [value];
475
+ result.OR = list.map((v) => parseWhere(v, dialect));
476
+ continue;
477
+ }
478
+ if (key === "NOT") {
479
+ if (Array.isArray(value)) {
480
+ andList = [...andList ?? [], ...value.map((v) => ({ NOT: parseWhere(v, dialect) }))];
481
+ } else {
482
+ result.NOT = parseWhere(value, dialect);
483
+ }
484
+ continue;
485
+ }
486
+ result[key] = parseFieldValue(value, dialect);
487
+ }
488
+ if (andList) result.AND = andList;
489
+ return result;
490
+ }
491
+ function parseDrizzleWhere(where, dialect) {
492
+ return parseWhere(where, dialect);
493
+ }
494
+ function hasQuantifierFilter(where) {
495
+ if (where === null || where === void 0) return false;
496
+ if (Array.isArray(where)) {
497
+ return where.some(hasQuantifierFilter);
498
+ }
499
+ if (typeof where !== "object" || where instanceof Date) {
500
+ return false;
501
+ }
502
+ for (const [key, value] of Object.entries(where)) {
503
+ if (value === void 0) continue;
504
+ if (key === "_every" || key === "_none") return true;
505
+ if (hasQuantifierFilter(value)) return true;
506
+ }
507
+ return false;
508
+ }
509
+
510
+ // src/parsers/sql-where.parser.ts
511
+ var import_drizzle_orm6 = require("drizzle-orm");
512
+ var import_vsrepo6 = require("vsrepo");
513
+ var FIELD_OPERATOR_KEYS2 = /* @__PURE__ */ new Set([
514
+ "equals",
515
+ "not",
516
+ "in",
517
+ "notIn",
518
+ "gt",
519
+ "gte",
520
+ "lt",
521
+ "lte",
522
+ "between",
523
+ "contains",
524
+ "startsWith",
525
+ "endsWith",
526
+ "ignoreCase"
527
+ ]);
528
+ function isFieldOperatorObject2(value) {
529
+ return Object.keys(value).some((key) => FIELD_OPERATOR_KEYS2.has(key));
530
+ }
531
+ function isArrayRelationFilter2(value) {
532
+ return "_some" in value || "_every" in value || "_none" in value;
533
+ }
534
+ function isObjectRelationFilter2(value) {
535
+ return "_with" in value || "_without" in value;
536
+ }
537
+ function buildFieldOperators(column, ops) {
538
+ const parts = [];
539
+ const likeFn = ops.ignoreCase === true ? (column2, pattern) => import_drizzle_orm6.sql`lower(${column2}) like lower(${pattern})` : import_drizzle_orm6.like;
540
+ for (const [key, val] of Object.entries(ops)) {
541
+ if (val === void 0) continue;
542
+ switch (key) {
543
+ case "ignoreCase":
544
+ break;
545
+ case "equals":
546
+ parts.push(val === null ? (0, import_drizzle_orm6.isNull)(column) : (0, import_drizzle_orm6.eq)(column, val));
547
+ break;
548
+ case "not": {
549
+ if (val === null) {
550
+ parts.push((0, import_drizzle_orm6.isNotNull)(column));
551
+ break;
552
+ }
553
+ const inner = isPlainObject(val) && isFieldOperatorObject2(val) ? buildFieldOperators(column, val) : (0, import_drizzle_orm6.eq)(column, val);
554
+ if (inner) parts.push((0, import_drizzle_orm6.not)(inner));
555
+ break;
556
+ }
557
+ case "in":
558
+ parts.push((0, import_drizzle_orm6.inArray)(column, val));
559
+ break;
560
+ case "notIn":
561
+ parts.push((0, import_drizzle_orm6.notInArray)(column, val));
562
+ break;
563
+ case "gt":
564
+ parts.push((0, import_drizzle_orm6.gt)(column, val));
565
+ break;
566
+ case "gte":
567
+ parts.push((0, import_drizzle_orm6.gte)(column, val));
568
+ break;
569
+ case "lt":
570
+ parts.push((0, import_drizzle_orm6.lt)(column, val));
571
+ break;
572
+ case "lte":
573
+ parts.push((0, import_drizzle_orm6.lte)(column, val));
574
+ break;
575
+ case "between": {
576
+ const [min, max] = val;
577
+ if (min !== void 0) parts.push((0, import_drizzle_orm6.gte)(column, min));
578
+ if (max !== void 0) parts.push((0, import_drizzle_orm6.lte)(column, max));
579
+ break;
580
+ }
581
+ case "contains":
582
+ parts.push(likeFn(column, `%${val}%`));
583
+ break;
584
+ case "startsWith":
585
+ parts.push(likeFn(column, `${val}%`));
586
+ break;
587
+ case "endsWith":
588
+ parts.push(likeFn(column, `%${val}`));
589
+ break;
590
+ }
591
+ }
592
+ if (parts.length === 0) return void 0;
593
+ return parts.length === 1 ? parts[0] : (0, import_drizzle_orm6.and)(...parts);
594
+ }
595
+ function buildJoinCondition(relation, ctx) {
596
+ const relatedColumns = relation.table;
597
+ const hereColumns = ctx.table;
598
+ if (relation.fkHere) {
599
+ return (0, import_drizzle_orm6.eq)(relatedColumns[relation.relatedPk], hereColumns[relation.fkHere]);
600
+ }
601
+ return (0, import_drizzle_orm6.eq)(relatedColumns[relation.fkThere], hereColumns[ctx.pk]);
602
+ }
603
+ function buildExists(relation, condition, ctx) {
604
+ const subquery = ctx.db.select({ one: import_drizzle_orm6.sql`1` }).from(relation.table).where(condition);
605
+ return (0, import_drizzle_orm6.exists)(subquery);
606
+ }
607
+ function buildRelationCondition(key, value, relation, ctx) {
608
+ const nestedCtx = { ...ctx, table: relation.table, relations: void 0 };
609
+ if (isArrayRelationFilter2(value)) {
610
+ if (relation.mode !== "otm") {
611
+ throw new import_vsrepo6.VSRepoAdapterError(
612
+ `Field '${key}': '_some'/'_every'/'_none' can only be used on a to-many ('otm') relation.`,
613
+ import_vsrepo6.AdapterErrorCode.INVALID_DATA,
614
+ null
615
+ );
616
+ }
617
+ const join2 = buildJoinCondition(relation, ctx);
618
+ if (value._some !== void 0) {
619
+ const nested3 = parsePlainWhere2(value._some, nestedCtx);
620
+ return buildExists(relation, nested3 ? (0, import_drizzle_orm6.and)(join2, nested3) : join2, ctx);
621
+ }
622
+ if (value._none !== void 0) {
623
+ const nested3 = parsePlainWhere2(value._none, nestedCtx);
624
+ return (0, import_drizzle_orm6.not)(buildExists(relation, nested3 ? (0, import_drizzle_orm6.and)(join2, nested3) : join2, ctx));
625
+ }
626
+ const nested2 = parsePlainWhere2(value._every, nestedCtx);
627
+ if (!nested2) return import_drizzle_orm6.sql`(1 = 1)`;
628
+ return (0, import_drizzle_orm6.not)(buildExists(relation, (0, import_drizzle_orm6.and)(join2, (0, import_drizzle_orm6.not)(nested2)), ctx));
629
+ }
630
+ if (isObjectRelationFilter2(value)) {
631
+ const isWithout = "_without" in value;
632
+ const filter = isWithout ? value._without : value._with;
633
+ const join2 = buildJoinCondition(relation, ctx);
634
+ const nested2 = parsePlainWhere2(filter, nestedCtx);
635
+ const condition = nested2 ? (0, import_drizzle_orm6.and)(join2, isWithout ? (0, import_drizzle_orm6.not)(nested2) : nested2) : join2;
636
+ return buildExists(relation, condition, ctx);
637
+ }
638
+ if (relation.mode === "otm") {
639
+ throw new import_vsrepo6.VSRepoAdapterError(
640
+ `Field '${key}': to-many relation filters require '_some' (or the unsupported '_every'/'_none').`,
641
+ import_vsrepo6.AdapterErrorCode.INVALID_DATA,
642
+ null
643
+ );
644
+ }
645
+ const join = buildJoinCondition(relation, ctx);
646
+ const nested = parsePlainWhere2(value, nestedCtx);
647
+ return buildExists(relation, nested ? (0, import_drizzle_orm6.and)(join, nested) : join, ctx);
648
+ }
649
+ function buildFieldCondition(column, value) {
650
+ if (value === null) return (0, import_drizzle_orm6.isNull)(column);
651
+ if (value instanceof Date || typeof value !== "object") {
652
+ return (0, import_drizzle_orm6.eq)(column, value);
653
+ }
654
+ if (Array.isArray(value)) {
655
+ return (0, import_drizzle_orm6.inArray)(column, value);
656
+ }
657
+ return buildFieldOperators(column, value);
658
+ }
659
+ function parsePlainWhere2(where, ctx) {
660
+ if (where === void 0 || where === null) return void 0;
661
+ const tableColumns = ctx.table;
662
+ const parts = [];
663
+ for (const [key, value] of Object.entries(where)) {
664
+ if (value === void 0) continue;
665
+ const relation = ctx.relations?.get(key);
666
+ if (relation) {
667
+ parts.push(buildRelationCondition(key, value, relation, ctx));
668
+ continue;
669
+ }
670
+ const column = tableColumns[key];
671
+ if (column === void 0) {
672
+ throw new import_vsrepo6.VSRepoAdapterError(
673
+ `Unknown field '${key}' in 'where': no column or configured relation with that name on table '${(0, import_drizzle_orm6.getTableName)(ctx.table)}'.`,
674
+ import_vsrepo6.AdapterErrorCode.FIELD_NOT_FOUND,
675
+ null
676
+ );
677
+ }
678
+ const condition = buildFieldCondition(column, value);
679
+ if (condition) parts.push(condition);
680
+ }
681
+ if (parts.length === 0) return void 0;
682
+ return parts.length === 1 ? parts[0] : (0, import_drizzle_orm6.and)(...parts);
683
+ }
684
+ function parseWhere2(where, ctx) {
685
+ if (where === void 0 || where === null) return void 0;
686
+ const parts = [];
687
+ let orPart;
688
+ const plainEntries = {};
689
+ for (const [key, value] of Object.entries(where)) {
690
+ if (value === void 0) continue;
691
+ if (key === "AND") {
692
+ const list = Array.isArray(value) ? value : [value];
693
+ for (const v of list) {
694
+ const c = parseWhere2(v, ctx);
695
+ if (c) parts.push(c);
696
+ }
697
+ continue;
698
+ }
699
+ if (key === "OR") {
700
+ const list = Array.isArray(value) ? value : [value];
701
+ const ors = list.map((v) => parseWhere2(v, ctx)).filter((c) => c !== void 0);
702
+ if (ors.length > 0) orPart = ors.length === 1 ? ors[0] : (0, import_drizzle_orm6.or)(...ors);
703
+ continue;
704
+ }
705
+ if (key === "NOT") {
706
+ const list = Array.isArray(value) ? value : [value];
707
+ for (const v of list) {
708
+ const c = parseWhere2(v, ctx);
709
+ if (c) parts.push((0, import_drizzle_orm6.not)(c));
710
+ }
711
+ continue;
712
+ }
713
+ plainEntries[key] = value;
714
+ }
715
+ const plainCondition = parsePlainWhere2(plainEntries, ctx);
716
+ if (plainCondition) parts.push(plainCondition);
717
+ if (orPart) parts.push(orPart);
718
+ if (parts.length === 0) return void 0;
719
+ return parts.length === 1 ? parts[0] : (0, import_drizzle_orm6.and)(...parts);
720
+ }
721
+ function parseSqlWhere(where, ctx) {
722
+ return parseWhere2(where, ctx);
723
+ }
724
+
725
+ // src/parsers/order-by.parser.ts
726
+ var import_vsrepo7 = require("vsrepo");
727
+ function isSortDirection(value) {
728
+ return value === "asc" || value === "desc" || value === "ASC" || value === "DESC";
729
+ }
730
+ function parseOrderByField(order) {
731
+ const result = {};
732
+ for (const [key, value] of Object.entries(order)) {
733
+ if (value === void 0) continue;
734
+ if (isSortDirection(value)) {
735
+ result[key] = value.toLowerCase();
736
+ continue;
737
+ }
738
+ if (isPlainObject(value)) {
739
+ throw new import_vsrepo7.VSRepoAdapterError(
740
+ `Ordering by a nested relation field ('${key}') isn't supported at the top level of a Drizzle relational query \u2014 nest the ordering inside that relation's own 'with' config instead.`,
741
+ import_vsrepo7.AdapterErrorCode.NOT_SUPPORTED,
742
+ null
743
+ );
744
+ }
745
+ result[key] = value;
746
+ }
747
+ return result;
748
+ }
749
+ function parseOrderBy(order) {
750
+ if (order === void 0 || order === null) return void 0;
751
+ if (!Array.isArray(order)) return parseOrderByField(order);
752
+ return order.reduce((acc, field) => ({ ...acc, ...parseOrderByField(field) }), {});
753
+ }
754
+
755
+ // src/parsers/sql-order-by.parser.ts
756
+ var import_drizzle_orm7 = require("drizzle-orm");
757
+ var import_vsrepo8 = require("vsrepo");
758
+ function isSortDirection2(value) {
759
+ return value === "asc" || value === "desc" || value === "ASC" || value === "DESC";
760
+ }
761
+ function pushOrderByField(table, order, acc) {
762
+ const tableColumns = table;
763
+ for (const [key, value] of Object.entries(order)) {
764
+ if (value === void 0) continue;
765
+ if (!isSortDirection2(value)) {
766
+ if (isPlainObject(value)) {
767
+ throw new import_vsrepo8.VSRepoAdapterError(
768
+ `Ordering by a nested relation field ('${key}') isn't supported by this adapter.`,
769
+ import_vsrepo8.AdapterErrorCode.NOT_SUPPORTED,
770
+ null
771
+ );
772
+ }
773
+ continue;
774
+ }
775
+ const column = tableColumns[key];
776
+ if (!column) continue;
777
+ acc.push(value.toString().toLowerCase() === "desc" ? (0, import_drizzle_orm7.desc)(column) : (0, import_drizzle_orm7.asc)(column));
778
+ }
779
+ }
780
+ function parseSqlOrderBy(table, order) {
781
+ if (order === void 0 || order === null) return void 0;
782
+ const acc = [];
783
+ const list = Array.isArray(order) ? order : [order];
784
+ for (const field of list) pushOrderByField(table, field, acc);
785
+ return acc.length > 0 ? acc : void 0;
786
+ }
787
+
788
+ // src/resolvers/merge-entities.resolver.ts
789
+ function deepMergeValue(target, source) {
790
+ if (Array.isArray(target) && Array.isArray(source)) {
791
+ return [...target, ...source];
792
+ }
793
+ if (isPlainObject(target) && isPlainObject(source)) {
794
+ return deepMergePlain(target, source);
795
+ }
796
+ return source;
797
+ }
798
+ function deepMergePlain(target, source) {
799
+ const merged = { ...target };
800
+ for (const [key, value] of Object.entries(source)) {
801
+ if (value === void 0) continue;
802
+ merged[key] = key in target ? deepMergeValue(target[key], value) : value;
803
+ }
804
+ return merged;
805
+ }
806
+ function mergeToManyRelation(target, source, relatedPk) {
807
+ const targetByPk = /* @__PURE__ */ new Map();
808
+ const targetWithoutPk = [];
809
+ for (const item of target) {
810
+ if (item[relatedPk] !== void 0) {
811
+ targetByPk.set(item[relatedPk], item);
812
+ } else {
813
+ targetWithoutPk.push(item);
814
+ }
815
+ }
816
+ const sourceWithoutPk = [];
817
+ for (const item of source) {
818
+ if (item[relatedPk] === void 0) {
819
+ sourceWithoutPk.push(item);
820
+ continue;
821
+ }
822
+ const existing = targetByPk.get(item[relatedPk]);
823
+ targetByPk.set(item[relatedPk], existing ? deepMergePlain(existing, item) : item);
824
+ }
825
+ return [...targetByPk.values(), ...targetWithoutPk, ...sourceWithoutPk];
826
+ }
827
+ function mergeEntities(result, obj, relations) {
828
+ if (!relations) {
829
+ return deepMergePlain(result, obj);
830
+ }
831
+ const merged = { ...result };
832
+ for (const [key, field] of Object.entries(obj)) {
833
+ if (field === void 0) continue;
834
+ const relation = relations.get(key);
835
+ if (!relation) {
836
+ merged[key] = field;
837
+ continue;
838
+ }
839
+ if (relation.mode !== "otm" && isPlainObject(merged[key])) {
840
+ merged[key] = field === null ? null : deepMergePlain(merged[key], field);
841
+ continue;
842
+ }
843
+ if (relation.mode === "otm" && Array.isArray(merged[key])) {
844
+ merged[key] = mergeToManyRelation(merged[key], field, relation.relatedPk);
845
+ continue;
846
+ }
847
+ merged[key] = field;
848
+ }
849
+ return merged;
850
+ }
851
+
852
+ // src/resolvers/relation-writes.resolver.ts
853
+ var import_drizzle_orm8 = require("drizzle-orm");
854
+ var import_vsrepo9 = require("vsrepo");
855
+ var SKIP = /* @__PURE__ */ Symbol("skip");
856
+ function omitKey(item, key) {
857
+ const clone = { ...item };
858
+ delete clone[key];
859
+ return clone;
860
+ }
861
+ function splitWritePayload(obj, relations, pkName, excludePk) {
862
+ const scalarFields = {};
863
+ const fkHereEntries = [];
864
+ const fkThereEntries = [];
865
+ for (const [key, value] of Object.entries(obj)) {
866
+ if (value === void 0) continue;
867
+ const relation = relations?.get(key);
868
+ if (!relation) {
869
+ if (excludePk && key === pkName) continue;
870
+ scalarFields[key] = value;
871
+ continue;
872
+ }
873
+ if (relation.fkHere) {
874
+ fkHereEntries.push([key, relation, value]);
875
+ } else {
876
+ fkThereEntries.push([key, relation, value]);
877
+ }
878
+ }
879
+ return { scalarFields, fkHereEntries, fkThereEntries };
880
+ }
881
+ async function resolveFkHereField(tx, relation, field, currentFkValue) {
882
+ const relatedTable = relation.table;
883
+ const pkColumn = relatedTable[relation.relatedPk];
884
+ if (field === null) {
885
+ if (relation.mode === "mto" && relation.nullable) return null;
886
+ if (relation.mode === "oto" && relation.restriction === "set") {
887
+ if (currentFkValue !== void 0 && currentFkValue !== null) {
888
+ await tx.delete(relation.table).where((0, import_drizzle_orm8.eq)(pkColumn, currentFkValue));
889
+ }
890
+ return null;
891
+ }
892
+ return SKIP;
893
+ }
894
+ const pkValue = field[relation.relatedPk];
895
+ if (pkValue === void 0) {
896
+ const [created] = await tx.insert(relation.table).values(field).returning();
897
+ return created[relation.relatedPk];
898
+ }
899
+ const existing = await tx.select({ pk: pkColumn }).from(relation.table).where((0, import_drizzle_orm8.eq)(pkColumn, pkValue)).limit(1);
900
+ if (existing.length === 0) {
901
+ await tx.insert(relation.table).values(field);
902
+ } else if (relation.restriction === "set") {
903
+ const dataWithoutPk = omitKey(field, relation.relatedPk);
904
+ if (Object.keys(dataWithoutPk).length > 0) {
905
+ await tx.update(relation.table).set(dataWithoutPk).where((0, import_drizzle_orm8.eq)(pkColumn, pkValue));
906
+ }
907
+ }
908
+ return pkValue;
909
+ }
910
+ async function resolveFkHereFields(tx, entries, scalarFields, currentRow) {
911
+ for (const [key, relation, value] of entries) {
912
+ if (value !== null && typeof value !== "object") {
913
+ throw new import_vsrepo9.VSRepoAdapterError(
914
+ `Field '${key}': expected an object or 'null' for a to-one relation, got '${typeof value}'.`,
915
+ import_vsrepo9.AdapterErrorCode.INVALID_DATA,
916
+ null
917
+ );
918
+ }
919
+ const currentFkValue = currentRow?.[relation.fkHere];
920
+ const resolved = await resolveFkHereField(tx, relation, value, currentFkValue);
921
+ if (resolved !== SKIP) {
922
+ scalarFields[relation.fkHere] = resolved;
923
+ }
924
+ }
925
+ }
926
+ async function resolveOtmField(tx, relation, items, ownPkValue) {
927
+ const relatedTable = relation.table;
928
+ const fkColumn = relatedTable[relation.fkThere];
929
+ const pkColumn = relatedTable[relation.relatedPk];
930
+ const withoutPk = items.filter((item) => item[relation.relatedPk] === void 0);
931
+ const withPk = items.filter((item) => item[relation.relatedPk] !== void 0);
932
+ const connectedIds = [];
933
+ for (const item of withoutPk) {
934
+ const [insertedRow] = await tx.insert(relation.table).values({ ...item, [relation.fkThere]: ownPkValue }).returning();
935
+ if (insertedRow?.[relation.relatedPk] !== void 0) {
936
+ connectedIds.push(insertedRow[relation.relatedPk]);
937
+ }
938
+ }
939
+ for (const item of withPk) {
940
+ const pkValue = item[relation.relatedPk];
941
+ connectedIds.push(pkValue);
942
+ const existing = await tx.select({ pk: pkColumn }).from(relation.table).where((0, import_drizzle_orm8.eq)(pkColumn, pkValue)).limit(1);
943
+ if (existing.length === 0) {
944
+ await tx.insert(relation.table).values({ ...item, [relation.fkThere]: ownPkValue });
945
+ continue;
946
+ }
947
+ const setData = relation.restriction === "set" ? { ...omitKey(item, relation.relatedPk), [relation.fkThere]: ownPkValue } : { [relation.fkThere]: ownPkValue };
948
+ await tx.update(relation.table).set(setData).where((0, import_drizzle_orm8.eq)(pkColumn, pkValue));
949
+ }
950
+ if (relation.restriction === "set") {
951
+ const condition = connectedIds.length > 0 ? (0, import_drizzle_orm8.and)((0, import_drizzle_orm8.eq)(fkColumn, ownPkValue), (0, import_drizzle_orm8.notInArray)(pkColumn, connectedIds)) : (0, import_drizzle_orm8.eq)(fkColumn, ownPkValue);
952
+ await tx.delete(relation.table).where(condition);
953
+ }
954
+ }
955
+ async function resolveOtoFkThereField(tx, relation, field, ownPkValue) {
956
+ const relatedTable = relation.table;
957
+ const fkColumn = relatedTable[relation.fkThere];
958
+ const pkColumn = relatedTable[relation.relatedPk];
959
+ if (field === null) {
960
+ if (relation.restriction === "set") {
961
+ await tx.delete(relation.table).where((0, import_drizzle_orm8.eq)(fkColumn, ownPkValue));
962
+ }
963
+ return;
964
+ }
965
+ const pkValue = field[relation.relatedPk];
966
+ let keepPk = pkValue;
967
+ if (pkValue === void 0) {
968
+ const [insertedRow] = await tx.insert(relation.table).values({ ...field, [relation.fkThere]: ownPkValue }).returning();
969
+ keepPk = insertedRow?.[relation.relatedPk];
970
+ } else {
971
+ const existing = await tx.select({ pk: pkColumn }).from(relation.table).where((0, import_drizzle_orm8.eq)(pkColumn, pkValue)).limit(1);
972
+ if (existing.length === 0) {
973
+ await tx.insert(relation.table).values({ ...field, [relation.fkThere]: ownPkValue });
974
+ } else {
975
+ const setData = relation.restriction === "set" ? { ...omitKey(field, relation.relatedPk), [relation.fkThere]: ownPkValue } : { [relation.fkThere]: ownPkValue };
976
+ await tx.update(relation.table).set(setData).where((0, import_drizzle_orm8.eq)(pkColumn, pkValue));
977
+ }
978
+ }
979
+ if (relation.restriction === "set" && keepPk !== void 0) {
980
+ await tx.delete(relation.table).where((0, import_drizzle_orm8.and)((0, import_drizzle_orm8.eq)(fkColumn, ownPkValue), (0, import_drizzle_orm8.ne)(pkColumn, keepPk)));
981
+ }
982
+ }
983
+ async function resolveFkThereFields(tx, entries, ownPkValue) {
984
+ for (const [key, relation, value] of entries) {
985
+ if (relation.mode === "otm") {
986
+ if (!Array.isArray(value)) {
987
+ throw new import_vsrepo9.VSRepoAdapterError(
988
+ `Field '${key}': expected an array for a to-many relation, got '${typeof value}'.`,
989
+ import_vsrepo9.AdapterErrorCode.INVALID_DATA,
990
+ null
991
+ );
992
+ }
993
+ await resolveOtmField(tx, relation, value, ownPkValue);
994
+ continue;
995
+ }
996
+ if (value !== null && typeof value !== "object") {
997
+ throw new import_vsrepo9.VSRepoAdapterError(
998
+ `Field '${key}': expected an object or 'null' for a to-one relation, got '${typeof value}'.`,
999
+ import_vsrepo9.AdapterErrorCode.INVALID_DATA,
1000
+ null
1001
+ );
1002
+ }
1003
+ await resolveOtoFkThereField(tx, relation, value, ownPkValue);
1004
+ }
1005
+ }
1006
+
1007
+ // src/drizzle.adapter.ts
1008
+ var DrizzleAdapter = class extends import_vsrepo10.VSRepoAdapter {
1009
+ table;
1010
+ db;
1011
+ dialect;
1012
+ pk;
1013
+ queryKey;
1014
+ relations;
1015
+ constructor(db, config) {
1016
+ super();
1017
+ const validated = validateDrizzleAdapterConfig(db, config);
1018
+ this.db = validated.db;
1019
+ this.table = validated.config.table;
1020
+ this.dialect = validated.config.dialect ?? "postgresql";
1021
+ this.queryKey = validated.config.queryKey;
1022
+ const fieldsConfig = resolveFieldsConfig(this.table);
1023
+ this.pk = fieldsConfig.pk;
1024
+ this.relations = validateRelations(this.table, this.dialect, validated.config.relations);
1025
+ }
1026
+ /**
1027
+ * Returns `db.query[queryKey]` (the relational query builder entry for
1028
+ * this adapter's table), reading from `db` when a transaction/executor
1029
+ * override is passed via `options.db`, otherwise from the root client.
1030
+ */
1031
+ getQueryBuilder(db) {
1032
+ const executor = db ?? this.db;
1033
+ return executor.query[this.queryKey];
1034
+ }
1035
+ /**
1036
+ * Resolves the "read" part of a query arg: `columns`/`with`/`where`/
1037
+ * `orderBy`/pagination.
1038
+ *
1039
+ * Per the adapter contract: when both `select` and `relations` are
1040
+ * given, `select` wins and `relations` is ignored entirely.
1041
+ */
1042
+ async resolveReadArgs(where, options, single = false) {
1043
+ options ??= {};
1044
+ let columns;
1045
+ let withArg;
1046
+ if (options.select) {
1047
+ const parsedSelect = parseColumns(options.select);
1048
+ columns = parsedSelect.columns;
1049
+ withArg = parsedSelect.with;
1050
+ } else if (options.relations) {
1051
+ withArg = parseWith(options.relations);
1052
+ }
1053
+ const found = await this.resolveFindWhere(where, {
1054
+ db: options.db,
1055
+ order: options.order,
1056
+ limit: single ? 1 : options.pagination?.limit,
1057
+ offset: single ? void 0 : options.pagination?.offset
1058
+ });
1059
+ return {
1060
+ where: found.where,
1061
+ columns,
1062
+ with: withArg,
1063
+ // When the prefetch already applied limit/offset, `IN (pks)` no longer preserves that
1064
+ // order on its own, so the same ordering has to be re-applied at this level too — but
1065
+ // limit/offset themselves must NOT be re-applied, since the pk set is already the exact page.
1066
+ orderBy: found.paginationApplied ? found.orderBy : parseOrderBy(options.order),
1067
+ limit: found.paginationApplied ? void 0 : options.pagination?.limit,
1068
+ offset: found.paginationApplied ? void 0 : options.pagination?.offset
1069
+ };
1070
+ }
1071
+ /** Builds the context `parseSqlWhere` needs to resolve `_with`/`_without`/`_some`/`_every`/`_none` relation filters. */
1072
+ getSqlWhereContext(db) {
1073
+ return {
1074
+ table: this.table,
1075
+ pk: this.pk,
1076
+ relations: this.relations,
1077
+ db: db ?? this.db
1078
+ };
1079
+ }
1080
+ /**
1081
+ * Resolves a user-supplied `VSRepoWhere<T>` into the `where` shape the
1082
+ * relational query API (`db.query[queryKey].findFirst/findMany`) accepts.
1083
+ *
1084
+ * The relational API's own object-shaped `where` (`where.parser.ts`) has
1085
+ * no native `_every`/`_none` semantics for to-many relations — so when
1086
+ * `where` contains one (`hasQuantifierFilter`), this instead:
1087
+ * 1. Resolves `where` into a `SQL` condition via `sql-where.parser.ts`
1088
+ * (which DOES support `_every`/`_none`, via `NOT EXISTS`);
1089
+ * 2. Runs `db.select({pk}).from(table).where(condition)`, applying the
1090
+ * SAME `order`/`limit`/`offset` the final query would've used
1091
+ * (`sql-order-by.parser.ts`), so the prefetch only ever pulls the
1092
+ * rows the caller actually needs, instead of every matching row;
1093
+ * 3. Returns `parseDrizzleWhere({ [pk]: { in: pks } })` instead — the
1094
+ * relational API then only has to filter by pk (trivial for it),
1095
+ * while still handling `columns`/`with` on the correct result set.
1096
+ *
1097
+ * Since SQL `IN (...)` doesn't preserve the given list's order, `resolveReadArgs`
1098
+ * re-applies `orderBy` (but NOT `limit`/`offset`, already baked into the pk set)
1099
+ * on the final relational query when `paginationApplied` comes back `true`.
1100
+ *
1101
+ * This keeps `_every`/`_none` support consistent between this adapter's
1102
+ * two `where` parsers — from the outside, `findOne`/`findMany`/etc. never
1103
+ * throw `NOT_SUPPORTED` for them, at the cost of an extra round-trip only
1104
+ * when they're actually used.
1105
+ */
1106
+ async resolveFindWhere(where, opts) {
1107
+ if (!hasQuantifierFilter(where)) {
1108
+ return { where: parseDrizzleWhere(where, this.dialect), paginationApplied: false };
1109
+ }
1110
+ const executor = opts?.db ?? this.db;
1111
+ const pkColumn = this.table[this.pk];
1112
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1113
+ const sqlOrderBy = parseSqlOrderBy(this.table, opts?.order);
1114
+ let qb = executor.select({ pk: pkColumn }).from(this.table).where(condition);
1115
+ if (sqlOrderBy) qb = qb.orderBy(...sqlOrderBy);
1116
+ if (opts?.limit !== void 0) qb = qb.limit(opts.limit);
1117
+ if (opts?.offset !== void 0) qb = qb.offset(opts.offset);
1118
+ const rows = await qb;
1119
+ const pks = rows.map((row) => row.pk);
1120
+ return {
1121
+ where: parseDrizzleWhere({ [this.pk]: { in: pks } }, this.dialect),
1122
+ orderBy: parseOrderBy(opts?.order),
1123
+ paginationApplied: opts?.limit !== void 0 || opts?.offset !== void 0
1124
+ };
1125
+ }
1126
+ /**
1127
+ * Strips relation fields from a payload — used by `createMany`/`updateMany`/
1128
+ * `updateManyReturning`, since batch statements only accept flat column
1129
+ * data (no nested writes). Throws `VSRepoAdapterError` (code
1130
+ * `NOT_SUPPORTED`) instead of silently dropping the field, when a
1131
+ * configured relation field is present in the payload.
1132
+ */
1133
+ stripRelationFields(obj) {
1134
+ if (!this.relations) return obj;
1135
+ const data = {};
1136
+ for (const [key, value] of Object.entries(obj)) {
1137
+ if (value === void 0) continue;
1138
+ if (this.relations.has(key)) {
1139
+ throw new import_vsrepo10.VSRepoAdapterError(
1140
+ `Field '${key}' is a configured relation, but this adapter's *Many operations don't support nested relation writes.`,
1141
+ import_vsrepo10.AdapterErrorCode.NOT_SUPPORTED,
1142
+ null
1143
+ );
1144
+ }
1145
+ data[key] = value;
1146
+ }
1147
+ return data;
1148
+ }
1149
+ isRootClient(db) {
1150
+ return typeof db?.rollback !== "function";
1151
+ }
1152
+ async runTransactional(db, fn) {
1153
+ if (db && !this.isRootClient(db)) {
1154
+ return fn(db);
1155
+ }
1156
+ return (db ?? this.db).transaction(fn);
1157
+ }
1158
+ async runInTransaction(fn, options) {
1159
+ if (options?.timeoutMs !== void 0) {
1160
+ throw new import_vsrepo10.VSRepoAdapterError(
1161
+ "This adapter doesn't support 'timeoutMs' in transactions.",
1162
+ import_vsrepo10.AdapterErrorCode.NOT_SUPPORTED,
1163
+ null
1164
+ );
1165
+ }
1166
+ try {
1167
+ return await this.db.transaction(fn, {
1168
+ isolationLevel: options?.isolationLevel && resolveIsolationLevel(options.isolationLevel)
1169
+ });
1170
+ } catch (error) {
1171
+ throw mapDrizzleError(error, "runInTransaction", this.dialect);
1172
+ }
1173
+ }
1174
+ getDbClient() {
1175
+ return this.db;
1176
+ }
1177
+ async query(rawQuery, options) {
1178
+ const executor = options?.db ?? this.db;
1179
+ try {
1180
+ const sqlQuery = resolveRawSql(this.dialect, rawQuery, options?.args);
1181
+ const result = await executor.execute(sqlQuery);
1182
+ return resolveRawResult(this.dialect, result, options?.modifying ?? false);
1183
+ } catch (error) {
1184
+ throw mapDrizzleError(error, "query", this.dialect);
1185
+ }
1186
+ }
1187
+ async findOne(where, options) {
1188
+ try {
1189
+ const arg = await this.resolveReadArgs(where, options, true);
1190
+ const result = await this.getQueryBuilder(options?.db).findFirst(arg);
1191
+ return result ?? null;
1192
+ } catch (error) {
1193
+ throw mapDrizzleError(error, "findOne", this.dialect);
1194
+ }
1195
+ }
1196
+ async findOneOrThrow(where, options) {
1197
+ try {
1198
+ const arg = await this.resolveReadArgs(where, options, true);
1199
+ const result = await this.getQueryBuilder(options?.db).findFirst(arg);
1200
+ if (!result) {
1201
+ throw new import_vsrepo10.VSRepoAdapterError(
1202
+ "'findOneOrThrow' found no record matching the given 'where'.",
1203
+ import_vsrepo10.AdapterErrorCode.NOT_FOUND,
1204
+ null
1205
+ );
1206
+ }
1207
+ return result;
1208
+ } catch (error) {
1209
+ throw mapDrizzleError(error, "findOneOrThrow", this.dialect);
1210
+ }
1211
+ }
1212
+ async findMany(where, options) {
1213
+ if (options?.distinct !== void 0) {
1214
+ throw new import_vsrepo10.VSRepoAdapterError(
1215
+ "This adapter doesn't support 'distinct' in 'findMany': Drizzle's relational query API (db.query[queryKey].findMany) has no 'distinct' option.",
1216
+ import_vsrepo10.AdapterErrorCode.NOT_SUPPORTED,
1217
+ null
1218
+ );
1219
+ }
1220
+ try {
1221
+ const arg = await this.resolveReadArgs(where, options);
1222
+ return await this.getQueryBuilder(options?.db).findMany(arg);
1223
+ } catch (error) {
1224
+ throw mapDrizzleError(error, "findMany", this.dialect);
1225
+ }
1226
+ }
1227
+ async save(obj, options) {
1228
+ try {
1229
+ const objAny = obj;
1230
+ const pkValue = objAny[this.pk];
1231
+ if (pkValue === void 0) {
1232
+ return await this.create(obj, options);
1233
+ }
1234
+ return await this.runTransactional(options?.db, async (tx) => {
1235
+ const pkColumn = this.table[this.pk];
1236
+ const existing = await tx.select({ pk: pkColumn }).from(this.table).where((0, import_drizzle_orm9.eq)(pkColumn, pkValue)).limit(1);
1237
+ if (existing.length === 0) {
1238
+ return this.create(obj, { ...options, db: tx });
1239
+ }
1240
+ return this.update({ [this.pk]: pkValue }, obj, { ...options, db: tx });
1241
+ });
1242
+ } catch (error) {
1243
+ throw mapDrizzleError(error, "save", this.dialect);
1244
+ }
1245
+ }
1246
+ async saveMany(objs, options) {
1247
+ try {
1248
+ return await this.runTransactional(
1249
+ options?.db,
1250
+ (tx) => Promise.all(objs.map((obj) => this.save(obj, { ...options, db: tx })))
1251
+ );
1252
+ } catch (error) {
1253
+ throw mapDrizzleError(error, "saveMany", this.dialect);
1254
+ }
1255
+ }
1256
+ async create(obj, options) {
1257
+ try {
1258
+ return await this.runTransactional(options?.db, async (tx) => {
1259
+ const objAny = obj;
1260
+ const { scalarFields, fkHereEntries, fkThereEntries } = splitWritePayload(
1261
+ objAny,
1262
+ this.relations,
1263
+ this.pk,
1264
+ false
1265
+ );
1266
+ await resolveFkHereFields(tx, fkHereEntries, scalarFields, void 0);
1267
+ const [created] = await tx.insert(this.table).values(scalarFields).returning();
1268
+ const ownPkValue = created[this.pk];
1269
+ await resolveFkThereFields(tx, fkThereEntries, ownPkValue);
1270
+ const readArg = await this.resolveReadArgs(
1271
+ { [this.pk]: ownPkValue },
1272
+ options
1273
+ );
1274
+ const result = await this.getQueryBuilder(tx).findFirst(readArg);
1275
+ return result ?? created;
1276
+ });
1277
+ } catch (error) {
1278
+ throw mapDrizzleError(error, "create", this.dialect);
1279
+ }
1280
+ }
1281
+ async createMany(objs, options) {
1282
+ try {
1283
+ const data = objs.map((obj) => this.stripRelationFields(obj));
1284
+ const executor = options?.db ?? this.db;
1285
+ let qb = executor.insert(this.table).values(data);
1286
+ if (options?.ignoreConflicts) qb = qb.onConflictDoNothing();
1287
+ const result = await qb;
1288
+ const affected = resolveRawResult(this.dialect, result, true);
1289
+ return { count: affected ?? data.length };
1290
+ } catch (error) {
1291
+ throw mapDrizzleError(error, "createMany", this.dialect);
1292
+ }
1293
+ }
1294
+ async createManyReturning(objs, options) {
1295
+ try {
1296
+ const data = objs.map((obj) => this.stripRelationFields(obj));
1297
+ const executor = options?.db ?? this.db;
1298
+ let qb = executor.insert(this.table).values(data);
1299
+ if (options?.ignoreConflicts) qb = qb.onConflictDoNothing();
1300
+ return await qb.returning();
1301
+ } catch (error) {
1302
+ throw mapDrizzleError(error, "createManyReturning", this.dialect);
1303
+ }
1304
+ }
1305
+ async delete(where, options) {
1306
+ try {
1307
+ return await this.runTransactional(options?.db, async (tx) => {
1308
+ const readArg = await this.resolveReadArgs(where, options, true);
1309
+ const current = await this.getQueryBuilder(tx).findFirst(readArg);
1310
+ if (!current) {
1311
+ throw new import_vsrepo10.VSRepoAdapterError(
1312
+ "'delete' found no record matching the given 'where'.",
1313
+ import_vsrepo10.AdapterErrorCode.NOT_FOUND,
1314
+ null
1315
+ );
1316
+ }
1317
+ const pkColumn = this.table[this.pk];
1318
+ await tx.delete(this.table).where((0, import_drizzle_orm9.eq)(pkColumn, current[this.pk]));
1319
+ return current;
1320
+ });
1321
+ } catch (error) {
1322
+ throw mapDrizzleError(error, "delete", this.dialect);
1323
+ }
1324
+ }
1325
+ async deleteMany(where, options) {
1326
+ try {
1327
+ const executor = options?.db ?? this.db;
1328
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1329
+ const result = await executor.delete(this.table).where(condition);
1330
+ const affected = resolveRawResult(this.dialect, result, true);
1331
+ return { count: affected ?? 0 };
1332
+ } catch (error) {
1333
+ throw mapDrizzleError(error, "deleteMany", this.dialect);
1334
+ }
1335
+ }
1336
+ async deleteManyReturning(where, options) {
1337
+ try {
1338
+ const executor = options?.db ?? this.db;
1339
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1340
+ return await executor.delete(this.table).where(condition).returning();
1341
+ } catch (error) {
1342
+ throw mapDrizzleError(error, "deleteManyReturning", this.dialect);
1343
+ }
1344
+ }
1345
+ async update(where, obj, options) {
1346
+ try {
1347
+ return await this.runTransactional(options?.db, async (tx) => {
1348
+ const current = await this.getQueryBuilder(tx).findFirst({
1349
+ where: (await this.resolveFindWhere(where, { db: tx, limit: 1 })).where
1350
+ });
1351
+ if (!current) {
1352
+ throw new import_vsrepo10.VSRepoAdapterError(
1353
+ "'update' found no record matching the given 'where'.",
1354
+ import_vsrepo10.AdapterErrorCode.NOT_FOUND,
1355
+ null
1356
+ );
1357
+ }
1358
+ const ownPkValue = current[this.pk];
1359
+ const objAny = obj;
1360
+ const { scalarFields, fkHereEntries, fkThereEntries } = splitWritePayload(
1361
+ objAny,
1362
+ this.relations,
1363
+ this.pk,
1364
+ true
1365
+ );
1366
+ await resolveFkHereFields(tx, fkHereEntries, scalarFields, current);
1367
+ if (Object.keys(scalarFields).length > 0) {
1368
+ const pkColumn = this.table[this.pk];
1369
+ await tx.update(this.table).set(scalarFields).where((0, import_drizzle_orm9.eq)(pkColumn, ownPkValue));
1370
+ }
1371
+ await resolveFkThereFields(tx, fkThereEntries, ownPkValue);
1372
+ const readArg = await this.resolveReadArgs(
1373
+ { [this.pk]: ownPkValue },
1374
+ options
1375
+ );
1376
+ const result = await this.getQueryBuilder(tx).findFirst(readArg);
1377
+ return result ?? current;
1378
+ });
1379
+ } catch (error) {
1380
+ throw mapDrizzleError(error, "update", this.dialect);
1381
+ }
1382
+ }
1383
+ async updateMany(where, obj, options) {
1384
+ try {
1385
+ const executor = options?.db ?? this.db;
1386
+ const data = this.stripRelationFields(obj);
1387
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1388
+ const result = await executor.update(this.table).set(data).where(condition);
1389
+ const affected = resolveRawResult(this.dialect, result, true);
1390
+ return { count: affected ?? 0 };
1391
+ } catch (error) {
1392
+ throw mapDrizzleError(error, "updateMany", this.dialect);
1393
+ }
1394
+ }
1395
+ async updateManyReturning(where, obj, options) {
1396
+ try {
1397
+ const executor = options?.db ?? this.db;
1398
+ const data = this.stripRelationFields(obj);
1399
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1400
+ return await executor.update(this.table).set(data).where(condition).returning();
1401
+ } catch (error) {
1402
+ throw mapDrizzleError(error, "updateManyReturning", this.dialect);
1403
+ }
1404
+ }
1405
+ async count(where, options) {
1406
+ try {
1407
+ const executor = options?.db ?? this.db;
1408
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1409
+ const [row] = await executor.select({ value: (0, import_drizzle_orm9.count)() }).from(this.table).where(condition);
1410
+ return Number(row?.value ?? 0);
1411
+ } catch (error) {
1412
+ throw mapDrizzleError(error, "count", this.dialect);
1413
+ }
1414
+ }
1415
+ async exists(where, options) {
1416
+ try {
1417
+ const executor = options?.db ?? this.db;
1418
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1419
+ const rows = await executor.select({ one: import_drizzle_orm9.sql`1` }).from(this.table).where(condition).limit(1);
1420
+ return rows.length > 0;
1421
+ } catch (error) {
1422
+ throw mapDrizzleError(error, "exists", this.dialect);
1423
+ }
1424
+ }
1425
+ async merge(where, obj, options) {
1426
+ try {
1427
+ const readArg = await this.resolveReadArgs(where, options);
1428
+ const result = await this.getQueryBuilder(options?.db).findFirst(readArg);
1429
+ if (!result) {
1430
+ throw new import_vsrepo10.VSRepoAdapterError(
1431
+ "'merge' found no record matching the given 'where'.",
1432
+ import_vsrepo10.AdapterErrorCode.NOT_FOUND,
1433
+ null
1434
+ );
1435
+ }
1436
+ return mergeEntities(result, obj, this.relations);
1437
+ } catch (error) {
1438
+ throw mapDrizzleError(error, "merge", this.dialect);
1439
+ }
1440
+ }
1441
+ async upsert(where, create, update, options) {
1442
+ try {
1443
+ return await this.runTransactional(options?.db, async (tx) => {
1444
+ const current = await this.getQueryBuilder(tx).findFirst({
1445
+ where: (await this.resolveFindWhere(where, { db: tx, limit: 1 })).where
1446
+ });
1447
+ if (current) {
1448
+ const ownPkValue = current[this.pk];
1449
+ return this.update({ [this.pk]: ownPkValue }, update, {
1450
+ ...options,
1451
+ db: tx
1452
+ });
1453
+ }
1454
+ return this.create(create, { ...options, db: tx });
1455
+ });
1456
+ } catch (error) {
1457
+ throw mapDrizzleError(error, "upsert", this.dialect);
1458
+ }
1459
+ }
1460
+ /** Shared implementation behind `incrementOne`/`decrementOne`/`multiplyOne`/`divideOne`. */
1461
+ async atomicUpdate(operation, field, toExpression, value, where, options) {
1462
+ try {
1463
+ return await this.runTransactional(options?.db, async (tx) => {
1464
+ const current = await this.getQueryBuilder(tx).findFirst({
1465
+ where: (await this.resolveFindWhere(where, { db: tx, limit: 1 })).where
1466
+ });
1467
+ if (!current) {
1468
+ throw new import_vsrepo10.VSRepoAdapterError(
1469
+ `'${operation}' found no record matching the given 'where'.`,
1470
+ import_vsrepo10.AdapterErrorCode.NOT_FOUND,
1471
+ null
1472
+ );
1473
+ }
1474
+ const ownPkValue = current[this.pk];
1475
+ const pkColumn = this.table[this.pk];
1476
+ const column = this.table[field];
1477
+ await tx.update(this.table).set({ [field]: toExpression(column, value) }).where((0, import_drizzle_orm9.eq)(pkColumn, ownPkValue));
1478
+ const readArg = await this.resolveReadArgs(
1479
+ { [this.pk]: ownPkValue },
1480
+ options
1481
+ );
1482
+ return await this.getQueryBuilder(tx).findFirst(readArg);
1483
+ });
1484
+ } catch (error) {
1485
+ throw mapDrizzleError(error, operation, this.dialect);
1486
+ }
1487
+ }
1488
+ incrementOne(field, value, where, options) {
1489
+ return this.atomicUpdate("incrementOne", field, (column, v) => import_drizzle_orm9.sql`${column} + ${v}`, value, where, options);
1490
+ }
1491
+ decrementOne(field, value, where, options) {
1492
+ return this.atomicUpdate("decrementOne", field, (column, v) => import_drizzle_orm9.sql`${column} - ${v}`, value, where, options);
1493
+ }
1494
+ multiplyOne(field, value, where, options) {
1495
+ return this.atomicUpdate("multiplyOne", field, (column, v) => import_drizzle_orm9.sql`${column} * ${v}`, value, where, options);
1496
+ }
1497
+ divideOne(field, value, where, options) {
1498
+ return this.atomicUpdate("divideOne", field, (column, v) => import_drizzle_orm9.sql`${column} / ${v}`, value, where, options);
1499
+ }
1500
+ /** Shared implementation behind `sum`/`average`/`min`/`max`. */
1501
+ async aggregate(operation, fn, field, where, options) {
1502
+ try {
1503
+ const executor = options?.db ?? this.db;
1504
+ const condition = parseSqlWhere(where, this.getSqlWhereContext(executor));
1505
+ const column = this.table[field];
1506
+ const [row] = await executor.select({ value: fn(column) }).from(this.table).where(condition);
1507
+ const raw = row?.value;
1508
+ if (raw === null || raw === void 0) return null;
1509
+ return typeof raw === "number" ? raw : Number(raw);
1510
+ } catch (error) {
1511
+ throw mapDrizzleError(error, operation, this.dialect);
1512
+ }
1513
+ }
1514
+ sum(field, where, options) {
1515
+ return this.aggregate("sum", import_drizzle_orm9.sum, field, where, options);
1516
+ }
1517
+ average(field, where, options) {
1518
+ return this.aggregate("average", import_drizzle_orm9.avg, field, where, options);
1519
+ }
1520
+ min(field, where, options) {
1521
+ return this.aggregate("min", import_drizzle_orm9.min, field, where, options);
1522
+ }
1523
+ max(field, where, options) {
1524
+ return this.aggregate("max", import_drizzle_orm9.max, field, where, options);
1525
+ }
1526
+ };
1527
+ // Annotate the CommonJS export names for ESM import in node:
1528
+ 0 && (module.exports = {
1529
+ DrizzleAdapter
1530
+ });
1531
+ //# sourceMappingURL=index.cjs.map