@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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +92 -0
- package/CLAUDE.md +98 -0
- package/README.md +33 -0
- package/dist/config/adopt-better-auth-tables.d.ts +107 -0
- package/dist/config/adopt-better-auth-tables.d.ts.map +1 -0
- package/dist/config/adopt-better-auth-tables.js +70 -0
- package/dist/config/adopt-better-auth-tables.js.map +1 -0
- package/dist/config/derive-auth-lists.d.ts +50 -0
- package/dist/config/derive-auth-lists.d.ts.map +1 -0
- package/dist/config/derive-auth-lists.js +274 -0
- package/dist/config/derive-auth-lists.js.map +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +43 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/plugin.d.ts.map +1 -1
- package/dist/config/plugin.js +52 -9
- package/dist/config/plugin.js.map +1 -1
- package/dist/config/types.d.ts +130 -3
- package/dist/config/types.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/lists/index.d.ts +17 -11
- package/dist/lists/index.d.ts.map +1 -1
- package/dist/lists/index.js +34 -208
- package/dist/lists/index.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +28 -7
- package/dist/server/index.js.map +1 -1
- package/package.json +2 -2
- package/src/config/adopt-better-auth-tables.ts +146 -0
- package/src/config/derive-auth-lists.ts +323 -0
- package/src/config/index.ts +58 -0
- package/src/config/plugin.ts +66 -9
- package/src/config/types.ts +146 -3
- package/src/index.ts +13 -0
- package/src/lists/index.ts +42 -202
- package/src/server/index.ts +31 -9
- package/tests/adopt-better-auth-tables.test.ts +183 -0
- package/tests/derive-auth-lists.test.ts +232 -0
- package/tests/plugin-derived-keys.test.ts +138 -0
- package/tests/plugin-schema-placement.test.ts +121 -0
- package/tsconfig.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,97 @@
|
|
|
1
1
|
# @opensaas/stack-auth
|
|
2
2
|
|
|
3
|
+
## 0.23.0
|
|
4
|
+
|
|
5
|
+
## 0.22.0
|
|
6
|
+
|
|
7
|
+
### Minor Changes
|
|
8
|
+
|
|
9
|
+
- [#509](https://github.com/OpenSaasAU/stack/pull/509) [`fdc48f8`](https://github.com/OpenSaasAU/stack/commit/fdc48f86a5a7f161bef0b512963e1511a8c8e00e) Thanks [@list({](https://github.com/list({)! - Add `adoptBetterAuthTables()` recipe for adopting an existing better-auth installation
|
|
10
|
+
|
|
11
|
+
A migrating project that already runs better-auth (its `AuthUser`/`AuthSession`/`AuthAccount`/`AuthVerification` tables live in a separate `auth` Postgres schema, and its app `User` is a different model) can now adopt those live tables without rebuilding the auth config by hand. The recipe presets the plugin-level `schema` plus each model's `modelName` (and optional column `fields` maps) to the conventions of a standard separate-schema better-auth install, so the derived Auth lists diff clean (Schema parity) against the live database — no destructive auth migration. The app's own domain `User` is left untouched; linking it to the Auth identity is the application's concern.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { config } from '@opensaas/stack-core'
|
|
15
|
+
import { authPlugin, adoptBetterAuthTables } from '@opensaas/stack-auth'
|
|
16
|
+
|
|
17
|
+
export default config({
|
|
18
|
+
db: { provider: 'postgresql', url: process.env.DATABASE_URL },
|
|
19
|
+
plugins: [
|
|
20
|
+
authPlugin({
|
|
21
|
+
// Defaults: AuthUser/AuthSession/AuthAccount/AuthVerification in the
|
|
22
|
+
// `auth` schema, pinned to your live table names (@@map) + schema (@@schema).
|
|
23
|
+
...adoptBetterAuthTables(),
|
|
24
|
+
emailAndPassword: { enabled: true },
|
|
25
|
+
}),
|
|
26
|
+
],
|
|
27
|
+
lists: {
|
|
28
|
+
// Your own domain User stays in `public` and is NOT touched by the plugin.
|
|
29
|
+
fields: { subjectId: text({ validation: { isRequired: true } }) } }),
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// Customise when your live tables diverge from the defaults:
|
|
34
|
+
adoptBetterAuthTables({
|
|
35
|
+
schema: 'identity', // default: 'auth'
|
|
36
|
+
modelNamePrefix: 'BA', // default: 'Auth'
|
|
37
|
+
fields: { user: { name: 'full_name' }, session: { userId: 'user_id' } },
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- [#497](https://github.com/OpenSaasAU/stack/pull/497) [`be4181a`](https://github.com/OpenSaasAU/stack/commit/be4181ada3f2d6386052df4d4869ad150d360f89) Thanks [@{](https://github.com/{)! - Derive the auth plugin's Auth lists from the better-auth config
|
|
42
|
+
|
|
43
|
+
`authPlugin` now mirrors the better-auth config a developer writes instead of hardcoding the keys `User`/`Session`/`Account`/`Verification`. Per-model `modelName` becomes the OpenSaaS list key (and a table `@@map`), and the `fields` column map becomes per-field `@map`s. The plugin only ever adds/extends its own derived keys, so an app's separate domain `User` is never overwritten. The runtime `getUser`/`getCurrentUser` helpers now resolve the user list key from the configured user model instead of a hardcoded `'user'`.
|
|
44
|
+
|
|
45
|
+
Default behaviour (no overrides) is unchanged: the lists are still keyed `User`/`Session`/`Account`/`Verification` with the original field shapes and no `@@map`.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// Adopt existing better-auth tables without a destructive migration
|
|
49
|
+
authPlugin({
|
|
50
|
+
modelName: 'AuthUser', fields: { name: 'full_name' } },
|
|
51
|
+
session: { modelName: 'AuthSession', fields: { userId: 'user_id' } },
|
|
52
|
+
account: { modelName: 'AuthAccount' },
|
|
53
|
+
verification: { modelName: 'AuthVerification' },
|
|
54
|
+
})
|
|
55
|
+
// -> lists keyed AuthUser/AuthSession/AuthAccount/AuthVerification
|
|
56
|
+
// with @@map + column @map matching the live tables
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Lists also gain a model-level `db.map` option, which emits a `@@map("...")` on the generated Prisma model so a list key can differ from its physical table name.
|
|
60
|
+
|
|
61
|
+
- [#502](https://github.com/OpenSaasAU/stack/pull/502) [`593390c`](https://github.com/OpenSaasAU/stack/commit/593390c57d9844ca7ada8f45b340c849f1d8d647) Thanks [@{](https://github.com/{)! - Add `authPlugin` schema placement so Auth lists can adopt an existing non-`public` better-auth layout (clean-diff adoption)
|
|
62
|
+
|
|
63
|
+
The auth lists can now be placed in a non-`public` Postgres schema (e.g. `auth`) so they diff CLEAN against a separate-schema better-auth installation. A plugin-level `schema` option applies `@@schema(...)` to all generated Auth lists, with a per-list override.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
authPlugin({
|
|
67
|
+
schema: 'auth', // all Auth lists get @@schema("auth")
|
|
68
|
+
modelName: 'AuthUser' },
|
|
69
|
+
session: { modelName: 'AuthSession' },
|
|
70
|
+
account: { modelName: 'AuthAccount' },
|
|
71
|
+
// per-model override: relocate one list to a different schema
|
|
72
|
+
verification: { modelName: 'AuthVerification', schema: 'auth_internal' },
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The plugin's `beforeGenerate` hook wires the datasource `schemas` array (always including `public`) and defaults any list without an explicit `db.schema` to `public`, producing a valid multi-schema Prisma schema. With no `schema` option the output is unchanged (greenfield default stays in `public`, no `@@schema`).
|
|
77
|
+
|
|
78
|
+
Core support added for this (mirroring the `db.map` → `@@map` work):
|
|
79
|
+
- List-level `db.schema` → the Prisma generator emits `@@schema("...")` on the model.
|
|
80
|
+
- Database-level `db.schemas` → the generator emits the datasource `schemas = [...]` array and enables the `multiSchema` preview feature.
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Core/generator building blocks
|
|
84
|
+
db: { provider: 'postgresql', schemas: ['public', 'auth'] }
|
|
85
|
+
AuthUser: list({ fields: { ... }, db: { map: 'AuthUser', schema: 'auth' } })
|
|
86
|
+
// Generates: model AuthUser { ... @@map("AuthUser") @@schema("auth") }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Patch Changes
|
|
90
|
+
|
|
91
|
+
- [#501](https://github.com/OpenSaasAU/stack/pull/501) [`e30f6a1`](https://github.com/OpenSaasAU/stack/commit/e30f6a1ef69dc65ae68b37539fa74c3f97823cfd) Thanks [@borisno2](https://github.com/borisno2)! - Keep `createdAt`/`updatedAt` on the auth lists now that auto-timestamps are off by default
|
|
92
|
+
|
|
93
|
+
The derived auth lists (User/Session/Account/Verification) now opt into `db: { timestamps: true }`. better-auth's adapter writes those columns and the schema converter returns `null` for them assuming the generator injects them, so the opt-in keeps the generated auth models intact.
|
|
94
|
+
|
|
3
95
|
## 0.21.0
|
|
4
96
|
|
|
5
97
|
### Minor Changes
|
package/CLAUDE.md
CHANGED
|
@@ -62,6 +62,104 @@ config({
|
|
|
62
62
|
// Result: { lists: { User, Session, Account, Verification, Post } }
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
### Deriving Auth lists from better-auth config
|
|
66
|
+
|
|
67
|
+
The four Auth lists are **derived** from the better-auth model config the
|
|
68
|
+
developer writes — not hardcoded. The pure derivation lives in
|
|
69
|
+
`src/config/derive-auth-lists.ts` (`deriveAuthLists`), which `getAuthLists`
|
|
70
|
+
and the plugin's add-vs-extend logic consume:
|
|
71
|
+
|
|
72
|
+
- per-model `modelName` → list key + table `@@map`
|
|
73
|
+
- per-model `fields` (better-auth field → column) → field-level `@map`
|
|
74
|
+
- the `userId` column override → the `user` relationship foreign-key `@map`
|
|
75
|
+
- relationship refs between the Auth lists follow the derived keys
|
|
76
|
+
(e.g. `Session.user → AuthUser.sessions`)
|
|
77
|
+
|
|
78
|
+
With no `modelName`/`fields` overrides the output is unchanged
|
|
79
|
+
(`User`/`Session`/`Account`/`Verification`, original field shapes, no `@@map`).
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// Adopt an existing better-auth installation (Auth lists ≠ app User)
|
|
83
|
+
authPlugin({
|
|
84
|
+
user: { modelName: 'AuthUser', fields: { name: 'full_name' } },
|
|
85
|
+
session: { modelName: 'AuthSession', fields: { userId: 'user_id' } },
|
|
86
|
+
})
|
|
87
|
+
// Adds AuthUser/AuthSession/... and leaves an app's own `User` untouched.
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Because the plugin only ever adds/extends its **derived** keys, an app's own
|
|
91
|
+
domain `User` (a different model from the better-auth user) is never extended
|
|
92
|
+
or overwritten when the user model is renamed. The runtime `getUser`/
|
|
93
|
+
`getCurrentUser` helpers resolve the user list's `context.db` key from the
|
|
94
|
+
configured user `modelName`.
|
|
95
|
+
|
|
96
|
+
### Schema placement (relocatable Auth lists)
|
|
97
|
+
|
|
98
|
+
A plugin-level `schema` option places all generated Auth lists in a non-`public`
|
|
99
|
+
Postgres schema via `@@schema(...)`, so they can adopt a separate-schema
|
|
100
|
+
better-auth layout (e.g. an `auth` schema) and reach **Schema parity** with the
|
|
101
|
+
live tables. Combined with the derived keys/`@@map`/field `@map`s above, the
|
|
102
|
+
generated lists diff CLEAN against an existing `auth`-schema install — they are
|
|
103
|
+
modelled for runtime/types without producing a migration.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
authPlugin({
|
|
107
|
+
schema: 'auth', // all Auth lists get @@schema("auth")
|
|
108
|
+
user: { modelName: 'AuthUser' },
|
|
109
|
+
session: { modelName: 'AuthSession' },
|
|
110
|
+
account: { modelName: 'AuthAccount' },
|
|
111
|
+
verification: { modelName: 'AuthVerification' },
|
|
112
|
+
// per-model override: relocate one list to a different schema
|
|
113
|
+
// verification: { modelName: 'AuthVerification', schema: 'auth_internal' },
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
How it wires up (Postgres multi-schema):
|
|
118
|
+
|
|
119
|
+
- Each Auth list gets a list-level `db.schema` → `@@schema(...)` (per-model
|
|
120
|
+
`schema` override, else the plugin-level `schema`).
|
|
121
|
+
- The plugin's `beforeGenerate` hook adds the auth schema(s) (always plus
|
|
122
|
+
`public`) to the datasource `db.schemas` array and defaults any list without
|
|
123
|
+
an explicit `db.schema` to `public`, so the generated multi-schema Prisma
|
|
124
|
+
schema is valid (the generator emits `previewFeatures = ["multiSchema"]` and
|
|
125
|
+
`schemas = [...]`).
|
|
126
|
+
- With no `schema` option the Auth lists stay in `public` and no `@@schema` /
|
|
127
|
+
`schemas` / preview feature is emitted (greenfield default unchanged).
|
|
128
|
+
|
|
129
|
+
### Adopting an existing better-auth install (`adoptBetterAuthTables`)
|
|
130
|
+
|
|
131
|
+
`adoptBetterAuthTables()` (`src/config/adopt-better-auth-tables.ts`) is a thin
|
|
132
|
+
recipe that returns the `AuthConfig` adoption knobs — the plugin-level `schema`
|
|
133
|
+
plus a per-model `modelName` (and optional column `fields` maps) — preset to the
|
|
134
|
+
conventions of a standard separate-schema better-auth install. It ties together
|
|
135
|
+
the keys/field derivation and schema placement so a migrator doesn't rebuild the
|
|
136
|
+
config by hand. Spread it into `authPlugin`:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { authPlugin, adoptBetterAuthTables } from '@opensaas/stack-auth'
|
|
140
|
+
|
|
141
|
+
authPlugin({
|
|
142
|
+
...adoptBetterAuthTables(), // schema: 'auth', AuthUser/AuthSession/AuthAccount/AuthVerification
|
|
143
|
+
emailAndPassword: { enabled: true },
|
|
144
|
+
})
|
|
145
|
+
// Options: adoptBetterAuthTables({ schema, modelNamePrefix, fields })
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
It is pure config (no side effects): everything it sets can also be written
|
|
149
|
+
directly on `authPlugin`, and spreading it before your own keys lets you
|
|
150
|
+
override per model. Because the derived user key is `AuthUser` (not `User`), an
|
|
151
|
+
app's own domain `User` is left untouched — the plugin only ever adds/extends
|
|
152
|
+
its derived keys. Combined with the derivation + schema placement above, the
|
|
153
|
+
generated Auth lists reach **Schema parity** (clean `schema:diff`) against a live
|
|
154
|
+
`auth`-schema install — they are modelled for runtime/types, not migrated.
|
|
155
|
+
|
|
156
|
+
**App User ≠ Auth identity.** The plugin models the **Auth identity** (the
|
|
157
|
+
better-auth user); it does not assume that list is the app's domain `User`.
|
|
158
|
+
Linking an app's `User` to the Auth identity (e.g. a `relationship({ ref:
|
|
159
|
+
'AuthUser' })` the app declares) is the application's concern. See the
|
|
160
|
+
[Authentication guide](../../docs/content/guides/authentication.md) (“Adopting an
|
|
161
|
+
existing better-auth installation”) for the end-to-end migrator walkthrough.
|
|
162
|
+
|
|
65
163
|
### Session Provider
|
|
66
164
|
|
|
67
165
|
Better-auth provides session to context via custom `prismaClientConstructor`:
|
package/README.md
CHANGED
|
@@ -203,6 +203,39 @@ authPlugin({
|
|
|
203
203
|
})
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
+
## Adopting an Existing better-auth Installation
|
|
207
|
+
|
|
208
|
+
Migrating a project that **already runs better-auth**? The plugin can adopt your
|
|
209
|
+
live tables rather than recreating them, so there's no destructive auth
|
|
210
|
+
migration. Use the `adoptBetterAuthTables()` recipe to preset the model/schema
|
|
211
|
+
knobs that match a standard separate-schema better-auth install:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { authPlugin, adoptBetterAuthTables } from '@opensaas/stack-auth'
|
|
215
|
+
|
|
216
|
+
authPlugin({
|
|
217
|
+
// Defaults: AuthUser/AuthSession/AuthAccount/AuthVerification in the `auth`
|
|
218
|
+
// Postgres schema — pinned to your live table names + schema (@@map/@@schema).
|
|
219
|
+
...adoptBetterAuthTables(),
|
|
220
|
+
emailAndPassword: { enabled: true },
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
// Customise when your live tables diverge from the defaults:
|
|
224
|
+
adoptBetterAuthTables({
|
|
225
|
+
schema: 'identity', // default: 'auth'
|
|
226
|
+
modelNamePrefix: 'BA', // default: 'Auth' (→ AuthUser/AuthSession/…)
|
|
227
|
+
fields: { user: { name: 'full_name' }, session: { userId: 'user_id' } },
|
|
228
|
+
})
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**App `User` vs the Auth identity.** The plugin models the **Auth identity** (the
|
|
232
|
+
better-auth user, e.g. `AuthUser`). It does not assume that list is your app's
|
|
233
|
+
own domain `User` — when the keys differ, your `User` is never extended or
|
|
234
|
+
overwritten. **Linking your domain `User` to the Auth identity is your app's
|
|
235
|
+
concern** (declare a `relationship({ ref: 'AuthUser' })` on your `User`). See the
|
|
236
|
+
[Authentication guide](https://stack.opensaas.au/docs/guides/authentication) for
|
|
237
|
+
the full migrator walkthrough and a Schema-parity (clean-diff) check.
|
|
238
|
+
|
|
206
239
|
## UI Components
|
|
207
240
|
|
|
208
241
|
### SignInForm
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Adopt existing better-auth tables" recipe.
|
|
3
|
+
*
|
|
4
|
+
* A migrating project usually already has a working, hand-wired better-auth
|
|
5
|
+
* installation: its tables are `AuthUser`/`AuthSession`/`AuthAccount`/
|
|
6
|
+
* `AuthVerification`, mapped into a separate `auth` Postgres schema, and its
|
|
7
|
+
* application `User` (`public.User`) is a *different* model. Reconstructing the
|
|
8
|
+
* matching {@link AuthConfig} by hand — four `modelName`s plus a `schema` on each
|
|
9
|
+
* model — is repetitive and easy to get wrong.
|
|
10
|
+
*
|
|
11
|
+
* {@link adoptBetterAuthTables} produces that {@link AuthConfig} fragment from a
|
|
12
|
+
* couple of options so the migrator doesn't rebuild it from scratch. It only
|
|
13
|
+
* sets the *adoption* knobs (per-model `modelName` + the plugin-level `schema`);
|
|
14
|
+
* the developer composes it with the rest of their auth config (providers,
|
|
15
|
+
* session fields, `extendUserList`, etc.):
|
|
16
|
+
*
|
|
17
|
+
* ```typescript
|
|
18
|
+
* authPlugin({
|
|
19
|
+
* ...adoptBetterAuthTables(),
|
|
20
|
+
* emailAndPassword: { enabled: true },
|
|
21
|
+
* sessionFields: ['userId', 'email', 'name'],
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* Combined with the keys/field derivation (`deriveAuthLists`) and schema
|
|
26
|
+
* placement, the generated Auth lists reach **Schema parity** with the live
|
|
27
|
+
* tables — they are modelled for runtime/types without producing a destructive
|
|
28
|
+
* auth migration. The recipe never touches the application's own domain `User`:
|
|
29
|
+
* its model names are `Auth`-prefixed by default and the plugin only ever
|
|
30
|
+
* adds/extends its *derived* keys.
|
|
31
|
+
*/
|
|
32
|
+
import type { AuthConfig } from './types.js';
|
|
33
|
+
/**
|
|
34
|
+
* Options for {@link adoptBetterAuthTables}.
|
|
35
|
+
*
|
|
36
|
+
* All options are optional and default to the conventions of a standard
|
|
37
|
+
* separate-schema better-auth install (an `auth` Postgres schema with
|
|
38
|
+
* `Auth`-prefixed model names).
|
|
39
|
+
*/
|
|
40
|
+
export type AdoptBetterAuthTablesOptions = {
|
|
41
|
+
/**
|
|
42
|
+
* The Postgres schema the live better-auth tables live in.
|
|
43
|
+
*
|
|
44
|
+
* Applied as the plugin-level {@link AuthConfig.schema}, placing every Auth
|
|
45
|
+
* list in this schema via `@@schema(...)`. Pass `'public'` (or any single
|
|
46
|
+
* schema) for an install that is not on a separate schema; pass an explicit
|
|
47
|
+
* value to match your layout.
|
|
48
|
+
*
|
|
49
|
+
* @default 'auth'
|
|
50
|
+
*/
|
|
51
|
+
schema?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Prefix applied to each better-auth model name to derive the list key /
|
|
54
|
+
* table name (e.g. prefix `'Auth'` → `AuthUser`/`AuthSession`/...).
|
|
55
|
+
*
|
|
56
|
+
* A live better-auth install with `modelName: 'AuthUser'` etc. is the common
|
|
57
|
+
* case; override this if your tables use a different prefix. Set to `''` to
|
|
58
|
+
* keep the default better-auth names (`User`/`Session`/...) — but note that an
|
|
59
|
+
* unprefixed `User` will share the app's `User` key, so prefer a prefix when
|
|
60
|
+
* your domain `User` is a separate model (see {@link AuthConfig.user}).
|
|
61
|
+
*
|
|
62
|
+
* @default 'Auth'
|
|
63
|
+
*/
|
|
64
|
+
modelNamePrefix?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Per-model better-auth field → column maps, keyed by model.
|
|
67
|
+
*
|
|
68
|
+
* Only needed when your live tables renamed columns away from the better-auth
|
|
69
|
+
* defaults (e.g. `name → full_name`). Merged into the matching model config so
|
|
70
|
+
* the derived field-level `@map`s match your live columns.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* adoptBetterAuthTables({
|
|
75
|
+
* fields: {
|
|
76
|
+
* user: { name: 'full_name' },
|
|
77
|
+
* session: { userId: 'user_id' },
|
|
78
|
+
* },
|
|
79
|
+
* })
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
fields?: {
|
|
83
|
+
user?: Record<string, string>;
|
|
84
|
+
session?: Record<string, string>;
|
|
85
|
+
account?: Record<string, string>;
|
|
86
|
+
verification?: Record<string, string>;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* The adoption-relevant slice of {@link AuthConfig}: the plugin-level `schema`
|
|
91
|
+
* and the per-model `modelName`/`fields`. Returned (not the full `AuthConfig`)
|
|
92
|
+
* so it spreads cleanly into the developer's own `authPlugin` config.
|
|
93
|
+
*/
|
|
94
|
+
export type AdoptBetterAuthTablesConfig = Pick<AuthConfig, 'schema' | 'user' | 'session' | 'account' | 'verification'>;
|
|
95
|
+
/**
|
|
96
|
+
* Build the adoption {@link AuthConfig} fragment for a pre-existing better-auth
|
|
97
|
+
* installation.
|
|
98
|
+
*
|
|
99
|
+
* Returns only the model/schema knobs needed to adopt the live tables; spread it
|
|
100
|
+
* into {@link authPlugin} alongside your own auth config.
|
|
101
|
+
*
|
|
102
|
+
* @param options - Adoption conventions (schema, model-name prefix, column maps)
|
|
103
|
+
* @returns An {@link AuthConfig} fragment with `schema` + per-model `modelName`
|
|
104
|
+
* (and any field column maps) set to match the live tables
|
|
105
|
+
*/
|
|
106
|
+
export declare function adoptBetterAuthTables(options?: AdoptBetterAuthTablesOptions): AdoptBetterAuthTablesConfig;
|
|
107
|
+
//# sourceMappingURL=adopt-better-auth-tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt-better-auth-tables.d.ts","sourceRoot":"","sources":["../../src/config/adopt-better-auth-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;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;CACF,CAAA;AAUD;;;;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,CAqB7B"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Adopt existing better-auth tables" recipe.
|
|
3
|
+
*
|
|
4
|
+
* A migrating project usually already has a working, hand-wired better-auth
|
|
5
|
+
* installation: its tables are `AuthUser`/`AuthSession`/`AuthAccount`/
|
|
6
|
+
* `AuthVerification`, mapped into a separate `auth` Postgres schema, and its
|
|
7
|
+
* application `User` (`public.User`) is a *different* model. Reconstructing the
|
|
8
|
+
* matching {@link AuthConfig} by hand — four `modelName`s plus a `schema` on each
|
|
9
|
+
* model — is repetitive and easy to get wrong.
|
|
10
|
+
*
|
|
11
|
+
* {@link adoptBetterAuthTables} produces that {@link AuthConfig} fragment from a
|
|
12
|
+
* couple of options so the migrator doesn't rebuild it from scratch. It only
|
|
13
|
+
* sets the *adoption* knobs (per-model `modelName` + the plugin-level `schema`);
|
|
14
|
+
* the developer composes it with the rest of their auth config (providers,
|
|
15
|
+
* session fields, `extendUserList`, etc.):
|
|
16
|
+
*
|
|
17
|
+
* ```typescript
|
|
18
|
+
* authPlugin({
|
|
19
|
+
* ...adoptBetterAuthTables(),
|
|
20
|
+
* emailAndPassword: { enabled: true },
|
|
21
|
+
* sessionFields: ['userId', 'email', 'name'],
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* Combined with the keys/field derivation (`deriveAuthLists`) and schema
|
|
26
|
+
* placement, the generated Auth lists reach **Schema parity** with the live
|
|
27
|
+
* tables — they are modelled for runtime/types without producing a destructive
|
|
28
|
+
* auth migration. The recipe never touches the application's own domain `User`:
|
|
29
|
+
* its model names are `Auth`-prefixed by default and the plugin only ever
|
|
30
|
+
* adds/extends its *derived* keys.
|
|
31
|
+
*/
|
|
32
|
+
/** The four better-auth models and their default (unprefixed) model names. */
|
|
33
|
+
const MODEL_DEFAULT_NAMES = {
|
|
34
|
+
user: 'User',
|
|
35
|
+
session: 'Session',
|
|
36
|
+
account: 'Account',
|
|
37
|
+
verification: 'Verification',
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Build the adoption {@link AuthConfig} fragment for a pre-existing better-auth
|
|
41
|
+
* installation.
|
|
42
|
+
*
|
|
43
|
+
* Returns only the model/schema knobs needed to adopt the live tables; spread it
|
|
44
|
+
* into {@link authPlugin} alongside your own auth config.
|
|
45
|
+
*
|
|
46
|
+
* @param options - Adoption conventions (schema, model-name prefix, column maps)
|
|
47
|
+
* @returns An {@link AuthConfig} fragment with `schema` + per-model `modelName`
|
|
48
|
+
* (and any field column maps) set to match the live tables
|
|
49
|
+
*/
|
|
50
|
+
export function adoptBetterAuthTables(options = {}) {
|
|
51
|
+
const { schema = 'auth', modelNamePrefix = 'Auth', fields = {} } = options;
|
|
52
|
+
const buildModel = (model) => {
|
|
53
|
+
const config = {
|
|
54
|
+
modelName: `${modelNamePrefix}${MODEL_DEFAULT_NAMES[model]}`,
|
|
55
|
+
};
|
|
56
|
+
const fieldMap = fields[model];
|
|
57
|
+
if (fieldMap && Object.keys(fieldMap).length > 0) {
|
|
58
|
+
config.fields = fieldMap;
|
|
59
|
+
}
|
|
60
|
+
return config;
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
schema,
|
|
64
|
+
user: buildModel('user'),
|
|
65
|
+
session: buildModel('session'),
|
|
66
|
+
account: buildModel('account'),
|
|
67
|
+
verification: buildModel('verification'),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=adopt-better-auth-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt-better-auth-tables.js","sourceRoot":"","sources":["../../src/config/adopt-better-auth-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA+DH,8EAA8E;AAC9E,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,cAAc;CACpB,CAAA;AAYV;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAwC,EAAE;IAE1C,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,OAAO,CAAA;IAE1E,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,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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
import type { ListConfig } from '@opensaas/stack-core';
|
|
24
|
+
import type { ExtendUserListConfig } from '../lists/index.js';
|
|
25
|
+
import type { NormalizedAuthModels } from './types.js';
|
|
26
|
+
/**
|
|
27
|
+
* The derived Auth list set together with the keys each list was placed under.
|
|
28
|
+
* Keys are surfaced separately so callers (plugin add-vs-extend logic, runtime
|
|
29
|
+
* user-key resolution) don't have to re-derive them.
|
|
30
|
+
*/
|
|
31
|
+
export type DerivedAuthLists = {
|
|
32
|
+
/** Derived list keys, one per better-auth model. */
|
|
33
|
+
keys: {
|
|
34
|
+
user: string;
|
|
35
|
+
session: string;
|
|
36
|
+
account: string;
|
|
37
|
+
verification: string;
|
|
38
|
+
};
|
|
39
|
+
/** The derived list configs, keyed by their derived list keys. */
|
|
40
|
+
lists: Record<string, ListConfig<any>>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Derive the OpenSaaS Auth lists from the resolved better-auth model config.
|
|
44
|
+
*
|
|
45
|
+
* @param models - Resolved better-auth per-model config (modelName + field column maps)
|
|
46
|
+
* @param userConfig - Extra User-list fields/access/hooks supplied via `extendUserList`
|
|
47
|
+
* @returns The derived list keys and the four Auth list configs keyed by those keys
|
|
48
|
+
*/
|
|
49
|
+
export declare function deriveAuthLists(models: NormalizedAuthModels, userConfig?: ExtendUserListConfig): DerivedAuthLists;
|
|
50
|
+
//# sourceMappingURL=derive-auth-lists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-auth-lists.d.ts","sourceRoot":"","sources":["../../src/config/derive-auth-lists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAA6B,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAajF;;;;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;AA+OD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,oBAAoB,EAC5B,UAAU,GAAE,oBAAyB,GACpC,gBAAgB,CAiBlB"}
|