@nextlyhq/adapter-drizzle 0.0.2-alpha.35 → 0.0.2-alpha.39

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) {
@@ -106,6 +106,21 @@ function createDatabaseError(options) {
106
106
  }
107
107
 
108
108
  // src/adapter.ts
109
+ function affectedRowCount(result) {
110
+ if (Array.isArray(result)) {
111
+ const header = result[0];
112
+ if (header && typeof header.affectedRows === "number") {
113
+ return header.affectedRows;
114
+ }
115
+ return result.length;
116
+ }
117
+ const record = result;
118
+ const rowCount = record?.rowCount;
119
+ if (typeof rowCount === "number") return rowCount;
120
+ const changes = record?.changes;
121
+ if (typeof changes === "number") return changes;
122
+ return 0;
123
+ }
109
124
  var DrizzleAdapter = class {
110
125
  // ============================================================
111
126
  // Drizzle Query API Support
@@ -173,6 +188,107 @@ var DrizzleAdapter = class {
173
188
  }
174
189
  return mapped;
175
190
  }
191
+ /**
192
+ * Map data keys from Drizzle JS property names to SQL column names for the
193
+ * raw-SQL transaction insert path. The transaction context builds INSERT
194
+ * statements from Object.keys(data) used directly as column identifiers, so a
195
+ * table whose Drizzle property names differ from its SQL column names
196
+ * (camelCase core tables like nextly_versions) needs its keys translated
197
+ * first. For tables whose property names already equal their column names
198
+ * (the dynamic dc_/single_/comp_ tables) every lookup is identity, so
199
+ * existing callers are unaffected.
200
+ */
201
+ mapKeysToSqlColumns(tableObj, data) {
202
+ if (!tableObj || typeof tableObj !== "object") return data;
203
+ const jsToSql = /* @__PURE__ */ new Map();
204
+ for (const [jsName, colDef] of Object.entries(
205
+ tableObj
206
+ )) {
207
+ if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
208
+ jsToSql.set(jsName, colDef.name);
209
+ }
210
+ }
211
+ if (jsToSql.size === 0) return data;
212
+ const out = {};
213
+ for (const [key, value] of Object.entries(data)) {
214
+ out[jsToSql.get(key) ?? key] = value;
215
+ }
216
+ return out;
217
+ }
218
+ /**
219
+ * Map a list of column identifiers (Drizzle property names) to their SQL
220
+ * column names, for the raw-SQL transaction insert paths that build a
221
+ * RETURNING clause from `options.returning`. Same identity behavior as
222
+ * `mapKeysToSqlColumns`: names that are already SQL columns (the dynamic
223
+ * dc_/single_/comp_ tables) pass through unchanged.
224
+ */
225
+ mapColumnNamesToSql(tableObj, names) {
226
+ if (!tableObj || typeof tableObj !== "object") return names;
227
+ const jsToSql = /* @__PURE__ */ new Map();
228
+ for (const [jsName, colDef] of Object.entries(
229
+ tableObj
230
+ )) {
231
+ if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
232
+ jsToSql.set(jsName, colDef.name);
233
+ }
234
+ }
235
+ if (jsToSql.size === 0) return names;
236
+ return names.map((n) => jsToSql.get(n) ?? n);
237
+ }
238
+ /**
239
+ * Remap a raw-SQL result row's KEYS from SQL column names to Drizzle property
240
+ * names, so the raw-SQL transaction insert paths return the same key casing
241
+ * as the non-transactional (Drizzle) insert. Keys only - values are left
242
+ * untouched, so this does not change how JSON/date columns are decoded. For
243
+ * tables whose property names already equal their SQL columns (the dynamic
244
+ * dc_/single_/comp_ tables) every lookup is identity, so existing callers see
245
+ * no change.
246
+ */
247
+ mapRowKeysToJs(tableObj, row) {
248
+ if (!tableObj || typeof tableObj !== "object" || !row || typeof row !== "object") {
249
+ return row;
250
+ }
251
+ const sqlToJs = /* @__PURE__ */ new Map();
252
+ for (const [jsName, colDef] of Object.entries(
253
+ tableObj
254
+ )) {
255
+ if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
256
+ sqlToJs.set(colDef.name, jsName);
257
+ }
258
+ }
259
+ if (sqlToJs.size === 0) return row;
260
+ const out = {};
261
+ for (const [key, value] of Object.entries(row)) {
262
+ out[sqlToJs.get(key) ?? key] = value;
263
+ }
264
+ return out;
265
+ }
266
+ /**
267
+ * Build a Drizzle column projection object (`{ propertyName: column }`) from a
268
+ * requested column list, used by `select` (columns) and `insert` (returning).
269
+ * A requested name resolves against either the Drizzle property name
270
+ * (camelCase) or the SQL column name (snake_case); the projection is keyed by
271
+ * the property name so the row shape matches a full select. Returns undefined
272
+ * for `"*"` or when nothing resolves, so callers fall back to all columns.
273
+ */
274
+ buildColumnProjection(tableObj, names) {
275
+ if (names == null || names === "*" || !tableObj || typeof tableObj !== "object") {
276
+ return void 0;
277
+ }
278
+ const cols = getColumns(tableObj);
279
+ const byAnyName = {};
280
+ for (const [jsName, col] of Object.entries(cols)) {
281
+ byAnyName[jsName] = { jsName, col };
282
+ const sqlName = col?.name;
283
+ if (typeof sqlName === "string") byAnyName[sqlName] = { jsName, col };
284
+ }
285
+ const projection = {};
286
+ for (const name of names) {
287
+ const hit = byAnyName[name];
288
+ if (hit) projection[hit.jsName] = hit.col;
289
+ }
290
+ return Object.keys(projection).length ? projection : void 0;
291
+ }
176
292
  // ============================================================
