@nextlyhq/adapter-drizzle 0.0.2-alpha.34 → 0.0.2-alpha.37

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.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { getTableColumns, desc, asc, and, or, not, like, notBetween, between, isNotNull, isNull, notInArray, inArray, ilike, lte, gte, lt, gt, ne, eq } from 'drizzle-orm';
1
+ import { getColumns, desc, asc, and, or, not, like, notBetween, between, isNotNull, isNull, notInArray, inArray, ilike, lte, gte, lt, gt, ne, eq } from 'drizzle-orm';
2
2
 
3
3
  // src/adapter.ts
4
4
  function buildDrizzleWhere(table, where) {
5
- const columns = getTableColumns(table);
5
+ const columns = getColumns(table);
6
6
  return processWhereClause(columns, where);
7
7
  }
8
8
  function processWhereClause(columns, where) {
@@ -173,6 +173,107 @@ var DrizzleAdapter = class {
173
173
  }
174
174
  return mapped;
175
175
  }
176
+ /**
177
+ * Map data keys from Drizzle JS property names to SQL column names for the
178
+ * raw-SQL transaction insert path. The transaction context builds INSERT
179
+ * statements from Object.keys(data) used directly as column identifiers, so a
180
+ * table whose Drizzle property names differ from its SQL column names
181
+ * (camelCase core tables like nextly_versions) needs its keys translated
182
+ * first. For tables whose property names already equal their column names
183
+ * (the dynamic dc_/single_/comp_ tables) every lookup is identity, so
184
+ * existing callers are unaffected.
185
+ */
186
+ mapKeysToSqlColumns(tableObj, data) {
187
+ if (!tableObj || typeof tableObj !== "object") return data;
188
+ const jsToSql = /* @__PURE__ */ new Map();
189
+ for (const [jsName, colDef] of Object.entries(
190
+ tableObj
191
+ )) {
192
+ if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
193
+ jsToSql.set(jsName, colDef.name);
194
+ }
195
+ }
196
+ if (jsToSql.size === 0) return data;
197
+ const out = {};
198
+ for (const [key, value] of Object.entries(data)) {
199
+ out[jsToSql.get(key) ?? key] = value;
200
+ }
201
+ return out;
202
+ }
203
+ /**
204
+ * Map a list of column identifiers (Drizzle property names) to their SQL
205
+ * column names, for the raw-SQL transaction insert paths that build a
206
+ * RETURNING clause from `options.returning`. Same identity behavior as
207
+ * `mapKeysToSqlColumns`: names that are already SQL columns (the dynamic
208
+ * dc_/single_/comp_ tables) pass through unchanged.
209
+ */
210
+ mapColumnNamesToSql(tableObj, names) {
211
+ if (!tableObj || typeof tableObj !== "object") return names;
212
+ const jsToSql = /* @__PURE__ */ new Map();
213
+ for (const [jsName, colDef] of Object.entries(
214
+ tableObj
215
+ )) {
216
+ if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
217
+ jsToSql.set(jsName, colDef.name);
218
+ }
219
+ }
220
+ if (jsToSql.size === 0) return names;
221
+ return names.map((n) => jsToSql.get(n) ?? n);
222
+ }
223
+ /**
224
+ * Remap a raw-SQL result row's KEYS from SQL column names to Drizzle property
225
+ * names, so the raw-SQL transaction insert paths return the same key casing
226
+ * as the non-transactional (Drizzle) insert. Keys only - values are left
227
+ * untouched, so this does not change how JSON/date columns are decoded. For
228
+ * tables whose property names already equal their SQL columns (the dynamic
229
+ * dc_/single_/comp_ tables) every lookup is identity, so existing callers see
230
+ * no change.
231
+ */
232
+ mapRowKeysToJs(tableObj, row) {
233
+ if (!tableObj || typeof tableObj !== "object" || !row || typeof row !== "object") {
234
+ return row;
235
+ }
236
+ const sqlToJs = /* @__PURE__ */ new Map();
237
+ for (const [jsName, colDef] of Object.entries(
238
+ tableObj
239
+ )) {
240
+ if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
241
+ sqlToJs.set(colDef.name, jsName);
242
+ }
243
+ }
244
+ if (sqlToJs.size === 0) return row;
245
+ const out = {};
246
+ for (const [key, value] of Object.entries(row)) {
247
+ out[sqlToJs.get(key) ?? key] = value;
248
+ }
249
+ return out;
250
+ }
251
+ /**
252
+ * Build a Drizzle column projection object (`{ propertyName: column }`) from a
253
+ * requested column list, used by `select` (columns) and `insert` (returning).
254
+ * A requested name resolves against either the Drizzle property name
255
+ * (camelCase) or the SQL column name (snake_case); the projection is keyed by
256
+ * the property name so the row shape matches a full select. Returns undefined
257
+ * for `"*"` or when nothing resolves, so callers fall back to all columns.
258
+ */
259
+ buildColumnProjection(tableObj, names) {
260
+ if (names == null || names === "*" || !tableObj || typeof tableObj !== "object") {
261
+ return void 0;
262
+ }
263
+ const cols = getColumns(tableObj);
264
+ const byAnyName = {};
265
+ for (const [jsName, col] of Object.entries(cols)) {
266
+ byAnyName[jsName] = { jsName, col };
267
+ const sqlName = col?.name;
268
+ if (typeof sqlName === "string") byAnyName[sqlName] = { jsName, col };
269
+ }
270
+ const projection = {};
271
+ for (const name of names) {
272
+ const hit = byAnyName[name];
273
+ if (hit) projection[hit.jsName] = hit.col;
274
+ }
275
+ return Object.keys(projection).length ? projection : void 0;
276
+ }
176
277
  // ============================================================
