@opensaas/stack-auth 0.21.0 → 0.23.0

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 (45) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +92 -0
  3. package/CLAUDE.md +98 -0
  4. package/README.md +33 -0
  5. package/dist/config/adopt-better-auth-tables.d.ts +107 -0
  6. package/dist/config/adopt-better-auth-tables.d.ts.map +1 -0
  7. package/dist/config/adopt-better-auth-tables.js +70 -0
  8. package/dist/config/adopt-better-auth-tables.js.map +1 -0
  9. package/dist/config/derive-auth-lists.d.ts +50 -0
  10. package/dist/config/derive-auth-lists.d.ts.map +1 -0
  11. package/dist/config/derive-auth-lists.js +274 -0
  12. package/dist/config/derive-auth-lists.js.map +1 -0
  13. package/dist/config/index.d.ts.map +1 -1
  14. package/dist/config/index.js +43 -0
  15. package/dist/config/index.js.map +1 -1
  16. package/dist/config/plugin.d.ts.map +1 -1
  17. package/dist/config/plugin.js +52 -9
  18. package/dist/config/plugin.js.map +1 -1
  19. package/dist/config/types.d.ts +130 -3
  20. package/dist/config/types.d.ts.map +1 -1
  21. package/dist/index.d.ts +4 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +6 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/lists/index.d.ts +17 -11
  26. package/dist/lists/index.d.ts.map +1 -1
  27. package/dist/lists/index.js +34 -208
  28. package/dist/lists/index.js.map +1 -1
  29. package/dist/server/index.d.ts.map +1 -1
  30. package/dist/server/index.js +28 -7
  31. package/dist/server/index.js.map +1 -1
  32. package/package.json +2 -2
  33. package/src/config/adopt-better-auth-tables.ts +146 -0
  34. package/src/config/derive-auth-lists.ts +323 -0
  35. package/src/config/index.ts +58 -0
  36. package/src/config/plugin.ts +66 -9
  37. package/src/config/types.ts +146 -3
  38. package/src/index.ts +13 -0
  39. package/src/lists/index.ts +42 -202
  40. package/src/server/index.ts +31 -9
  41. package/tests/adopt-better-auth-tables.test.ts +183 -0
  42. package/tests/derive-auth-lists.test.ts +232 -0
  43. package/tests/plugin-derived-keys.test.ts +138 -0
  44. package/tests/plugin-schema-placement.test.ts +121 -0
  45. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Pure `better-auth config → Auth lists` derivation.
