@better-auth/drizzle-adapter 1.7.4 → 1.7.6

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,4 +1,4 @@
1
- import { a as insensitiveInArray, c as buildRelationKeysByModel, i as insensitiveIlike, l as getOneToOneRelationKey, o as insensitiveNe, r as insensitiveEq, s as insensitiveNotInArray, t as findDrizzleSchemaProblems } from "./schema-check-_Aj1MGau.mjs";
1
+ import { a as insensitiveInArray, c as buildRelationKeysByModel, i as insensitiveIlike, l as getOneToOneRelationKey, o as insensitiveNe, r as insensitiveEq, s as insensitiveNotInArray, t as findDrizzleSchemaProblems } from "./schema-check-DFZjRat1.mjs";
2
2
  import { createAdapterFactory } from "@better-auth/core/db/adapter";
3
3
  import { checksSchema, createSchemaCheck, registerSchemaCheck } from "@better-auth/core/db/internal";
4
4
  import { logger } from "@better-auth/core/env";
@@ -49,7 +49,8 @@ function hasDriverRowCount(result) {
49
49
  const drizzleAdapter = (db, config) => {
50
50
  let lazyOptions = null;
51
51
  let mysqlNoIdWarned = false;
52
- const relationKeysByModel = buildRelationKeysByModel(db._?.schema);
52
+ let relationKeysByModel;
53
+ const getRelationKeysByModel = () => relationKeysByModel ??= buildRelationKeysByModel(db._?.schema);
53
54
  const createCustomAdapter = (db, inTransaction = false) => ({ getFieldName, getDefaultFieldName, getDefaultModelName, options, schema: baSchema }) => {
54
55
  if (config.provider === "mysql" && options.advanced?.database?.generateId === false && !mysqlNoIdWarned) {
55
56
  mysqlNoIdWarned = true;
@@ -62,10 +63,10 @@ const drizzleAdapter = (db, config) => {
62
63
  if (!schemaModel) throw new BetterAuthError(`[# Drizzle Adapter]: The model "${model}" was not found in the schema object. Please pass the schema directly to the adapter options.`);
63
64
  return schemaModel;
64
65
  }
65
- const withReturning = async (model, builder, data, where) => {
66
+ const withReturning = async (model, modelKey, builder, data, where) => {
66
67
  if (config.provider !== "mysql") return (await builder.returning())[0];
67
68
  await builder.execute();
68
- const schemaModel = getSchema(model);
69
+ const table = getSchema(model);
69
70
  const builderVal = builder.config?.values;
70
71
  if (where?.length) {
71
72
  const clause = convertWhereClause(where.map((w) => {
@@ -74,39 +75,39 @@ const drizzleAdapter = (db, config) => {
74
75
  value: data[w.field]
75
76
  };
76
77
  return w;
77
- }), model);
78
- return (await db.select().from(schemaModel).where(...clause))[0];
78
+ }), model, modelKey);
79
+ return (await db.select().from(table).where(...clause))[0];
79
80
  }
80
81
  const fetchInserted = async (tx) => {
81
82
  const builderId = builderVal?.[0]?.id?.value;
82
- if (builderId) return (await tx.select().from(schemaModel).where(eq(schemaModel.id, builderId)).limit(1).execute())[0] ?? null;
83
- if (data.id) return (await tx.select().from(schemaModel).where(eq(schemaModel.id, data.id)).limit(1).execute())[0] ?? null;
84
- if (options.advanced?.database?.generateId === "serial" && schemaModel.id) {
85
- const lastId = (await tx.select({ id: sql`LAST_INSERT_ID()` }).from(schemaModel).limit(1).execute())[0]?.id;
86
- if (lastId) return (await tx.select().from(schemaModel).where(eq(schemaModel.id, lastId)).limit(1).execute())[0] ?? null;
83
+ if (builderId) return (await tx.select().from(table).where(eq(table.id, builderId)).limit(1).execute())[0] ?? null;
84
+ if (data.id) return (await tx.select().from(table).where(eq(table.id, data.id)).limit(1).execute())[0] ?? null;
85
+ if (options.advanced?.database?.generateId === "serial" && table.id) {
86
+ const lastId = (await tx.select({ id: sql`LAST_INSERT_ID()` }).from(table).limit(1).execute())[0]?.id;
87
+ if (lastId) return (await tx.select().from(table).where(eq(table.id, lastId)).limit(1).execute())[0] ?? null;
87
88
  }
88
- const modelSchema = baSchema[getDefaultModelName(model)]?.fields;
89
+ const modelSchema = baSchema[modelKey]?.fields;
89
90
  if (modelSchema) for (const [fieldKey, fieldAttr] of Object.entries(modelSchema)) {
90
91
  if (!fieldAttr.unique) continue;
91
92
  const dbFieldName = getFieldName({
92
- model,
93
+ model: modelKey,
93
94
  field: fieldKey
94
95
  });
95
96
  const val = data[dbFieldName];
96
97
  if (val === void 0 || val === null) continue;
97
- if (!schemaModel[dbFieldName]) continue;
98
- const res = await tx.select().from(schemaModel).where(eq(schemaModel[dbFieldName], val)).limit(1).execute();
98
+ if (!table[dbFieldName]) continue;
99
+ const res = await tx.select().from(table).where(eq(table[dbFieldName], val)).limit(1).execute();
99
100
  if (res[0]) return res[0];
100
101
  }
101
102
  const conditions = [];
102
103
  for (const [key, val] of Object.entries(data)) {
103
- if (val === void 0 || !schemaModel[key]) continue;
104
- conditions.push(val === null ? isNull(schemaModel[key]) : eq(schemaModel[key], val));
104
+ if (val === void 0 || !table[key]) continue;
105
+ conditions.push(val === null ? isNull(table[key]) : eq(table[key], val));
105
106
  }
106
107
  if (conditions.length > 0) {
107
108
  const combined = and(...conditions);
108
109
  if (combined) {
109
- const res = await tx.select().from(schemaModel).where(combined).limit(2).execute();
110
+ const res = await tx.select().from(table).where(combined).limit(2).execute();
110
111
  if (res.length === 1) return res[0];
111
112
  }
112
113
  }
@@ -115,11 +116,11 @@ const drizzleAdapter = (db, config) => {
115
116
  };
116
117
  return inTransaction ? fetchInserted(db) : db.transaction(fetchInserted);
117
118
  };
118
- function convertWhereClause(where, model) {
119
+ function convertWhereClause(where, model, modelKey) {
119
120
  const schemaModel = getSchema(model);
120
121
  const resolveFieldName = (where) => {
121
122
  const field = getFieldName({
122
- model,
123
+ model: modelKey,
123
124
  field: where.field
124
125
  });
125
126
  if (!is(schemaModel[field], Column)) throw new BetterAuthError(`The field "${where.field}" does not exist in the schema for the model "${model}". Please update your schema.`);
@@ -294,10 +295,12 @@ const drizzleAdapter = (db, config) => {
294
295
  }
295
296
  return null;
296
297
  }
297
- function getJoinRelationKey(baseModel, joinModel, relationKeys, isUnique) {
298
+ function getJoinRelationKey(baseModel, joinModel, baseModelKey, joinModelKey, relationKeys, isUnique) {
298
299
  if (isUnique) return getOneToOneRelationKey({
299
300
  baseModel,
300
301
  joinModel,
302
+ baseModelKey,
303
+ joinModelKey,
301
304
  relationKeys,
302
305
  schema: baSchema,
303
306
  getDefaultModelName
@@ -305,14 +308,14 @@ const drizzleAdapter = (db, config) => {
305
308
  return config.usePlural ? joinModel : `${joinModel}s`;
306
309
  }
307
310
  return {
308
- async create({ model, data: values }) {
309
- const schemaModel = getSchema(model);
310
- checkMissingFields(schemaModel, model, values);
311
- return await withReturning(model, db.insert(schemaModel).values(values), values);
311
+ async create({ model, modelKey = model, data: values }) {
312
+ const table = getSchema(model);
313
+ checkMissingFields(table, modelKey, values);
314
+ return await withReturning(model, modelKey, db.insert(table).values(values), values);
312
315
  },
313
- async findOne({ model, where, select, join }) {
314
- const schemaModel = getSchema(model);
315
- const clause = convertWhereClause(where, model);
316
+ async findOne({ model, modelKey = model, where, select, join }) {
317
+ const table = getSchema(model);
318
+ const clause = convertWhereClause(where, model, modelKey);
316
319
  if (join) {
317
320
  const queryModel = getQueryModel(model);
318
321
  if (!db.query || !queryModel) {
@@ -321,13 +324,13 @@ const drizzleAdapter = (db, config) => {
321
324
  } else {
322
325
  let includes;
323
326
  const renamedJoinResults = [];
324
- const relationKeys = relationKeysByModel.get(queryModel);
327
+ const relationKeys = getRelationKeysByModel().get(queryModel);
325
328
  includes = {};
326
329
  const joinEntries = Object.entries(join);
327
330
  for (const [joinModel, joinAttr] of joinEntries) {
328
331
  const limit = joinAttr.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
329
332
  const isUnique = joinAttr.relation === "one-to-one";
330
- const relationKey = getJoinRelationKey(model, joinModel, relationKeys, isUnique);
333
+ const relationKey = getJoinRelationKey(model, joinModel, modelKey, joinAttr.modelKey ?? joinModel, relationKeys, isUnique);
331
334
  includes[relationKey] = isUnique ? true : { limit };
332
335
  if (relationKey !== joinModel) renamedJoinResults.push({
333
336
  key: relationKey,
@@ -338,7 +341,7 @@ const drizzleAdapter = (db, config) => {
338
341
  where: clause[0],
339
342
  columns: select?.length && select.length > 0 ? select.reduce((acc, field) => {
340
343
  acc[getFieldName({
341
- model,
344
+ model: modelKey,
342
345
  field
343
346
  })] = true;
344
347
  return acc;
@@ -354,20 +357,20 @@ const drizzleAdapter = (db, config) => {
354
357
  }
355
358
  const res = await db.select(select?.length && select.length > 0 ? select.reduce((acc, field) => {
356
359
  const fieldName = getFieldName({
357
- model,
360
+ model: modelKey,
358
361
  field
359
362
  });
360
363
  return {
361
364
  ...acc,
362
- [fieldName]: schemaModel[fieldName]
365
+ [fieldName]: table[fieldName]
363
366
  };
364
- }, {}) : void 0).from(schemaModel).where(...clause);
367
+ }, {}) : void 0).from(table).where(...clause);
365
368
  if (!res.length) return null;
366
369
  return res[0];
367
370
  },
368
- async findMany({ model, where, sortBy, limit, select, offset, join }) {
369
- const schemaModel = getSchema(model);
370
- const clause = where ? convertWhereClause(where, model) : [];
371
+ async findMany({ model, modelKey = model, where, sortBy, limit, select, offset, join }) {
372
+ const table = getSchema(model);
373
+ const clause = where ? convertWhereClause(where, model, modelKey) : [];
371
374
  const sortFn = sortBy?.direction === "desc" ? desc : asc;
372
375
  if (join) {
373
376
  const queryModel = getQueryModel(model);
@@ -377,13 +380,13 @@ const drizzleAdapter = (db, config) => {
377
380
  } else {
378
381
  let includes;
379
382
  const renamedJoinResults = [];
380
- const relationKeys = relationKeysByModel.get(queryModel);
383
+ const relationKeys = getRelationKeysByModel().get(queryModel);
381
384
  includes = {};
382
385
  const joinEntries = Object.entries(join);
383
386
  for (const [joinModel, joinAttr] of joinEntries) {
384
387
  const isUnique = joinAttr.relation === "one-to-one";
385
388
  const limit = joinAttr.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
386
- const relationKey = getJoinRelationKey(model, joinModel, relationKeys, isUnique);
389
+ const relationKey = getJoinRelationKey(model, joinModel, modelKey, joinAttr.modelKey ?? joinModel, relationKeys, isUnique);
387
390
  includes[relationKey] = isUnique ? true : { limit };
388
391
  if (relationKey !== joinModel) renamedJoinResults.push({
389
392
  key: relationKey,
@@ -391,8 +394,8 @@ const drizzleAdapter = (db, config) => {
391
394
  });
392
395
  }
393
396
  let orderBy = void 0;
394
- if (sortBy?.field) orderBy = [sortFn(schemaModel[getFieldName({
395
- model,
397
+ if (sortBy?.field) orderBy = [sortFn(table[getFieldName({
398
+ model: modelKey,
396
399
  field: sortBy?.field
397
400
  })])];
398
401
  const res = await db.query[queryModel].findMany({
@@ -400,7 +403,7 @@ const drizzleAdapter = (db, config) => {
400
403
  with: includes,
401
404
  columns: select?.length && select.length > 0 ? select.reduce((acc, field) => {
402
405
  acc[getFieldName({
403
- model,
406
+ model: modelKey,
404
407
  field
405
408
  })] = true;
406
409
  return acc;
@@ -418,70 +421,70 @@ const drizzleAdapter = (db, config) => {
418
421
  }
419
422
  let builder = db.select(select?.length && select.length > 0 ? select.reduce((acc, field) => {
420
423
  const fieldName = getFieldName({
421
- model,
424
+ model: modelKey,
422
425
  field
423
426
  });
424
427
  return {
425
428
  ...acc,
426
- [fieldName]: schemaModel[fieldName]
429
+ [fieldName]: table[fieldName]
427
430
  };
428
- }, {}) : void 0).from(schemaModel);
431
+ }, {}) : void 0).from(table);
429
432
  const effectiveLimit = limit;
430
433
  const effectiveOffset = offset;
431
434
  if (typeof effectiveLimit !== "undefined") builder = builder.limit(effectiveLimit);
432
435
  if (typeof effectiveOffset !== "undefined") builder = builder.offset(effectiveOffset);
433
- if (sortBy?.field) builder = builder.orderBy(sortFn(schemaModel[getFieldName({
434
- model,
436
+ if (sortBy?.field) builder = builder.orderBy(sortFn(table[getFieldName({
437
+ model: modelKey,
435
438
  field: sortBy?.field
436
439
  })]));
437
440
  return await builder.where(...clause);
438
441
  },
439
- async count({ model, where }) {
440
- const schemaModel = getSchema(model);
441
- const clause = where ? convertWhereClause(where, model) : [];
442
- return (await db.select({ count: count() }).from(schemaModel).where(...clause))[0].count;
442
+ async count({ model, modelKey = model, where }) {
443
+ const table = getSchema(model);
444
+ const clause = where ? convertWhereClause(where, model, modelKey) : [];
445
+ return (await db.select({ count: count() }).from(table).where(...clause))[0].count;
443
446
  },
444
- async update({ model, where, update: values }) {
445
- const schemaModel = getSchema(model);
446
- const clause = convertWhereClause(where, model);
447
- return await withReturning(model, db.update(schemaModel).set(values).where(...clause), values, where);
447
+ async update({ model, modelKey = model, where, update: values }) {
448
+ const table = getSchema(model);
449
+ const clause = convertWhereClause(where, model, modelKey);
450
+ return await withReturning(model, modelKey, db.update(table).set(values).where(...clause), values, where);
448
451
  },
449
- async updateMany({ model, where, update: values }) {
450
- const schemaModel = getSchema(model);
451
- const clause = convertWhereClause(where, model);
452
- return getAffectedRowCount(await db.update(schemaModel).set(values).where(...clause), "updateMany", {
452
+ async updateMany({ model, modelKey = model, where, update: values }) {
453
+ const table = getSchema(model);
454
+ const clause = convertWhereClause(where, model, modelKey);
455
+ return getAffectedRowCount(await db.update(table).set(values).where(...clause), "updateMany", {
453
456
  model,
454
457
  where
455
458
  });
456
459
  },
457
- async delete({ model, where }) {
458
- const schemaModel = getSchema(model);
459
- const clause = convertWhereClause(where, model);
460
- return await db.delete(schemaModel).where(...clause);
460
+ async delete({ model, modelKey = model, where }) {
461
+ const table = getSchema(model);
462
+ const clause = convertWhereClause(where, model, modelKey);
463
+ return await db.delete(table).where(...clause);
461
464
  },
462
- async deleteMany({ model, where }) {
463
- const schemaModel = getSchema(model);
464
- const clause = convertWhereClause(where, model);
465
- return getAffectedRowCount(await db.delete(schemaModel).where(...clause), "deleteMany", {
465
+ async deleteMany({ model, modelKey = model, where }) {
466
+ const table = getSchema(model);
467
+ const clause = convertWhereClause(where, model, modelKey);
468
+ return getAffectedRowCount(await db.delete(table).where(...clause), "deleteMany", {
466
469
  model,
467
470
  where
468
471
  });
469
472
  },
470
- async consumeOne({ model, where }) {
471
- const schemaModel = getSchema(model);
472
- const clause = convertWhereClause(where, model);
473
+ async consumeOne({ model, modelKey = model, where }) {
474
+ const table = getSchema(model);
475
+ const clause = convertWhereClause(where, model, modelKey);
473
476
  const idField = getFieldName({
474
- model,
477
+ model: modelKey,
475
478
  field: "id"
476
479
  });
477
- const idColumn = schemaModel[idField];
480
+ const idColumn = table[idField];
478
481
  if (config.provider === "mysql") {
479
482
  const claimFromTransaction = async (tx) => {
480
- const target = (await tx.select().from(schemaModel).where(...clause).for("update").limit(1))[0];
483
+ const target = (await tx.select().from(table).where(...clause).for("update").limit(1))[0];
481
484
  if (!target) return null;
482
485
  const targetId = target[idField] ?? target.id;
483
486
  if (targetId === void 0 || targetId === null || !idColumn) return null;
484
- return getAffectedRowCount(await tx.delete(schemaModel).where(eq(idColumn, targetId)).execute(), "consumeOne", {
487
+ return getAffectedRowCount(await tx.delete(table).where(eq(idColumn, targetId)).execute(), "consumeOne", {
485
488
  model,
486
489
  where
487
490
  }) > 0 ? target : null;
@@ -489,49 +492,49 @@ const drizzleAdapter = (db, config) => {
489
492
  return inTransaction ? claimFromTransaction(db) : db.transaction(claimFromTransaction);
490
493
  }
491
494
  if (!idColumn) return null;
492
- const targetIds = db.select({ id: idColumn }).from(schemaModel).where(...clause).limit(1);
493
- return (await db.delete(schemaModel).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
495
+ const targetIds = db.select({ id: idColumn }).from(table).where(...clause).limit(1);
496
+ return (await db.delete(table).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
494
497
  },
495
- async incrementOne({ model, where, increment, set }) {
496
- const schemaModel = getSchema(model);
497
- const clause = convertWhereClause(where, model);
498
+ async incrementOne({ model, modelKey = model, where, increment, set }) {
499
+ const table = getSchema(model);
500
+ const clause = convertWhereClause(where, model, modelKey);
498
501
  const idField = getFieldName({
499
- model,
502
+ model: modelKey,
500
503
  field: "id"
501
504
  });
502
- const idColumn = schemaModel[idField];
505
+ const idColumn = table[idField];
503
506
  const assignments = {};
504
507
  for (const [field, delta] of Object.entries(increment)) {
505
508
  const columnName = getFieldName({
506
- model,
509
+ model: modelKey,
507
510
  field
508
511
  });
509
- const column = schemaModel[columnName];
512
+ const column = table[columnName];
510
513
  if (!column) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
511
514
  assignments[columnName] = sql`${column} + ${sql.param(delta)}`;
512
515
  }
513
516
  if (set) for (const [field, value] of Object.entries(set)) {
514
517
  const columnName = getFieldName({
515
- model,
518
+ model: modelKey,
516
519
  field
517
520
  });
518
- if (!schemaModel[columnName]) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
521
+ if (!table[columnName]) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
519
522
  assignments[columnName] = value;
520
523
  }
521
524
  if (config.provider === "mysql") {
522
525
  const mutateInTransaction = async (tx) => {
523
- const target = (await tx.select().from(schemaModel).where(...clause).for("update").limit(1))[0];
526
+ const target = (await tx.select().from(table).where(...clause).for("update").limit(1))[0];
524
527
  if (!target) return null;
525
528
  const targetId = target[idField] ?? target.id;
526
529
  if (targetId === void 0 || targetId === null || !idColumn) return null;
527
- await tx.update(schemaModel).set(assignments).where(eq(idColumn, targetId)).execute();
528
- return (await tx.select().from(schemaModel).where(eq(idColumn, targetId)).limit(1).execute())[0] ?? null;
530
+ await tx.update(table).set(assignments).where(eq(idColumn, targetId)).execute();
531
+ return (await tx.select().from(table).where(eq(idColumn, targetId)).limit(1).execute())[0] ?? null;
529
532
  };
530
533
  return inTransaction ? mutateInTransaction(db) : db.transaction(mutateInTransaction);
531
534
  }
532
535
  if (!idColumn) return null;
533
- const targetIds = db.select({ id: idColumn }).from(schemaModel).where(...clause).limit(1);
534
- return (await db.update(schemaModel).set(assignments).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
536
+ const targetIds = db.select({ id: idColumn }).from(table).where(...clause).limit(1);
537
+ return (await db.update(table).set(assignments).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
535
538
  },
536
539
  options: config
537
540
  };
@@ -569,7 +572,7 @@ const drizzleAdapter = (db, config) => {
569
572
  return (options) => {
570
573
  lazyOptions = options;
571
574
  const instance = adapter(options);
572
- if (checksSchema(options)) registerSchemaCheck(instance, createSchemaCheck(async () => findDrizzleSchemaProblems(config.schema ?? db._?.fullSchema ?? {}, options, config.usePlural), "drizzle"));
575
+ registerSchemaCheck(instance, createSchemaCheck(() => findDrizzleSchemaProblems(config.schema ?? db._?.fullSchema ?? {}, options, config.usePlural), "drizzle"), { runtimeEnabled: checksSchema(options) });
573
576
  return instance;
574
577
  };
575
578
  };
@@ -1,4 +1,4 @@
1
- import { a as insensitiveInArray, c as buildRelationKeysByModel, l as getOneToOneRelationKey, n as escapedLike, o as insensitiveNe, r as insensitiveEq, s as insensitiveNotInArray, t as findDrizzleSchemaProblems } from "../schema-check-_Aj1MGau.mjs";
1
+ import { a as insensitiveInArray, c as buildRelationKeysByModel, l as getOneToOneRelationKey, n as escapedLike, o as insensitiveNe, r as insensitiveEq, s as insensitiveNotInArray, t as findDrizzleSchemaProblems } from "../schema-check-DFZjRat1.mjs";
2
2
  import { createAdapterFactory } from "@better-auth/core/db/adapter";
3
3
  import { checksSchema, createSchemaCheck, registerSchemaCheck } from "@better-auth/core/db/internal";
4
4
  import { logger } from "@better-auth/core/env";
@@ -73,7 +73,8 @@ function applyWhereOperator(column, w, fieldLabel, provider) {
73
73
  const drizzleAdapter = (db, config) => {
74
74
  let lazyOptions = null;
75
75
  let mysqlNoIdWarned = false;
76
- const relationKeysByModel = buildRelationKeysByModel(db._?.relations);
76
+ let relationKeysByModel;
77
+ const getRelationKeysByModel = () => relationKeysByModel ??= buildRelationKeysByModel(db._?.relations);
77
78
  const createCustomAdapter = (db, inTransaction = false) => ({ getFieldName, getDefaultModelName, options, schema: baSchema }) => {
78
79
  if (config.provider === "mysql" && options.advanced?.database?.generateId === false && !mysqlNoIdWarned) {
79
80
  mysqlNoIdWarned = true;
@@ -109,10 +110,12 @@ const drizzleAdapter = (db, config) => {
109
110
  }
110
111
  return null;
111
112
  }
112
- function getJoinRelationKey(baseModel, joinModel, relationKeys, isUnique) {
113
+ function getJoinRelationKey(baseModel, joinModel, baseModelKey, joinModelKey, relationKeys, isUnique) {
113
114
  if (isUnique) return getOneToOneRelationKey({
114
115
  baseModel,
115
116
  joinModel,
117
+ baseModelKey,
118
+ joinModelKey,
116
119
  relationKeys,
117
120
  schema: baSchema,
118
121
  getDefaultModelName
@@ -120,7 +123,7 @@ const drizzleAdapter = (db, config) => {
120
123
  if (config.usePlural || joinModel.endsWith("s")) return joinModel;
121
124
  return `${joinModel}s`;
122
125
  }
123
- const withReturning = async (model, builder, data, where) => {
126
+ const withReturning = async (model, modelKey, builder, data, where) => {
124
127
  if (config.provider !== "mysql") return (await builder.returning())[0];
125
128
  const isSerialInsert = where === void 0 && options.advanced?.database?.generateId === "serial";
126
129
  const insertResult = isSerialInsert ? await builder.$returningId().execute() : await builder.execute();
@@ -133,7 +136,7 @@ const drizzleAdapter = (db, config) => {
133
136
  value: data[w.field]
134
137
  };
135
138
  return w;
136
- }), model);
139
+ }), model, modelKey);
137
140
  return (await db.select().from(schemaModel).where(...clause))[0];
138
141
  }
139
142
  const fetchInserted = async (tx) => {
@@ -142,11 +145,11 @@ const drizzleAdapter = (db, config) => {
142
145
  if (data.id) return (await tx.select().from(schemaModel).where(eq(schemaModel.id, data.id)).limit(1).execute())[0] ?? null;
143
146
  const insertId = isSerialInsert ? insertResult?.[0]?.id : void 0;
144
147
  if (insertId && schemaModel.id) return (await tx.select().from(schemaModel).where(eq(schemaModel.id, insertId)).limit(1).execute())[0] ?? null;
145
- const modelSchema = baSchema[getDefaultModelName(model)]?.fields;
148
+ const modelSchema = baSchema[modelKey]?.fields;
146
149
  if (modelSchema) for (const [fieldKey, fieldAttr] of Object.entries(modelSchema)) {
147
150
  if (!fieldAttr.unique) continue;
148
151
  const dbFieldName = getFieldName({
149
- model,
152
+ model: modelKey,
150
153
  field: fieldKey
151
154
  });
152
155
  const val = data[dbFieldName];
@@ -172,10 +175,10 @@ const drizzleAdapter = (db, config) => {
172
175
  };
173
176
  return inTransaction ? fetchInserted(db) : db.transaction(fetchInserted);
174
177
  };
175
- function resolveColumn(model, w) {
178
+ function resolveColumn(model, modelKey, w) {
176
179
  const schemaModel = getSchema(model);
177
180
  const field = getFieldName({
178
- model,
181
+ model: modelKey,
179
182
  field: w.field
180
183
  });
181
184
  if (!schemaModel[field]) throw new BetterAuthError(`The field "${w.field}" does not exist in the schema for the model "${model}". Please update your schema.`);
@@ -184,32 +187,32 @@ const drizzleAdapter = (db, config) => {
184
187
  field
185
188
  };
186
189
  }
187
- function convertWhereClause(where, model) {
190
+ function convertWhereClause(where, model, modelKey) {
188
191
  if (!where) return [];
189
192
  if (where.length === 1) {
190
193
  const w = where[0];
191
194
  if (!w) return [];
192
- const { column } = resolveColumn(model, w);
195
+ const { column } = resolveColumn(model, modelKey, w);
193
196
  return [applyWhereOperator(column, w, w.field, config.provider)];
194
197
  }
195
198
  const andGroup = where.filter((w) => w.connector === "AND" || !w.connector);
196
199
  const orGroup = where.filter((w) => w.connector === "OR");
197
200
  const combined = and(and(...andGroup.map((w) => {
198
- const { column } = resolveColumn(model, w);
201
+ const { column } = resolveColumn(model, modelKey, w);
199
202
  return applyWhereOperator(column, w, w.field, config.provider);
200
203
  })), or(...orGroup.map((w) => {
201
- const { column } = resolveColumn(model, w);
204
+ const { column } = resolveColumn(model, modelKey, w);
202
205
  return applyWhereOperator(column, w, w.field, config.provider);
203
206
  })));
204
207
  return combined ? [combined] : [];
205
208
  }
206
- function convertNewWhereClause(where, model) {
209
+ function convertNewWhereClause(where, model, modelKey) {
207
210
  const schemaModel = getSchema(model);
208
211
  if (!where || where.length === 0) return {};
209
212
  const rawCondition = (w, field) => ({ RAW: (table) => applyWhereOperator(table[field], w, w.field, config.provider) });
210
213
  const convertWhereToColumn = (w) => {
211
214
  const field = getFieldName({
212
- model,
215
+ model: modelKey,
213
216
  field: w.field
214
217
  });
215
218
  if (!schemaModel[field]) throw new BetterAuthError(`The field "${w.field}" does not exist in the schema for the model "${model}". Please update your schema.`);
@@ -277,14 +280,14 @@ const drizzleAdapter = (db, config) => {
277
280
  for (const key in values) if (!schema[key]) throw new BetterAuthError(`The field "${key}" does not exist in the "${model}" Drizzle schema. Please update your drizzle schema or re-generate using "npx auth@latest generate".`);
278
281
  }
279
282
  return {
280
- async create({ model, data: values }) {
281
- const schemaModel = getSchema(model);
282
- checkMissingFields(schemaModel, model, values);
283
- return await withReturning(model, db.insert(schemaModel).values(values), values);
283
+ async create({ model, modelKey = model, data: values }) {
284
+ const table = getSchema(model);
285
+ checkMissingFields(table, modelKey, values);
286
+ return await withReturning(model, modelKey, db.insert(table).values(values), values);
284
287
  },
285
- async findOne({ model, where, select, join }) {
286
- const schemaModel = getSchema(model);
287
- const clause = convertWhereClause(where, model);
288
+ async findOne({ model, modelKey = model, where, select, join }) {
289
+ const table = getSchema(model);
290
+ const clause = convertWhereClause(where, model, modelKey);
288
291
  if (join) {
289
292
  const queryModel = getQueryModel(model);
290
293
  if (!db.query || !queryModel) {
@@ -293,25 +296,25 @@ const drizzleAdapter = (db, config) => {
293
296
  } else {
294
297
  let includes;
295
298
  const renamedJoinResults = [];
296
- const relationKeys = relationKeysByModel.get(queryModel);
299
+ const relationKeys = getRelationKeysByModel().get(queryModel);
297
300
  includes = {};
298
301
  const joinEntries = Object.entries(join);
299
302
  for (const [joinModel, joinAttr] of joinEntries) {
300
303
  const limit = joinAttr.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
301
304
  const isUnique = joinAttr.relation === "one-to-one";
302
- const relationKey = getJoinRelationKey(model, joinModel, relationKeys, isUnique);
305
+ const relationKey = getJoinRelationKey(model, joinModel, modelKey, joinAttr.modelKey ?? joinModel, relationKeys, isUnique);
303
306
  includes[relationKey] = isUnique ? true : { limit };
304
307
  if (relationKey !== joinModel) renamedJoinResults.push({
305
308
  key: relationKey,
306
309
  target: joinModel
307
310
  });
308
311
  }
309
- const clause = convertNewWhereClause(where, model);
312
+ const clause = convertNewWhereClause(where, model, modelKey);
310
313
  const res = await db.query[queryModel].findFirst({
311
314
  where: clause,
312
315
  columns: select?.length && select.length > 0 ? select.reduce((acc, field) => {
313
316
  acc[getFieldName({
314
- model,
317
+ model: modelKey,
315
318
  field
316
319
  })] = true;
317
320
  return acc;
@@ -327,20 +330,20 @@ const drizzleAdapter = (db, config) => {
327
330
  }
328
331
  const res = await db.select(select?.length && select.length > 0 ? select.reduce((acc, field) => {
329
332
  const fieldName = getFieldName({
330
- model,
333
+ model: modelKey,
331
334
  field
332
335
  });
333
336
  return {
334
337
  ...acc,
335
- [fieldName]: schemaModel[fieldName]
338
+ [fieldName]: table[fieldName]
336
339
  };
337
- }, {}) : void 0).from(schemaModel).where(...clause);
340
+ }, {}) : void 0).from(table).where(...clause);
338
341
  if (!res.length) return null;
339
342
  return res[0];
340
343
  },
341
- async findMany({ model, where, sortBy, limit, select, offset, join }) {
342
- const schemaModel = getSchema(model);
343
- const clause = where ? convertWhereClause(where, model) : [];
344
+ async findMany({ model, modelKey = model, where, sortBy, limit, select, offset, join }) {
345
+ const table = getSchema(model);
346
+ const clause = where ? convertWhereClause(where, model, modelKey) : [];
344
347
  const sortFn = sortBy?.direction === "desc" ? desc : asc;
345
348
  if (join) {
346
349
  const queryModel = getQueryModel(model);
@@ -350,13 +353,13 @@ const drizzleAdapter = (db, config) => {
350
353
  } else {
351
354
  let includes;
352
355
  const renamedJoinResults = [];
353
- const relationKeys = relationKeysByModel.get(queryModel);
356
+ const relationKeys = getRelationKeysByModel().get(queryModel);
354
357
  includes = {};
355
358
  const joinEntries = Object.entries(join);
356
359
  for (const [joinModel, joinAttr] of joinEntries) {
357
360
  const isUnique = joinAttr.relation === "one-to-one";
358
361
  const limit = joinAttr.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
359
- const relationKey = getJoinRelationKey(model, joinModel, relationKeys, isUnique);
362
+ const relationKey = getJoinRelationKey(model, joinModel, modelKey, joinAttr.modelKey ?? joinModel, relationKeys, isUnique);
360
363
  includes[relationKey] = isUnique ? true : { limit };
361
364
  if (relationKey !== joinModel) renamedJoinResults.push({
362
365
  key: relationKey,
@@ -365,15 +368,15 @@ const drizzleAdapter = (db, config) => {
365
368
  }
366
369
  let orderBy = void 0;
367
370
  if (sortBy?.field) orderBy = { [getFieldName({
368
- model,
371
+ model: modelKey,
369
372
  field: sortBy.field
370
373
  })]: sortBy.direction === "desc" ? "desc" : "asc" };
371
374
  const res = await db.query[queryModel].findMany({
372
- where: where ? convertNewWhereClause(where, model) : void 0,
375
+ where: where ? convertNewWhereClause(where, model, modelKey) : void 0,
373
376
  with: includes,
374
377
  columns: select?.length && select.length > 0 ? select.reduce((acc, field) => {
375
378
  acc[getFieldName({
376
- model,
379
+ model: modelKey,
377
380
  field
378
381
  })] = true;
379
382
  return acc;
@@ -391,70 +394,70 @@ const drizzleAdapter = (db, config) => {
391
394
  }
392
395
  let builder = db.select(select?.length && select.length > 0 ? select.reduce((acc, field) => {
393
396
  const fieldName = getFieldName({
394
- model,
397
+ model: modelKey,
395
398
  field
396
399
  });
397
400
  return {
398
401
  ...acc,
399
- [fieldName]: schemaModel[fieldName]
402
+ [fieldName]: table[fieldName]
400
403
  };
401
- }, {}) : void 0).from(schemaModel);
404
+ }, {}) : void 0).from(table);
402
405
  const effectiveLimit = limit;
403
406
  const effectiveOffset = offset;
404
407
  if (typeof effectiveLimit !== "undefined") builder = builder.limit(effectiveLimit);
405
408
  if (typeof effectiveOffset !== "undefined") builder = builder.offset(effectiveOffset);
406
- if (sortBy?.field) builder = builder.orderBy(sortFn(schemaModel[getFieldName({
407
- model,
409
+ if (sortBy?.field) builder = builder.orderBy(sortFn(table[getFieldName({
410
+ model: modelKey,
408
411
  field: sortBy?.field
409
412
  })]));
410
413
  return await builder.where(...clause);
411
414
  },
412
- async count({ model, where }) {
413
- const schemaModel = getSchema(model);
414
- const clause = where ? convertWhereClause(where, model) : [];
415
- return (await db.select({ count: count() }).from(schemaModel).where(...clause))[0].count;
415
+ async count({ model, modelKey = model, where }) {
416
+ const table = getSchema(model);
417
+ const clause = where ? convertWhereClause(where, model, modelKey) : [];
418
+ return (await db.select({ count: count() }).from(table).where(...clause))[0].count;
416
419
  },
417
- async update({ model, where, update: values }) {
418
- const schemaModel = getSchema(model);
419
- const clause = convertWhereClause(where, model);
420
- return await withReturning(model, db.update(schemaModel).set(values).where(...clause), values, where);
420
+ async update({ model, modelKey = model, where, update: values }) {
421
+ const table = getSchema(model);
422
+ const clause = convertWhereClause(where, model, modelKey);
423
+ return await withReturning(model, modelKey, db.update(table).set(values).where(...clause), values, where);
421
424
  },
422
- async updateMany({ model, where, update: values }) {
423
- const schemaModel = getSchema(model);
424
- const clause = convertWhereClause(where, model);
425
- return getAffectedRowCount(await db.update(schemaModel).set(values).where(...clause), "updateMany", {
425
+ async updateMany({ model, modelKey = model, where, update: values }) {
426
+ const table = getSchema(model);
427
+ const clause = convertWhereClause(where, model, modelKey);
428
+ return getAffectedRowCount(await db.update(table).set(values).where(...clause), "updateMany", {
426
429
  model,
427
430
  where
428
431
  });
429
432
  },
430
- async delete({ model, where }) {
431
- const schemaModel = getSchema(model);
432
- const clause = convertWhereClause(where, model);
433
- return await db.delete(schemaModel).where(...clause);
433
+ async delete({ model, modelKey = model, where }) {
434
+ const table = getSchema(model);
435
+ const clause = convertWhereClause(where, model, modelKey);
436
+ return await db.delete(table).where(...clause);
434
437
  },
435
- async deleteMany({ model, where }) {
436
- const schemaModel = getSchema(model);
437
- const clause = convertWhereClause(where, model);
438
- return getAffectedRowCount(await db.delete(schemaModel).where(...clause), "deleteMany", {
438
+ async deleteMany({ model, modelKey = model, where }) {
439
+ const table = getSchema(model);
440
+ const clause = convertWhereClause(where, model, modelKey);
441
+ return getAffectedRowCount(await db.delete(table).where(...clause), "deleteMany", {
439
442
  model,
440
443
  where
441
444
  });
442
445
  },
443
- async consumeOne({ model, where }) {
444
- const schemaModel = getSchema(model);
445
- const clause = convertWhereClause(where, model);
446
+ async consumeOne({ model, modelKey = model, where }) {
447
+ const table = getSchema(model);
448
+ const clause = convertWhereClause(where, model, modelKey);
446
449
  const idField = getFieldName({
447
- model,
450
+ model: modelKey,
448
451
  field: "id"
449
452
  });
450
- const idColumn = schemaModel[idField];
453
+ const idColumn = table[idField];
451
454
  if (config.provider === "mysql") {
452
455
  const claimFromTransaction = async (tx) => {
453
- const target = (await tx.select().from(schemaModel).where(...clause).for("update").limit(1))[0];
456
+ const target = (await tx.select().from(table).where(...clause).for("update").limit(1))[0];
454
457
  if (!target) return null;
455
458
  const targetId = target[idField] ?? target.id;
456
459
  if (targetId === void 0 || targetId === null || !idColumn) return null;
457
- return getAffectedRowCount(await tx.delete(schemaModel).where(eq(idColumn, targetId)).execute(), "consumeOne", {
460
+ return getAffectedRowCount(await tx.delete(table).where(eq(idColumn, targetId)).execute(), "consumeOne", {
458
461
  model,
459
462
  where
460
463
  }) > 0 ? target : null;
@@ -462,49 +465,49 @@ const drizzleAdapter = (db, config) => {
462
465
  return inTransaction ? claimFromTransaction(db) : db.transaction(claimFromTransaction);
463
466
  }
464
467
  if (!idColumn) return null;
465
- const targetIds = db.select({ id: idColumn }).from(schemaModel).where(...clause).limit(1);
466
- return (await db.delete(schemaModel).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
468
+ const targetIds = db.select({ id: idColumn }).from(table).where(...clause).limit(1);
469
+ return (await db.delete(table).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
467
470
  },
468
- async incrementOne({ model, where, increment, set }) {
469
- const schemaModel = getSchema(model);
470
- const clause = convertWhereClause(where, model);
471
+ async incrementOne({ model, modelKey = model, where, increment, set }) {
472
+ const table = getSchema(model);
473
+ const clause = convertWhereClause(where, model, modelKey);
471
474
  const idField = getFieldName({
472
- model,
475
+ model: modelKey,
473
476
  field: "id"
474
477
  });
475
- const idColumn = schemaModel[idField];
478
+ const idColumn = table[idField];
476
479
  const assignments = {};
477
480
  for (const [field, delta] of Object.entries(increment)) {
478
481
  const columnName = getFieldName({
479
- model,
482
+ model: modelKey,
480
483
  field
481
484
  });
482
- const column = schemaModel[columnName];
485
+ const column = table[columnName];
483
486
  if (!column) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
484
487
  assignments[columnName] = sql`${column} + ${sql.param(delta)}`;
485
488
  }
486
489
  if (set) for (const [field, value] of Object.entries(set)) {
487
490
  const columnName = getFieldName({
488
- model,
491
+ model: modelKey,
489
492
  field
490
493
  });
491
- if (!schemaModel[columnName]) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
494
+ if (!table[columnName]) throw new BetterAuthError(`The field "${field}" does not exist in the schema for the model "${model}". Please update your schema.`);
492
495
  assignments[columnName] = value;
493
496
  }
494
497
  if (config.provider === "mysql") {
495
498
  const mutateInTransaction = async (tx) => {
496
- const target = (await tx.select().from(schemaModel).where(...clause).for("update").limit(1))[0];
499
+ const target = (await tx.select().from(table).where(...clause).for("update").limit(1))[0];
497
500
  if (!target) return null;
498
501
  const targetId = target[idField] ?? target.id;
499
502
  if (targetId === void 0 || targetId === null || !idColumn) return null;
500
- await tx.update(schemaModel).set(assignments).where(eq(idColumn, targetId)).execute();
501
- return (await tx.select().from(schemaModel).where(eq(idColumn, targetId)).limit(1).execute())[0] ?? null;
503
+ await tx.update(table).set(assignments).where(eq(idColumn, targetId)).execute();
504
+ return (await tx.select().from(table).where(eq(idColumn, targetId)).limit(1).execute())[0] ?? null;
502
505
  };
503
506
  return inTransaction ? mutateInTransaction(db) : db.transaction(mutateInTransaction);
504
507
  }
505
508
  if (!idColumn) return null;
506
- const targetIds = db.select({ id: idColumn }).from(schemaModel).where(...clause).limit(1);
507
- return (await db.update(schemaModel).set(assignments).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
509
+ const targetIds = db.select({ id: idColumn }).from(table).where(...clause).limit(1);
510
+ return (await db.update(table).set(assignments).where(inArray(idColumn, targetIds)).returning())[0] ?? null;
508
511
  },
509
512
  async createSchema(props) {
510
513
  const { generateDrizzleSchema } = await import("../generate-drizzle-schema-iWvrXnu0.mjs");
@@ -546,14 +549,14 @@ const drizzleAdapter = (db, config) => {
546
549
  return (options) => {
547
550
  lazyOptions = options;
548
551
  const instance = adapter(options);
549
- if (checksSchema(options)) registerSchemaCheck(instance, createSchemaCheck(async () => {
552
+ registerSchemaCheck(instance, createSchemaCheck(() => {
550
553
  const relations = db._?.relations ?? {};
551
554
  return findDrizzleSchemaProblems({
552
555
  ...db._?.fullSchema,
553
556
  ...Object.fromEntries(Object.entries(relations).map(([name, relation]) => [name, relation.table])),
554
557
  ...config.schema
555
558
  }, options, config.usePlural);
556
- }, "drizzle"));
559
+ }, "drizzle"), { runtimeEnabled: checksSchema(options) });
557
560
  return instance;
558
561
  };
559
562
  };
@@ -15,9 +15,9 @@ function buildRelationKeysByModel(relationRegistry) {
15
15
  }
16
16
  return relationKeysByModel;
17
17
  }
18
- function getOneToOneRelationKey({ baseModel, joinModel, relationKeys, schema, getDefaultModelName }) {
19
- const defaultBaseModelName = getDefaultModelName(baseModel);
20
- const defaultJoinModelName = getDefaultModelName(joinModel);
18
+ function getOneToOneRelationKey({ baseModel, joinModel, baseModelKey, joinModelKey, relationKeys, schema, getDefaultModelName }) {
19
+ const defaultBaseModelName = baseModelKey ?? getDefaultModelName(baseModel);
20
+ const defaultJoinModelName = joinModelKey ?? getDefaultModelName(joinModel);
21
21
  const joinModelFields = schema[defaultJoinModelName]?.fields ?? {};
22
22
  const generatedRelationKey = Object.values(joinModelFields).some((field) => field.references && getDefaultModelName(field.references.model) === defaultBaseModelName) ? joinModel : schema[defaultJoinModelName]?.modelName ?? defaultJoinModelName;
23
23
  if (!relationKeys?.size) return joinModel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/drizzle-adapter",
3
- "version": "1.7.4",
3
+ "version": "1.7.6",
4
4
  "bugs": {
5
5
  "url": "https://github.com/better-auth/better-auth/issues"
6
6
  },
@@ -45,7 +45,7 @@
45
45
  "peerDependencies": {
46
46
  "@better-auth/utils": "0.4.2",
47
47
  "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0",
48
- "@better-auth/core": "^1.7.4"
48
+ "@better-auth/core": "^1.7.6"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "drizzle-orm": {
@@ -57,7 +57,7 @@
57
57
  "drizzle-orm": "^0.45.2",
58
58
  "tsdown": "0.21.10",
59
59
  "typescript": "^6.0.3",
60
- "@better-auth/core": "1.7.4"
60
+ "@better-auth/core": "1.7.6"
61
61
  },
62
62
  "scripts": {
63
63
  "build": "tsdown",