177
293
  // Connection Status (Default implementations, can override)
178
294
  // ============================================================
@@ -326,12 +442,13 @@ var DrizzleAdapter = class {
326
442
  * });
327
443
  * ```
328
444
  */
329
- async select(table, options) {
445
+ async select(table, options, executor) {
330
446
  const tableObj = this.getTableObject(table);
331
447
  if (tableObj) {
332
448
  try {
333
- const db = this.getDrizzle();
334
- let query = db.select().from(tableObj);
449
+ const db = executor ?? this.getDrizzle();
450
+ const projection = options?.columns?.length ? this.buildColumnProjection(tableObj, options.columns) : void 0;
451
+ let query = projection ? db.select(projection).from(tableObj) : db.select().from(tableObj);
335
452
  if (options?.where) {
336
453
  const whereCondition = buildDrizzleWhere(
337
454
  tableObj,
@@ -342,7 +459,7 @@ var DrizzleAdapter = class {
342
459
  }
343
460
  }
344
461
  if (options?.orderBy?.length) {
345
- const columns = getTableColumns(tableObj);
462
+ const columns = getColumns(tableObj);
346
463
  const orderClauses = options.orderBy.map((o) => {
347
464
  const col = columns[o.column];
348
465
  if (!col) return void 0;
@@ -389,8 +506,12 @@ var DrizzleAdapter = class {
389
506
  * });
390
507
  * ```
391
508
  */