3
+ *
4
+ * This module is intentionally free of side effects and plugin/runtime
5
+ * concerns: given the resolved better-auth model config (per-model `modelName`
6
+ * and `fields` column maps) plus any custom User fields, it produces the four
7
+ * OpenSaaS Auth lists (user/session/account/verification) with:
8
+ *
9
+ * - list keys taken from each model's `modelName`
10
+ * - a table `@@map` (list-level `db.map`) when the key differs from the
11
+ * default better-auth model name
12
+ * - field-level `@map` (`db.map`) for any better-auth field → column override
13
+ * - relationship refs between the auth lists wired to the *derived* keys
14
+ * (e.g. `Session.user → AuthUser.sessions`)
15
+ *
16
+ * When the developer supplies no `modelName`/`fields` overrides, the output is
17
+ * byte-for-byte the historical default set keyed `User`/`Session`/`Account`/
18
+ * `Verification` with the original field shapes — see the unit tests.
19
+ *
20
+ * `getAuthLists`/`convertBetterAuthSchema` (and the runtime user-key
21
+ * resolution) consume this module so derivation lives in exactly one place.
22
+ */
23
+
24
+ import { list } from '@opensaas/stack-core'
25
+ import { text, timestamp, checkbox, relationship } from '@opensaas/stack-core/fields'
26
+ import type { ListConfig } from '@opensaas/stack-core'
27
+ import type { ExtendUserListConfig } from '../lists/index.js'
28
+ import type { NormalizedAuthModelConfig, NormalizedAuthModels } from './types.js'
29
+
30
+ /**
31
+ * Default better-auth model names — used to decide whether a `@@map` is needed
32
+ * (only when the configured `modelName` differs from the default).
33
+ */
34
+ const DEFAULT_MODEL_NAMES = {
35
+ user: 'User',
36
+ session: 'Session',
37
+ account: 'Account',
38
+ verification: 'Verification',
39
+ } as const
40
+
41
+ /**
42
+ * The derived Auth list set together with the keys each list was placed under.
43
+ * Keys are surfaced separately so callers (plugin add-vs-extend logic, runtime
44
+ * user-key resolution) don't have to re-derive them.
45
+ */
46
+ export type DerivedAuthLists = {
47
+ /** Derived list keys, one per better-auth model. */
48
+ keys: {
49
+ user: string
50
+ session: string
51
+ account: string
52
+ verification: string
53
+ }
54
+ /** The derived list configs, keyed by their derived list keys. */
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ListConfig must accept any TypeInfo
56
+ lists: Record<string, ListConfig<any>>
57
+ }
58
+
59
+ /**
60
+ * Build the list-level `db` config (`timestamps` + `@@map` + `@@schema`) for a
61
+ * derived list.
62
+ *
63
+ * Always opts the list into auto-timestamps (`timestamps: true`). better-auth's
64
+ * adapter writes `createdAt`/`updatedAt` on every auth row and the schema
65
+ * converter returns `null` for those columns (it assumes the generator injects
66
+ * them). Now that auto-timestamps are OFF by default (ADR-0004), each derived
67
+ * Auth list must opt back in so the generated models keep those columns and
68
+ * better-auth keeps working.
69
+ *
70
+ * When the developer renames the model (e.g. `modelName: 'AuthUser'`), we also
71
+ * pin the physical table name to that model name via `@@map("AuthUser")` so the
72
+ * generated list adopts the developer's live table exactly. When a `schema` is
73
+ * configured (plugin-level or per-model), the list is placed in that Postgres
74
+ * schema via `@@schema(...)`.
75
+ *
76
+ * With no `modelName`/`schema` overrides we emit only `timestamps: true`,
77
+ * leaving the default `User`/`Session`/... table/schema output unchanged.
78
+ */
79
+ function listDb(
80
+ model: NormalizedAuthModelConfig,
81
+ defaultModelName: string,
82
+ ): { timestamps: true; map?: string; schema?: string } {
83
+ const map = model.modelName !== defaultModelName ? model.modelName : undefined
84
+ const schema = model.schema
85
+ return {
86
+ timestamps: true,
87
+ ...(map !== undefined ? { map } : {}),
88
+ ...(schema !== undefined ? { schema } : {}),
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Resolve the `db.map` (`@map` column override) for a better-auth field, or
94
+ * `undefined` when there is no override (so default output is unchanged).
95
+ *
96
+ * The field builders capture `options.db` in a closure when generating Prisma
97
+ * types, so the column map MUST be passed through the builder's `db` option
98
+ * rather than patched onto the returned field object.
99
+ */
100
+ function fieldDb(fieldName: string, fields: Record<string, string>): { map: string } | undefined {
101
+ const column = fields[fieldName]
102
+ return column ? { map: column } : undefined
103
+ }
104
+
105
+ /**
106
+ * Build the foreign-key `db` config for a `user` relationship, honouring a
107
+ * `userId` column override from the better-auth `fields` map.
108
+ */
109
+ function userForeignKeyDb(
110
+ fields: Record<string, string>,
111
+ ): { foreignKey: { map: string } } | undefined {
112
+ const column = fields.userId
113
+ return column ? { foreignKey: { map: column } } : undefined
114
+ }
115
+
116
+ /**
117
+ * Create the Auth user list, applying derived field column maps + table map and
118
+ * wiring the session/account relationships to the derived keys.
119
+ */
120
+ function createUserList(
121
+ model: NormalizedAuthModelConfig,
122
+ keys: DerivedAuthLists['keys'],
123
+ userConfig: ExtendUserListConfig,
124
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ListConfig must accept any TypeInfo
125
+ ): ListConfig<any> {
126
+ const f = model.fields
127
+ return list({
128
+ fields: {
129
+ name: text({ validation: { isRequired: true }, db: fieldDb('name', f) }),
130
+ email: text({
131
+ validation: { isRequired: true },
132
+ isIndexed: 'unique',
133
+ db: fieldDb('email', f),
134
+ }),
135
+ emailVerified: checkbox({ defaultValue: false, db: fieldDb('emailVerified', f) }),
136
+ image: text({ db: fieldDb('image', f) }),
137
+
138
+ // Relationships to the other auth lists — refs follow the derived keys.
139
+ sessions: relationship({ ref: `${keys.session}.user`, many: true }),
140
+ accounts: relationship({ ref: `${keys.account}.user`, many: true }),
141
+
142
+ // Custom fields from user config
143
+ ...(userConfig.fields || {}),
144
+ },
145
+ db: listDb(model, DEFAULT_MODEL_NAMES.user),
146
+ access: userConfig.access || {
147
+ operation: {
148
+ query: () => true,
149
+ create: () => true,
150
+ update: ({ session, item }) => {
151
+ if (!session) return false
152
+ const userId = (session as { userId?: string }).userId
153
+ const itemId = (item as { id?: string })?.id
154
+ return userId === itemId
155
+ },
156
+ delete: ({ session, item }) => {
157
+ if (!session) return false
158
+ const userId = (session as { userId?: string }).userId
159
+ const itemId = (item as { id?: string })?.id
160
+ return userId === itemId
161
+ },
162
+ },
163
+ },
164
+ hooks: userConfig.hooks,
165
+ })
166
+ }
167
+
168
+ /**
169
+ * Create the Auth session list.
170
+ */
171
+ function createSessionList(
172
+ model: NormalizedAuthModelConfig,
173
+ keys: DerivedAuthLists['keys'],
174
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ListConfig must accept any TypeInfo
175
+ ): ListConfig<any> {
176
+ const f = model.fields
177
+ return list({
178
+ fields: {
179
+ token: text({
180
+ validation: { isRequired: true },
181
+ isIndexed: 'unique',
182
+ db: fieldDb('token', f),
183
+ }),
184
+ expiresAt: timestamp({ db: fieldDb('expiresAt', f) }),
185
+ ipAddress: text({ db: fieldDb('ipAddress', f) }),
186
+ userAgent: text({ db: fieldDb('userAgent', f) }),
187
+ user: relationship({
188
+ ref: `${keys.user}.sessions`,
189
+ db: userForeignKeyDb(f),
190
+ }),
191
+ },
192
+ db: listDb(model, DEFAULT_MODEL_NAMES.session),
193
+ access: {
194
+ operation: {
195
+ query: ({ session }) => {
196
+ if (!session) return false
197
+ const userId = (session as { userId?: string }).userId
198
+ if (!userId) return false
199
+ return {
200
+ user: { id: { equals: userId } },
201
+ } as Record<string, unknown>
202
+ },
203
+ create: () => true,
204
+ update: () => false,
205
+ delete: ({ session, item }) => {
206
+ if (!session) return false
207
+ const userId = (session as { userId?: string }).userId
208
+ const itemUserId = (item as { user?: { id?: string } })?.user?.id
209
+ return userId === itemUserId
210
+ },
211
+ },
212
+ },
213
+ })
214
+ }
215
+
216
+ /**
217
+ * Create the Auth account list.
218
+ */
219
+ function createAccountList(
220
+ model: NormalizedAuthModelConfig,
221
+ keys: DerivedAuthLists['keys'],
222
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ListConfig must accept any TypeInfo
223
+ ): ListConfig<any> {
224
+ const f = model.fields
225
+ return list({
226
+ fields: {
227
+ accountId: text({ validation: { isRequired: true }, db: fieldDb('accountId', f) }),
228
+ providerId: text({ validation: { isRequired: true }, db: fieldDb('providerId', f) }),
229
+ user: relationship({
230
+ ref: `${keys.user}.accounts`,
231
+ db: userForeignKeyDb(f),
232
+ }),
233
+ accessToken: text({ db: fieldDb('accessToken', f) }),
234
+ refreshToken: text({ db: fieldDb('refreshToken', f) }),
235
+ accessTokenExpiresAt: timestamp({ db: fieldDb('accessTokenExpiresAt', f) }),
236
+ refreshTokenExpiresAt: timestamp({ db: fieldDb('refreshTokenExpiresAt', f) }),
237
+ scope: text({ db: fieldDb('scope', f) }),
238
+ idToken: text({ db: fieldDb('idToken', f) }),
239
+ password: text({ db: fieldDb('password', f) }),
240
+ },
241
+ db: listDb(model, DEFAULT_MODEL_NAMES.account),
242
+ access: {
243
+ operation: {
244
+ query: ({ session }) => {
245
+ if (!session) return false
246
+ const userId = (session as { userId?: string }).userId
247
+ if (!userId) return false
248
+ return {
249
+ user: { id: { equals: userId } },
250
+ } as Record<string, unknown>
251
+ },
252
+ create: () => true,
253
+ update: ({ session, item }) => {
254
+ if (!session) return false
255
+ const userId = (session as { userId?: string }).userId
256
+ const itemUserId = (item as { user?: { id?: string } })?.user?.id
257
+ return userId === itemUserId
258
+ },
259
+ delete: ({ session, item }) => {
260
+ if (!session) return false
261
+ const userId = (session as { userId?: string }).userId
262
+ const itemUserId = (item as { user?: { id?: string } })?.user?.id
263
+ return userId === itemUserId
264
+ },
265
+ },
266
+ },
267
+ })
268
+ }
269
+
270
+ /**
271
+ * Create the Auth verification list.
272
+ */
273
+ function createVerificationList(
274
+ model: NormalizedAuthModelConfig,
275
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ListConfig must accept any TypeInfo
276
+ ): ListConfig<any> {
277
+ const f = model.fields
278
+ return list({
279
+ fields: {
280
+ identifier: text({ validation: { isRequired: true }, db: fieldDb('identifier', f) }),
281
+ value: text({ validation: { isRequired: true }, db: fieldDb('value', f) }),
282
+ expiresAt: timestamp({ db: fieldDb('expiresAt', f) }),
283
+ },
284
+ db: listDb(model, DEFAULT_MODEL_NAMES.verification),
285
+ access: {
286
+ operation: {
287
+ query: () => false,
288
+ create: () => true,
289
+ update: () => false,
290
+ delete: () => true,
291
+ },
292
+ },
293
+ })
294
+ }
295
+
296
+ /**
297
+ * Derive the OpenSaaS Auth lists from the resolved better-auth model config.
298
+ *
299
+ * @param models - Resolved better-auth per-model config (modelName + field column maps)
300
+ * @param userConfig - Extra User-list fields/access/hooks supplied via `extendUserList`
301
+ * @returns The derived list keys and the four Auth list configs keyed by those keys
302
+ */
303
+ export function deriveAuthLists(
304
+ models: NormalizedAuthModels,
305
+ userConfig: ExtendUserListConfig = {},
306
+ ): DerivedAuthLists {
307
+ const keys = {
308
+ user: models.user.modelName,
309
+ session: models.session.modelName,
310
+ account: models.account.modelName,
311
+ verification: models.verification.modelName,
312
+ }
313
+
314
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ListConfig must accept any TypeInfo
315
+ const lists: Record<string, ListConfig<any>> = {
316
+ [keys.user]: createUserList(models.user, keys, userConfig),
317
+ [keys.session]: createSessionList(models.session, keys),
318
+ [keys.account]: createAccountList(models.account, keys),
319
+ [keys.verification]: createVerificationList(models.verification),
320
+ }
321
+
322
+ return { keys, lists }
323
+ }
@@ -1,11 +1,63 @@
1
1
  import type {
2
2
  AuthConfig,
3
+ AuthModelConfig,
3
4
  NormalizedAuthConfig,
5
+ NormalizedAuthModelConfig,
6
+ NormalizedAuthModels,
4
7
  EmailPasswordConfig,
5
8
  EmailVerificationConfig,
6
9
  PasswordResetConfig,
7
10
  } from './types.js'
8
11
 
12
+ /**
13
+ * Default better-auth model names. Used when the developer does not override
14
+ * `modelName`, preserving the historical `User`/`Session`/`Account`/`Verification`
15
+ * keys exactly.
16
+ */
17
+ const DEFAULT_MODEL_NAMES = {
18
+ user: 'User',
19
+ session: 'Session',
20
+ account: 'Account',
21
+ verification: 'Verification',
22
+ } as const
23
+
24
+ /**
25
+ * Resolve a single better-auth model config block into its normalized form,
26
+ * falling back to the better-auth default model name and an empty column map.
27
+ * The model's Postgres schema is the per-model `schema` override when present,
28
+ * otherwise the plugin-level `schema` default (or `undefined` for `public`).
29
+ */
30
+ function normalizeModelConfig(
31
+ config: AuthModelConfig | undefined,
32
+ defaultModelName: string,
33
+ defaultSchema: string | undefined,
34
+ ): NormalizedAuthModelConfig {
35
+ return {
36
+ modelName: config?.modelName || defaultModelName,
37
+ fields: config?.fields || {},
38
+ schema: config?.schema ?? defaultSchema,
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Resolve the better-auth model config for all four auth models.
44
+ * `defaultSchema` is the plugin-level `schema` applied to every model unless a
45
+ * per-model `schema` override is given.
46
+ */
47
+ function normalizeAuthModels(config: AuthConfig): NormalizedAuthModels {
48
+ const defaultSchema = config.schema
49
+ return {
50
+ user: normalizeModelConfig(config.user, DEFAULT_MODEL_NAMES.user, defaultSchema),
51
+ session: normalizeModelConfig(config.session, DEFAULT_MODEL_NAMES.session, defaultSchema),
52
+ account: normalizeModelConfig(config.account, DEFAULT_MODEL_NAMES.account, defaultSchema),
53
+ verification: normalizeModelConfig(
54
+ config.verification,
55
+ DEFAULT_MODEL_NAMES.verification,
56
+ defaultSchema,
57
+ ),
58
+ }
59
+ }
60
+
9
61
  /**
10
62
  * Normalize auth configuration with defaults
11
63
  */
@@ -47,12 +99,18 @@ export function normalizeAuthConfig(config: AuthConfig): NormalizedAuthConfig {
47
99
  // Session fields defaults
48
100
  const sessionFields = config.sessionFields || ['userId', 'email', 'name']
49
101
 
102
+ // Resolve better-auth per-model config (modelName + field column maps).
103
+ // Defaults preserve the historical User/Session/Account/Verification keys.
104
+ const models = normalizeAuthModels(config)
105
+
50
106
  return {
51
107
  emailAndPassword,
52
108
  emailVerification,
53
109
  passwordReset,
54
110
  socialProviders: config.socialProviders || {},
55
111
  session,
112
+ models,
113
+ schema: config.schema,
56
114
  sessionFields,
57
115
  extendUserList: config.extendUserList || {},
58
116
  sendEmail:
@@ -1,4 +1,5 @@
1
1
  import type { Plugin } from '@opensaas/stack-core/extend'
2
+ import { getDbKey } from '@opensaas/stack-core'
2
3
  import type { AuthConfig, NormalizedAuthConfig } from './types.js'
3
4
  import { normalizeAuthConfig } from './index.js'
4
5
  import { getAuthLists } from '../lists/index.js'
@@ -38,8 +39,12 @@ export function authPlugin(config: AuthConfig): Plugin {
38
39
  },
39
40
 
40
41
  init: async (context) => {
41
- // Get auth lists from base Better Auth schema
42
- const authLists = getAuthLists(normalized.extendUserList)
42
+ // Derive the auth lists from the better-auth model config (modelName +
43
+ // field column maps). With no overrides this yields the historical
44
+ // User/Session/Account/Verification keys; with overrides (e.g.
45
+ // user.modelName: 'AuthUser') the lists are keyed and column-mapped to
46
+ // match the developer's live better-auth tables.
47
+ const authLists = getAuthLists(normalized.extendUserList, normalized.models)
43
48
 
44
49
  // Extract additional lists from Better Auth plugins
45
50
  for (const plugin of normalized.betterAuthPlugins) {
@@ -66,10 +71,18 @@ export function authPlugin(config: AuthConfig): Plugin {
66
71
  }
67
72
  }
68
73
 
69
- // Add all auth lists
74
+ // Add all auth lists.
75
+ //
76
+ // The plugin only ever touches its OWN derived keys. When a developer
77
+ // renames the auth user model (e.g. user.modelName: 'AuthUser'), the
78
+ // derived key is 'AuthUser' and an app's separate 'User' list is left
79
+ // untouched — the plugin never extends/overwrites a list it didn't
80
+ // derive. Extending only kicks in when an existing list shares the
81
+ // derived key (e.g. the default 'User'), which is the intended
82
+ // "merge auth fields into my User" behaviour.
70
83
  for (const [listName, listConfig] of Object.entries(authLists)) {
71
84
  if (context.config.lists[listName]) {
72
- // If user defined a User list, extend it with auth fields
85
+ // A list already exists under this derived key merge auth fields in.
73
86
  context.extendList(listName, {
74
87
  fields: listConfig.fields,
75
88
  hooks: listConfig.hooks,
@@ -87,7 +100,54 @@ export function authPlugin(config: AuthConfig): Plugin {
87
100
  context.setPluginData<NormalizedAuthConfig>('auth', normalized)
88
101
  },
89
102
 
103
+ beforeGenerate: (generationConfig) => {
104
+ // Collect every schema the Auth lists are placed in (per-model schema,
105
+ // else the plugin-level schema). When none is configured the Auth lists
106
+ // stay in the default `public` schema and we leave the config untouched —
107
+ // the greenfield default Prisma schema is unchanged (no `schemas`, no
108
+ // `previewFeatures`, no `@@schema`).
109
+ const authSchemas = Array.from(
110
+ new Set(
111
+ Object.values(normalized.models)
112
+ .map((model) => model.schema)
113
+ .filter((schema): schema is string => Boolean(schema)),
114
+ ),
115
+ )
116
+
117
+ if (authSchemas.length === 0) {
118
+ return generationConfig
119
+ }
120
+
121
+ // Multi-schema Prisma requires the datasource to list every schema in use
122
+ // AND every model to carry an `@@schema`. Merge the auth schema(s) into the
123
+ // datasource `schemas` array (always including `public` for the app's own
124
+ // lists), and default any list without an explicit `db.schema` to `public`
125
+ // so the generated multi-schema schema is coherent and valid.
126
+ const schemas = Array.from(
127
+ new Set(['public', ...(generationConfig.db.schemas ?? []), ...authSchemas]),
128
+ )
129
+
130
+ const lists = Object.fromEntries(
131
+ Object.entries(generationConfig.lists).map(([listKey, listConfig]) => {
132
+ if (listConfig.db?.schema) {
133
+ return [listKey, listConfig]
134
+ }
135
+ return [listKey, { ...listConfig, db: { ...listConfig.db, schema: 'public' } }]
136
+ }),
137
+ )
138
+
139
+ return {
140
+ ...generationConfig,
141
+ db: { ...generationConfig.db, schemas },
142
+ lists,
143
+ }
144
+ },
145
+
90
146
  runtime: (context) => {
147
+ // Resolve the user list's context.db key from the configured user model.
148
+ // context.db is keyed camelCase, so 'User' -> 'user', 'AuthUser' -> 'authUser'.
149
+ const userDbKey = getDbKey(normalized.models.user.modelName)
150
+
91
151
  // Provide auth-related utilities at runtime
92
152
  return {
93
153
  /**
@@ -95,9 +155,7 @@ export function authPlugin(config: AuthConfig): Plugin {
95
155
  * Uses the access-controlled context to fetch user data
96
156
  */
97
157
  getUser: async (userId: string) => {
98
- // Use 'authUser' if custom User list name was provided, otherwise 'user'
99
- const userListKey = 'user' // TODO: Make this configurable based on list name
100
- return await context.db[userListKey].findUnique({
158
+ return await context.db[userDbKey].findUnique({
101
159
  where: { id: userId },
102
160
  })
103
161
  },
@@ -110,8 +168,7 @@ export function authPlugin(config: AuthConfig): Plugin {
110
168
  if (!context.session?.userId) {
111
169
  return null
112
170
  }
113
- const userListKey = 'user'
114
- return await context.db[userListKey].findUnique({
171
+ return await context.db[userDbKey].findUnique({
115
172
  where: { id: context.session.userId },
116
173
  })
117
174
  },