@farming-labs/orm-sql 0.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 ADDED
@@ -0,0 +1,926 @@
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, desc) => {
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: !(desc = __getOwnPropDesc(from, key)) || desc.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
+ createMysqlDriver: () => createMysqlDriver,
24
+ createPgClientDriver: () => createPgClientDriver,
25
+ createPgPoolDriver: () => createPgPoolDriver,
26
+ createSqliteDriver: () => createSqliteDriver
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+ var import_node_crypto = require("crypto");
30
+ var import_orm = require("@farming-labs/orm");
31
+ var manifestCache = /* @__PURE__ */ new WeakMap();
32
+ function getManifest(schema) {
33
+ const cached = manifestCache.get(schema);
34
+ if (cached) return cached;
35
+ const next = (0, import_orm.createManifest)(schema);
36
+ manifestCache.set(schema, next);
37
+ return next;
38
+ }
39
+ function quoteIdentifier(value, dialect) {
40
+ if (dialect === "mysql") {
41
+ return `\`${value.replace(/`/g, "``")}\``;
42
+ }
43
+ return `"${value.replace(/"/g, '""')}"`;
44
+ }
45
+ function createPlaceholder(dialect, state, value) {
46
+ state.params.push(value);
47
+ return dialect === "postgres" ? `$${state.params.length}` : "?";
48
+ }
49
+ function parseReference(reference) {
50
+ if (!reference) return null;
51
+ const [model, field] = reference.split(".");
52
+ if (!model || !field) return null;
53
+ return { model, field };
54
+ }
55
+ function identityField(model) {
56
+ if (model.fields.id) return model.fields.id;
57
+ const uniqueField = Object.values(model.fields).find((field) => field.unique);
58
+ if (uniqueField) return uniqueField;
59
+ throw new Error(
60
+ `Model "${model.name}" requires an "id" field or a unique field for the SQL runtime.`
61
+ );
62
+ }
63
+ function applyDefault(value, field) {
64
+ if (value !== void 0) return value;
65
+ if (field.generated === "id") return (0, import_node_crypto.randomUUID)();
66
+ if (field.generated === "now") return /* @__PURE__ */ new Date();
67
+ if (typeof field.defaultValue === "function") {
68
+ return field.defaultValue();
69
+ }
70
+ return field.defaultValue;
71
+ }
72
+ function encodeValue(field, dialect, value) {
73
+ if (value === void 0) return value;
74
+ if (value === null) return null;
75
+ if (field.kind === "boolean") {
76
+ if (dialect === "postgres") return Boolean(value);
77
+ return value ? 1 : 0;
78
+ }
79
+ if (field.kind === "datetime") {
80
+ return value instanceof Date ? value.toISOString() : value;
81
+ }
82
+ return value;
83
+ }
84
+ function decodeValue(field, value) {
85
+ if (value === void 0) return value;
86
+ if (value === null) return null;
87
+ if (field.kind === "boolean") {
88
+ if (typeof value === "boolean") return value;
89
+ if (typeof value === "number") return value !== 0;
90
+ if (typeof value === "string") {
91
+ return value === "1" || value.toLowerCase() === "true" || value.toLowerCase() === "t";
92
+ }
93
+ }
94
+ if (field.kind === "datetime") {
95
+ if (value instanceof Date) return value;
96
+ return new Date(String(value));
97
+ }
98
+ return value;
99
+ }
100
+ function decodeRow(model, row) {
101
+ const output = {};
102
+ for (const field of Object.values(model.fields)) {
103
+ output[field.name] = decodeValue(field, row[field.name]);
104
+ }
105
+ return output;
106
+ }
107
+ function mergeWhere(...clauses) {
108
+ const defined = clauses.filter(Boolean);
109
+ if (!defined.length) return void 0;
110
+ if (defined.length === 1) return defined[0];
111
+ return {
112
+ AND: defined
113
+ };
114
+ }
115
+ function isFilterObject(value) {
116
+ return !!value && typeof value === "object" && !(value instanceof Date) && !Array.isArray(value);
117
+ }
118
+ function extractEqualityValue(filter) {
119
+ if (!isFilterObject(filter)) {
120
+ return {
121
+ supported: true,
122
+ value: filter
123
+ };
124
+ }
125
+ const keys = Object.keys(filter);
126
+ if (keys.length === 1 && "eq" in filter) {
127
+ return {
128
+ supported: true,
129
+ value: filter.eq
130
+ };
131
+ }
132
+ return {
133
+ supported: false,
134
+ value: void 0
135
+ };
136
+ }
137
+ function extractUpsertConflict(model, where) {
138
+ const keys = Object.keys(where).filter((key) => key !== "AND" && key !== "OR" && key !== "NOT");
139
+ if ("AND" in where || "OR" in where || "NOT" in where || keys.length !== 1) {
140
+ throw new Error(
141
+ `Upsert on model "${model.name}" requires a single unique equality filter in "where".`
142
+ );
143
+ }
144
+ const fieldName = keys[0];
145
+ const field = model.fields[fieldName];
146
+ if (!field) {
147
+ throw new Error(`Unknown field "${fieldName}" on model "${model.name}".`);
148
+ }
149
+ if (!(field.kind === "id" || field.unique)) {
150
+ throw new Error(
151
+ `Upsert on model "${model.name}" requires the "where" field "${fieldName}" to be unique or an id field.`
152
+ );
153
+ }
154
+ const { supported, value } = extractEqualityValue(where[fieldName]);
155
+ if (!supported || value === void 0 || value === null) {
156
+ throw new Error(
157
+ `Upsert on model "${model.name}" requires the "where" field "${fieldName}" to use a single non-null equality value.`
158
+ );
159
+ }
160
+ return {
161
+ field,
162
+ value
163
+ };
164
+ }
165
+ function mergeUpsertCreateData(model, createData, conflict) {
166
+ const currentValue = createData[conflict.field.name];
167
+ if (currentValue !== void 0 && currentValue !== conflict.value) {
168
+ throw new Error(
169
+ `Upsert on model "${model.name}" requires create.${conflict.field.name} to match where.${conflict.field.name}.`
170
+ );
171
+ }
172
+ return {
173
+ ...createData,
174
+ [conflict.field.name]: currentValue ?? conflict.value
175
+ };
176
+ }
177
+ function validateUpsertUpdateData(model, updateData, conflict) {
178
+ const nextValue = updateData[conflict.field.name];
179
+ if (nextValue !== void 0 && nextValue !== conflict.value) {
180
+ throw new Error(
181
+ `Upsert on model "${model.name}" cannot change the conflict field "${conflict.field.name}".`
182
+ );
183
+ }
184
+ }
185
+ function compileFieldFilter(model, fieldName, filter, dialect, state) {
186
+ const field = model.fields[fieldName];
187
+ if (!field) {
188
+ throw new Error(`Unknown field "${fieldName}" on model "${model.name}".`);
189
+ }
190
+ const column = `${quoteIdentifier(model.table, dialect)}.${quoteIdentifier(field.column, dialect)}`;
191
+ if (!isFilterObject(filter)) {
192
+ if (filter === null) return `${column} is null`;
193
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, filter));
194
+ return `${column} = ${placeholder}`;
195
+ }
196
+ const clauses = [];
197
+ if ("eq" in filter) {
198
+ if (filter.eq === null) {
199
+ clauses.push(`${column} is null`);
200
+ } else {
201
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, filter.eq));
202
+ clauses.push(`${column} = ${placeholder}`);
203
+ }
204
+ }
205
+ if ("not" in filter) {
206
+ if (filter.not === null) {
207
+ clauses.push(`${column} is not null`);
208
+ } else {
209
+ const placeholder = createPlaceholder(
210
+ dialect,
211
+ state,
212
+ encodeValue(field, dialect, filter.not)
213
+ );
214
+ clauses.push(`${column} <> ${placeholder}`);
215
+ }
216
+ }
217
+ if ("in" in filter) {
218
+ const values = Array.isArray(filter.in) ? filter.in : [];
219
+ if (!values.length) {
220
+ clauses.push("1 = 0");
221
+ } else {
222
+ const placeholders = values.map(
223
+ (value) => createPlaceholder(dialect, state, encodeValue(field, dialect, value))
224
+ );
225
+ clauses.push(`${column} in (${placeholders.join(", ")})`);
226
+ }
227
+ }
228
+ if ("contains" in filter) {
229
+ const placeholder = createPlaceholder(dialect, state, String(filter.contains ?? ""));
230
+ clauses.push(
231
+ dialect === "postgres" ? `strpos(${column}, ${placeholder}) > 0` : `instr(${column}, ${placeholder}) > 0`
232
+ );
233
+ }
234
+ if ("gt" in filter) {
235
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, filter.gt));
236
+ clauses.push(`${column} > ${placeholder}`);
237
+ }
238
+ if ("gte" in filter) {
239
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, filter.gte));
240
+ clauses.push(`${column} >= ${placeholder}`);
241
+ }
242
+ if ("lt" in filter) {
243
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, filter.lt));
244
+ clauses.push(`${column} < ${placeholder}`);
245
+ }
246
+ if ("lte" in filter) {
247
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, filter.lte));
248
+ clauses.push(`${column} <= ${placeholder}`);
249
+ }
250
+ if (!clauses.length) return "1 = 1";
251
+ if (clauses.length === 1) return clauses[0];
252
+ return `(${clauses.join(" and ")})`;
253
+ }
254
+ function compileWhere(model, where, dialect, state) {
255
+ if (!where) return void 0;
256
+ const clauses = [];
257
+ for (const [key, value] of Object.entries(where)) {
258
+ if (key === "AND") {
259
+ const items = Array.isArray(value) ? value : [];
260
+ if (!items.length) continue;
261
+ const nested = items.map((item) => compileWhere(model, item, dialect, state)).filter(Boolean).map((item) => `(${item})`);
262
+ if (nested.length) clauses.push(nested.join(" and "));
263
+ continue;
264
+ }
265
+ if (key === "OR") {
266
+ const items = Array.isArray(value) ? value : [];
267
+ if (!items.length) continue;
268
+ const nested = items.map((item) => compileWhere(model, item, dialect, state)).filter(Boolean).map((item) => `(${item})`);
269
+ if (nested.length) clauses.push(`(${nested.join(" or ")})`);
270
+ continue;
271
+ }
272
+ if (key === "NOT") {
273
+ const nested = compileWhere(model, value, dialect, state);
274
+ if (nested) clauses.push(`not (${nested})`);
275
+ continue;
276
+ }
277
+ clauses.push(compileFieldFilter(model, key, value, dialect, state));
278
+ }
279
+ if (!clauses.length) return void 0;
280
+ return clauses.join(" and ");
281
+ }
282
+ function compileOrderBy(model, orderBy, dialect) {
283
+ if (!orderBy) return "";
284
+ const parts = Object.entries(orderBy).filter(([fieldName]) => fieldName in model.fields).map(([fieldName, direction]) => {
285
+ const field = model.fields[fieldName];
286
+ return `${quoteIdentifier(model.table, dialect)}.${quoteIdentifier(field.column, dialect)} ${direction === "desc" ? "desc" : "asc"}`;
287
+ });
288
+ if (!parts.length) return "";
289
+ return ` order by ${parts.join(", ")}`;
290
+ }
291
+ function compilePagination(dialect, take, skip) {
292
+ if (take === void 0 && skip === void 0) return "";
293
+ if (take !== void 0 && skip !== void 0) {
294
+ return ` limit ${take} offset ${skip}`;
295
+ }
296
+ if (take !== void 0) {
297
+ return ` limit ${take}`;
298
+ }
299
+ if (dialect === "postgres") {
300
+ return ` offset ${skip ?? 0}`;
301
+ }
302
+ if (dialect === "mysql") {
303
+ return ` limit 18446744073709551615 offset ${skip ?? 0}`;
304
+ }
305
+ return ` limit -1 offset ${skip ?? 0}`;
306
+ }
307
+ function buildSelectStatement(model, dialect, args) {
308
+ const state = { params: [] };
309
+ const selectList = Object.values(model.fields).map(
310
+ (field) => `${quoteIdentifier(model.table, dialect)}.${quoteIdentifier(field.column, dialect)} as ${quoteIdentifier(field.name, dialect)}`
311
+ );
312
+ let sql = `select ${selectList.join(", ")} from ${quoteIdentifier(model.table, dialect)}`;
313
+ const where = compileWhere(model, args.where, dialect, state);
314
+ if (where) sql += ` where ${where}`;
315
+ sql += compileOrderBy(model, args.orderBy, dialect);
316
+ sql += compilePagination(dialect, args.take, args.skip);
317
+ return { sql, params: state.params };
318
+ }
319
+ function buildCountStatement(model, dialect, where) {
320
+ const state = { params: [] };
321
+ let sql = `select count(*) as ${quoteIdentifier("count", dialect)} from ${quoteIdentifier(model.table, dialect)}`;
322
+ const compiledWhere = compileWhere(model, where, dialect, state);
323
+ if (compiledWhere) sql += ` where ${compiledWhere}`;
324
+ return { sql, params: state.params };
325
+ }
326
+ function buildInsertRow(model, data) {
327
+ const row = {};
328
+ for (const field of Object.values(model.fields)) {
329
+ row[field.name] = applyDefault(data[field.name], field);
330
+ }
331
+ return row;
332
+ }
333
+ function buildIdentityWhere(model, row) {
334
+ const field = identityField(model);
335
+ const value = row[field.name];
336
+ if (value === void 0) {
337
+ throw new Error(
338
+ `Model "${model.name}" could not resolve the identity field "${field.name}" from the current row.`
339
+ );
340
+ }
341
+ return {
342
+ [field.name]: value
343
+ };
344
+ }
345
+ function buildInsertStatement(model, dialect, row) {
346
+ const state = { params: [] };
347
+ const fields = Object.values(model.fields).filter((field) => row[field.name] !== void 0);
348
+ const columns = fields.map((field) => quoteIdentifier(field.column, dialect));
349
+ const values = fields.map(
350
+ (field) => createPlaceholder(dialect, state, encodeValue(field, dialect, row[field.name]))
351
+ );
352
+ return {
353
+ sql: `insert into ${quoteIdentifier(model.table, dialect)} (${columns.join(", ")}) values (${values.join(", ")})`,
354
+ params: state.params
355
+ };
356
+ }
357
+ function buildUpsertStatement(model, dialect, row, updateData, conflictField) {
358
+ const state = { params: [] };
359
+ const insertFields = Object.values(model.fields).filter((field) => row[field.name] !== void 0);
360
+ const columns = insertFields.map((field) => quoteIdentifier(field.column, dialect));
361
+ const values = insertFields.map(
362
+ (field) => createPlaceholder(dialect, state, encodeValue(field, dialect, row[field.name]))
363
+ );
364
+ const updateEntries = Object.entries(updateData).filter(([, value]) => value !== void 0);
365
+ const conflictColumn = quoteIdentifier(conflictField.column, dialect);
366
+ let sql = `insert into ${quoteIdentifier(model.table, dialect)} (${columns.join(", ")}) values (${values.join(", ")})`;
367
+ if (dialect === "mysql") {
368
+ const updateClause2 = updateEntries.length ? updateEntries.map(([fieldName, value]) => {
369
+ const field = model.fields[fieldName];
370
+ if (!field) {
371
+ throw new Error(`Unknown field "${fieldName}" on model "${model.name}".`);
372
+ }
373
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, value));
374
+ return `${quoteIdentifier(field.column, dialect)} = ${placeholder}`;
375
+ }) : [`${conflictColumn} = ${conflictColumn}`];
376
+ sql += ` on duplicate key update ${updateClause2.join(", ")}`;
377
+ return {
378
+ sql,
379
+ params: state.params
380
+ };
381
+ }
382
+ if (!updateEntries.length) {
383
+ sql += ` on conflict (${conflictColumn}) do nothing`;
384
+ return {
385
+ sql,
386
+ params: state.params
387
+ };
388
+ }
389
+ const updateClause = updateEntries.map(([fieldName, value]) => {
390
+ const field = model.fields[fieldName];
391
+ if (!field) {
392
+ throw new Error(`Unknown field "${fieldName}" on model "${model.name}".`);
393
+ }
394
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, value));
395
+ return `${quoteIdentifier(field.column, dialect)} = ${placeholder}`;
396
+ });
397
+ sql += ` on conflict (${conflictColumn}) do update set ${updateClause.join(", ")}`;
398
+ return {
399
+ sql,
400
+ params: state.params
401
+ };
402
+ }
403
+ function buildUpdateStatement(model, dialect, data, where) {
404
+ const state = { params: [] };
405
+ const entries = Object.entries(data).filter(([, value]) => value !== void 0);
406
+ if (!entries.length) {
407
+ return null;
408
+ }
409
+ const setClause = entries.map(([fieldName, value]) => {
410
+ const field = model.fields[fieldName];
411
+ if (!field) {
412
+ throw new Error(`Unknown field "${fieldName}" on model "${model.name}".`);
413
+ }
414
+ const placeholder = createPlaceholder(dialect, state, encodeValue(field, dialect, value));
415
+ return `${quoteIdentifier(field.column, dialect)} = ${placeholder}`;
416
+ });
417
+ const compiledWhere = compileWhere(model, where, dialect, state);
418
+ if (!compiledWhere) {
419
+ throw new Error(`Update on model "${model.name}" requires a where clause.`);
420
+ }
421
+ return {
422
+ sql: `update ${quoteIdentifier(model.table, dialect)} set ${setClause.join(", ")} where ${compiledWhere}`,
423
+ params: state.params
424
+ };
425
+ }
426
+ function buildDeleteStatement(model, dialect, where) {
427
+ const state = { params: [] };
428
+ const compiledWhere = compileWhere(model, where, dialect, state);
429
+ if (!compiledWhere) {
430
+ throw new Error(`Delete on model "${model.name}" requires a where clause.`);
431
+ }
432
+ return {
433
+ sql: `delete from ${quoteIdentifier(model.table, dialect)} where ${compiledWhere}`,
434
+ params: state.params
435
+ };
436
+ }
437
+ function createSqliteAdapter(database) {
438
+ let transactionDepth = 0;
439
+ const adapter = {
440
+ dialect: "sqlite",
441
+ async query(sql, params) {
442
+ const statement = database.prepare(sql);
443
+ if (/^\s*(select|with)\b/i.test(sql)) {
444
+ const rows = statement.all(...params);
445
+ return {
446
+ rows,
447
+ affectedRows: rows.length
448
+ };
449
+ }
450
+ const result = statement.run(...params);
451
+ return {
452
+ rows: [],
453
+ affectedRows: Number(result?.changes ?? 0)
454
+ };
455
+ },
456
+ async transaction(run) {
457
+ const savepoint = `farming_labs_${transactionDepth + 1}`;
458
+ if (transactionDepth === 0) {
459
+ database.exec("begin");
460
+ } else {
461
+ database.exec(`savepoint ${savepoint}`);
462
+ }
463
+ transactionDepth += 1;
464
+ try {
465
+ const result = await run(adapter);
466
+ transactionDepth -= 1;
467
+ if (transactionDepth === 0) {
468
+ database.exec("commit");
469
+ } else {
470
+ database.exec(`release savepoint ${savepoint}`);
471
+ }
472
+ return result;
473
+ } catch (error) {
474
+ transactionDepth -= 1;
475
+ if (transactionDepth === 0) {
476
+ database.exec("rollback");
477
+ } else {
478
+ database.exec(`rollback to savepoint ${savepoint}`);
479
+ database.exec(`release savepoint ${savepoint}`);
480
+ }
481
+ throw error;
482
+ }
483
+ }
484
+ };
485
+ return adapter;
486
+ }
487
+ function createPgTransactionalAdapter(client) {
488
+ let transactionDepth = 0;
489
+ const adapter = {
490
+ dialect: "postgres",
491
+ async query(sql, params) {
492
+ const result = await client.query(sql, params);
493
+ return {
494
+ rows: result.rows ?? [],
495
+ affectedRows: Number(result.rowCount ?? result.rows?.length ?? 0)
496
+ };
497
+ },
498
+ async transaction(run) {
499
+ const savepoint = `farming_labs_${transactionDepth + 1}`;
500
+ if (transactionDepth === 0) {
501
+ await client.query("begin");
502
+ } else {
503
+ await client.query(`savepoint ${savepoint}`);
504
+ }
505
+ transactionDepth += 1;
506
+ try {
507
+ const result = await run(adapter);
508
+ transactionDepth -= 1;
509
+ if (transactionDepth === 0) {
510
+ await client.query("commit");
511
+ } else {
512
+ await client.query(`release savepoint ${savepoint}`);
513
+ }
514
+ return result;
515
+ } catch (error) {
516
+ transactionDepth -= 1;
517
+ if (transactionDepth === 0) {
518
+ await client.query("rollback");
519
+ } else {
520
+ await client.query(`rollback to savepoint ${savepoint}`);
521
+ await client.query(`release savepoint ${savepoint}`);
522
+ }
523
+ throw error;
524
+ }
525
+ }
526
+ };
527
+ return adapter;
528
+ }
529
+ function createPgPoolAdapter(pool) {
530
+ return {
531
+ dialect: "postgres",
532
+ async query(sql, params) {
533
+ const result = await pool.query(sql, params);
534
+ return {
535
+ rows: result.rows ?? [],
536
+ affectedRows: Number(result.rowCount ?? result.rows?.length ?? 0)
537
+ };
538
+ },
539
+ async transaction(run) {
540
+ const client = await pool.connect();
541
+ try {
542
+ return await createPgTransactionalAdapter(client).transaction(run);
543
+ } finally {
544
+ client.release?.();
545
+ }
546
+ }
547
+ };
548
+ }
549
+ function createMysqlTransactionalAdapter(connection) {
550
+ let transactionDepth = 0;
551
+ const adapter = {
552
+ dialect: "mysql",
553
+ async query(sql, params) {
554
+ const [result] = await connection.execute(sql, params);
555
+ if (Array.isArray(result)) {
556
+ return {
557
+ rows: result,
558
+ affectedRows: result.length
559
+ };
560
+ }
561
+ return {
562
+ rows: [],
563
+ affectedRows: Number(result.affectedRows ?? 0)
564
+ };
565
+ },
566
+ async transaction(run) {
567
+ const savepoint = `farming_labs_${transactionDepth + 1}`;
568
+ if (transactionDepth === 0) {
569
+ await connection.beginTransaction();
570
+ } else {
571
+ await connection.execute(`savepoint ${savepoint}`);
572
+ }
573
+ transactionDepth += 1;
574
+ try {
575
+ const result = await run(adapter);
576
+ transactionDepth -= 1;
577
+ if (transactionDepth === 0) {
578
+ await connection.commit();
579
+ } else {
580
+ await connection.execute(`release savepoint ${savepoint}`);
581
+ }
582
+ return result;
583
+ } catch (error) {
584
+ transactionDepth -= 1;
585
+ if (transactionDepth === 0) {
586
+ await connection.rollback();
587
+ } else {
588
+ await connection.execute(`rollback to savepoint ${savepoint}`);
589
+ await connection.execute(`release savepoint ${savepoint}`);
590
+ }
591
+ throw error;
592
+ }
593
+ }
594
+ };
595
+ return adapter;
596
+ }
597
+ function createMysqlPoolAdapter(pool) {
598
+ return {
599
+ dialect: "mysql",
600
+ async query(sql, params) {
601
+ const [result] = await pool.execute(sql, params);
602
+ if (Array.isArray(result)) {
603
+ return {
604
+ rows: result,
605
+ affectedRows: result.length
606
+ };
607
+ }
608
+ return {
609
+ rows: [],
610
+ affectedRows: Number(result.affectedRows ?? 0)
611
+ };
612
+ },
613
+ async transaction(run) {
614
+ const connection = await pool.getConnection();
615
+ try {
616
+ return await createMysqlTransactionalAdapter(connection).transaction(run);
617
+ } finally {
618
+ connection.release?.();
619
+ }
620
+ }
621
+ };
622
+ }
623
+ function createSqlDriver(adapter) {
624
+ async function loadRows(schema, modelName, args) {
625
+ const manifest = getManifest(schema);
626
+ const model = manifest.models[modelName];
627
+ const statement = buildSelectStatement(model, adapter.dialect, args);
628
+ const result = await adapter.query(statement.sql, statement.params);
629
+ const rows = result.rows.map((row) => decodeRow(model, row));
630
+ return Promise.all(rows.map((row) => projectRow(schema, modelName, row, args.select)));
631
+ }
632
+ async function loadOneRow(schema, modelName, args) {
633
+ const rows = await loadRows(schema, modelName, {
634
+ ...args,
635
+ take: 1
636
+ });
637
+ return rows[0] ?? null;
638
+ }
639
+ async function loadRawOneRow(schema, modelName, args) {
640
+ const manifest = getManifest(schema);
641
+ const model = manifest.models[modelName];
642
+ const statement = buildSelectStatement(model, adapter.dialect, {
643
+ ...args,
644
+ take: 1
645
+ });
646
+ const result = await adapter.query(statement.sql, statement.params);
647
+ const row = result.rows[0];
648
+ return row ? decodeRow(model, row) : null;
649
+ }
650
+ async function projectRow(schema, modelName, row, select) {
651
+ const manifest = getManifest(schema);
652
+ const model = manifest.models[modelName];
653
+ const output = {};
654
+ if (!select) {
655
+ for (const fieldName of Object.keys(model.fields)) {
656
+ output[fieldName] = row[fieldName];
657
+ }
658
+ return output;
659
+ }
660
+ for (const [key, value] of Object.entries(select)) {
661
+ if (value === void 0) continue;
662
+ if (key in model.fields && value === true) {
663
+ output[key] = row[key];
664
+ continue;
665
+ }
666
+ if (key in schema.models[modelName].relations) {
667
+ output[key] = await resolveRelation(
668
+ schema,
669
+ modelName,
670
+ key,
671
+ row,
672
+ value
673
+ );
674
+ }
675
+ }
676
+ return output;
677
+ }
678
+ async function resolveRelation(schema, modelName, relationName, row, value) {
679
+ const manifest = getManifest(schema);
680
+ const relation = schema.models[modelName].relations[relationName];
681
+ const relationArgs = value === true ? {} : value;
682
+ if (relation.kind === "belongsTo") {
683
+ const foreignField = manifest.models[modelName].fields[relation.foreignKey];
684
+ const targetReference = parseReference(foreignField?.references);
685
+ const targetField2 = targetReference?.field ?? identityField(manifest.models[relation.target]).name;
686
+ const foreignValue = row[relation.foreignKey];
687
+ if (foreignValue == null) return null;
688
+ return loadOneRow(schema, relation.target, {
689
+ where: mergeWhere(
690
+ relationArgs.where,
691
+ {
692
+ [targetField2]: foreignValue
693
+ }
694
+ ),
695
+ orderBy: relationArgs.orderBy,
696
+ select: relationArgs.select
697
+ });
698
+ }
699
+ if (relation.kind === "hasOne") {
700
+ const targetModel = manifest.models[relation.target];
701
+ const foreignField = targetModel.fields[relation.foreignKey];
702
+ const sourceReference = parseReference(foreignField?.references);
703
+ const sourceField2 = sourceReference?.field ?? identityField(manifest.models[modelName]).name;
704
+ const sourceValue2 = row[sourceField2];
705
+ if (sourceValue2 == null) return null;
706
+ return loadOneRow(schema, relation.target, {
707
+ where: mergeWhere(
708
+ relationArgs.where,
709
+ {
710
+ [relation.foreignKey]: sourceValue2
711
+ }
712
+ ),
713
+ orderBy: relationArgs.orderBy,
714
+ select: relationArgs.select
715
+ });
716
+ }
717
+ if (relation.kind === "hasMany") {
718
+ const targetModel = manifest.models[relation.target];
719
+ const foreignField = targetModel.fields[relation.foreignKey];
720
+ const sourceReference = parseReference(foreignField?.references);
721
+ const sourceField2 = sourceReference?.field ?? identityField(manifest.models[modelName]).name;
722
+ const sourceValue2 = row[sourceField2];
723
+ if (sourceValue2 == null) return [];
724
+ return loadRows(schema, relation.target, {
725
+ where: mergeWhere(
726
+ relationArgs.where,
727
+ {
728
+ [relation.foreignKey]: sourceValue2
729
+ }
730
+ ),
731
+ orderBy: relationArgs.orderBy,
732
+ take: relationArgs.take,
733
+ skip: relationArgs.skip,
734
+ select: relationArgs.select
735
+ });
736
+ }
737
+ const throughModel = manifest.models[relation.through];
738
+ const throughFromReference = parseReference(throughModel.fields[relation.from]?.references);
739
+ const throughToReference = parseReference(throughModel.fields[relation.to]?.references);
740
+ const sourceField = throughFromReference?.field ?? identityField(manifest.models[modelName]).name;
741
+ const targetField = throughToReference?.field ?? identityField(manifest.models[relation.target]).name;
742
+ const sourceValue = row[sourceField];
743
+ if (sourceValue == null) return [];
744
+ const throughRows = await loadRows(schema, relation.through, {
745
+ where: {
746
+ [relation.from]: sourceValue
747
+ }
748
+ });
749
+ const targetIds = throughRows.map((item) => item[relation.to]).filter((item) => item != null);
750
+ if (!targetIds.length) return [];
751
+ return loadRows(schema, relation.target, {
752
+ where: mergeWhere(
753
+ relationArgs.where,
754
+ {
755
+ [targetField]: {
756
+ in: targetIds
757
+ }
758
+ }
759
+ ),
760
+ orderBy: relationArgs.orderBy,
761
+ take: relationArgs.take,
762
+ skip: relationArgs.skip,
763
+ select: relationArgs.select
764
+ });
765
+ }
766
+ const driver = {
767
+ async findMany(schema, model, args) {
768
+ return loadRows(schema, model, args);
769
+ },
770
+ async findFirst(schema, model, args) {
771
+ return loadOneRow(schema, model, args);
772
+ },
773
+ async findUnique(schema, model, args) {
774
+ return loadOneRow(schema, model, args);
775
+ },
776
+ async count(schema, model, args) {
777
+ const manifest = getManifest(schema);
778
+ const statement = buildCountStatement(
779
+ manifest.models[model],
780
+ adapter.dialect,
781
+ args?.where
782
+ );
783
+ const result = await adapter.query(statement.sql, statement.params);
784
+ const rawCount = result.rows[0]?.count;
785
+ if (typeof rawCount === "number") return rawCount;
786
+ return Number.parseInt(String(rawCount ?? 0), 10);
787
+ },
788
+ async create(schema, model, args) {
789
+ const manifest = getManifest(schema);
790
+ identityField(manifest.models[model]);
791
+ const row = buildInsertRow(
792
+ manifest.models[model],
793
+ args.data
794
+ );
795
+ const statement = buildInsertStatement(manifest.models[model], adapter.dialect, row);
796
+ await adapter.query(statement.sql, statement.params);
797
+ return loadOneRow(schema, model, {
798
+ where: buildIdentityWhere(manifest.models[model], row),
799
+ select: args.select
800
+ });
801
+ },
802
+ async createMany(schema, model, args) {
803
+ const results = [];
804
+ for (const entry of args.data) {
805
+ results.push(
806
+ await driver.create(schema, model, {
807
+ data: entry,
808
+ select: args.select
809
+ })
810
+ );
811
+ }
812
+ return results;
813
+ },
814
+ async update(schema, model, args) {
815
+ const manifest = getManifest(schema);
816
+ const current = await loadRawOneRow(schema, model, {
817
+ where: args.where
818
+ });
819
+ if (!current) return null;
820
+ const update = buildUpdateStatement(
821
+ manifest.models[model],
822
+ adapter.dialect,
823
+ args.data,
824
+ buildIdentityWhere(manifest.models[model], current)
825
+ );
826
+ if (update) {
827
+ await adapter.query(update.sql, update.params);
828
+ }
829
+ return loadOneRow(schema, model, {
830
+ where: buildIdentityWhere(manifest.models[model], current),
831
+ select: args.select
832
+ });
833
+ },
834
+ async updateMany(schema, model, args) {
835
+ const manifest = getManifest(schema);
836
+ const update = buildUpdateStatement(
837
+ manifest.models[model],
838
+ adapter.dialect,
839
+ args.data,
840
+ args.where
841
+ );
842
+ if (!update) return 0;
843
+ const result = await adapter.query(update.sql, update.params);
844
+ return result.affectedRows;
845
+ },
846
+ async upsert(schema, model, args) {
847
+ const manifest = getManifest(schema);
848
+ const modelManifest = manifest.models[model];
849
+ const conflict = extractUpsertConflict(modelManifest, args.where);
850
+ validateUpsertUpdateData(
851
+ modelManifest,
852
+ args.update,
853
+ conflict
854
+ );
855
+ const row = buildInsertRow(
856
+ modelManifest,
857
+ mergeUpsertCreateData(
858
+ modelManifest,
859
+ args.create,
860
+ conflict
861
+ )
862
+ );
863
+ const statement = buildUpsertStatement(
864
+ modelManifest,
865
+ adapter.dialect,
866
+ row,
867
+ args.update,
868
+ conflict.field
869
+ );
870
+ await adapter.query(statement.sql, statement.params);
871
+ return loadOneRow(schema, model, {
872
+ where: args.where,
873
+ select: args.select
874
+ });
875
+ },
876
+ async delete(schema, model, args) {
877
+ const manifest = getManifest(schema);
878
+ const current = await loadRawOneRow(schema, model, {
879
+ where: args.where
880
+ });
881
+ if (!current) return 0;
882
+ const statement = buildDeleteStatement(
883
+ manifest.models[model],
884
+ adapter.dialect,
885
+ buildIdentityWhere(manifest.models[model], current)
886
+ );
887
+ const result = await adapter.query(statement.sql, statement.params);
888
+ return result.affectedRows;
889
+ },
890
+ async deleteMany(schema, model, args) {
891
+ const manifest = getManifest(schema);
892
+ const statement = buildDeleteStatement(
893
+ manifest.models[model],
894
+ adapter.dialect,
895
+ args.where
896
+ );
897
+ const result = await adapter.query(statement.sql, statement.params);
898
+ return result.affectedRows;
899
+ },
900
+ async transaction(_schema, run) {
901
+ return adapter.transaction(async (txAdapter) => run(createSqlDriver(txAdapter)));
902
+ }
903
+ };
904
+ return driver;
905
+ }
906
+ function createSqliteDriver(database) {
907
+ return createSqlDriver(createSqliteAdapter(database));
908
+ }
909
+ function createPgPoolDriver(pool) {
910
+ return createSqlDriver(createPgPoolAdapter(pool));
911
+ }
912
+ function createPgClientDriver(client) {
913
+ return createSqlDriver(createPgTransactionalAdapter(client));
914
+ }
915
+ function createMysqlDriver(poolOrConnection) {
916
+ const adapter = "getConnection" in poolOrConnection ? createMysqlPoolAdapter(poolOrConnection) : createMysqlTransactionalAdapter(poolOrConnection);
917
+ return createSqlDriver(adapter);
918
+ }
919
+ // Annotate the CommonJS export names for ESM import in node:
920
+ 0 && (module.exports = {
921
+ createMysqlDriver,
922
+ createPgClientDriver,
923
+ createPgPoolDriver,
924
+ createSqliteDriver
925
+ });
926
+ //# sourceMappingURL=index.cjs.map