@better-auth/kysely-adapter 1.7.0-beta.3 → 1.7.0-beta.4
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,5 +1,6 @@
|
|
|
1
1
|
import { Kysely, MssqlDialect, MysqlDialect, PostgresDialect, SqliteDialect, sql } from "kysely";
|
|
2
2
|
import { createAdapterFactory } from "@better-auth/core/db/adapter";
|
|
3
|
+
import { logger } from "@better-auth/core/env";
|
|
3
4
|
import { capitalizeFirstLetter } from "@better-auth/core/utils/string";
|
|
4
5
|
//#region src/dialect.ts
|
|
5
6
|
function getKyselyDatabaseType(db) {
|
|
@@ -43,7 +44,7 @@ const createKyselyAdapter = async (config) => {
|
|
|
43
44
|
if ("getConnection" in db) dialect = new MysqlDialect(db);
|
|
44
45
|
if ("connect" in db) dialect = new PostgresDialect({ pool: db });
|
|
45
46
|
if ("fileControl" in db) {
|
|
46
|
-
const { BunSqliteDialect } = await import("./bun-sqlite-dialect-
|
|
47
|
+
const { BunSqliteDialect } = await import("./bun-sqlite-dialect-DzNwOpKv.mjs");
|
|
47
48
|
dialect = new BunSqliteDialect({ database: db });
|
|
48
49
|
}
|
|
49
50
|
if ("createSession" in db) {
|
|
@@ -124,8 +125,13 @@ function insensitiveNe(columnRef, value) {
|
|
|
124
125
|
//#region src/kysely-adapter.ts
|
|
125
126
|
const kyselyAdapter = (db, config) => {
|
|
126
127
|
let lazyOptions = null;
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
let mysqlNoIdWarned = false;
|
|
129
|
+
const createCustomAdapter = (db, inTransaction = false) => {
|
|
130
|
+
return ({ getFieldName, schema, getDefaultFieldName, getDefaultModelName, getFieldAttributes, getModelName, options }) => {
|
|
131
|
+
if (config?.type === "mysql" && options.advanced?.database?.generateId === false && !mysqlNoIdWarned) {
|
|
132
|
+
mysqlNoIdWarned = true;
|
|
133
|
+
logger.warn("[Kysely Adapter] MySQL does not support INSERT...RETURNING. With generateId set to false, the adapter uses best-effort fallback strategies (unique columns, full-field match) to retrieve inserted rows. For reliable behavior, use Better Auth's default ID generation, a custom generateId function, or generateId: \"serial\" for auto-increment.");
|
|
134
|
+
}
|
|
129
135
|
const selectAllJoins = (join) => {
|
|
130
136
|
const allSelects = [];
|
|
131
137
|
const allSelectsStr = [];
|
|
@@ -149,33 +155,58 @@ const kyselyAdapter = (db, config) => {
|
|
|
149
155
|
};
|
|
150
156
|
};
|
|
151
157
|
const withReturning = async (values, builder, model, where) => {
|
|
152
|
-
let res;
|
|
153
158
|
if (config?.type === "mysql") {
|
|
154
159
|
await builder.execute();
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
160
|
+
if (where.length > 0) {
|
|
161
|
+
const field = values.id ? "id" : where[0]?.field ? where[0].field : "id";
|
|
162
|
+
const value = values[field] !== void 0 ? values[field] : where[0]?.value;
|
|
163
|
+
return await db.selectFrom(model).selectAll().where(getFieldName({
|
|
158
164
|
model,
|
|
159
165
|
field
|
|
160
|
-
}), "
|
|
161
|
-
return res;
|
|
166
|
+
}), value === null ? "is" : "=", value).limit(1).executeTakeFirst();
|
|
162
167
|
}
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
168
|
+
const fetchInserted = async (trx) => {
|
|
169
|
+
if (values.id) return await trx.selectFrom(model).selectAll().where(getFieldName({
|
|
170
|
+
model,
|
|
171
|
+
field: "id"
|
|
172
|
+
}), "=", values.id).limit(1).executeTakeFirst();
|
|
173
|
+
if (options.advanced?.database?.generateId === "serial") {
|
|
174
|
+
const lastId = (await sql`SELECT LAST_INSERT_ID() as id`.execute(trx)).rows[0]?.id;
|
|
175
|
+
if (lastId) return await trx.selectFrom(model).selectAll().where(getFieldName({
|
|
176
|
+
model,
|
|
177
|
+
field: "id"
|
|
178
|
+
}), "=", lastId).limit(1).executeTakeFirst();
|
|
179
|
+
}
|
|
180
|
+
const modelSchema = schema[getDefaultModelName(model)]?.fields;
|
|
181
|
+
if (modelSchema) for (const [fieldKey, fieldAttr] of Object.entries(modelSchema)) {
|
|
182
|
+
if (!fieldAttr.unique) continue;
|
|
183
|
+
const dbFieldName = getFieldName({
|
|
184
|
+
model,
|
|
185
|
+
field: fieldKey
|
|
186
|
+
});
|
|
187
|
+
const val = values[dbFieldName];
|
|
188
|
+
if (val === void 0 || val === null) continue;
|
|
189
|
+
const row = await trx.selectFrom(model).selectAll().where(dbFieldName, "=", val).limit(1).executeTakeFirst();
|
|
190
|
+
if (row) return row;
|
|
191
|
+
}
|
|
192
|
+
let query = trx.selectFrom(model).selectAll();
|
|
193
|
+
let hasConditions = false;
|
|
194
|
+
for (const [key, val] of Object.entries(values)) {
|
|
195
|
+
if (val === void 0) continue;
|
|
196
|
+
query = query.where(key, val === null ? "is" : "=", val);
|
|
197
|
+
hasConditions = true;
|
|
198
|
+
}
|
|
199
|
+
if (hasConditions) {
|
|
200
|
+
const rows = await query.limit(2).execute();
|
|
201
|
+
if (rows.length === 1) return rows[0];
|
|
202
|
+
}
|
|
203
|
+
logger.warn(`[Kysely Adapter] Unable to safely identify the inserted "${model}" row on MySQL. Enable Better Auth ID generation or use generateId: "serial" for reliable behavior.`);
|
|
204
|
+
return null;
|
|
205
|
+
};
|
|
206
|
+
return inTransaction ? fetchInserted(db) : db.transaction().execute(fetchInserted);
|
|
176
207
|
}
|
|
177
|
-
|
|
178
|
-
return
|
|
208
|
+
if (config?.type === "mssql") return await builder.outputAll("inserted").executeTakeFirst();
|
|
209
|
+
return await builder.returningAll().executeTakeFirst();
|
|
179
210
|
};
|
|
180
211
|
function convertWhereClause(model, w) {
|
|
181
212
|
if (!w) return {
|
|
@@ -425,6 +456,43 @@ const kyselyAdapter = (db, config) => {
|
|
|
425
456
|
const res = (await query.executeTakeFirst()).numDeletedRows;
|
|
426
457
|
return res > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : Number(res);
|
|
427
458
|
},
|
|
459
|
+
async consumeOne({ model, where }) {
|
|
460
|
+
const { and, or } = convertWhereClause(model, where);
|
|
461
|
+
const applyWhere = (query) => {
|
|
462
|
+
if (and) query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));
|
|
463
|
+
if (or) query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));
|
|
464
|
+
return query;
|
|
465
|
+
};
|
|
466
|
+
const idField = getFieldName({
|
|
467
|
+
model,
|
|
468
|
+
field: "id"
|
|
469
|
+
});
|
|
470
|
+
const deleteSelectedRow = async (db, row) => {
|
|
471
|
+
const targetId = row[idField] ?? row.id;
|
|
472
|
+
if (targetId === void 0 || targetId === null) return null;
|
|
473
|
+
const query = db.deleteFrom(model).where(`${model}.${idField}`, "=", targetId);
|
|
474
|
+
if (config?.type === "mysql") {
|
|
475
|
+
const result = await query.executeTakeFirst();
|
|
476
|
+
return Number(result.numDeletedRows) > 0 ? row : null;
|
|
477
|
+
}
|
|
478
|
+
if (config?.type === "mssql") return await query.outputAll("deleted").executeTakeFirst() ?? null;
|
|
479
|
+
return await query.returningAll().executeTakeFirst() ?? null;
|
|
480
|
+
};
|
|
481
|
+
const deleteWithReturning = async (query) => {
|
|
482
|
+
if (config?.type === "mssql") return await query.outputAll("deleted").executeTakeFirst() ?? null;
|
|
483
|
+
return await query.returningAll().executeTakeFirst() ?? null;
|
|
484
|
+
};
|
|
485
|
+
if (config?.type === "mysql") {
|
|
486
|
+
const claimFromTransaction = async (trx) => {
|
|
487
|
+
const row = await applyWhere(trx.selectFrom(model).selectAll().forUpdate()).limit(1).executeTakeFirst();
|
|
488
|
+
if (!row) return null;
|
|
489
|
+
return deleteSelectedRow(trx, row);
|
|
490
|
+
};
|
|
491
|
+
return inTransaction ? claimFromTransaction(db) : db.transaction().execute(claimFromTransaction);
|
|
492
|
+
}
|
|
493
|
+
const targetIds = applyWhere(db.selectFrom(model).select(`${model}.${idField}`)).limit(1);
|
|
494
|
+
return deleteWithReturning(db.deleteFrom(model).where(`${model}.${idField}`, "in", targetIds));
|
|
495
|
+
},
|
|
428
496
|
options: config
|
|
429
497
|
};
|
|
430
498
|
};
|
|
@@ -443,8 +511,11 @@ const kyselyAdapter = (db, config) => {
|
|
|
443
511
|
supportsUUIDs: config?.type === "postgres" ? true : false,
|
|
444
512
|
transaction: config?.transaction ? (cb) => db.transaction().execute((trx) => {
|
|
445
513
|
return cb(createAdapterFactory({
|
|
446
|
-
config:
|
|
447
|
-
|
|
514
|
+
config: {
|
|
515
|
+
...adapterOptions.config,
|
|
516
|
+
transaction: false
|
|
517
|
+
},
|
|
518
|
+
adapter: createCustomAdapter(trx, true)
|
|
448
519
|
})(lazyOptions));
|
|
449
520
|
}) : false
|
|
450
521
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/kysely-adapter",
|
|
3
|
-
"version": "1.7.0-beta.
|
|
3
|
+
"version": "1.7.0-beta.4",
|
|
4
4
|
"description": "Kysely adapter for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@better-auth/utils": "0.4.
|
|
44
|
-
"kysely": "^0.28.
|
|
45
|
-
"@better-auth/core": "^1.7.0-beta.
|
|
43
|
+
"@better-auth/utils": "0.4.1",
|
|
44
|
+
"kysely": "^0.28.17 || ^0.29.0",
|
|
45
|
+
"@better-auth/core": "^1.7.0-beta.4"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"kysely": {
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@cloudflare/workers-types": "^4.20250121.0",
|
|
54
|
-
"@better-auth/utils": "0.4.
|
|
55
|
-
"kysely": "^0.28.
|
|
54
|
+
"@better-auth/utils": "0.4.1",
|
|
55
|
+
"kysely": "^0.28.17 || ^0.29.0",
|
|
56
56
|
"tsdown": "0.21.1",
|
|
57
57
|
"typescript": "^5.9.3",
|
|
58
|
-
"@better-auth/core": "1.7.0-beta.
|
|
58
|
+
"@better-auth/core": "1.7.0-beta.4"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "tsdown",
|