177
278
  // Connection Status (Default implementations, can override)
178
279
  // ============================================================
@@ -326,12 +427,13 @@ var DrizzleAdapter = class {
326
427
  * });
327
428
  * ```
328
429
  */
329
- async select(table, options) {
430
+ async select(table, options, executor) {
330
431
  const tableObj = this.getTableObject(table);
331
432
  if (tableObj) {
332
433
  try {
333
- const db = this.getDrizzle();
334
- let query = db.select().from(tableObj);
434
+ const db = executor ?? this.getDrizzle();
435
+ const projection = options?.columns?.length ? this.buildColumnProjection(tableObj, options.columns) : void 0;
436
+ let query = projection ? db.select(projection).from(tableObj) : db.select().from(tableObj);
335
437
  if (options?.where) {
336
438
  const whereCondition = buildDrizzleWhere(
337
439
  tableObj,
@@ -342,7 +444,7 @@ var DrizzleAdapter = class {
342
444
  }
343
445
  }
344
446
  if (options?.orderBy?.length) {
345
- const columns = getTableColumns(tableObj);
447
+ const columns = getColumns(tableObj);
346
448
  const orderClauses = options.orderBy.map((o) => {
347
449
  const col = columns[o.column];
348
450
  if (!col) return void 0;
@@ -389,8 +491,12 @@ var DrizzleAdapter = class {
389
491
  * });
390
492
  * ```
391
493
  */
