@delmaredigital/payload-better-auth 0.3.13 → 0.3.14

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/README.md CHANGED
@@ -576,7 +576,7 @@ const user = await getServerUser<User>(payload, headersList)
576
576
  // user.role, user.firstName, etc. are fully typed
577
577
  ```
578
578
 
579
- ### `createSessionHelpers<TUser>()`
579
+ ### `createSessionHelpers<TUser>(options?)`
580
580
 
581
581
  Create typed session helpers bound to your User type. Define once, import everywhere — no generics needed at call sites:
582
582
 
@@ -596,6 +596,18 @@ const session = await getServerSession(payload, headersList)
596
596
  // session.user is typed as User — no generic needed
597
597
  ```
598
598
 
599
+ **Serial IDs (Payload default):** Better Auth always returns string IDs from `api.getSession()`, which causes Payload relationship fields to reject them. Pass `idType: 'number'` to coerce ID fields to numbers automatically:
600
+
601
+ ```ts
602
+ export const { getServerSession, getServerUser } = createSessionHelpers<User>({
603
+ idType: 'number', // coerces user.id, session.userId, etc. to numbers
604
+ })
605
+ ```
606
+
607
+ | Option | Type | Description |
608
+ |--------|------|-------------|
609
+ | `idType` | `'number' \| 'text'` | Set to `'number'` when using serial IDs to coerce string IDs to numbers. Matches the adapter's `adapterConfig.idType` option. |
610
+
599
611
  ### `withBetterAuthDefaults(options)`
600
612
 
601
613
  Applies sensible defaults to Better Auth options. Useful for simplifying common configurations.
package/dist/index.d.ts CHANGED
@@ -23,7 +23,7 @@ export type { ApiKeyInfo, ApiKeyAccessConfig, } from './utils/apiKeyAccess.js';
23
23
  export { detectAuthConfig } from './utils/detectAuthConfig.js';
24
24
  export type { AuthDetectionResult } from './utils/detectAuthConfig.js';
25
25
  export { getServerSession, getServerUser, createSessionHelpers } from './utils/session.js';
26
- export type { Session } from './utils/session.js';
26
+ export type { Session, SessionHelperOptions } from './utils/session.js';
27
27
  export { firstUserAdminHooks } from './utils/firstUserAdmin.js';
28
28
  export type { FirstUserAdminOptions } from './utils/firstUserAdmin.js';
29
29
  export { withBetterAuthDefaults, apiKeyWithDefaults } from './utils/betterAuthDefaults.js';
@@ -69,6 +69,19 @@ export declare function getServerSession<TUser = DefaultUser>(payload: BasePaylo
69
69
  * ```
70
70
  */
71
71
  export declare function getServerUser<TUser = DefaultUser>(payload: BasePayload, headers: Headers): Promise<TUser | null>;
72
+ export type SessionHelperOptions = {
73
+ /**
74
+ * ID type strategy matching your adapter's `adapterConfig.idType`.
75
+ *
76
+ * Set to `'number'` when using Payload's default serial IDs.
77
+ * Better Auth always returns string IDs from `api.getSession()` —
78
+ * this option coerces `id` and `*Id` / `*_id` fields to numbers
79
+ * so they work directly in Payload relationship fields.
80
+ *
81
+ * @default undefined (no coercion)
82
+ */
83
+ idType?: 'number' | 'text';
84
+ };
72
85
  /**
73
86
  * Create typed session helpers bound to your User type.
74
87
  *
@@ -84,15 +97,24 @@ export declare function getServerUser<TUser = DefaultUser>(payload: BasePayload,
84
97
  * export const { getServerSession, getServerUser } = createSessionHelpers<User>()
85
98
  * ```
86
99
  *
100
+ * @example
101
+ * ```ts
102
+ * // With serial IDs (Payload default) — coerces string IDs to numbers
103
+ * export const { getServerSession, getServerUser } = createSessionHelpers<User>({
104
+ * idType: 'number',
105
+ * })
106
+ * ```
107
+ *
87
108
  * ```ts
88
109
  * // app/page.tsx
89
110
  * import { getServerSession } from '@/lib/auth'
90
111
  *
91
112
  * const session = await getServerSession(payload, headersList)
92
113
  * // session.user is typed as User — no generic needed
114
+ * // session.user.id is a number when idType: 'number'
93
115
  * ```
94
116
  */
95
- export declare function createSessionHelpers<TUser = DefaultUser>(): {
117
+ export declare function createSessionHelpers<TUser = DefaultUser>(options?: SessionHelperOptions): {
96
118
  getServerSession: (payload: BasePayload, headers: Headers) => Promise<Session<TUser> | null>;
97
119
  getServerUser: (payload: BasePayload, headers: Headers) => Promise<TUser | null>;
98
120
  };
@@ -68,6 +68,24 @@
68
68
  const session = await getServerSession(payload, headers);
69
69
  return session?.user ?? null;
70
70
  }
71
+ /**
72
+ * Coerce numeric-string ID fields to numbers on a shallow object.
73
+ * Matches the adapter's heuristic: `id`, fields ending in `Id` or `_id`.
74
+ */ function coerceIds(obj) {
75
+ if (!obj || typeof obj !== 'object') return obj;
76
+ const result = {
77
+ ...obj
78
+ };
79
+ for (const [key, value] of Object.entries(result)){
80
+ if (typeof value !== 'string') continue;
81
+ if (key === 'id' || /(?:Id|_id)$/.test(key)) {
82
+ if (/^\d+$/.test(value)) {
83
+ result[key] = parseInt(value, 10);
84
+ }
85
+ }
86
+ }
87
+ return result;
88
+ }
71
89
  /**
72
90
  * Create typed session helpers bound to your User type.
73
91
  *
@@ -83,16 +101,37 @@
83
101
  * export const { getServerSession, getServerUser } = createSessionHelpers<User>()
84
102
  * ```
85
103
  *
104
+ * @example
105
+ * ```ts
106
+ * // With serial IDs (Payload default) — coerces string IDs to numbers
107
+ * export const { getServerSession, getServerUser } = createSessionHelpers<User>({
108
+ * idType: 'number',
109
+ * })
110
+ * ```
111
+ *
86
112
  * ```ts
87
113
  * // app/page.tsx
88
114
  * import { getServerSession } from '@/lib/auth'
89
115
  *
90
116
  * const session = await getServerSession(payload, headersList)
91
117
  * // session.user is typed as User — no generic needed
118
+ * // session.user.id is a number when idType: 'number'
92
119
  * ```
93
- */ export function createSessionHelpers() {
120
+ */ export function createSessionHelpers(options) {
121
+ const shouldCoerceIds = options?.idType === 'number';
122
+ const typedGetServerSession = async (payload, headers)=>{
123
+ const session = await getServerSession(payload, headers);
124
+ if (!session || !shouldCoerceIds) return session;
125
+ return {
126
+ user: coerceIds(session.user),
127
+ session: coerceIds(session.session)
128
+ };
129
+ };
94
130
  return {
95
- getServerSession: (payload, headers)=>getServerSession(payload, headers),
96
- getServerUser: (payload, headers)=>getServerUser(payload, headers)
131
+ getServerSession: typedGetServerSession,
132
+ getServerUser: async (payload, headers)=>{
133
+ const session = await typedGetServerSession(payload, headers);
134
+ return session?.user ?? null;
135
+ }
97
136
  };
98
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delmaredigital/payload-better-auth",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "Better Auth adapter and plugins for Payload CMS",
5
5
  "type": "module",
6
6
  "license": "MIT",