@opensaas/stack-auth 0.37.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @opensaas/stack-auth@0.37.0 build /home/runner/work/stack/stack/packages/auth
2
+ > @opensaas/stack-auth@0.38.0 build /home/runner/work/stack/stack/packages/auth
3
3
  > tsc
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @opensaas/stack-auth
2
2
 
3
+ ## 0.38.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#888](https://github.com/OpenSaasAU/stack/pull/888) [`8183827`](https://github.com/OpenSaasAU/stack/commit/8183827ec65d6cfd7153028f84057ab65dfdc7dd) Thanks [@borisno2](https://github.com/borisno2)! - `buildBetterAuthOptions()` and `createAuth()` now accept an optional third argument — your app's `betterAuthPlugins` array, the same array passed to `authPlugin({ betterAuthPlugins })` — so the returned options/`Auth` type carries the literal plugin tuple instead of the widened `BetterAuthOptions`/`Auth<BetterAuthOptions>`. Without this, `betterAuth()` constructed from the widened return loses plugin-derived `auth.api.*` endpoints (e.g. `emailOTP()`'s `signInEmailOTP`) and a `customSession()` plugin's replaced session shape.
8
+
9
+ ```typescript
10
+ export const appBetterAuthPlugins = [emailOTP({ sendVerificationOTP })] // same array passed to authPlugin({ betterAuthPlugins })
11
+
12
+ export const auth = betterAuth({
13
+ ...(await buildBetterAuthOptions(config, rawOpensaasContext, appBetterAuthPlugins)),
14
+ })
15
+ // auth.api.signInEmailOTP is now typed, and auth.api.getSession() returns your customSession() shape.
16
+ ```
17
+
18
+ The supplied tuple is for typing only — the plugin array used at runtime is always the one resolved from `authPlugin({ betterAuthPlugins })`. Passing a tuple that isn't the same plugin instances in the same order throws, naming the mismatch, so the two can't silently drift apart. Calling either function with no third argument is unchanged — same widened return type, same runtime options, fully backwards compatible.
19
+
20
+ Also, `AuthConfig`/`NormalizedAuthConfig`'s `betterAuthPlugins` field is now typed as better-auth's own `BetterAuthPlugin[]` instead of `any[]`.
21
+
22
+ - [#889](https://github.com/OpenSaasAU/stack/pull/889) [`b9b9357`](https://github.com/OpenSaasAU/stack/commit/b9b935719774b01a81cfd2082387b76806c1a484) Thanks [@borisno2](https://github.com/borisno2)! - Fix `getSessionFromAuth` to project `sessionFields` from the _resolved_ better-auth session instead of only its `user` sub-object. A `customSession` plugin's replaced shape with no `user` key is now correctly treated as a signed-in session (never misreported as anonymous), and a session-only field (e.g. the admin plugin's `impersonatedBy`) is now resolvable. Errors from the underlying session lookup now propagate instead of silently becoming `null`, and a `sessionFields` entry that can't be resolved is omitted and logs a warning (once per field, per process) instead of vanishing silently.
23
+
24
+ The scaffolded `getSession()` — the CLI feature generator's `lib/auth.ts` template, and `examples/starter-auth`/`examples/auth-demo` — now call this single shared helper, reading `sessionFields` from the resolved config at runtime instead of baking a field list in at generation time. `examples/auth-demo`'s `getSession()` also now correctly returns `null` for an anonymous visitor (previously returned a truthy object of `undefined` values).
25
+
26
+ ```typescript
27
+ authPlugin({ sessionFields: ['userId', 'email', 'name', 'role'] })
28
+ ```
29
+
30
+ ```typescript
31
+ // lib/auth.ts
32
+ export async function getSession() {
33
+ const resolvedConfig = await config
34
+ const authConfig = resolvedConfig._pluginData?.auth as NormalizedAuthConfig | undefined
35
+ const sessionFields = authConfig?.sessionFields ?? ['userId', 'email', 'name']
36
+ return getSessionFromAuth(auth, sessionFields, await headers())
37
+ }
38
+ ```
39
+
3
40
  ## 0.37.0
4
41
 
5
42
  ### Minor Changes
package/CLAUDE.md CHANGED
@@ -28,8 +28,8 @@ Auto-generated lists:
28
28
 
29
29
  ### Server (`src/server/index.ts`)
30
30
 
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()`
31
+ - `createAuth(config, rawContext?, betterAuthPlugins?)` - Creates Better-auth instance with MCP plugin support
32
+ - `buildBetterAuthOptions(config, rawContext?, betterAuthPlugins?)` - Returns the same `BetterAuthOptions` `createAuth()` builds, without constructing an instance — for apps that need to hand-wire their own `betterAuth()`. The optional third argument (the app's own `betterAuthPlugins` array) makes the return type carry that literal plugin tuple instead of the widened array type — see "Typed `auth.api.*` reads" below.
33
33
  - Returns `{ handler, signIn, signOut, ... }` - Better-auth methods
34
34
 
35
35
  ### Client (`src/client/index.ts`)
@@ -235,7 +235,8 @@ const context = createContext(config, prisma, session)
235
235
 
236
236
  ### Session Fields Configuration
237
237
 
238
- Control which User fields appear in session:
238
+ `sessionFields` describes a **flattened projection** of the resolved better-auth session, not
239
+ the session's own shape:
239
240
 
240
241
  ```typescript
241
242
  authPlugin({ sessionFields: ['userId', 'email', 'name', 'role'] })
@@ -247,6 +248,15 @@ access: {
247
248
  }
248
249
  ```
249
250
 
251
+ `getSessionFromAuth()` (`@opensaas/stack-auth/server`) is the single implementation of this
252
+ projection — the scaffolded `getSession()` calls it with `sessionFields` read from the resolved
253
+ config at runtime. Each name resolves against a fixed precedence (a top-level key on the
254
+ resolved session, then `user`, then `session`), with `userId` special-cased to the user's `id`.
255
+ A `customSession` better-auth plugin fully replaces the resolved shape and can nest fields
256
+ anywhere; reconciling that against `sessionFields` is the app's job — an unresolvable name is
257
+ omitted and warns once (per field, per process) rather than silently becoming `undefined`. See
258
+ the `sessionFields` reference (`docs/content/reference/auth.md`) for the full contract.
259
+
250
260
  ### Session Type Safety
251
261
 
252
262
  To get autocomplete and type safety for session fields, use module augmentation:
@@ -391,6 +401,43 @@ can't be synchronous. It gives an incremental path onto `createAuth()`: adopt
391
401
  the builder first, then fold options into `betterAuthOptions` above as the
392
402
  stack grows first-class config for them.
393
403
 
404
+ **Typed `auth.api.*` reads.** Called with just `(config, context)`, both
405
+ `buildBetterAuthOptions()` and `createAuth()` return the widened
406
+ `BetterAuthOptions` / `Auth<BetterAuthOptions>` — better-auth infers plugin
407
+ endpoints and a `customSession()`'s replaced session shape from the _literal_
408
+ options type, so the widened form erases them (an `emailOTP()` plugin loses
409
+ `auth.api.signInEmailOTP`; `auth.api.getSession()` falls back to `{ user,
410
+ session }` instead of a `customSession()` shape). Both functions take the
411
+ app's `betterAuthPlugins` array — the exact same array passed to
412
+ `authPlugin({ betterAuthPlugins })` — as an optional third argument, and their
413
+ return type then carries that literal tuple (plus the `nextCookies()` the
414
+ stack always appends last) instead of the widened array type:
415
+
416
+ ```typescript
417
+ export const appBetterAuthPlugins = [emailOTP({ sendVerificationOTP })] // same array passed to authPlugin({ betterAuthPlugins })
418
+
419
+ export const auth = betterAuth({
420
+ ...(await buildBetterAuthOptions(config, rawOpensaasContext, appBetterAuthPlugins)),
421
+ })
422
+ // auth.api.signInEmailOTP is now typed.
423
+ ```
424
+
425
+ The supplied tuple is for typing only — the plugin array used at runtime is
426
+ always the one resolved from `authPlugin({ betterAuthPlugins })` — so both
427
+ functions verify the supplied tuple is the same plugin instances in the same
428
+ order as the resolved array, throwing a prefixed error naming the mismatch if
429
+ not (`assertPluginTupleMatchesResolved` in `src/server/index.ts`). This is
430
+ what closes the drift hole a hand-rolled re-pass of the plugin array would
431
+ otherwise open.
432
+
433
+ `createAuth()`'s lazy `Proxy` does not behave identically to a real `Auth`
434
+ instance for every property regardless of which form you use — every access,
435
+ including a non-function property, is surfaced through an `async` wrapper (so
436
+ `auth.options` reads back as a `Promise`, not the plain object a real
437
+ instance returns synchronously). Reach for `buildBetterAuthOptions()` plus
438
+ `betterAuth()` instead when the app reads `auth.api.*` in typed code — it
439
+ constructs a real instance and does not have this gap.
440
+
394
441
  ## Integration Points
395
442
 
396
443
  ### With @opensaas/stack-core
@@ -90,7 +90,7 @@ export function authPlugin(config) {
90
90
  // `oauth_application`, `passkey`) still register as new lists via
91
91
  // `addList`, same as before.
92
92
  for (const plugin of normalized.betterAuthPlugins) {
93
- if (plugin && typeof plugin === 'object' && 'schema' in plugin) {
93
+ if (plugin && typeof plugin === 'object' && plugin.schema) {
94
94
  // Plugin has schema property - convert to OpenSaaS lists
95
95
  const pluginSchema = plugin.schema;
96
96
  const pluginLists = convertBetterAuthSchema(pluginSchema, baseModelKeys);
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/config/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/config/plugin.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { ListConfig } from '@opensaas/stack-core';
2
- import type { BetterAuthOptions, User } from 'better-auth';
2
+ import type { BetterAuthOptions, BetterAuthPlugin, User } from 'better-auth';
3
3
  import type { ExtendUserListConfig } from '../lists/index.js';
4
4
  /**
5
5
  * better-auth's own callback shape for `sendVerificationEmail`/
@@ -321,8 +321,21 @@ export type AuthConfig = {
321
321
  */
322
322
  schema?: string;
323
323
  /**
324
- * Which fields to include in the session object
325
- * This determines what data is available in access control functions
324
+ * Which fields to include in the session object passed to access control
325
+ * functions a **flattened projection** of the resolved better-auth
326
+ * session, not the session's own shape. `getSessionFromAuth` (the
327
+ * implementation the scaffolded `getSession()` calls) resolves each name
328
+ * against a fixed precedence: a top-level key on the resolved session
329
+ * object, then the `user` object, then the `session` sub-object.
330
+ * `userId` is special-cased to the authenticated user's `id`.
331
+ *
332
+ * A `customSession` better-auth plugin fully replaces the resolved shape
333
+ * (it can nest fields anywhere, e.g. under its own custom key) —
334
+ * reconciling that shape against `sessionFields` is the application's job.
335
+ * A listed name that can't be resolved is omitted and warns once per
336
+ * field per process, naming what was checked, rather than silently
337
+ * becoming `undefined` in an access control function.
338
+ *
326
339
  * @default ['userId', 'email', 'name']
327
340
  *
328
341
  * @example
@@ -375,7 +388,7 @@ export type AuthConfig = {
375
388
  * ]
376
389
  * ```
377
390
  */
378
- betterAuthPlugins?: any[];
391
+ betterAuthPlugins?: BetterAuthPlugin[];
379
392
  /**
380
393
  * Rate limiting configuration
381
394
  * Controls rate limiting for authentication endpoints
@@ -489,7 +502,7 @@ export type NormalizedAuthConfig = Required<Omit<AuthConfig, 'emailAndPassword'
489
502
  * default (used to wire the datasource `schemas` array during generation).
490
503
  */
491
504
  schema?: string;
492
- betterAuthPlugins: any[];
505
+ betterAuthPlugins: BetterAuthPlugin[];
493
506
  rateLimit?: {
494
507
  enabled: boolean;
495
508
  window?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=build-better-auth-options.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-better-auth-options.test.d.ts","sourceRoot":"","sources":["../../src/server/build-better-auth-options.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { describe, it, expectTypeOf } from 'vitest';
2
+ import { buildBetterAuthOptions } from './index.js';
3
+ // `ReturnType<typeof buildBetterAuthOptions>` on the overloaded export itself
4
+ // resolves against its last (generic) signature, not the call-site-selected
5
+ // one — wrapping each call shape in its own ordinary function and reading
6
+ // `ReturnType<typeof wrapper>` instead forces TS to resolve overloads exactly
7
+ // as a real call site would.
8
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- referenced only via `typeof` below
9
+ function callWithNoPlugins(config, context) {
10
+ return buildBetterAuthOptions(config, context);
11
+ }
12
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- referenced only via `typeof` below
13
+ function callWithPlugins(config, context, plugins) {
14
+ return buildBetterAuthOptions(config, context, plugins);
15
+ }
16
+ describe('buildBetterAuthOptions plugin-tuple typing', () => {
17
+ it('back-compat: the no-argument call still returns the widened BetterAuthOptions', () => {
18
+ expectTypeOf().toEqualTypeOf();
19
+ });
20
+ it('preserves plugin-derived auth.api.* endpoints and a customSession shape', () => {
21
+ // emailOTP() endpoints exist on the constructed Auth's `api` — erased entirely
22
+ // when constructed from the widened `BetterAuthOptions` (see #876).
23
+ expectTypeOf().not.toBeNever();
24
+ expectTypeOf().not.toBeNever();
25
+ expectTypeOf().not.toBeNever();
26
+ expectTypeOf().toEqualTypeOf();
27
+ });
28
+ });
29
+ //# sourceMappingURL=build-better-auth-options.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-better-auth-options.test.js","sourceRoot":"","sources":["../../src/server/build-better-auth-options.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAKnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAWnD,8EAA8E;AAC9E,4EAA4E;AAC5E,0EAA0E;AAC1E,8EAA8E;AAC9E,6BAA6B;AAC7B,mGAAmG;AACnG,SAAS,iBAAiB,CACxB,MAAgD,EAChD,OAA+C;IAE/C,OAAO,sBAAsB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAChD,CAAC;AAED,mGAAmG;AACnG,SAAS,eAAe,CACtB,MAAgD,EAChD,OAA+C,EAC/C,OAAoB;IAEpB,OAAO,sBAAsB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AACzD,CAAC;AAMD,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;IAC1D,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACvF,YAAY,EAAe,CAAC,aAAa,EAAqB,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,+EAA+E;QAC/E,oEAAoE;QACpE,YAAY,EAA4C,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;QACxE,YAAY,EAAiD,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;QAC7E,YAAY,EAAkD,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;QAI9E,YAAY,EAAoB,CAAC,aAAa,EAAqB,CAAA;IACrE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1,6 +1,19 @@
1
1
  import { betterAuth } from 'better-auth';
2
- import type { BetterAuthOptions } from 'better-auth';
3
- import type { OpenSaasConfig, AccessContext } from '@opensaas/stack-core';
2
+ import { nextCookies } from 'better-auth/next-js';
3
+ import type { Auth, BetterAuthOptions, BetterAuthPlugin } from 'better-auth';
4
+ import type { OpenSaasConfig, AccessContext, Session } from '@opensaas/stack-core';
5
+ /**
6
+ * The `BetterAuthOptions` shape produced when an app's own plugin tuple is
7
+ * passed to `buildBetterAuthOptions()`/`createAuth()` — the tuple plus the
8
+ * `nextCookies()` plugin the stack always appends last. Carrying the literal
9
+ * tuple type (rather than the widened `BetterAuthPlugin[]`) is what lets
10
+ * `betterAuth()` re-infer plugin endpoints (e.g. `emailOTP()`'s
11
+ * `api.signInEmailOTP`) and a `customSession()` plugin's replaced session
12
+ * shape from the resulting options object.
13
+ */
14
+ type ResolvedBetterAuthOptions<TPlugins extends readonly BetterAuthPlugin[]> = Omit<BetterAuthOptions, 'plugins'> & {
15
+ plugins: [...TPlugins, ReturnType<typeof nextCookies>];
16
+ };
4
17
  /**
5
18
  * Build the `BetterAuthOptions` a better-auth instance for this OpenSaas
6
19
  * config should be constructed with — the same options `createAuth()` uses
@@ -10,42 +23,107 @@ import type { OpenSaasConfig, AccessContext } from '@opensaas/stack-core';
10
23
  * authoritative for everything it models; the app's additions on top become
11
24
  * an explicit, reviewable diff instead of a parallel, hand-duplicated config.
12
25
  *
13
- * @example
26
+ * Called with just `(config, context)`, the return type is the widened
27
+ * `BetterAuthOptions` — `betterAuth()` infers its plugin/session types from
28
+ * the *literal* type of the options object, so constructing from this
29
+ * widened return erases plugin endpoints (e.g. `emailOTP()`'s
30
+ * `api.signInEmailOTP`) and a `customSession()` plugin's replaced session
31
+ * shape. **If your app reads `auth.api.*` in typed code and uses either of
32
+ * those, pass its plugin tuple as the third argument** — the exact same
33
+ * array already passed to `authPlugin({ betterAuthPlugins })` — so the
34
+ * return type carries the literal tuple instead:
35
+ *
14
36
  * ```typescript
15
37
  * import { betterAuth } from 'better-auth'
38
+ * import { emailOTP } from 'better-auth/plugins'
16
39
  * import { buildBetterAuthOptions } from '@opensaas/stack-auth/server'
17
40
  *
41
+ * export const appBetterAuthPlugins = [emailOTP()] // same array passed to authPlugin({ betterAuthPlugins })
42
+ *
18
43
  * export const auth = betterAuth({
19
- * ...(await buildBetterAuthOptions(config, context)),
44
+ * ...(await buildBetterAuthOptions(config, context, appBetterAuthPlugins)),
20
45
  * databaseHooks: { user: { create: { after: syncDomainUser } } },
21
46
  * })
47
+ * // auth.api.signInEmailOTP / auth.api.getSession()'s customSession shape are now typed.
22
48
  * ```
49
+ *
50
+ * The supplied tuple is for typing only — the array actually used at runtime
51
+ * is always the one resolved from `authPlugin({ betterAuthPlugins })`, with
52
+ * exactly one `nextCookies()` appended last. Passing a tuple that isn't the
53
+ * same plugin instances in the same order throws, so the two can't silently
54
+ * drift apart.
55
+ *
56
+ * Note `createAuth()`'s lazy Proxy does not behave identically to a real
57
+ * `Auth` instance for every property (see its own doc comment) — reach for
58
+ * this builder plus `betterAuth()` instead when the app reads `auth.api.*`
59
+ * in typed code.
23
60
  */
24
61
  export declare function buildBetterAuthOptions(opensaasConfig: OpenSaasConfig | Promise<OpenSaasConfig>, context: AccessContext | Promise<AccessContext>): Promise<BetterAuthOptions>;
62
+ export declare function buildBetterAuthOptions<const TPlugins extends readonly BetterAuthPlugin[]>(opensaasConfig: OpenSaasConfig | Promise<OpenSaasConfig>, context: AccessContext | Promise<AccessContext>, plugins: TPlugins): Promise<ResolvedBetterAuthOptions<TPlugins>>;
25
63
  /**
26
64
  * Create a better-auth instance from OpenSaas config
27
65
  * This should be called once at app startup
28
66
  *
29
- * @example
67
+ * Returns a lazy `Proxy` (see the caveat below), typed as `Auth<BetterAuthOptions>`
68
+ * when called with just `(config, context)` — the widened type, same erasure
69
+ * caveat as {@link buildBetterAuthOptions}'s no-argument form. **If your app
70
+ * reads `auth.api.*` in typed code and relies on a plugin's endpoints (e.g.
71
+ * `emailOTP()`) or a `customSession()`'s replaced session shape, pass its
72
+ * plugin tuple as the third argument** — the exact same array already passed
73
+ * to `authPlugin({ betterAuthPlugins })` — so the declared type carries the
74
+ * literal tuple instead:
75
+ *
30
76
  * ```typescript
31
77
  * // lib/auth.ts
32
78
  * import { createAuth } from '@opensaas/stack-auth/server'
33
79
  * import config from '../opensaas.config'
34
80
  * import { rawOpensaasContext } from '@/.opensaas/context'
35
81
  *
36
- * export const auth = createAuth(config, rawOpensaasContext)
82
+ * export const appBetterAuthPlugins = [emailOTP()] // same array passed to authPlugin({ betterAuthPlugins })
83
+ *
84
+ * export const auth = createAuth(config, rawOpensaasContext, appBetterAuthPlugins)
37
85
  * ```
86
+ *
87
+ * As with the builder, the supplied tuple is for typing only, and a tuple
88
+ * that isn't the same plugin instances in the same order throws.
89
+ *
90
+ * **Proxy caveat:** the lazy `Proxy` this returns does not behave identically
91
+ * to a real `Auth` instance for every property — every access, including a
92
+ * non-function property, is surfaced through an `async` wrapper (so e.g.
93
+ * `auth.options` reads back as a `Promise`, not the plain object a real
94
+ * instance would return synchronously). The declared type does not model
95
+ * this difference; where it matters, reach for {@link buildBetterAuthOptions}
96
+ * plus `betterAuth()` instead, which constructs a real instance.
38
97
  */
39
- export declare function createAuth(opensaasConfig: OpenSaasConfig | Promise<OpenSaasConfig>, context: AccessContext | Promise<AccessContext>): import("better-auth").Auth<BetterAuthOptions>;
98
+ export declare function createAuth(opensaasConfig: OpenSaasConfig | Promise<OpenSaasConfig>, context: AccessContext | Promise<AccessContext>): Auth<BetterAuthOptions>;
99
+ export declare function createAuth<const TPlugins extends readonly BetterAuthPlugin[]>(opensaasConfig: OpenSaasConfig | Promise<OpenSaasConfig>, context: AccessContext | Promise<AccessContext>, plugins: TPlugins): Auth<ResolvedBetterAuthOptions<TPlugins>>;
40
100
  /**
41
- * Get session from better-auth and transform it to OpenSaas session format.
101
+ * Get session from better-auth and transform it to OpenSaas session format
102
+ * a flattened projection of `sessionFields` off the *resolved* session
103
+ * object, not just its `user` sub-object. This is what makes a
104
+ * `customSession` plugin's fields (added at the top level, or a
105
+ * session-only field like the admin plugin's `impersonatedBy`) reachable.
106
+ * See the `sessionFields` reference for the resolution precedence.
107
+ *
108
+ * Returns `null` only when there is genuinely no session — a resolved
109
+ * session with no `user` key (a `customSession` plugin that dropped it) is
110
+ * still a session and still gets projected, never misreported as anonymous.
111
+ * A listed field that can't be resolved from the session shape is omitted
112
+ * and warns once per field per process (see `warnUnresolvedSessionField`)
113
+ * instead of silently vanishing into an access-control function reading
114
+ * `undefined`.
115
+ *
116
+ * Errors from the underlying `auth.api.getSession()` call propagate rather
117
+ * than becoming `null` — collapsing a lookup failure (e.g. a session-store
118
+ * outage) into "anonymous" is indistinguishable from a mass sign-out under
119
+ * fail-closed access control, so the caller must see it.
42
120
  *
43
- * Not called by any generated code today — apps currently hand-roll this same
44
- * transform against `auth.api.getSession({ headers: await headers() })` (see
45
- * `examples/starter-auth/lib/auth.ts`). Exported as a reusable helper for that
46
- * pattern; pass the caller's request headers (e.g. Next.js `await headers()`
47
- * in a Server Component/action) so a session cookie can actually be resolved.
121
+ * Not called by any generated code before this helper existed — apps used to
122
+ * hand-roll this same transform against `auth.api.getSession({ headers:
123
+ * await headers() })`. Exported as the single reusable implementation; pass
124
+ * the caller's request headers (e.g. Next.js `await headers()` in a Server
125
+ * Component/action) so a session cookie can actually be resolved.
48
126
  */
49
- export declare function getSessionFromAuth(auth: ReturnType<typeof betterAuth>, sessionFields: string[], headers: Headers): Promise<Record<string, unknown> | null>;
127
+ export declare function getSessionFromAuth(auth: ReturnType<typeof betterAuth>, sessionFields: string[], headers: Headers): Promise<Session | null>;
50
128
  export type { BetterAuthOptions };
51
129
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAkHzE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,sBAAsB,CAC1C,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,EACxD,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,GAC9C,OAAO,CAAC,iBAAiB,CAAC,CA+H5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,EACxD,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,iDAoEhD;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,EACnC,aAAa,EAAE,MAAM,EAAE,EACvB,OAAO,EAAE,OAAO,2CAwBjB;AAED,YAAY,EAAE,iBAAiB,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAIlF;;;;;;;;GAQG;AACH,KAAK,yBAAyB,CAAC,QAAQ,SAAS,SAAS,gBAAgB,EAAE,IAAI,IAAI,CACjF,iBAAiB,EACjB,SAAS,CACV,GAAG;IACF,OAAO,EAAE,CAAC,GAAG,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CACvD,CAAA;AA+ID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAsB,sBAAsB,CAC1C,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,EACxD,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,GAC9C,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAC7B,wBAAsB,sBAAsB,CAAC,KAAK,CAAC,QAAQ,SAAS,SAAS,gBAAgB,EAAE,EAC7F,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,EACxD,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,EAC/C,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC,CAAA;AA2I/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,UAAU,CACxB,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,EACxD,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,GAC9C,IAAI,CAAC,iBAAiB,CAAC,CAAA;AAC1B,wBAAgB,UAAU,CAAC,KAAK,CAAC,QAAQ,SAAS,SAAS,gBAAgB,EAAE,EAC3E,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,EACxD,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,EAC/C,OAAO,EAAE,QAAQ,GAChB,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC,CAAA;AA8I5C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,EACnC,aAAa,EAAE,MAAM,EAAE,EACvB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAoBzB;AAED,YAAY,EAAE,iBAAiB,EAAE,CAAA"}