392
- async selectOne(table, options) {
393
- const results = await this.select(table, { ...options, limit: 1 });
509
+ async selectOne(table, options, executor) {
510
+ const results = await this.select(
511
+ table,
512
+ { ...options, limit: 1 },
513
+ executor
514
+ );
394
515
  return results.length > 0 ? results[0] : null;
395
516
  }
396
517
  /**
@@ -422,19 +543,22 @@ var DrizzleAdapter = class {
422
543
  const mappedData = this.mapDataToColumnNames(tableObj, data);
423
544
  const db = this.getDrizzle();
424
545
  const caps = this.getCapabilities();
425
- if (caps.supportsReturning && options?.returning) {
426
- const result2 = await db.insert(tableObj).values(mappedData).returning();
546
+ const returning = options?.returning;
547
+ const wantsReturning = returning != null && !(Array.isArray(returning) && returning.length === 0);
548
+ if (caps.supportsReturning && wantsReturning) {
549
+ const projection = this.buildColumnProjection(tableObj, returning);
550
+ const insertQuery = db.insert(tableObj).values(mappedData);
551
+ const result2 = await (projection ? insertQuery.returning(projection) : insertQuery.returning());
427
552
  return Array.isArray(result2) ? result2[0] : result2;
428
553
  }
429
554
  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
- }
555
+ if (!caps.supportsReturning && wantsReturning && data.id !== void 0) {
556
+ return await this.selectOne(table, {
557
+ columns: returning === "*" ? void 0 : returning,
558
+ where: {
559
+ and: [{ column: "id", op: "=", value: data.id }]
560
+ }
561
+ });
438
562
  }
439
563
  return Array.isArray(result) ? result[0] : result;
440
564
  } catch (error) {
@@ -504,11 +628,11 @@ var DrizzleAdapter = class {
504
628
  * );
505
629
  * ```
506
630
  */
507
- async update(table, data, where, options) {
631
+ async update(table, data, where, options, executor) {
508
632
  const tableObj = this.getTableObject(table);
509
633
  if (tableObj) {
510
634
  try {
511
- const db = this.getDrizzle();
635
+ const db = executor ?? this.getDrizzle();
512
636
  const caps = this.getCapabilities();
513
637
  const mappedData = this.mapDataToColumnNames(tableObj, data);
514
638
  let query = db.update(tableObj).set(mappedData);
@@ -521,7 +645,7 @@ var DrizzleAdapter = class {
521
645
  }
522
646
  await query;
523
647
  if (!caps.supportsReturning && options?.returning) {
524
- return await this.select(table, { where });
648
+ return await this.select(table, { where }, executor);
525
649
  }
526
650
  return [];
527
651
  } catch (error) {
@@ -556,18 +680,18 @@ var DrizzleAdapter = class {
556
680
  * console.log(`Deleted ${count} users`);
557
681
  * ```
558
682
  */
559
- async delete(table, where, _options) {
683
+ async delete(table, where, _options, executor) {
560
684
  const tableObj = this.getTableObject(table);
561
685
  if (tableObj) {
562
686
  try {
563
- const db = this.getDrizzle();
687
+ const db = executor ?? this.getDrizzle();
564
688
  let query = db.delete(tableObj);
565
689
  const whereCondition = buildDrizzleWhere(tableObj, where);
566
690
  if (whereCondition) {
567
691
  query = query.where(whereCondition);
568
692
  }
569
693
  const result = await query;
570
- return Array.isArray(result) ? result.length : result?.rowCount ?? result?.changes ?? 0;
694
+ return affectedRowCount(result);
571
695
  } catch (error) {
572
696
  throw this.handleQueryError(error, "delete", table);
573
697
  }
@@ -605,13 +729,13 @@ var DrizzleAdapter = class {
605
729
  * });
606
730
  * ```
607
731
  */
608
- async upsert(table, data, options) {
732
+ async upsert(table, data, options, executor) {
609
733
  const tableObj = this.getTableObject(table);
610
734
  if (tableObj) {
611
735
  try {
612
- const db = this.getDrizzle();
736
+ const db = executor ?? this.getDrizzle();
613
737
  const caps = this.getCapabilities();
614
- const columns = getTableColumns(tableObj);
738
+ const columns = getColumns(tableObj);
615
739
  const conflictTarget = options.conflictColumns.map((col) => columns[col]).filter(Boolean);
616
740
  const conflictSet = new Set(options.conflictColumns);
617
741
  const updateData = {};
@@ -636,17 +760,21 @@ var DrizzleAdapter = class {
636
760
  }
637
761
  await query;
638
762
  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
- });
763
+ return await this.selectOne(
764
+ table,
765
+ {
766
+ where: {
767
+ and: [
768
+ {
769
+ column: options.conflictColumns[0],
770
+ op: "=",
771
+ value: data[options.conflictColumns[0]]
772
+ }
773
+ ]
774
+ }
775
+ },
776
+ executor
777
+ );
650
778
  }
651
779
  return data;
652
780
  } catch (error) {
@@ -972,7 +1100,7 @@ var DrizzleAdapter = class {
972
1100
  break;
973
1101
  case "mysql":
974
1102
  sql = `
975
- SELECT table_name
1103
+ SELECT table_name AS table_name
976
1104
  FROM information_schema.tables
977
1105
  WHERE table_schema = DATABASE()
978
1106
  AND table_type = 'BASE TABLE'