@opensaas/stack-auth 0.36.0 → 0.38.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 +146 -0
- package/CLAUDE.md +153 -9
- 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 +143 -28
- package/dist/config/types.d.ts.map +1 -1
- package/dist/server/build-better-auth-options.test.d.ts +2 -0
- package/dist/server/build-better-auth-options.test.d.ts.map +1 -0
- package/dist/server/build-better-auth-options.test.js +29 -0
- package/dist/server/build-better-auth-options.test.js.map +1 -0
- package/dist/server/index.d.ts +112 -8
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +284 -96
- package/dist/server/index.js.map +1 -1
- package/dist/server/schema-converter.d.ts +3 -3
- package/dist/server/schema-converter.d.ts.map +1 -1
- package/package.json +5 -5
- 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 +40 -28
- package/src/config/types.ts +144 -27
- package/src/server/build-better-auth-options.test.ts +59 -0
- package/src/server/index.ts +470 -106
- package/src/server/schema-converter.ts +3 -3
- 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 +723 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +7 -1
package/dist/server/index.js
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import { betterAuth } from 'better-auth';
|
|
2
2
|
import { prismaAdapter } from 'better-auth/adapters/prisma';
|
|
3
3
|
import { nextCookies } from 'better-auth/next-js';
|
|
4
|
+
/**
|
|
5
|
+
* Guard against the supplied plugin tuple silently drifting from the plugin
|
|
6
|
+
* array actually resolved from `authPlugin({ betterAuthPlugins })` — the
|
|
7
|
+
* supplied tuple exists for typing only, so if it isn't the exact same
|
|
8
|
+
* instances in the exact same order, the type it produces would be a lie
|
|
9
|
+
* about what `betterAuth()` is actually constructed with.
|
|
10
|
+
*/
|
|
11
|
+
function assertPluginTupleMatchesResolved(supplied, resolved) {
|
|
12
|
+
if (supplied.length !== resolved.length) {
|
|
13
|
+
throw new Error('[@opensaas/stack-auth] The plugin tuple passed to `buildBetterAuthOptions()` / `createAuth()` ' +
|
|
14
|
+
`has ${supplied.length} plugin(s), but the plugin array resolved from \`authPlugin({ ` +
|
|
15
|
+
`betterAuthPlugins })\` has ${resolved.length}. Pass the exact same array (without ` +
|
|
16
|
+
'`nextCookies()` — the stack appends that itself).');
|
|
17
|
+
}
|
|
18
|
+
const mismatchIndex = supplied.findIndex((plugin, index) => plugin !== resolved[index]);
|
|
19
|
+
if (mismatchIndex !== -1) {
|
|
20
|
+
throw new Error('[@opensaas/stack-auth] The plugin tuple passed to `buildBetterAuthOptions()` / `createAuth()` ' +
|
|
21
|
+
`does not match the plugin array resolved from \`authPlugin({ betterAuthPlugins })\` at index ` +
|
|
22
|
+
`${mismatchIndex} (got plugin "${supplied[mismatchIndex]?.id}", expected the same instance as ` +
|
|
23
|
+
`"${resolved[mismatchIndex]?.id}"). Pass the exact same array — same instances, same order.`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
4
26
|
/**
|
|
5
27
|
* Get better-auth database configuration from OpenSaas config
|
|
6
28
|
*/
|
|
@@ -24,25 +46,177 @@ function toBetterAuthModelOptions(model) {
|
|
|
24
46
|
options.fields = model.fields;
|
|
25
47
|
return Object.keys(options).length > 0 ? options : undefined;
|
|
26
48
|
}
|
|
49
|
+
const MODELS_WITH_NO_ADDITIONAL_FIELDS_PASSTHROUGH = [
|
|
50
|
+
'user',
|
|
51
|
+
'session',
|
|
52
|
+
'account',
|
|
53
|
+
'verification',
|
|
54
|
+
];
|
|
27
55
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
* Reject `betterAuthOptions` keys that already have a dedicated, non-passthrough
|
|
57
|
+
* seam — accepting them here would create two unranked ways to set the same
|
|
58
|
+
* thing, or (for `additionalFields`) silently diverge from the generated
|
|
59
|
+
* Prisma schema. See the `betterAuthOptions` doc comment on `AuthConfig`.
|
|
60
|
+
*/
|
|
61
|
+
function assertNoUnsupportedPassthroughKeys(betterAuthOptions) {
|
|
62
|
+
if ('database' in betterAuthOptions) {
|
|
63
|
+
throw new Error('[@opensaas/stack-auth] `betterAuthOptions.database` is not supported — the stack ' +
|
|
64
|
+
'derives the database adapter from your `db` config and the running context. ' +
|
|
65
|
+
'Configure the database through `db` in `opensaas.config.ts` instead.');
|
|
66
|
+
}
|
|
67
|
+
if ('plugins' in betterAuthOptions) {
|
|
68
|
+
throw new Error('[@opensaas/stack-auth] `betterAuthOptions.plugins` is not supported — better-auth ' +
|
|
69
|
+
'plugins are added through `authPlugin({ betterAuthPlugins: [...] })`, which the stack ' +
|
|
70
|
+
'appends `nextCookies()` after. Use `betterAuthPlugins` instead.');
|
|
71
|
+
}
|
|
72
|
+
for (const model of MODELS_WITH_NO_ADDITIONAL_FIELDS_PASSTHROUGH) {
|
|
73
|
+
const modelOptions = betterAuthOptions[model];
|
|
74
|
+
if (modelOptions &&
|
|
75
|
+
typeof modelOptions === 'object' &&
|
|
76
|
+
!Array.isArray(modelOptions) &&
|
|
77
|
+
'additionalFields' in modelOptions) {
|
|
78
|
+
throw new Error(`[@opensaas/stack-auth] \`betterAuthOptions.${model}.additionalFields\` is not ` +
|
|
79
|
+
'supported — it adds columns that would not be reflected in the generated Prisma ' +
|
|
80
|
+
'schema. Add fields to the derived list instead: ' +
|
|
81
|
+
(model === 'user'
|
|
82
|
+
? '`extendUserList`, or declare the list yourself in your own `lists` config.'
|
|
83
|
+
: 'declare the derived list yourself in your own `lists` config (the auth plugin ' +
|
|
84
|
+
'merges in field additions for the models it derives).'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function isPlainObject(value) {
|
|
89
|
+
return (typeof value === 'object' &&
|
|
90
|
+
value !== null &&
|
|
91
|
+
!Array.isArray(value) &&
|
|
92
|
+
Object.getPrototypeOf(value) === Object.prototype);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Deep-merge `overrides` onto `base`, recursing into plain-object values so a
|
|
96
|
+
* nested addition (one database hook, one session sub-option) merges
|
|
97
|
+
* alongside sibling keys the stack already set there rather than replacing
|
|
98
|
+
* the whole branch. Arrays and any other value type replace outright.
|
|
99
|
+
* `overrides` wins on every key collision.
|
|
40
100
|
*/
|
|
41
|
-
|
|
101
|
+
function mergeBetterAuthOptions(base, overrides) {
|
|
102
|
+
const result = { ...base };
|
|
103
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
104
|
+
const baseValue = result[key];
|
|
105
|
+
result[key] =
|
|
106
|
+
isPlainObject(baseValue) && isPlainObject(value)
|
|
107
|
+
? mergeBetterAuthOptions(baseValue, value)
|
|
108
|
+
: value;
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
export async function buildBetterAuthOptions(opensaasConfig, context, plugins) {
|
|
113
|
+
const resolvedConfig = await Promise.resolve(opensaasConfig);
|
|
114
|
+
const resolvedContext = await Promise.resolve(context);
|
|
115
|
+
// Extract auth config from plugin data
|
|
116
|
+
const authConfig = resolvedConfig._pluginData?.auth;
|
|
117
|
+
if (!authConfig) {
|
|
118
|
+
throw new Error('Auth config not found. Make sure to use authPlugin() in your opensaas.config.ts');
|
|
119
|
+
}
|
|
120
|
+
// `requireConfirmation` has no better-auth equivalent — it's a UI-only
|
|
121
|
+
// concern the pre-built forms already take as their own
|
|
122
|
+
// `requirePasswordConfirmation` prop. Warn rather than silently drop it,
|
|
123
|
+
// since setting it here looks like it should do something.
|
|
124
|
+
if (authConfig.emailAndPassword.enabled &&
|
|
125
|
+
authConfig.emailAndPassword.requireConfirmation !== true) {
|
|
126
|
+
console.warn('[@opensaas/stack-auth] `emailAndPassword.requireConfirmation` has no effect here — ' +
|
|
127
|
+
'createAuth() has no better-auth option to forward it to. Pass ' +
|
|
128
|
+
'`requirePasswordConfirmation` directly to <SignUpForm> / <ResetPasswordForm> instead.');
|
|
129
|
+
}
|
|
130
|
+
// `passwordReset` is wired through better-auth's `emailAndPassword` config
|
|
131
|
+
// (there's no password to reset without a password-based account), so it
|
|
132
|
+
// silently has no effect if email/password auth itself isn't enabled.
|
|
133
|
+
if (authConfig.passwordReset.enabled && !authConfig.emailAndPassword.enabled) {
|
|
134
|
+
console.warn('[@opensaas/stack-auth] `passwordReset.enabled` has no effect here — ' +
|
|
135
|
+
'`emailAndPassword.enabled` is false, so there is no password-based account to reset.');
|
|
136
|
+
}
|
|
137
|
+
assertNoUnsupportedPassthroughKeys(authConfig.betterAuthOptions);
|
|
138
|
+
const resolvedPlugins = authConfig.betterAuthPlugins || [];
|
|
139
|
+
if (plugins) {
|
|
140
|
+
assertPluginTupleMatchesResolved(plugins, resolvedPlugins);
|
|
141
|
+
}
|
|
142
|
+
// Build better-auth configuration
|
|
143
|
+
const betterAuthConfig = {
|
|
144
|
+
database: getDatabaseConfig(resolvedConfig.db, resolvedContext),
|
|
145
|
+
// Mirror the per-model config (modelName + field column maps) back to
|
|
146
|
+
// better-auth so the running auth instance reads/writes the same
|
|
147
|
+
// tables/columns the OpenSaaS Auth lists were derived from.
|
|
148
|
+
user: toBetterAuthModelOptions(authConfig.models.user),
|
|
149
|
+
session: {
|
|
150
|
+
...toBetterAuthModelOptions(authConfig.models.session),
|
|
151
|
+
expiresIn: authConfig.session.expiresIn || 604800,
|
|
152
|
+
// better-auth treats `updateAge: 0` as "refresh on every request", not
|
|
153
|
+
// "never refresh" — disabling refresh entirely requires its separate
|
|
154
|
+
// `disableSessionRefresh` flag regardless of `updateAge`.
|
|
155
|
+
...(authConfig.session.updateAge === false
|
|
156
|
+
? { disableSessionRefresh: true }
|
|
157
|
+
: { updateAge: authConfig.session.updateAge }),
|
|
158
|
+
},
|
|
159
|
+
account: toBetterAuthModelOptions(authConfig.models.account),
|
|
160
|
+
verification: toBetterAuthModelOptions(authConfig.models.verification),
|
|
161
|
+
// Enable email and password if configured
|
|
162
|
+
emailAndPassword: authConfig.emailAndPassword.enabled
|
|
163
|
+
? {
|
|
164
|
+
enabled: true,
|
|
165
|
+
requireEmailVerification: authConfig.emailVerification.enabled,
|
|
166
|
+
minPasswordLength: authConfig.emailAndPassword.minPasswordLength,
|
|
167
|
+
...(authConfig.passwordReset.enabled
|
|
168
|
+
? {
|
|
169
|
+
sendResetPassword: authConfig.emailAndPassword.sendResetPassword,
|
|
170
|
+
resetPasswordTokenExpiresIn: authConfig.passwordReset.tokenExpiration,
|
|
171
|
+
}
|
|
172
|
+
: {}),
|
|
173
|
+
}
|
|
174
|
+
: undefined,
|
|
175
|
+
// Email verification (independent of emailAndPassword — also covers
|
|
176
|
+
// e.g. a social-provider account whose email isn't yet verified)
|
|
177
|
+
emailVerification: authConfig.emailVerification.enabled
|
|
178
|
+
? {
|
|
179
|
+
sendVerificationEmail: authConfig.emailVerification.sendVerificationEmail,
|
|
180
|
+
sendOnSignUp: authConfig.emailVerification.sendOnSignUp,
|
|
181
|
+
expiresIn: authConfig.emailVerification.tokenExpiration,
|
|
182
|
+
}
|
|
183
|
+
: undefined,
|
|
184
|
+
// Trust host (required for production)
|
|
185
|
+
trustedOrigins: process.env.BETTER_AUTH_TRUSTED_ORIGINS?.split(',') || [],
|
|
186
|
+
// Social providers
|
|
187
|
+
socialProviders: Object.entries(authConfig.socialProviders)
|
|
188
|
+
.filter(([_, config]) => config?.enabled !== false)
|
|
189
|
+
.reduce((acc, [provider, config]) => {
|
|
190
|
+
if (config) {
|
|
191
|
+
acc[provider] = {
|
|
192
|
+
clientId: config.clientId,
|
|
193
|
+
clientSecret: config.clientSecret,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return acc;
|
|
197
|
+
}, {}),
|
|
198
|
+
// Rate limiting configuration
|
|
199
|
+
rateLimit: authConfig.rateLimit
|
|
200
|
+
? {
|
|
201
|
+
enabled: authConfig.rateLimit.enabled,
|
|
202
|
+
window: authConfig.rateLimit.window,
|
|
203
|
+
max: authConfig.rateLimit.max,
|
|
204
|
+
}
|
|
205
|
+
: undefined,
|
|
206
|
+
// Pass through any additional Better Auth plugins, then append
|
|
207
|
+
// nextCookies LAST so it can write the Set-Cookie headers produced by
|
|
208
|
+
// any auth.api.* call made inside a Next.js server action into Next's
|
|
209
|
+
// cookie store. This is what makes the server-action auth forms (which
|
|
210
|
+
// call auth.api.signInEmail/signUpEmail/etc. server-side) actually
|
|
211
|
+
// persist a session. It must be the final plugin in the array.
|
|
212
|
+
plugins: [...resolvedPlugins, nextCookies()],
|
|
213
|
+
};
|
|
214
|
+
return mergeBetterAuthOptions(betterAuthConfig, authConfig.betterAuthOptions);
|
|
215
|
+
}
|
|
216
|
+
export function createAuth(opensaasConfig, context, plugins) {
|
|
42
217
|
// Resolve config and context asynchronously
|
|
43
218
|
const configPromise = Promise.resolve(opensaasConfig);
|
|
44
219
|
const contextPromise = Promise.resolve(context);
|
|
45
|
-
// Create auth instance lazily when needed
|
|
46
220
|
let authInstance = null;
|
|
47
221
|
let authPromise = null;
|
|
48
222
|
async function getAuthInstance() {
|
|
@@ -50,66 +224,9 @@ export function createAuth(opensaasConfig, context) {
|
|
|
50
224
|
return authInstance;
|
|
51
225
|
if (!authPromise) {
|
|
52
226
|
authPromise = (async () => {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const authConfig = resolvedConfig._pluginData?.auth;
|
|
57
|
-
if (!authConfig) {
|
|
58
|
-
throw new Error('Auth config not found. Make sure to use authPlugin() in your opensaas.config.ts');
|
|
59
|
-
}
|
|
60
|
-
// Build better-auth configuration
|
|
61
|
-
const betterAuthConfig = {
|
|
62
|
-
database: getDatabaseConfig(resolvedConfig.db, resolvedContext),
|
|
63
|
-
// Mirror the per-model config (modelName + field column maps) back to
|
|
64
|
-
// better-auth so the running auth instance reads/writes the same
|
|
65
|
-
// tables/columns the OpenSaaS Auth lists were derived from.
|
|
66
|
-
user: toBetterAuthModelOptions(authConfig.models.user),
|
|
67
|
-
session: {
|
|
68
|
-
...toBetterAuthModelOptions(authConfig.models.session),
|
|
69
|
-
expiresIn: authConfig.session.expiresIn || 604800,
|
|
70
|
-
updateAge: authConfig.session.updateAge
|
|
71
|
-
? (authConfig.session.expiresIn || 604800) / 10
|
|
72
|
-
: 0,
|
|
73
|
-
},
|
|
74
|
-
account: toBetterAuthModelOptions(authConfig.models.account),
|
|
75
|
-
verification: toBetterAuthModelOptions(authConfig.models.verification),
|
|
76
|
-
// Enable email and password if configured
|
|
77
|
-
emailAndPassword: authConfig.emailAndPassword.enabled
|
|
78
|
-
? {
|
|
79
|
-
enabled: true,
|
|
80
|
-
requireEmailVerification: authConfig.emailVerification.enabled,
|
|
81
|
-
}
|
|
82
|
-
: undefined,
|
|
83
|
-
// Trust host (required for production)
|
|
84
|
-
trustedOrigins: process.env.BETTER_AUTH_TRUSTED_ORIGINS?.split(',') || [],
|
|
85
|
-
// Social providers
|
|
86
|
-
socialProviders: Object.entries(authConfig.socialProviders)
|
|
87
|
-
.filter(([_, config]) => config?.enabled !== false)
|
|
88
|
-
.reduce((acc, [provider, config]) => {
|
|
89
|
-
if (config) {
|
|
90
|
-
acc[provider] = {
|
|
91
|
-
clientId: config.clientId,
|
|
92
|
-
clientSecret: config.clientSecret,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
return acc;
|
|
96
|
-
}, {}),
|
|
97
|
-
// Rate limiting configuration
|
|
98
|
-
rateLimit: authConfig.rateLimit
|
|
99
|
-
? {
|
|
100
|
-
enabled: authConfig.rateLimit.enabled,
|
|
101
|
-
window: authConfig.rateLimit.window,
|
|
102
|
-
max: authConfig.rateLimit.max,
|
|
103
|
-
}
|
|
104
|
-
: undefined,
|
|
105
|
-
// Pass through any additional Better Auth plugins, then append
|
|
106
|
-
// nextCookies LAST so it can write the Set-Cookie headers produced by
|
|
107
|
-
// any auth.api.* call made inside a Next.js server action into Next's
|
|
108
|
-
// cookie store. This is what makes the server-action auth forms (which
|
|
109
|
-
// call auth.api.signInEmail/signUpEmail/etc. server-side) actually
|
|
110
|
-
// persist a session. It must be the final plugin in the array.
|
|
111
|
-
plugins: [...(authConfig.betterAuthPlugins || []), nextCookies()],
|
|
112
|
-
};
|
|
227
|
+
const betterAuthConfig = plugins
|
|
228
|
+
? await buildBetterAuthOptions(configPromise, contextPromise, plugins)
|
|
229
|
+
: await buildBetterAuthOptions(configPromise, contextPromise);
|
|
113
230
|
authInstance = betterAuth(betterAuthConfig);
|
|
114
231
|
return authInstance;
|
|
115
232
|
})();
|
|
@@ -158,31 +275,102 @@ export function createAuth(opensaasConfig, context) {
|
|
|
158
275
|
});
|
|
159
276
|
}
|
|
160
277
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
278
|
+
* Field names already warned about failing to resolve against a session, so a
|
|
279
|
+
* given field warns at most once per process rather than once per request.
|
|
163
280
|
*/
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
281
|
+
const unresolvedSessionFieldWarnings = new Set();
|
|
282
|
+
/**
|
|
283
|
+
* Warn (once per field, per process) that a `sessionFields` entry could not
|
|
284
|
+
* be resolved from the session shape `auth.api.getSession()` actually
|
|
285
|
+
* returned — naming the field and what keys were available to check, so the
|
|
286
|
+
* gap is visible here instead of surfacing later as an access-control
|
|
287
|
+
* function silently reading `undefined`.
|
|
288
|
+
*/
|
|
289
|
+
function warnUnresolvedSessionField(field, resolvedSession) {
|
|
290
|
+
if (unresolvedSessionFieldWarnings.has(field))
|
|
291
|
+
return;
|
|
292
|
+
unresolvedSessionFieldWarnings.add(field);
|
|
293
|
+
const user = isPlainObject(resolvedSession.user) ? resolvedSession.user : undefined;
|
|
294
|
+
const sessionRow = isPlainObject(resolvedSession.session) ? resolvedSession.session : undefined;
|
|
295
|
+
console.warn(`[@opensaas/stack-auth] sessionFields: "${field}" was not found on the resolved session. ` +
|
|
296
|
+
`Checked its top-level keys (${Object.keys(resolvedSession).join(', ') || 'none'}), ` +
|
|
297
|
+
`its "user" object (${user ? Object.keys(user).join(', ') || 'none' : 'not present'}), ` +
|
|
298
|
+
`and its "session" object (${sessionRow ? Object.keys(sessionRow).join(', ') || 'none' : 'not present'}). ` +
|
|
299
|
+
`The field is omitted from the projected session. A \`customSession\` plugin that nests this ` +
|
|
300
|
+
`value elsewhere is the app's own to reconcile — see the \`sessionFields\` reference. ` +
|
|
301
|
+
`This warning will not repeat for "${field}".`);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Resolve a single `sessionFields` entry off the resolved better-auth
|
|
305
|
+
* session (whatever `auth.api.getSession()` returned — the default `{
|
|
306
|
+
* session, user }` shape, or a `customSession` plugin's replaced shape).
|
|
307
|
+
*
|
|
308
|
+
* `userId` is special-cased to the authenticated user's `id` — the
|
|
309
|
+
* documented default apps depend on. Every other name resolves against a
|
|
310
|
+
* fixed precedence so a collision between sources is predictable rather
|
|
311
|
+
* than incidental: a top-level key on the resolved session object, then the
|
|
312
|
+
* `user` object, then the `session` sub-object.
|
|
313
|
+
*/
|
|
314
|
+
function resolveSessionField(field, resolvedSession) {
|
|
315
|
+
const user = isPlainObject(resolvedSession.user) ? resolvedSession.user : undefined;
|
|
316
|
+
if (field === 'userId') {
|
|
317
|
+
return user && 'id' in user ? { found: true, value: user.id } : { found: false };
|
|
318
|
+
}
|
|
319
|
+
if (field in resolvedSession) {
|
|
320
|
+
return { found: true, value: resolvedSession[field] };
|
|
321
|
+
}
|
|
322
|
+
if (user && field in user) {
|
|
323
|
+
return { found: true, value: user[field] };
|
|
183
324
|
}
|
|
184
|
-
|
|
325
|
+
const sessionRow = isPlainObject(resolvedSession.session) ? resolvedSession.session : undefined;
|
|
326
|
+
if (sessionRow && field in sessionRow) {
|
|
327
|
+
return { found: true, value: sessionRow[field] };
|
|
328
|
+
}
|
|
329
|
+
return { found: false };
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get session from better-auth and transform it to OpenSaas session format —
|
|
333
|
+
* a flattened projection of `sessionFields` off the *resolved* session
|
|
334
|
+
* object, not just its `user` sub-object. This is what makes a
|
|
335
|
+
* `customSession` plugin's fields (added at the top level, or a
|
|
336
|
+
* session-only field like the admin plugin's `impersonatedBy`) reachable.
|
|
337
|
+
* See the `sessionFields` reference for the resolution precedence.
|
|
338
|
+
*
|
|
339
|
+
* Returns `null` only when there is genuinely no session — a resolved
|
|
340
|
+
* session with no `user` key (a `customSession` plugin that dropped it) is
|
|
341
|
+
* still a session and still gets projected, never misreported as anonymous.
|
|
342
|
+
* A listed field that can't be resolved from the session shape is omitted
|
|
343
|
+
* and warns once per field per process (see `warnUnresolvedSessionField`)
|
|
344
|
+
* instead of silently vanishing into an access-control function reading
|
|
345
|
+
* `undefined`.
|
|
346
|
+
*
|
|
347
|
+
* Errors from the underlying `auth.api.getSession()` call propagate rather
|
|
348
|
+
* than becoming `null` — collapsing a lookup failure (e.g. a session-store
|
|
349
|
+
* outage) into "anonymous" is indistinguishable from a mass sign-out under
|
|
350
|
+
* fail-closed access control, so the caller must see it.
|
|
351
|
+
*
|
|
352
|
+
* Not called by any generated code before this helper existed — apps used to
|
|
353
|
+
* hand-roll this same transform against `auth.api.getSession({ headers:
|
|
354
|
+
* await headers() })`. Exported as the single reusable implementation; pass
|
|
355
|
+
* the caller's request headers (e.g. Next.js `await headers()` in a Server
|
|
356
|
+
* Component/action) so a session cookie can actually be resolved.
|
|
357
|
+
*/
|
|
358
|
+
export async function getSessionFromAuth(auth, sessionFields, headers) {
|
|
359
|
+
const resolvedSession = await auth.api.getSession({ headers });
|
|
360
|
+
if (!resolvedSession) {
|
|
185
361
|
return null;
|
|
186
362
|
}
|
|
363
|
+
const resolvedSessionRecord = resolvedSession;
|
|
364
|
+
const result = {};
|
|
365
|
+
for (const field of sessionFields) {
|
|
366
|
+
const resolved = resolveSessionField(field, resolvedSessionRecord);
|
|
367
|
+
if (resolved.found) {
|
|
368
|
+
result[field] = resolved.value;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
warnUnresolvedSessionField(field, resolvedSessionRecord);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return result;
|
|
187
375
|
}
|
|
188
376
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,13 +8,13 @@ import type { ListConfig } from '@opensaas/stack-core';
|
|
|
8
8
|
* Inferred from better-auth internal types
|
|
9
9
|
*/
|
|
10
10
|
type BetterAuthFieldAttribute = {
|
|
11
|
-
type: string;
|
|
11
|
+
type: string | string[];
|
|
12
12
|
required?: boolean;
|
|
13
13
|
unique?: boolean;
|
|
14
14
|
references?: {
|
|
15
15
|
model: string;
|
|
16
16
|
field: string;
|
|
17
|
-
onDelete?: 'cascade' | 'set null' | '
|
|
17
|
+
onDelete?: 'no action' | 'restrict' | 'cascade' | 'set null' | 'set default';
|
|
18
18
|
};
|
|
19
19
|
defaultValue?: unknown;
|
|
20
20
|
returned?: boolean;
|
|
@@ -24,7 +24,7 @@ type BetterAuthFieldAttribute = {
|
|
|
24
24
|
* Better Auth table schema structure
|
|
25
25
|
*/
|
|
26
26
|
type BetterAuthTableSchema = {
|
|
27
|
-
modelName
|
|
27
|
+
modelName?: string;
|
|
28
28
|
fields: Record<string, BetterAuthFieldAttribute>;
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-converter.d.ts","sourceRoot":"","sources":["../../src/server/schema-converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,sBAAsB,CAAA;AAEnE;;;GAGG;AACH,KAAK,wBAAwB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"schema-converter.d.ts","sourceRoot":"","sources":["../../src/server/schema-converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,sBAAsB,CAAA;AAEnE;;;GAGG;AACH,KAAK,wBAAwB,GAAG;IAC9B,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE;QACX,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;KAC7E,CAAA;IACD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED;;GAEG;AACH,KAAK,qBAAqB,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAA;CACjD,CAAA;AA2DD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,qBAAqB,GAEjC,UAAU,CAAC,GAAG,CAAC,CA4BjB;AAED;;;GAGG;AACH,KAAK,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,cAAc,CAAA;AAEvE;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAA;AA0BzE;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,EAC7C,aAAa,GAAE,iBAAsB,GAEpC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAejC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensaas/stack-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Better-auth integration for OpenSaas Stack",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,13 +60,13 @@
|
|
|
60
60
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
61
61
|
"@vitest/coverage-v8": "^4.1.10",
|
|
62
62
|
"@vitest/ui": "^4.1.10",
|
|
63
|
-
"better-auth": "^1.
|
|
63
|
+
"better-auth": "^1.6.25",
|
|
64
64
|
"next": "^16.2.10",
|
|
65
|
-
"react": "^19.2.
|
|
65
|
+
"react": "^19.2.8",
|
|
66
66
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
67
67
|
"vitest": "^4.1.10",
|
|
68
|
-
"@opensaas/stack-cli": "0.
|
|
69
|
-
"@opensaas/stack-core": "0.
|
|
68
|
+
"@opensaas/stack-cli": "0.38.0",
|
|
69
|
+
"@opensaas/stack-core": "0.38.0"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "tsc",
|
|
@@ -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
|
|
|
33
49
|
import type { AuthConfig, AuthModelConfig } from './types.js'
|
|
@@ -89,6 +105,39 @@ export type AdoptBetterAuthTablesOptions = {
|
|
|
89
105
|
account?: Record<string, string>
|
|
90
106
|
verification?: Record<string, string>
|
|
91
107
|
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Set every model's physical table name to better-auth's own default
|
|
111
|
+
* lowercase table name (`user`, `session`, `account`, `verification`) —
|
|
112
|
+
* independent of the prefixed list key/`modelName`.
|
|
113
|
+
*
|
|
114
|
+
* This is the single most common adoption shape: a project that ran
|
|
115
|
+
* better-auth before adding the stack has exactly these tables, and the
|
|
116
|
+
* default `modelNamePrefix: 'Auth'` alone would otherwise pin the table
|
|
117
|
+
* name to the prefixed model name (`AuthUser`, ...), which `prisma migrate
|
|
118
|
+
* diff` reads as a rename against the live `user` table.
|
|
119
|
+
*
|
|
120
|
+
* Ignored for a model with an explicit entry in {@link tableNames}.
|
|
121
|
+
*
|
|
122
|
+
* @default false
|
|
123
|
+
*/
|
|
124
|
+
useBetterAuthTableNames?: boolean
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Per-model explicit table name overrides, keyed by model. Takes
|
|
128
|
+
* precedence over `useBetterAuthTableNames` for that model.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* adoptBetterAuthTables({ tableNames: { user: 'users' } })
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
tableNames?: {
|
|
136
|
+
user?: string
|
|
137
|
+
session?: string
|
|
138
|
+
account?: string
|
|
139
|
+
verification?: string
|
|
140
|
+
}
|
|
92
141
|
}
|
|
93
142
|
|
|
94
143
|
/** The four better-auth models and their default (unprefixed) model names. */
|
|
@@ -99,6 +148,14 @@ const MODEL_DEFAULT_NAMES = {
|
|
|
99
148
|
verification: 'Verification',
|
|
100
149
|
} as const
|
|
101
150
|
|
|
151
|
+
/** better-auth's own default lowercase table names, per model. */
|
|
152
|
+
const BETTER_AUTH_DEFAULT_TABLE_NAMES = {
|
|
153
|
+
user: 'user',
|
|
154
|
+
session: 'session',
|
|
155
|
+
account: 'account',
|
|
156
|
+
verification: 'verification',
|
|
157
|
+
} as const
|
|
158
|
+
|
|
102
159
|
/**
|
|
103
160
|
* The adoption-relevant slice of {@link AuthConfig}: the plugin-level `schema`
|
|
104
161
|
* and the per-model `modelName`/`fields`. Returned (not the full `AuthConfig`)
|
|
@@ -123,12 +180,24 @@ export type AdoptBetterAuthTablesConfig = Pick<
|
|
|
123
180
|
export function adoptBetterAuthTables(
|
|
124
181
|
options: AdoptBetterAuthTablesOptions = {},
|
|
125
182
|
): AdoptBetterAuthTablesConfig {
|
|
126
|
-
const {
|
|
183
|
+
const {
|
|
184
|
+
schema = 'auth',
|
|
185
|
+
modelNamePrefix = 'Auth',
|
|
186
|
+
fields = {},
|
|
187
|
+
useBetterAuthTableNames = false,
|
|
188
|
+
tableNames = {},
|
|
189
|
+
} = options
|
|
127
190
|
|
|
128
191
|
const buildModel = (model: keyof typeof MODEL_DEFAULT_NAMES): AuthModelConfig => {
|
|
129
192
|
const config: AuthModelConfig = {
|
|
130
193
|
modelName: `${modelNamePrefix}${MODEL_DEFAULT_NAMES[model]}`,
|
|
131
194
|
}
|
|
195
|
+
const tableName =
|
|
196
|
+
tableNames[model] ??
|
|
197
|
+
(useBetterAuthTableNames ? BETTER_AUTH_DEFAULT_TABLE_NAMES[model] : undefined)
|
|
198
|
+
if (tableName !== undefined) {
|
|
199
|
+
config.tableName = tableName
|
|
200
|
+
}
|
|
132
201
|
const fieldMap = fields[model]
|
|
133
202
|
if (fieldMap && Object.keys(fieldMap).length > 0) {
|
|
134
203
|
config.fields = fieldMap
|