@nextlyhq/adapter-drizzle 0.0.2-alpha.5 → 0.0.2-alpha.51
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/{adapter-BxJVtttb.d.ts → adapter-C-DmzBg8.d.ts} +90 -58
- package/dist/{adapter-nvlxFkF-.d.cts → adapter-CZUQ2aV4.d.cts} +90 -58
- package/dist/{error-um1d_3Uo.d.cts → error-BrdknH2s.d.cts} +18 -1
- package/dist/{error-um1d_3Uo.d.ts → error-BrdknH2s.d.ts} +18 -1
- package/dist/index.cjs +215 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.mjs +216 -39
- package/dist/index.mjs.map +1 -1
- package/dist/{migration-BbO5meEV.d.cts → migration-BUc56kip.d.cts} +78 -0
- package/dist/{migration-Qe70wDOC.d.ts → migration-Bj84e15B.d.ts} +78 -0
- package/dist/migrations.d.cts +5 -4
- package/dist/migrations.d.ts +5 -4
- package/dist/types/index.cjs +8 -0
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +3 -2
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.mjs +8 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/version-check.d.cts +1 -1
- package/dist/version-check.d.ts +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ var drizzleOrm = require('drizzle-orm');
|
|
|
4
4
|
|
|
5
5
|
// src/adapter.ts
|
|
6
6
|
function buildDrizzleWhere(table, where) {
|
|
7
|
-
const columns = drizzleOrm.
|
|
7
|
+
const columns = drizzleOrm.getColumns(table);
|
|
8
8
|
return processWhereClause(columns, where);
|
|
9
9
|
}
|
|
10
10
|
function processWhereClause(columns, where) {
|
|
@@ -108,6 +108,21 @@ function createDatabaseError(options) {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
// src/adapter.ts
|
|
111
|
+
function affectedRowCount(result) {
|
|
112
|
+
if (Array.isArray(result)) {
|
|
113
|
+
const header = result[0];
|
|
114
|
+
if (header && typeof header.affectedRows === "number") {
|
|
115
|
+
return header.affectedRows;
|
|
116
|
+
}
|
|
117
|
+
return result.length;
|
|
118
|
+
}
|
|
119
|
+
const record = result;
|
|
120
|
+
const rowCount = record?.rowCount;
|
|
121
|
+
if (typeof rowCount === "number") return rowCount;
|
|
122
|
+
const changes = record?.changes;
|
|
123
|
+
if (typeof changes === "number") return changes;
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
111
126
|
var DrizzleAdapter = class {
|
|
112
127
|
// ============================================================
|
|
113
128
|
// Drizzle Query API Support
|
|
@@ -136,6 +151,45 @@ var DrizzleAdapter = class {
|
|
|
136
151
|
getTableObject(tableName) {
|
|
137
152
|
return this.tableResolver?.getTable(tableName) ?? null;
|
|
138
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Run a Drizzle-built statement and return its rows.
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* The CRUD methods resolve their table through the schema registry and reject
|
|
159
|
+
* any name it does not declare, which leaves no way to read from a table the
|
|
160
|
+
* ORM does not know — one mid-rename, above all — except by assembling SQL and
|
|
161
|
+
* quoting identifiers by hand. This takes Drizzle's `sql` template instead, so
|
|
162
|
+
* the dialect in use decides the quoting and the parameter binding.
|
|
163
|
+
*
|
|
164
|
+
* Concrete rather than abstract so existing adapters keep working unchanged.
|
|
165
|
+
* The three drivers disagree about both the call and the result: node-postgres
|
|
166
|
+
* returns `{ rows }`, mysql2 a `[rows, fields]` tuple, and better-sqlite3 has
|
|
167
|
+
* no `execute` at all and answers `all`. Keeping that here rather than at each
|
|
168
|
+
* call site is the point — a caller reasoning about it would be reasoning
|
|
169
|
+
* about a driver it cannot see.
|
|
170
|
+
*
|
|
171
|
+
* @param statement - Drizzle `sql` template to run
|
|
172
|
+
* @returns Rows the statement produced
|
|
173
|
+
*/
|
|
174
|
+
async queryStatement(statement) {
|
|
175
|
+
if (this.getCapabilities().dialect === "sqlite") {
|
|
176
|
+
const db2 = this.getDrizzle();
|
|
177
|
+
return await db2.all(statement);
|
|
178
|
+
}
|
|
179
|
+
const db = this.getDrizzle();
|
|
180
|
+
const result = await db.execute(statement);
|
|
181
|
+
if (Array.isArray(result)) {
|
|
182
|
+
return Array.isArray(result[0]) ? result[0] : result;
|
|
183
|
+
}
|
|
184
|
+
if (typeof result === "object" && result !== null && Array.isArray(result.rows)) {
|
|
185
|
+
return result.rows;
|
|
186
|
+
}
|
|
187
|
+
throw this.createDatabaseError(
|
|
188
|
+
"query",
|
|
189
|
+
"Drizzle statement returned a result shape this adapter does not recognise; refusing to report it as an empty result.",
|
|
190
|
+
void 0
|
|
191
|
+
);
|
|
192
|
+
}
|
|
139
193
|
/**
|
|
140
194
|
* Map data keys from SQL column names (snake_case) to Drizzle JS property names (camelCase).
|
|
141
195
|
* Drizzle schemas define columns as e.g. `createdAt: timestamp("created_at")` — the JS
|
|
@@ -175,6 +229,107 @@ var DrizzleAdapter = class {
|
|
|
175
229
|
}
|
|
176
230
|
return mapped;
|
|
177
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Map data keys from Drizzle JS property names to SQL column names for the
|
|
234
|
+
* raw-SQL transaction insert path. The transaction context builds INSERT
|
|
235
|
+
* statements from Object.keys(data) used directly as column identifiers, so a
|
|
236
|
+
* table whose Drizzle property names differ from its SQL column names
|
|
237
|
+
* (camelCase core tables like nextly_versions) needs its keys translated
|
|
238
|
+
* first. For tables whose property names already equal their column names
|
|
239
|
+
* (the dynamic dc_/single_/comp_ tables) every lookup is identity, so
|
|
240
|
+
* existing callers are unaffected.
|
|
241
|
+
*/
|
|
242
|
+
mapKeysToSqlColumns(tableObj, data) {
|
|
243
|
+
if (!tableObj || typeof tableObj !== "object") return data;
|
|
244
|
+
const jsToSql = /* @__PURE__ */ new Map();
|
|
245
|
+
for (const [jsName, colDef] of Object.entries(
|
|
246
|
+
tableObj
|
|
247
|
+
)) {
|
|
248
|
+
if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
|
|
249
|
+
jsToSql.set(jsName, colDef.name);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (jsToSql.size === 0) return data;
|
|
253
|
+
const out = {};
|
|
254
|
+
for (const [key, value] of Object.entries(data)) {
|
|
255
|
+
out[jsToSql.get(key) ?? key] = value;
|
|
256
|
+
}
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Map a list of column identifiers (Drizzle property names) to their SQL
|
|
261
|
+
* column names, for the raw-SQL transaction insert paths that build a
|
|
262
|
+
* RETURNING clause from `options.returning`. Same identity behavior as
|
|
263
|
+
* `mapKeysToSqlColumns`: names that are already SQL columns (the dynamic
|
|
264
|
+
* dc_/single_/comp_ tables) pass through unchanged.
|
|
265
|
+
*/
|
|
266
|
+
mapColumnNamesToSql(tableObj, names) {
|
|
267
|
+
if (!tableObj || typeof tableObj !== "object") return names;
|
|
268
|
+
const jsToSql = /* @__PURE__ */ new Map();
|
|
269
|
+
for (const [jsName, colDef] of Object.entries(
|
|
270
|
+
tableObj
|
|
271
|
+
)) {
|
|
272
|
+
if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
|
|
273
|
+
jsToSql.set(jsName, colDef.name);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (jsToSql.size === 0) return names;
|
|
277
|
+
return names.map((n) => jsToSql.get(n) ?? n);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Remap a raw-SQL result row's KEYS from SQL column names to Drizzle property
|
|
281
|
+
* names, so the raw-SQL transaction insert paths return the same key casing
|
|
282
|
+
* as the non-transactional (Drizzle) insert. Keys only - values are left
|
|
283
|
+
* untouched, so this does not change how JSON/date columns are decoded. For
|
|
284
|
+
* tables whose property names already equal their SQL columns (the dynamic
|
|
285
|
+
* dc_/single_/comp_ tables) every lookup is identity, so existing callers see
|
|
286
|
+
* no change.
|
|
287
|
+
*/
|
|
288
|
+
mapRowKeysToJs(tableObj, row) {
|
|
289
|
+
if (!tableObj || typeof tableObj !== "object" || !row || typeof row !== "object") {
|
|
290
|
+
return row;
|
|
291
|
+
}
|
|
292
|
+
const sqlToJs = /* @__PURE__ */ new Map();
|
|
293
|
+
for (const [jsName, colDef] of Object.entries(
|
|
294
|
+
tableObj
|
|
295
|
+
)) {
|
|
296
|
+
if (colDef && typeof colDef === "object" && "name" in colDef && typeof colDef.name === "string") {
|
|
297
|
+
sqlToJs.set(colDef.name, jsName);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (sqlToJs.size === 0) return row;
|
|
301
|
+
const out = {};
|
|
302
|
+
for (const [key, value] of Object.entries(row)) {
|
|
303
|
+
out[sqlToJs.get(key) ?? key] = value;
|
|
304
|
+
}
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Build a Drizzle column projection object (`{ propertyName: column }`) from a
|
|
309
|
+
* requested column list, used by `select` (columns) and `insert` (returning).
|
|
310
|
+
* A requested name resolves against either the Drizzle property name
|
|
311
|
+
* (camelCase) or the SQL column name (snake_case); the projection is keyed by
|
|
312
|
+
* the property name so the row shape matches a full select. Returns undefined
|
|
313
|
+
* for `"*"` or when nothing resolves, so callers fall back to all columns.
|
|
314
|
+
*/
|
|
315
|
+
buildColumnProjection(tableObj, names) {
|
|
316
|
+
if (names == null || names === "*" || !tableObj || typeof tableObj !== "object") {
|
|
317
|
+
return void 0;
|
|
318
|
+
}
|
|
319
|
+
const cols = drizzleOrm.getColumns(tableObj);
|
|
320
|
+
const byAnyName = {};
|
|
321
|
+
for (const [jsName, col] of Object.entries(cols)) {
|
|
322
|
+
byAnyName[jsName] = { jsName, col };
|
|
323
|
+
const sqlName = col?.name;
|
|
324
|
+
if (typeof sqlName === "string") byAnyName[sqlName] = { jsName, col };
|
|
325
|
+
}
|
|
326
|
+
const projection = {};
|
|
327
|
+
for (const name of names) {
|
|
328
|
+
const hit = byAnyName[name];
|
|
329
|
+
if (hit) projection[hit.jsName] = hit.col;
|
|
330
|
+
}
|
|
331
|
+
return Object.keys(projection).length ? projection : void 0;
|
|
332
|
+
}
|
|
178
333
|
// ============================================================
|
|
179
334
|
// Connection Status (Default implementations, can override)
|
|
180
335
|
// ============================================================
|
|
@@ -328,12 +483,13 @@ var DrizzleAdapter = class {
|
|
|
328
483
|
* });
|
|
329
484
|
* ```
|
|
330
485
|
*/
|
|
331
|
-
async select(table, options) {
|
|
486
|
+
async select(table, options, executor) {
|
|
332
487
|
const tableObj = this.getTableObject(table);
|
|
333
488
|
if (tableObj) {
|
|
334
489
|
try {
|
|
335
|
-
const db = this.getDrizzle();
|
|
336
|
-
|
|
490
|
+
const db = executor ?? this.getDrizzle();
|
|
491
|
+
const projection = options?.columns?.length ? this.buildColumnProjection(tableObj, options.columns) : void 0;
|
|
492
|
+
let query = projection ? db.select(projection).from(tableObj) : db.select().from(tableObj);
|
|
337
493
|
if (options?.where) {
|
|
338
494
|
const whereCondition = buildDrizzleWhere(
|
|
339
495
|
tableObj,
|
|
@@ -344,7 +500,7 @@ var DrizzleAdapter = class {
|
|
|
344
500
|
}
|
|
345
501
|
}
|
|
346
502
|
if (options?.orderBy?.length) {
|
|
347
|
-
const columns = drizzleOrm.
|
|
503
|
+
const columns = drizzleOrm.getColumns(tableObj);
|
|
348
504
|
const orderClauses = options.orderBy.map((o) => {
|
|
349
505
|
const col = columns[o.column];
|
|
350
506
|
if (!col) return void 0;
|
|
@@ -360,6 +516,16 @@ var DrizzleAdapter = class {
|
|
|
360
516
|
if (options?.offset !== void 0) {
|
|
361
517
|
query = query.offset(options.offset);
|
|
362
518
|
}
|
|
519
|
+
if (options?.forUpdate && !executor) {
|
|
520
|
+
throw this.createDatabaseError(
|
|
521
|
+
"query",
|
|
522
|
+
"forUpdate requires a transaction executor: a lock request on the pooled connection takes no durable lock and cannot prevent a concurrent write.",
|
|
523
|
+
void 0
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
if (options?.forUpdate && this.dialect !== "sqlite") {
|
|
527
|
+
query = query.for("update");
|
|
528
|
+
}
|
|
363
529
|
return await query;
|
|
364
530
|
} catch (error) {
|
|
365
531
|
throw this.handleQueryError(error, "select", table);
|
|
@@ -391,8 +557,12 @@ var DrizzleAdapter = class {
|
|
|
391
557
|
* });
|
|
392
558
|
* ```
|
|
393
559
|
*/
|
|
394
|
-
async selectOne(table, options) {
|
|
395
|
-
const results = await this.select(
|
|
560
|
+
async selectOne(table, options, executor) {
|
|
561
|
+
const results = await this.select(
|
|
562
|
+
table,
|
|
563
|
+
{ ...options, limit: 1 },
|
|
564
|
+
executor
|
|
565
|
+
);
|
|
396
566
|
return results.length > 0 ? results[0] : null;
|
|
397
567
|
}
|
|
398
568
|
/**
|
|
@@ -424,19 +594,22 @@ var DrizzleAdapter = class {
|
|
|
424
594
|
const mappedData = this.mapDataToColumnNames(tableObj, data);
|
|
425
595
|
const db = this.getDrizzle();
|
|
426
596
|
const caps = this.getCapabilities();
|
|
427
|
-
|
|
428
|
-
|
|
597
|
+
const returning = options?.returning;
|
|
598
|
+
const wantsReturning = returning != null && !(Array.isArray(returning) && returning.length === 0);
|
|
599
|
+
if (caps.supportsReturning && wantsReturning) {
|
|
600
|
+
const projection = this.buildColumnProjection(tableObj, returning);
|
|
601
|
+
const insertQuery = db.insert(tableObj).values(mappedData);
|
|
602
|
+
const result2 = await (projection ? insertQuery.returning(projection) : insertQuery.returning());
|
|
429
603
|
return Array.isArray(result2) ? result2[0] : result2;
|
|
430
604
|
}
|
|
431
605
|
const result = await db.insert(tableObj).values(mappedData);
|
|
432
|
-
if (!caps.supportsReturning &&
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
606
|
+
if (!caps.supportsReturning && wantsReturning && data.id !== void 0) {
|
|
607
|
+
return await this.selectOne(table, {
|
|
608
|
+
columns: returning === "*" ? void 0 : returning,
|
|
609
|
+
where: {
|
|
610
|
+
and: [{ column: "id", op: "=", value: data.id }]
|
|
611
|
+
}
|
|
612
|
+
});
|
|
440
613
|
}
|
|
441
614
|
return Array.isArray(result) ? result[0] : result;
|
|
442
615
|
} catch (error) {
|
|
@@ -506,11 +679,11 @@ var DrizzleAdapter = class {
|
|
|
506
679
|
* );
|
|
507
680
|
* ```
|
|
508
681
|
*/
|
|
509
|
-
async update(table, data, where, options) {
|
|
682
|
+
async update(table, data, where, options, executor) {
|
|
510
683
|
const tableObj = this.getTableObject(table);
|
|
511
684
|
if (tableObj) {
|
|
512
685
|
try {
|
|
513
|
-
const db = this.getDrizzle();
|
|
686
|
+
const db = executor ?? this.getDrizzle();
|
|
514
687
|
const caps = this.getCapabilities();
|
|
515
688
|
const mappedData = this.mapDataToColumnNames(tableObj, data);
|
|
516
689
|
let query = db.update(tableObj).set(mappedData);
|
|
@@ -523,7 +696,7 @@ var DrizzleAdapter = class {
|
|
|
523
696
|
}
|
|
524
697
|
await query;
|
|
525
698
|
if (!caps.supportsReturning && options?.returning) {
|
|
526
|
-
return await this.select(table, { where });
|
|
699
|
+
return await this.select(table, { where }, executor);
|
|
527
700
|
}
|
|
528
701
|
return [];
|
|
529
702
|
} catch (error) {
|
|
@@ -558,18 +731,18 @@ var DrizzleAdapter = class {
|
|
|
558
731
|
* console.log(`Deleted ${count} users`);
|
|
559
732
|
* ```
|
|
560
733
|
*/
|
|
561
|
-
async delete(table, where, _options) {
|
|
734
|
+
async delete(table, where, _options, executor) {
|
|
562
735
|
const tableObj = this.getTableObject(table);
|
|
563
736
|
if (tableObj) {
|
|
564
737
|
try {
|
|
565
|
-
const db = this.getDrizzle();
|
|
738
|
+
const db = executor ?? this.getDrizzle();
|
|
566
739
|
let query = db.delete(tableObj);
|
|
567
740
|
const whereCondition = buildDrizzleWhere(tableObj, where);
|
|
568
741
|
if (whereCondition) {
|
|
569
742
|
query = query.where(whereCondition);
|
|
570
743
|
}
|
|
571
744
|
const result = await query;
|
|
572
|
-
return
|
|
745
|
+
return affectedRowCount(result);
|
|
573
746
|
} catch (error) {
|
|
574
747
|
throw this.handleQueryError(error, "delete", table);
|
|
575
748
|
}
|
|
@@ -607,13 +780,13 @@ var DrizzleAdapter = class {
|
|
|
607
780
|
* });
|
|
608
781
|
* ```
|
|
609
782
|
*/
|
|
610
|
-
async upsert(table, data, options) {
|
|
783
|
+
async upsert(table, data, options, executor) {
|
|
611
784
|
const tableObj = this.getTableObject(table);
|
|
612
785
|
if (tableObj) {
|
|
613
786
|
try {
|
|
614
|
-
const db = this.getDrizzle();
|
|
787
|
+
const db = executor ?? this.getDrizzle();
|
|
615
788
|
const caps = this.getCapabilities();
|
|
616
|
-
const columns = drizzleOrm.
|
|
789
|
+
const columns = drizzleOrm.getColumns(tableObj);
|
|
617
790
|
const conflictTarget = options.conflictColumns.map((col) => columns[col]).filter(Boolean);
|
|
618
791
|
const conflictSet = new Set(options.conflictColumns);
|
|
619
792
|
const updateData = {};
|
|
@@ -638,17 +811,21 @@ var DrizzleAdapter = class {
|
|
|
638
811
|
}
|
|
639
812
|
await query;
|
|
640
813
|
if (options.conflictColumns.length && data[options.conflictColumns[0]] !== void 0) {
|
|
641
|
-
return await this.selectOne(
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
814
|
+
return await this.selectOne(
|
|
815
|
+
table,
|
|
816
|
+
{
|
|
817
|
+
where: {
|
|
818
|
+
and: [
|
|
819
|
+
{
|
|
820
|
+
column: options.conflictColumns[0],
|
|
821
|
+
op: "=",
|
|
822
|
+
value: data[options.conflictColumns[0]]
|
|
823
|
+
}
|
|
824
|
+
]
|
|
825
|
+
}
|
|
826
|
+
},
|
|
827
|
+
executor
|
|
828
|
+
);
|
|
652
829
|
}
|
|
653
830
|
return data;
|
|
654
831
|
} catch (error) {
|
|
@@ -974,7 +1151,7 @@ var DrizzleAdapter = class {
|
|
|
974
1151
|
break;
|
|
975
1152
|
case "mysql":
|
|
976
1153
|
sql = `
|
|
977
|
-
SELECT table_name
|
|
1154
|
+
SELECT table_name AS table_name
|
|
978
1155
|
FROM information_schema.tables
|
|
979
1156
|
WHERE table_schema = DATABASE()
|
|
980
1157
|
AND table_type = 'BASE TABLE'
|