@better-auth/drizzle-adapter 1.6.16 → 1.6.17

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.
Files changed (2) hide show
  1. package/dist/index.mjs +76 -9
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -38,6 +38,36 @@ function insensitiveNe(column, value) {
38
38
  }
39
39
  //#endregion
40
40
  //#region src/drizzle-adapter.ts
41
+ /**
42
+ * Derive the number of affected rows from a Drizzle write result.
43
+ *
44
+ * Drizzle's drivers report affected rows under different shapes: postgres-js
45
+ * exposes `rowCount`, mysql2 reports `affectedRows`/`rowsAffected` (sometimes as
46
+ * the first element of a result-header array), and better-sqlite3 uses
47
+ * `changes`. This normalizes those so `updateMany` and `deleteMany` honor the
48
+ * `Promise<number>` adapter contract instead of leaking the raw driver result.
49
+ */
50
+ function getAffectedRowCount(result, operation, context) {
51
+ let count = 0;
52
+ if (result && typeof result === "object" && "rowCount" in result) count = result.rowCount;
53
+ else if (Array.isArray(result)) count = result.length > 0 && hasDriverRowCount(result[0]) ? readDriverRowCount(result[0]) : result.length;
54
+ else if (hasDriverRowCount(result)) count = readDriverRowCount(result);
55
+ if (typeof count !== "number") {
56
+ logger.error(`[Drizzle Adapter] The result of the ${operation} operation is not a number. This is likely a bug in the adapter. Please report this issue to the Better Auth team.`, {
57
+ result,
58
+ ...context
59
+ });
60
+ return 0;
61
+ }
62
+ return count;
63
+ }
64
+ function hasDriverRowCount(result) {
65
+ return !!result && typeof result === "object" && ("affectedRows" in result || "rowsAffected" in result || "changes" in result);
66
+ }
67
+ function readDriverRowCount(result) {
68
+ const r = result;
69
+ return r.affectedRows ?? r.rowsAffected ?? r.changes;
70
+ }
41
71
  const drizzleAdapter = (db, config) => {
42
72
  let lazyOptions = null;
43
73
  let mysqlNoIdWarned = false;
@@ -431,7 +461,10 @@ const drizzleAdapter = (db, config) => {
431
461
  async updateMany({ model, where, update: values }) {
432
462
  const schemaModel = getSchema(model);
433
463
  const clause = convertWhereClause(where, model);
434
- return await db.update(schemaModel).set(values).where(...clause);
464
+ return getAffectedRowCount(await db.update(schemaModel).set(values).where(...clause), "updateMany", {
465
+ model,
466
+ where
467
+ });
435
468
  },
436
469
  async delete({ model, where }) {
437
470
  const schemaModel = getSchema(model);
@@ -441,17 +474,10 @@ const drizzleAdapter = (db, config) => {
441
474
  async deleteMany({ model, where }) {
442
475
  const schemaModel = getSchema(model);
443
476
  const clause = convertWhereClause(where, model);
444
- const res = await db.delete(schemaModel).where(...clause);
445
- let count = 0;
446
- if (res && "rowCount" in res) count = res.rowCount;
447
- else if (Array.isArray(res)) count = res.length;
448
- else if (res && ("affectedRows" in res || "rowsAffected" in res || "changes" in res)) count = res.affectedRows ?? res.rowsAffected ?? res.changes;
449
- if (typeof count !== "number") logger.error("[Drizzle Adapter] The result of the deleteMany operation is not a number. This is likely a bug in the adapter. Please report this issue to the Better Auth team.", {
450
- res,
477
+ return getAffectedRowCount(await db.delete(schemaModel).where(...clause), "deleteMany", {
451
478
  model,
452
479
  where
453
480
  });
454
- return count;
455
481
  },
456
482
  async consumeOne({ model, where }) {
457
483
  const schemaModel = getSchema(model);
@@ -476,6 +502,47 @@ const drizzleAdapter = (db, config) => {
476
502
  const targetIds = db.select({ id: idColumn }).from(schemaModel).where(...clause).limit(1);
477
503
  return (await db.delete(schemaModel).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
478
504
  },
505
+ async incrementOne({ model, where, increment, set }) {
506
+ const schemaModel = getSchema(model);
507
+ const clause = convertWhereClause(where, model);
508
+ const idField = getFieldName({
509
+ model,
510
+ field: "id"
511
+ });
512
+ const idColumn = schemaModel[idField];
513
+ const assignments = {};
514
+ for (const [field, delta] of Object.entries(increment)) {
515
+ const columnName = getFieldName({
516
+ model,
517
+ field
518
+ });
519
+ const column = schemaModel[columnName];
520
+ if (!column) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
521
+ assignments[columnName] = sql`${column} + ${delta}`;
522
+ }
523
+ if (set) for (const [field, value] of Object.entries(set)) {
524
+ const columnName = getFieldName({
525
+ model,
526
+ field
527
+ });
528
+ if (!schemaModel[columnName]) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
529
+ assignments[columnName] = value;
530
+ }
531
+ if (config.provider === "mysql") {
532
+ const mutateInTransaction = async (tx) => {
533
+ const target = (await tx.select().from(schemaModel).where(...clause).for("update").limit(1))[0];
534
+ if (!target) return null;
535
+ const targetId = target[idField] ?? target.id;
536
+ if (targetId === void 0 || targetId === null || !idColumn) return null;
537
+ await tx.update(schemaModel).set(assignments).where(eq(idColumn, targetId)).execute();
538
+ return (await tx.select().from(schemaModel).where(eq(idColumn, targetId)).limit(1).execute())[0] ?? null;
539
+ };
540
+ return inTransaction ? mutateInTransaction(db) : db.transaction(mutateInTransaction);
541
+ }
542
+ if (!idColumn) return null;
543
+ const targetIds = db.select({ id: idColumn }).from(schemaModel).where(...clause).limit(1);
544
+ return (await db.update(schemaModel).set(assignments).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
545
+ },
479
546
  options: config
480
547
  };
481
548
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/drizzle-adapter",
3
- "version": "1.6.16",
3
+ "version": "1.6.17",
4
4
  "description": "Drizzle adapter for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -37,7 +37,7 @@
37
37
  "peerDependencies": {
38
38
  "@better-auth/utils": "0.4.1",
39
39
  "drizzle-orm": "^0.45.2",
40
- "@better-auth/core": "^1.6.16"
40
+ "@better-auth/core": "^1.6.17"
41
41
  },
42
42
  "peerDependenciesMeta": {
43
43
  "drizzle-orm": {
@@ -49,7 +49,7 @@
49
49
  "drizzle-orm": "^0.45.2",
50
50
  "tsdown": "0.21.1",
51
51
  "typescript": "^5.9.3",
52
- "@better-auth/core": "1.6.16"
52
+ "@better-auth/core": "1.6.17"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "tsdown",