392
- async selectOne(table, options) {
393
- const results = await this.select(table, { ...options, limit: 1 });
494
+ async selectOne(table, options, executor) {
495
+ const results = await this.select(
496
+ table,
497
+ { ...options, limit: 1 },
498
+ executor
499
+ );
394
500
  return results.length > 0 ? results[0] : null;
395
501
  }
396
502
  /**
@@ -422,19 +528,22 @@ var DrizzleAdapter = class {
422
528
  const mappedData = this.mapDataToColumnNames(tableObj, data);
423
529
  const db = this.getDrizzle();
424
530
  const caps = this.getCapabilities();
425
- if (caps.supportsReturning && options?.returning) {
426
- const result2 = await db.insert(tableObj).values(mappedData).returning();
531
+ const returning = options?.returning;
532
+ const wantsReturning = returning != null && !(Array.isArray(returning) && returning.length === 0);
533
+ if (caps.supportsReturning && wantsReturning) {
534
+ const projection = this.buildColumnProjection(tableObj, returning);
535
+ const insertQuery = db.insert(tableObj).values(mappedData);
536
+ const result2 = await (projection ? insertQuery.returning(projection) : insertQuery.returning());
427
537
  return Array.isArray(result2) ? result2[0] : result2;
428
538
  }
429
539
  const result = await db.insert(tableObj).values(mappedData);
430
- if (!caps.supportsReturning && options?.returning) {
431
- if (data.id !== void 0) {
432
- return await this.selectOne(table, {
433
- where: {
434
- and: [{ column: "id", op: "=", value: data.id }]
435
- }
436
- });
437
- }
540
+ if (!caps.supportsReturning && wantsReturning && data.id !== void 0) {
541
+ return await this.selectOne(table, {
542
+ columns: returning === "*" ? void 0 : returning,
543
+ where: {
544
+ and: [{ column: "id", op: "=", value: data.id }]
545
+ }
546
+ });
438
547
  }
439
548
  return Array.isArray(result) ? result[0] : result;
440
549
  } catch (error) {
@@ -504,11 +613,11 @@ var DrizzleAdapter = class {
504
613
  * );
505
614
  * ```
506
615
  */
507
- async update(table, data, where, options) {
616
+ async update(table, data, where, options, executor) {
508
617
  const tableObj = this.getTableObject(table);
509
618
  if (tableObj) {
510
619
  try {
511
- const db = this.getDrizzle();
620
+ const db = executor ?? this.getDrizzle();
512
621
  const caps = this.getCapabilities();
513
622
  const mappedData = this.mapDataToColumnNames(tableObj, data);
514
623
  let query = db.update(tableObj).set(mappedData);
@@ -521,7 +630,7 @@ var DrizzleAdapter = class {
521
630
  }
522
631
  await query;
523
632
  if (!caps.supportsReturning && options?.returning) {
524
- return await this.select(table, { where });
633
+ return await this.select(table, { where }, executor);
525
634
  }
526
635
  return [];
527
636
  } catch (error) {
@@ -556,11 +665,11 @@ var DrizzleAdapter = class {
556
665
  * console.log(`Deleted ${count} users`);
557
666
  * ```
558
667
  */
559
- async delete(table, where, _options) {
668
+ async delete(table, where, _options, executor) {
560
669
  const tableObj = this.getTableObject(table);
561
670
  if (tableObj) {
562
671
  try {
563
- const db = this.getDrizzle();
672
+ const db = executor ?? this.getDrizzle();
564
673
  let query = db.delete(tableObj);
565
674
  const whereCondition = buildDrizzleWhere(tableObj, where);
566
675
  if (whereCondition) {
@@ -605,13 +714,13 @@ var DrizzleAdapter = class {
605
714
  * });
606
715
  * ```
607
716
  */
608
- async upsert(table, data, options) {
717
+ async upsert(table, data, options, executor) {
609
718
  const tableObj = this.getTableObject(table);
610
719
  if (tableObj) {
611
720
  try {
612
- const db = this.getDrizzle();
721
+ const db = executor ?? this.getDrizzle();
613
722
  const caps = this.getCapabilities();
614
- const columns = getTableColumns(tableObj);
723
+ const columns = getColumns(tableObj);
615
724
  const conflictTarget = options.conflictColumns.map((col) => columns[col]).filter(Boolean);
616
725
  const conflictSet = new Set(options.conflictColumns);
617
726
  const updateData = {};
@@ -636,17 +745,21 @@ var DrizzleAdapter = class {
636
745
  }
637
746
  await query;
638
747
  if (options.conflictColumns.length && data[options.conflictColumns[0]] !== void 0) {
639
- return await this.selectOne(table, {
640
- where: {
641
- and: [
642
- {
643
- column: options.conflictColumns[0],
644
- op: "=",
645
- value: data[options.conflictColumns[0]]
646
- }
647
- ]
648
- }
649
- });
748
+ return await this.selectOne(
749
+ table,
750
+ {
751
+ where: {
752
+ and: [
753
+ {
754
+ column: options.conflictColumns[0],
755
+ op: "=",
756
+ value: data[options.conflictColumns[0]]
757
+ }
758
+ ]
759
+ }
760
+ },
761
+ executor
762
+ );
650
763
  }
651
764
  return data;
652
765
  } catch (error) {
@@ -972,7 +1085,7 @@ var DrizzleAdapter = class {
972
1085
  break;
973
1086
  case "mysql":
974
1087
  sql = `
975
- SELECT table_name
1088
+ SELECT table_name AS table_name
976
1089
  FROM information_schema.tables
977
1090
  WHERE table_schema = DATABASE()
978
1091
  AND table_type = 'BASE TABLE'