@opensaas/stack-auth 0.35.0 → 0.37.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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +111 -0
- package/CLAUDE.md +104 -7
- package/README.md +18 -7
- package/dist/config/adopt-better-auth-tables.d.ts +47 -0
- package/dist/config/adopt-better-auth-tables.d.ts.map +1 -1
- package/dist/config/adopt-better-auth-tables.js +29 -1
- package/dist/config/adopt-better-auth-tables.js.map +1 -1
- package/dist/config/derive-auth-lists.d.ts +7 -5
- package/dist/config/derive-auth-lists.d.ts.map +1 -1
- package/dist/config/derive-auth-lists.js +33 -34
- package/dist/config/derive-auth-lists.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +41 -11
- package/dist/config/index.js.map +1 -1
- package/dist/config/plugin.d.ts.map +1 -1
- package/dist/config/plugin.js +39 -27
- package/dist/config/plugin.js.map +1 -1
- package/dist/config/types.d.ts +126 -24
- package/dist/config/types.d.ts.map +1 -1
- package/dist/server/index.d.ts +29 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +193 -66
- package/dist/server/index.js.map +1 -1
- package/package.json +3 -3
- package/src/config/adopt-better-auth-tables.ts +70 -1
- package/src/config/derive-auth-lists.ts +37 -38
- package/src/config/index.ts +47 -12
- package/src/config/plugin.ts +39 -27
- package/src/config/types.ts +127 -21
- package/src/server/index.ts +244 -80
- package/tests/adopt-better-auth-tables.test.ts +99 -0
- package/tests/config.test.ts +66 -8
- package/tests/derive-auth-lists.test.ts +79 -5
- package/tests/generated-fk-shape.test.ts +65 -0
- package/tests/plugin-derived-keys.test.ts +48 -0
- package/tests/server.test.ts +517 -0
- package/tsconfig.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,116 @@
|
|
|
1
1
|
# @opensaas/stack-auth
|
|
2
2
|
|
|
3
|
+
## 0.37.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#872](https://github.com/OpenSaasAU/stack/pull/872) [`17acf04`](https://github.com/OpenSaasAU/stack/commit/17acf046b494da184c2b77434a7b4d3400ca32f2) Thanks [@borisno2](https://github.com/borisno2)! - `createAuth()` now forwards `AuthConfig` options it previously normalized but silently dropped: `emailAndPassword.minPasswordLength`, `passwordReset.enabled`/`tokenExpiration` (wired to better-auth's `sendResetPassword`), and `emailVerification.enabled`/`sendOnSignUp`/`tokenExpiration` (wired to `sendVerificationEmail`).
|
|
8
|
+
|
|
9
|
+
The stack does not wrap these email callbacks in any way — `emailAndPassword.sendResetPassword` and `emailVerification.sendVerificationEmail` are better-auth's own option shape, forwarded straight through, so an app configures them exactly as it would when calling `betterAuth()` directly:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
authPlugin({
|
|
13
|
+
emailAndPassword: {
|
|
14
|
+
enabled: true,
|
|
15
|
+
sendResetPassword: async ({ user, url }) => {
|
|
16
|
+
await resend.emails.send({
|
|
17
|
+
to: user.email,
|
|
18
|
+
subject: 'Reset your password',
|
|
19
|
+
html: `<a href="${url}">Reset your password</a>`,
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
emailVerification: {
|
|
24
|
+
enabled: true,
|
|
25
|
+
sendVerificationEmail: async ({ user, url }) => {
|
|
26
|
+
await resend.emails.send({
|
|
27
|
+
to: user.email,
|
|
28
|
+
subject: 'Verify your email',
|
|
29
|
+
html: `<a href="${url}">Verify your email</a>`,
|
|
30
|
+
})
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If not provided, reset/verification emails are logged to console instead of sent — apps relying on the previous no-op behavior (verification/reset emails silently not sending) will start sending real emails once `emailVerification`/`passwordReset` are enabled and these callbacks are configured.
|
|
37
|
+
|
|
38
|
+
Two related fixes, both changing existing behavior:
|
|
39
|
+
|
|
40
|
+
- `session.updateAge` is retyped from `boolean` to `number | false` — the number of seconds between session refreshes, passed straight through to better-auth's own `session.updateAge` instead of being computed as `expiresIn / 10`. The default changes from `true` to `86400` (1 day), matching better-auth's own default. Update any `updateAge: true` config to a duration in seconds (e.g. `86400`). `updateAge: false` now correctly maps to better-auth's `disableSessionRefresh: true` (previously it mapped to `updateAge: 0`, which better-auth treats as "refresh on every request" — the opposite of disabling refresh).
|
|
41
|
+
- `getSessionFromAuth(auth, sessionFields, headers)` gains a required third `headers: Headers` parameter. Previously it always called `auth.api.getSession({ headers: new Headers() })`, an empty header set that could never resolve a session cookie, so the function always returned `null`. Callers must now pass the request's real headers (e.g. Next.js `await headers()`).
|
|
42
|
+
|
|
43
|
+
Setting `emailAndPassword.requireConfirmation` (while `emailAndPassword.enabled` is true) now logs a `console.warn` — it has no better-auth server-side equivalent (it's a UI-only "confirm password" concern). Pass `requirePasswordConfirmation` directly to `<SignUpForm>`/`<ResetPasswordForm>` instead. Similarly, `passwordReset.enabled` now warns if `emailAndPassword.enabled` is false, since password reset has no effect without a password-based account.
|
|
44
|
+
|
|
45
|
+
- [#871](https://github.com/OpenSaasAU/stack/pull/871) [`06375ca`](https://github.com/OpenSaasAU/stack/commit/06375cad571677e92bfe84c35ff55240f3546a1f) Thanks [@{](https://github.com/{)! - Add a per-model `tableName` option, independent of `modelName`, so a renamed Auth list key can still adopt a differently-named live table — most commonly better-auth's own default lowercase table names (`user`, `session`, `account`, `verification`).
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
authPlugin({
|
|
49
|
+
modelName: 'AuthUser', tableName: 'user' },
|
|
50
|
+
session: { modelName: 'AuthSession', tableName: 'session' },
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`adoptBetterAuthTables()` gains matching `useBetterAuthTableNames` and `tableNames` options:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
adoptBetterAuthTables({ useBetterAuthTableNames: true })
|
|
58
|
+
// or explicitly:
|
|
59
|
+
adoptBetterAuthTables({ tableNames: { user: 'user', session: 'session' } })
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
With no `tableName` set, behaviour is unchanged: the table name still follows `modelName` when it differs from the better-auth default, otherwise no `@@map` is emitted.
|
|
63
|
+
|
|
64
|
+
- [#874](https://github.com/OpenSaasAU/stack/pull/874) [`7ef9dbc`](https://github.com/OpenSaasAU/stack/commit/7ef9dbc2f94cc4e7ab831ecafb3ef65159a3c55e) Thanks [@borisno2](https://github.com/borisno2)! - Add a `betterAuthOptions` escape hatch on `AuthConfig` for better-auth options the stack doesn't model, plus an exported `buildBetterAuthOptions()` builder for apps that still need to hand-wire their own `betterAuth()` instance.
|
|
65
|
+
|
|
66
|
+
`betterAuthOptions` is deep-merged onto the options `createAuth()` builds, applied last — a plain-object value merges recursively alongside sibling keys the stack already set (e.g. `session: { cookieCache }` doesn't clobber `session.expiresIn`), and wins on any genuine key collision:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
authPlugin({
|
|
70
|
+
betterAuthOptions: {
|
|
71
|
+
databaseHooks: { user: { create: { after: syncDomainUser } } },
|
|
72
|
+
session: { cookieCache: { enabled: true, maxAge: 300 } },
|
|
73
|
+
verification: { storeIdentifier: 'hashed' },
|
|
74
|
+
baseURL: process.env.BETTER_AUTH_URL,
|
|
75
|
+
},
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`database`, `plugins`, and `additionalFields` under `user`/`session`/`account`/`verification` are rejected — they already have dedicated seams (`db` config, `betterAuthPlugins`), or have schema consequences a passthrough can't also apply to the generated Prisma schema.
|
|
80
|
+
|
|
81
|
+
`buildBetterAuthOptions(config, context)` returns the exact same options object `createAuth()` uses, for apps that need a resolved `betterAuth()` instance rather than `createAuth()`'s lazy proxy:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { betterAuth } from 'better-auth'
|
|
85
|
+
import { buildBetterAuthOptions } from '@opensaas/stack-auth/server'
|
|
86
|
+
|
|
87
|
+
export const auth = betterAuth({
|
|
88
|
+
...(await buildBetterAuthOptions(config, rawOpensaasContext)),
|
|
89
|
+
databaseHooks: { user: { create: { after: syncDomainUser } } },
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- [#870](https://github.com/OpenSaasAU/stack/pull/870) [`7b6189f`](https://github.com/OpenSaasAU/stack/commit/7b6189fa60119a45082ba62dd71d915d93de529c) Thanks [@relationship({](https://github.com/relationship({)! - A relationship field's foreign key can now be declared non-nullable via `db.isNullable: false` — the generated FK column and its relation field lose their `?` together. Omitting the option leaves every existing relationship unchanged (still nullable by default).
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
|
|
97
|
+
ref: 'User.sessions',
|
|
98
|
+
db: { isNullable: false },
|
|
99
|
+
})
|
|
100
|
+
// Generates: userId String (was String?)
|
|
101
|
+
// user User @relation(...) (was User?)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`@opensaas/stack-auth`'s derived Auth lists now use this to match better-auth's own Prisma schema: `Session.expiresAt`, `Verification.expiresAt`, and the `Session.user`/`Account.user` foreign keys generate as required instead of nullable.
|
|
105
|
+
|
|
106
|
+
**Migration note:** this changes the generated schema for existing greenfield apps. Running `opensaas generate` followed by `prisma db push`/`prisma migrate dev` will produce a migration that adds `NOT NULL` to `Session.expiresAt`, `Verification.expiresAt`, `Session.userId`, and `Account.userId`. Since better-auth's own adapter always writes these columns, no existing row should violate the new constraint — but back up production data before applying, as with any schema migration.
|
|
107
|
+
|
|
108
|
+
### Patch Changes
|
|
109
|
+
|
|
110
|
+
- [#867](https://github.com/OpenSaasAU/stack/pull/867) [`43b4d17`](https://github.com/OpenSaasAU/stack/commit/43b4d1738340f05b1cf8bec3315927b3004816dd) Thanks [@borisno2](https://github.com/borisno2)! - Fix a better-auth plugin's schema extension of a base model (`user`/`session`/`account`/`verification`) silently dropping the derived Auth list's `db` (`map`/`schema`/`timestamps`) and `access` config.
|
|
111
|
+
|
|
112
|
+
## 0.36.0
|
|
113
|
+
|
|
3
114
|
## 0.35.0
|
|
4
115
|
|
|
5
116
|
## 0.34.0
|
package/CLAUDE.md
CHANGED
|
@@ -29,6 +29,7 @@ Auto-generated lists:
|
|
|
29
29
|
### Server (`src/server/index.ts`)
|
|
30
30
|
|
|
31
31
|
- `createAuth(config, rawContext?)` - Creates Better-auth instance with MCP plugin support
|
|
32
|
+
- `buildBetterAuthOptions(config, rawContext?)` - Returns the same `BetterAuthOptions` `createAuth()` builds, without constructing an instance — for apps that need to hand-wire their own `betterAuth()`
|
|
32
33
|
- Returns `{ handler, signIn, signOut, ... }` - Better-auth methods
|
|
33
34
|
|
|
34
35
|
### Client (`src/client/index.ts`)
|
|
@@ -71,13 +72,16 @@ developer writes — not hardcoded. The pure derivation lives in
|
|
|
71
72
|
`src/config/derive-auth-lists.ts` (`deriveAuthLists`), which `getAuthLists`
|
|
72
73
|
and the plugin's add-vs-extend logic consume:
|
|
73
74
|
|
|
74
|
-
- per-model `modelName` → list key
|
|
75
|
+
- per-model `modelName` → list key (and Prisma model name)
|
|
76
|
+
- per-model `tableName` → table `@@map`, **independent of `modelName`**
|
|
77
|
+
(defaults to `modelName` when it differs from the better-auth default,
|
|
78
|
+
otherwise unset — i.e. unchanged output when `tableName` isn't set)
|
|
75
79
|
- per-model `fields` (better-auth field → column) → field-level `@map`
|
|
76
80
|
- the `userId` column override → the `user` relationship foreign-key `@map`
|
|
77
81
|
- relationship refs between the Auth lists follow the derived keys
|
|
78
82
|
(e.g. `Session.user → AuthUser.sessions`)
|
|
79
83
|
|
|
80
|
-
With no `modelName`/`fields` overrides the output is unchanged
|
|
84
|
+
With no `modelName`/`tableName`/`fields` overrides the output is unchanged
|
|
81
85
|
(`User`/`Session`/`Account`/`Verification`, original field shapes, no `@@map`).
|
|
82
86
|
|
|
83
87
|
```typescript
|
|
@@ -89,6 +93,15 @@ authPlugin({
|
|
|
89
93
|
// Adds AuthUser/AuthSession/... and leaves an app's own `User` untouched.
|
|
90
94
|
```
|
|
91
95
|
|
|
96
|
+
```typescript
|
|
97
|
+
// modelName sets the list key; tableName independently pins the live table —
|
|
98
|
+
// e.g. a prefixed list key adopting better-auth's own default lowercase table.
|
|
99
|
+
authPlugin({
|
|
100
|
+
user: { modelName: 'AuthUser', tableName: 'user' },
|
|
101
|
+
session: { modelName: 'AuthSession', tableName: 'session' },
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
92
105
|
Because the plugin only ever adds/extends its **derived** keys, an app's own
|
|
93
106
|
domain `User` (a different model from the better-auth user) is never extended
|
|
94
107
|
or overwritten when the user model is renamed. The runtime `getUser`/
|
|
@@ -164,10 +177,10 @@ How it wires up (Postgres multi-schema):
|
|
|
164
177
|
|
|
165
178
|
`adoptBetterAuthTables()` (`src/config/adopt-better-auth-tables.ts`) is a thin
|
|
166
179
|
recipe that returns the `AuthConfig` adoption knobs — the plugin-level `schema`
|
|
167
|
-
plus a per-model `modelName` (and optional column `fields` maps) —
|
|
168
|
-
conventions of a standard separate-schema better-auth install. It
|
|
169
|
-
the keys/field derivation and schema placement so a migrator
|
|
170
|
-
config by hand. Spread it into `authPlugin`:
|
|
180
|
+
plus a per-model `modelName` (and optional column `fields`/`tableName` maps) —
|
|
181
|
+
preset to the conventions of a standard separate-schema better-auth install. It
|
|
182
|
+
ties together the keys/field derivation and schema placement so a migrator
|
|
183
|
+
doesn't rebuild the config by hand. Spread it into `authPlugin`:
|
|
171
184
|
|
|
172
185
|
```typescript
|
|
173
186
|
import { authPlugin, adoptBetterAuthTables } from '@opensaas/stack-auth'
|
|
@@ -176,7 +189,23 @@ authPlugin({
|
|
|
176
189
|
...adoptBetterAuthTables(), // schema: 'auth', AuthUser/AuthSession/AuthAccount/AuthVerification
|
|
177
190
|
emailAndPassword: { enabled: true },
|
|
178
191
|
})
|
|
179
|
-
// Options: adoptBetterAuthTables({ schema, modelNamePrefix, fields })
|
|
192
|
+
// Options: adoptBetterAuthTables({ schema, modelNamePrefix, fields, useBetterAuthTableNames, tableNames })
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The most common adoption shape is a project that ran better-auth **before**
|
|
196
|
+
Stack, so its live tables are still better-auth's own default lowercase names
|
|
197
|
+
(`user`/`session`/`account`/`verification`) even though the derived list keys
|
|
198
|
+
need an `Auth` prefix to avoid colliding with the app's own domain `User`.
|
|
199
|
+
`useBetterAuthTableNames: true` sets every model's `tableName` to that
|
|
200
|
+
default; the per-model `tableNames` map is the escape hatch for a mix (it
|
|
201
|
+
wins over `useBetterAuthTableNames` for any model it names):
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
authPlugin({
|
|
205
|
+
...adoptBetterAuthTables({ useBetterAuthTableNames: true }),
|
|
206
|
+
// → AuthUser/AuthSession/AuthAccount/AuthVerification list keys,
|
|
207
|
+
// @@map("user")/@@map("session")/@@map("account")/@@map("verification")
|
|
208
|
+
})
|
|
180
209
|
```
|
|
181
210
|
|
|
182
211
|
It is pure config (no side effects): everything it sets can also be written
|
|
@@ -294,6 +323,74 @@ authPlugin({
|
|
|
294
323
|
})
|
|
295
324
|
```
|
|
296
325
|
|
|
326
|
+
### Escape hatch for unmodelled better-auth options (`betterAuthOptions`)
|
|
327
|
+
|
|
328
|
+
`AuthConfig` models a deliberately closed set of better-auth options. For
|
|
329
|
+
anything the stack doesn't model — database hooks, `session.cookieCache`,
|
|
330
|
+
`baseURL`, `verification.storeIdentifier`, and so on — pass it through
|
|
331
|
+
`betterAuthOptions`, typed as better-auth's own `BetterAuthOptions` so it
|
|
332
|
+
tracks better-auth's surface without the stack re-declaring it:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
authPlugin({
|
|
336
|
+
betterAuthOptions: {
|
|
337
|
+
databaseHooks: { user: { create: { after: syncDomainUser } } },
|
|
338
|
+
session: { cookieCache: { enabled: true, maxAge: 300 } },
|
|
339
|
+
verification: { storeIdentifier: 'hashed' },
|
|
340
|
+
baseURL: process.env.BETTER_AUTH_URL,
|
|
341
|
+
},
|
|
342
|
+
})
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
`createAuth()` (`src/server/index.ts`) deep-merges `betterAuthOptions` onto
|
|
346
|
+
the options it builds from the rest of `AuthConfig`, applied **last**:
|
|
347
|
+
plain-object values merge recursively per key (so `session: { cookieCache }`
|
|
348
|
+
lands alongside the stack's own `session.expiresIn`/`updateAge` instead of
|
|
349
|
+
replacing the whole `session` block), arrays and other value types replace
|
|
350
|
+
outright, and `betterAuthOptions` wins on any genuine key collision. The
|
|
351
|
+
merge and the option-building it merges onto both live in
|
|
352
|
+
`buildBetterAuthOptions()`, the single place `createAuth()` and the exported
|
|
353
|
+
builder share — they cannot drift from each other because `createAuth()`
|
|
354
|
+
calls it directly rather than reimplementing it.
|
|
355
|
+
|
|
356
|
+
`database` and `plugins` are rejected outright (`assertNoUnsupportedPassthroughKeys`
|
|
357
|
+
in `src/server/index.ts`): they already have dedicated seams (`db` in the
|
|
358
|
+
stack config, and `betterAuthPlugins` respectively), and accepting them here
|
|
359
|
+
would create two unranked ways to set the same thing — worse for `plugins`,
|
|
360
|
+
since the stack must append `nextCookies()` last (see "Auth forms submit
|
|
361
|
+
through server actions" below). `additionalFields` under `user`/`session`/
|
|
362
|
+
`account`/`verification` is rejected too — it adds columns with no
|
|
363
|
+
corresponding change to the generated Prisma schema, which is exactly the
|
|
364
|
+
silent-divergence failure mode this passthrough exists to avoid elsewhere.
|
|
365
|
+
Add fields to the derived list instead: `extendUserList` for the user model,
|
|
366
|
+
or declare the list yourself in your own `lists` config for the others (the
|
|
367
|
+
auth plugin's `addList`-vs-`extendList` logic — see "Deriving Auth lists from
|
|
368
|
+
better-auth config" above — merges in field additions for any list matching
|
|
369
|
+
one of its derived keys).
|
|
370
|
+
|
|
371
|
+
### Hand-wiring `betterAuth()` from the stack config (`buildBetterAuthOptions`)
|
|
372
|
+
|
|
373
|
+
An app that needs a resolved `betterAuth()` instance at module-init time
|
|
374
|
+
(rather than `createAuth()`'s lazy proxy) can derive its options from the
|
|
375
|
+
stack config instead of duplicating them:
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import { betterAuth } from 'better-auth'
|
|
379
|
+
import { buildBetterAuthOptions } from '@opensaas/stack-auth/server'
|
|
380
|
+
|
|
381
|
+
export const auth = betterAuth({
|
|
382
|
+
...(await buildBetterAuthOptions(config, rawOpensaasContext)),
|
|
383
|
+
databaseHooks: { user: { create: { after: syncDomainUser } } }, // not yet in betterAuthOptions
|
|
384
|
+
})
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
This is the same async-resolve-then-construct step `createAuth()` performs
|
|
388
|
+
internally, exported standalone — see ADR-0014 and root `CLAUDE.md`'s
|
|
389
|
+
"Getting the ORM client outside a request" for why `createAuth()` itself
|
|
390
|
+
can't be synchronous. It gives an incremental path onto `createAuth()`: adopt
|
|
391
|
+
the builder first, then fold options into `betterAuthOptions` above as the
|
|
392
|
+
stack grows first-class config for them.
|
|
393
|
+
|
|
297
394
|
## Integration Points
|
|
298
395
|
|
|
299
396
|
### With @opensaas/stack-core
|
package/README.md
CHANGED
|
@@ -164,7 +164,15 @@ authPlugin({
|
|
|
164
164
|
emailAndPassword: {
|
|
165
165
|
enabled: true,
|
|
166
166
|
minPasswordLength: 8,
|
|
167
|
-
requireConfirmation: true,
|
|
167
|
+
requireConfirmation: true, // UI-only — pass to <SignUpForm>/<ResetPasswordForm> directly
|
|
168
|
+
// Passed straight through to better-auth's own `emailAndPassword.sendResetPassword`
|
|
169
|
+
sendResetPassword: async ({ user, url }) => {
|
|
170
|
+
await yourEmailService.send({
|
|
171
|
+
to: user.email,
|
|
172
|
+
subject: 'Reset your password',
|
|
173
|
+
html: `<a href="${url}">Reset your password</a>`,
|
|
174
|
+
})
|
|
175
|
+
},
|
|
168
176
|
},
|
|
169
177
|
|
|
170
178
|
// Email verification
|
|
@@ -172,6 +180,14 @@ authPlugin({
|
|
|
172
180
|
enabled: true,
|
|
173
181
|
sendOnSignUp: true,
|
|
174
182
|
tokenExpiration: 86400, // 24 hours in seconds
|
|
183
|
+
// Passed straight through to better-auth's own `emailVerification.sendVerificationEmail`
|
|
184
|
+
sendVerificationEmail: async ({ user, url }) => {
|
|
185
|
+
await yourEmailService.send({
|
|
186
|
+
to: user.email,
|
|
187
|
+
subject: 'Verify your email',
|
|
188
|
+
html: `<a href="${url}">Verify your email</a>`,
|
|
189
|
+
})
|
|
190
|
+
},
|
|
175
191
|
},
|
|
176
192
|
|
|
177
193
|
// Password reset
|
|
@@ -195,7 +211,7 @@ authPlugin({
|
|
|
195
211
|
// Session configuration
|
|
196
212
|
session: {
|
|
197
213
|
expiresIn: 604800, // 7 days in seconds
|
|
198
|
-
updateAge:
|
|
214
|
+
updateAge: 86400, // seconds between session refreshes; set `false` to disable
|
|
199
215
|
},
|
|
200
216
|
|
|
201
217
|
// Fields to include in session object
|
|
@@ -208,11 +224,6 @@ authPlugin({
|
|
|
208
224
|
company: text(),
|
|
209
225
|
},
|
|
210
226
|
},
|
|
211
|
-
|
|
212
|
-
// Custom email sending function
|
|
213
|
-
sendEmail: async ({ to, subject, html }) => {
|
|
214
|
-
await yourEmailService.send({ to, subject, html })
|
|
215
|
-
},
|
|
216
227
|
})
|
|
217
228
|
```
|
|
218
229
|
|
|
@@ -28,6 +28,22 @@
|
|
|
28
28
|
* auth migration. The recipe never touches the application's own domain `User`:
|
|
29
29
|
* its model names are `Auth`-prefixed by default and the plugin only ever
|
|
30
30
|
* adds/extends its *derived* keys.
|
|
31
|
+
*
|
|
32
|
+
* The single most common adoption shape is a project that ran better-auth
|
|
33
|
+
* *before* adding Stack: its live tables are still better-auth's own default
|
|
34
|
+
* lowercase names (`user`/`session`/`account`/`verification`), even though the
|
|
35
|
+
* derived list keys need the `Auth` prefix to avoid colliding with the app's
|
|
36
|
+
* own domain `User`. Pass `useBetterAuthTableNames: true` to point every
|
|
37
|
+
* model's physical table at that default while keeping the prefixed list keys
|
|
38
|
+
* (or `tableNames` for an explicit per-model override):
|
|
39
|
+
*
|
|
40
|
+
* ```typescript
|
|
41
|
+
* authPlugin({
|
|
42
|
+
* ...adoptBetterAuthTables({ useBetterAuthTableNames: true }),
|
|
43
|
+
* // AuthUser/AuthSession/AuthAccount/AuthVerification list keys,
|
|
44
|
+
* // @@map("user")/@@map("session")/@@map("account")/@@map("verification")
|
|
45
|
+
* })
|
|
46
|
+
* ```
|
|
31
47
|
*/
|
|
32
48
|
import type { AuthConfig } from './types.js';
|
|
33
49
|
/**
|
|
@@ -85,6 +101,37 @@ export type AdoptBetterAuthTablesOptions = {
|
|
|
85
101
|
account?: Record<string, string>;
|
|
86
102
|
verification?: Record<string, string>;
|
|
87
103
|
};
|
|
104
|
+
/**
|
|
105
|
+
* Set every model's physical table name to better-auth's own default
|
|
106
|
+
* lowercase table name (`user`, `session`, `account`, `verification`) —
|
|
107
|
+
* independent of the prefixed list key/`modelName`.
|
|
108
|
+
*
|
|
109
|
+
* This is the single most common adoption shape: a project that ran
|
|
110
|
+
* better-auth before adding the stack has exactly these tables, and the
|
|
111
|
+
* default `modelNamePrefix: 'Auth'` alone would otherwise pin the table
|
|
112
|
+
* name to the prefixed model name (`AuthUser`, ...), which `prisma migrate
|
|
113
|
+
* diff` reads as a rename against the live `user` table.
|
|
114
|
+
*
|
|
115
|
+
* Ignored for a model with an explicit entry in {@link tableNames}.
|
|
116
|
+
*
|
|
117
|
+
* @default false
|
|
118
|
+
*/
|
|
119
|
+
useBetterAuthTableNames?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Per-model explicit table name overrides, keyed by model. Takes
|
|
122
|
+
* precedence over `useBetterAuthTableNames` for that model.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* adoptBetterAuthTables({ tableNames: { user: 'users' } })
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
tableNames?: {
|
|
130
|
+
user?: string;
|
|
131
|
+
session?: string;
|
|
132
|
+
account?: string;
|
|
133
|
+
verification?: string;
|
|
134
|
+
};
|
|
88
135
|
};
|
|
89
136
|
/**
|
|
90
137
|
* The adoption-relevant slice of {@link AuthConfig}: the plugin-level `schema`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt-better-auth-tables.d.ts","sourceRoot":"","sources":["../../src/config/adopt-better-auth-tables.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"adopt-better-auth-tables.d.ts","sourceRoot":"","sources":["../../src/config/adopt-better-auth-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,YAAY,CAAA;AAE7D;;;;;;GAMG;AACH,MAAM,MAAM,4BAA4B,GAAG;IACzC;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAChC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACtC,CAAA;IAED;;;;;;;;;;;;;;OAcG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;IAEjC;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;CACF,CAAA;AAkBD;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,UAAU,EACV,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,cAAc,CAC3D,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,4BAAiC,GACzC,2BAA2B,CAiC7B"}
|
|
@@ -28,6 +28,22 @@
|
|
|
28
28
|
* auth migration. The recipe never touches the application's own domain `User`:
|
|
29
29
|
* its model names are `Auth`-prefixed by default and the plugin only ever
|
|
30
30
|
* adds/extends its *derived* keys.
|
|
31
|
+
*
|
|
32
|
+
* The single most common adoption shape is a project that ran better-auth
|
|
33
|
+
* *before* adding Stack: its live tables are still better-auth's own default
|
|
34
|
+
* lowercase names (`user`/`session`/`account`/`verification`), even though the
|
|
35
|
+
* derived list keys need the `Auth` prefix to avoid colliding with the app's
|
|
36
|
+
* own domain `User`. Pass `useBetterAuthTableNames: true` to point every
|
|
37
|
+
* model's physical table at that default while keeping the prefixed list keys
|
|
38
|
+
* (or `tableNames` for an explicit per-model override):
|
|
39
|
+
*
|
|
40
|
+
* ```typescript
|
|
41
|
+
* authPlugin({
|
|
42
|
+
* ...adoptBetterAuthTables({ useBetterAuthTableNames: true }),
|
|
43
|
+
* // AuthUser/AuthSession/AuthAccount/AuthVerification list keys,
|
|
44
|
+
* // @@map("user")/@@map("session")/@@map("account")/@@map("verification")
|
|
45
|
+
* })
|
|
46
|
+
* ```
|
|
31
47
|
*/
|
|
32
48
|
/** The four better-auth models and their default (unprefixed) model names. */
|
|
33
49
|
const MODEL_DEFAULT_NAMES = {
|
|
@@ -36,6 +52,13 @@ const MODEL_DEFAULT_NAMES = {
|
|
|
36
52
|
account: 'Account',
|
|
37
53
|
verification: 'Verification',
|
|
38
54
|
};
|
|
55
|
+
/** better-auth's own default lowercase table names, per model. */
|
|
56
|
+
const BETTER_AUTH_DEFAULT_TABLE_NAMES = {
|
|
57
|
+
user: 'user',
|
|
58
|
+
session: 'session',
|
|
59
|
+
account: 'account',
|
|
60
|
+
verification: 'verification',
|
|
61
|
+
};
|
|
39
62
|
/**
|
|
40
63
|
* Build the adoption {@link AuthConfig} fragment for a pre-existing better-auth
|
|
41
64
|
* installation.
|
|
@@ -48,11 +71,16 @@ const MODEL_DEFAULT_NAMES = {
|
|
|
48
71
|
* (and any field column maps) set to match the live tables
|
|
49
72
|
*/
|
|
50
73
|
export function adoptBetterAuthTables(options = {}) {
|
|
51
|
-
const { schema = 'auth', modelNamePrefix = 'Auth', fields = {} } = options;
|
|
74
|
+
const { schema = 'auth', modelNamePrefix = 'Auth', fields = {}, useBetterAuthTableNames = false, tableNames = {}, } = options;
|
|
52
75
|
const buildModel = (model) => {
|
|
53
76
|
const config = {
|
|
54
77
|
modelName: `${modelNamePrefix}${MODEL_DEFAULT_NAMES[model]}`,
|
|
55
78
|
};
|
|
79
|
+
const tableName = tableNames[model] ??
|
|
80
|
+
(useBetterAuthTableNames ? BETTER_AUTH_DEFAULT_TABLE_NAMES[model] : undefined);
|
|
81
|
+
if (tableName !== undefined) {
|
|
82
|
+
config.tableName = tableName;
|
|
83
|
+
}
|
|
56
84
|
const fieldMap = fields[model];
|
|
57
85
|
if (fieldMap && Object.keys(fieldMap).length > 0) {
|
|
58
86
|
config.fields = fieldMap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt-better-auth-tables.js","sourceRoot":"","sources":["../../src/config/adopt-better-auth-tables.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"adopt-better-auth-tables.js","sourceRoot":"","sources":["../../src/config/adopt-better-auth-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAgGH,8EAA8E;AAC9E,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,cAAc;CACpB,CAAA;AAEV,kEAAkE;AAClE,MAAM,+BAA+B,GAAG;IACtC,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,cAAc;CACpB,CAAA;AAYV;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAO,GAAiC,EAAE;IAE1C,MAAM,EACJ,MAAM,GAAG,MAAM,EACf,eAAe,GAAG,MAAM,EACxB,MAAM,GAAG,EAAE,EACX,uBAAuB,GAAG,KAAK,EAC/B,UAAU,GAAG,EAAE,GAChB,GAAG,OAAO,CAAA;IAEX,MAAM,UAAU,GAAG,CAAC,KAAuC,EAAmB,EAAE;QAC9E,MAAM,MAAM,GAAoB;YAC9B,SAAS,EAAE,GAAG,eAAe,GAAG,mBAAmB,CAAC,KAAK,CAAC,EAAE;SAC7D,CAAA;QACD,MAAM,SAAS,GACb,UAAU,CAAC,KAAK,CAAC;YACjB,CAAC,uBAAuB,CAAC,CAAC,CAAC,+BAA+B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QAChF,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,CAAC,SAAS,GAAG,SAAS,CAAA;QAC9B,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAC9B,IAAI,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAA;QAC1B,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IAED,OAAO;QACL,MAAM;QACN,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;QACxB,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC;QAC9B,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC;QAC9B,YAAY,EAAE,UAAU,CAAC,cAAc,CAAC;KACzC,CAAA;AACH,CAAC"}
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* Pure `better-auth config → Auth lists` derivation.
|
|
3
3
|
*
|
|
4
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
|
|
7
|
-
* OpenSaaS Auth lists (user/session/account/verification)
|
|
5
|
+
* concerns: given the resolved better-auth model config (per-model `modelName`,
|
|
6
|
+
* `tableName`, and `fields` column maps) plus any custom User fields, it
|
|
7
|
+
* produces the four OpenSaaS Auth lists (user/session/account/verification)
|
|
8
|
+
* with:
|
|
8
9
|
*
|
|
9
10
|
* - list keys taken from each model's `modelName`
|
|
10
|
-
* - a table `@@map` (list-level `db.map`)
|
|
11
|
-
*
|
|
11
|
+
* - a table `@@map` (list-level `db.map`) taken from each model's resolved
|
|
12
|
+
* `tableName` — independent of `modelName`, so a renamed list key can still
|
|
13
|
+
* adopt a differently-named live table
|
|
12
14
|
* - field-level `@map` (`db.map`) for any better-auth field → column override
|
|
13
15
|
* - relationship refs between the auth lists wired to the *derived* keys
|
|
14
16
|
* (e.g. `Session.user → AuthUser.sessions`)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive-auth-lists.d.ts","sourceRoot":"","sources":["../../src/config/derive-auth-lists.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"derive-auth-lists.d.ts","sourceRoot":"","sources":["../../src/config/derive-auth-lists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAA6B,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEnG;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,oDAAoD;IACpD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,kEAAkE;IAElE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;CACvC,CAAA;AAiND;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,oBAAoB,EAC5B,UAAU,GAAE,oBAAyB,EACrC,YAAY,GAAE,gBAAqB,GAClC,gBAAgB,CAiBlB"}
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* Pure `better-auth config → Auth lists` derivation.
|
|
3
3
|
*
|
|
4
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
|
|
7
|
-
* OpenSaaS Auth lists (user/session/account/verification)
|
|
5
|
+
* concerns: given the resolved better-auth model config (per-model `modelName`,
|
|
6
|
+
* `tableName`, and `fields` column maps) plus any custom User fields, it
|
|
7
|
+
* produces the four OpenSaaS Auth lists (user/session/account/verification)
|
|
8
|
+
* with:
|
|
8
9
|
*
|
|
9
10
|
* - list keys taken from each model's `modelName`
|
|
10
|
-
* - a table `@@map` (list-level `db.map`)
|
|
11
|
-
*
|
|
11
|
+
* - a table `@@map` (list-level `db.map`) taken from each model's resolved
|
|
12
|
+
* `tableName` — independent of `modelName`, so a renamed list key can still
|
|
13
|
+
* adopt a differently-named live table
|
|
12
14
|
* - field-level `@map` (`db.map`) for any better-auth field → column override
|
|
13
15
|
* - relationship refs between the auth lists wired to the *derived* keys
|
|
14
16
|
* (e.g. `Session.user → AuthUser.sessions`)
|
|
@@ -25,16 +27,6 @@
|
|
|
25
27
|
*/
|
|
26
28
|
import { list } from '@opensaas/stack-core';
|
|
27
29
|
import { text, timestamp, checkbox, relationship } from '@opensaas/stack-core/fields';
|
|
28
|
-
/**
|
|
29
|
-
* Default better-auth model names — used to decide whether a `@@map` is needed
|
|
30
|
-
* (only when the configured `modelName` differs from the default).
|
|
31
|
-
*/
|
|
32
|
-
const DEFAULT_MODEL_NAMES = {
|
|
33
|
-
user: 'User',
|
|
34
|
-
session: 'Session',
|
|
35
|
-
account: 'Account',
|
|
36
|
-
verification: 'Verification',
|
|
37
|
-
};
|
|
38
30
|
/**
|
|
39
31
|
* Build the list-level `db` config (`timestamps` + `@@map` + `@@schema`) for a
|
|
40
32
|
* derived list.
|
|
@@ -46,21 +38,20 @@ const DEFAULT_MODEL_NAMES = {
|
|
|
46
38
|
* Auth list must opt back in so the generated models keep those columns and
|
|
47
39
|
* better-auth keeps working.
|
|
48
40
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* schema via `@@schema(...)`.
|
|
41
|
+
* The physical table name (`@@map`) comes from the model's resolved
|
|
42
|
+
* `tableName` — independent of the list key/`modelName` — so a renamed list
|
|
43
|
+
* key can still adopt a differently-named live table (e.g. better-auth's own
|
|
44
|
+
* default lowercase table names). When a `schema` is configured (plugin-level
|
|
45
|
+
* or per-model), the list is placed in that Postgres schema via `@@schema(...)`.
|
|
54
46
|
*
|
|
55
|
-
* With no `
|
|
47
|
+
* With no `tableName`/`schema` overrides we emit only `timestamps: true`,
|
|
56
48
|
* leaving the default `User`/`Session`/... table/schema output unchanged.
|
|
57
49
|
*/
|
|
58
|
-
function listDb(model
|
|
59
|
-
const map = model.modelName !== defaultModelName ? model.modelName : undefined;
|
|
50
|
+
function listDb(model) {
|
|
60
51
|
const schema = model.schema;
|
|
61
52
|
return {
|
|
62
53
|
timestamps: true,
|
|
63
|
-
...(
|
|
54
|
+
...(model.tableName !== undefined ? { map: model.tableName } : {}),
|
|
64
55
|
...(schema !== undefined ? { schema } : {}),
|
|
65
56
|
};
|
|
66
57
|
}
|
|
@@ -80,14 +71,18 @@ function fieldDb(fieldName, fields) {
|
|
|
80
71
|
* Build the `db` config for a `user` relationship (`Session.user` /
|
|
81
72
|
* `Account.user`), honouring a `userId` column override from the better-auth
|
|
82
73
|
* `fields` map and mirroring better-auth's own FK shape: no separate FK index
|
|
83
|
-
* — the index is applied at the field level via `isIndexed: false` —
|
|
84
|
-
* `onDelete: Cascade`,
|
|
85
|
-
* better-auth
|
|
86
|
-
*
|
|
74
|
+
* — the index is applied at the field level via `isIndexed: false` —
|
|
75
|
+
* `onDelete: Cascade`, and a required (non-nullable) foreign key, since
|
|
76
|
+
* better-auth's adapter always writes a `userId` on every session/account row
|
|
77
|
+
* it creates. This means a generated Auth schema diffs clean against a live
|
|
78
|
+
* better-auth database on all three dimensions instead of showing a spurious
|
|
79
|
+
* index drop, a referential-action change, and a `DROP NOT NULL` (issues #679,
|
|
80
|
+
* #863).
|
|
87
81
|
*/
|
|
88
82
|
function userRelationshipDb(fields) {
|
|
89
83
|
const column = fields.userId;
|
|
90
84
|
return {
|
|
85
|
+
isNullable: false,
|
|
91
86
|
...(column ? { foreignKey: { map: column } } : {}),
|
|
92
87
|
extendPrismaSchema: ({ fkLine, relationLine }) => ({
|
|
93
88
|
fkLine,
|
|
@@ -122,7 +117,7 @@ function createUserList(model, keys, userConfig, access) {
|
|
|
122
117
|
// Custom fields from user config
|
|
123
118
|
...(userConfig.fields || {}),
|
|
124
119
|
},
|
|
125
|
-
db: listDb(model
|
|
120
|
+
db: listDb(model),
|
|
126
121
|
access: userConfig.access || access,
|
|
127
122
|
hooks: userConfig.hooks,
|
|
128
123
|
});
|
|
@@ -142,7 +137,9 @@ function createSessionList(model, keys, access) {
|
|
|
142
137
|
isIndexed: 'unique',
|
|
143
138
|
db: fieldDb('token', f),
|
|
144
139
|
}),
|
|
145
|
-
expiresAt: timestamp({
|
|
140
|
+
expiresAt: timestamp({
|
|
141
|
+
db: { isNullable: false, ...fieldDb('expiresAt', f) },
|
|
142
|
+
}),
|
|
146
143
|
ipAddress: text({ db: fieldDb('ipAddress', f) }),
|
|
147
144
|
userAgent: text({ db: fieldDb('userAgent', f) }),
|
|
148
145
|
user: relationship({
|
|
@@ -151,7 +148,7 @@ function createSessionList(model, keys, access) {
|
|
|
151
148
|
db: userRelationshipDb(f),
|
|
152
149
|
}),
|
|
153
150
|
},
|
|
154
|
-
db: listDb(model
|
|
151
|
+
db: listDb(model),
|
|
155
152
|
access,
|
|
156
153
|
});
|
|
157
154
|
}
|
|
@@ -180,7 +177,7 @@ function createAccountList(model, keys, access) {
|
|
|
180
177
|
idToken: text({ db: fieldDb('idToken', f) }),
|
|
181
178
|
password: text({ db: fieldDb('password', f) }),
|
|
182
179
|
},
|
|
183
|
-
db: listDb(model
|
|
180
|
+
db: listDb(model),
|
|
184
181
|
access,
|
|
185
182
|
});
|
|
186
183
|
}
|
|
@@ -196,9 +193,11 @@ function createVerificationList(model, access) {
|
|
|
196
193
|
fields: {
|
|
197
194
|
identifier: text({ validation: { isRequired: true }, db: fieldDb('identifier', f) }),
|
|
198
195
|
value: text({ validation: { isRequired: true }, db: fieldDb('value', f) }),
|
|
199
|
-
expiresAt: timestamp({
|
|
196
|
+
expiresAt: timestamp({
|
|
197
|
+
db: { isNullable: false, ...fieldDb('expiresAt', f) },
|
|
198
|
+
}),
|
|
200
199
|
},
|
|
201
|
-
db: listDb(model
|
|
200
|
+
db: listDb(model),
|
|
202
201
|
access,
|
|
203
202
|
});
|
|
204
203
|
}
|