@delmaredigital/payload-better-auth 0.3.7 → 0.3.8
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 +12 -1
- package/dist/adapter/collections.d.ts.map +1 -1
- package/dist/adapter/collections.js +126 -88
- package/dist/adapter/collections.js.map +1 -1
- package/dist/adapter/index.js +197 -150
- package/dist/adapter/index.js.map +1 -1
- package/dist/components/BeforeLogin.d.ts +1 -1
- package/dist/components/BeforeLogin.d.ts.map +1 -1
- package/dist/components/BeforeLogin.js +15 -7
- package/dist/components/BeforeLogin.js.map +1 -1
- package/dist/components/LoginView.d.ts +2 -2
- package/dist/components/LoginView.d.ts.map +1 -1
- package/dist/components/LoginView.js +660 -218
- package/dist/components/LoginView.js.map +1 -1
- package/dist/components/LoginViewWrapper.d.ts +1 -1
- package/dist/components/LoginViewWrapper.d.ts.map +1 -1
- package/dist/components/LoginViewWrapper.js +14 -4
- package/dist/components/LoginViewWrapper.js.map +1 -1
- package/dist/components/LogoutButton.d.ts +1 -1
- package/dist/components/LogoutButton.d.ts.map +1 -1
- package/dist/components/LogoutButton.js +19 -11
- package/dist/components/LogoutButton.js.map +1 -1
- package/dist/components/PasskeyRegisterButton.d.ts +2 -2
- package/dist/components/PasskeyRegisterButton.d.ts.map +1 -1
- package/dist/components/PasskeyRegisterButton.js +20 -16
- package/dist/components/PasskeyRegisterButton.js.map +1 -1
- package/dist/components/PasskeySignInButton.d.ts +2 -2
- package/dist/components/PasskeySignInButton.d.ts.map +1 -1
- package/dist/components/PasskeySignInButton.js +14 -12
- package/dist/components/PasskeySignInButton.js.map +1 -1
- package/dist/components/auth/ForgotPasswordView.d.ts +1 -1
- package/dist/components/auth/ForgotPasswordView.d.ts.map +1 -1
- package/dist/components/auth/ForgotPasswordView.js +133 -43
- package/dist/components/auth/ForgotPasswordView.js.map +1 -1
- package/dist/components/auth/ResetPasswordView.d.ts +1 -1
- package/dist/components/auth/ResetPasswordView.d.ts.map +1 -1
- package/dist/components/auth/ResetPasswordView.js +154 -50
- package/dist/components/auth/ResetPasswordView.js.map +1 -1
- package/dist/components/auth/index.js +2 -2
- package/dist/components/auth/index.js.map +1 -1
- package/dist/components/management/ApiKeysManagementClient.d.ts +2 -2
- package/dist/components/management/ApiKeysManagementClient.d.ts.map +1 -1
- package/dist/components/management/ApiKeysManagementClient.js +539 -222
- package/dist/components/management/ApiKeysManagementClient.js.map +1 -1
- package/dist/components/management/PasskeysManagementClient.d.ts +2 -2
- package/dist/components/management/PasskeysManagementClient.d.ts.map +1 -1
- package/dist/components/management/PasskeysManagementClient.js +215 -92
- package/dist/components/management/PasskeysManagementClient.js.map +1 -1
- package/dist/components/management/SecurityNavLinks.d.ts +1 -1
- package/dist/components/management/SecurityNavLinks.d.ts.map +1 -1
- package/dist/components/management/SecurityNavLinks.js +51 -24
- package/dist/components/management/SecurityNavLinks.js.map +1 -1
- package/dist/components/management/TwoFactorManagementClient.d.ts +2 -2
- package/dist/components/management/TwoFactorManagementClient.d.ts.map +1 -1
- package/dist/components/management/TwoFactorManagementClient.js +270 -111
- package/dist/components/management/TwoFactorManagementClient.js.map +1 -1
- package/dist/components/management/index.js +2 -2
- package/dist/components/management/index.js.map +1 -1
- package/dist/components/management/views/ApiKeysView.d.ts +1 -1
- package/dist/components/management/views/ApiKeysView.d.ts.map +1 -1
- package/dist/components/management/views/ApiKeysView.js +19 -4
- package/dist/components/management/views/ApiKeysView.js.map +1 -1
- package/dist/components/management/views/PasskeysView.d.ts +1 -1
- package/dist/components/management/views/PasskeysView.d.ts.map +1 -1
- package/dist/components/management/views/PasskeysView.js +16 -4
- package/dist/components/management/views/PasskeysView.js.map +1 -1
- package/dist/components/management/views/TwoFactorView.d.ts +1 -1
- package/dist/components/management/views/TwoFactorView.d.ts.map +1 -1
- package/dist/components/management/views/TwoFactorView.js +16 -4
- package/dist/components/management/views/TwoFactorView.js.map +1 -1
- package/dist/components/management/views/index.js +2 -2
- package/dist/components/management/views/index.js.map +1 -1
- package/dist/components/twoFactor/TwoFactorSetupView.d.ts +1 -1
- package/dist/components/twoFactor/TwoFactorSetupView.d.ts.map +1 -1
- package/dist/components/twoFactor/TwoFactorSetupView.js +240 -87
- package/dist/components/twoFactor/TwoFactorSetupView.js.map +1 -1
- package/dist/components/twoFactor/TwoFactorVerifyView.d.ts +1 -1
- package/dist/components/twoFactor/TwoFactorVerifyView.d.ts.map +1 -1
- package/dist/components/twoFactor/TwoFactorVerifyView.js +108 -45
- package/dist/components/twoFactor/TwoFactorVerifyView.js.map +1 -1
- package/dist/components/twoFactor/index.js +2 -2
- package/dist/components/twoFactor/index.js.map +1 -1
- package/dist/exports/client.js +9 -10
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/components.js +2 -2
- package/dist/exports/components.js.map +1 -1
- package/dist/exports/management.js +3 -3
- package/dist/exports/management.js.map +1 -1
- package/dist/exports/rsc.js +2 -2
- package/dist/exports/rsc.js.map +1 -1
- package/dist/generated-types.js +4 -2
- package/dist/generated-types.js.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/plugin/index.js +198 -162
- package/dist/plugin/index.js.map +1 -1
- package/dist/scripts/generate-types.js +66 -50
- package/dist/scripts/generate-types.js.map +1 -1
- package/dist/types/apiKey.js +7 -2
- package/dist/types/apiKey.js.map +1 -1
- package/dist/types/betterAuth.js +23 -2
- package/dist/types/betterAuth.js.map +1 -1
- package/dist/utils/access.js +78 -81
- package/dist/utils/access.js.map +1 -1
- package/dist/utils/apiKeyAccess.js +65 -72
- package/dist/utils/apiKeyAccess.js.map +1 -1
- package/dist/utils/betterAuthDefaults.js +8 -8
- package/dist/utils/betterAuthDefaults.js.map +1 -1
- package/dist/utils/detectAuthConfig.js +8 -11
- package/dist/utils/detectAuthConfig.js.map +1 -1
- package/dist/utils/detectEnabledPlugins.js +6 -7
- package/dist/utils/detectEnabledPlugins.js.map +1 -1
- package/dist/utils/firstUserAdmin.js +18 -20
- package/dist/utils/firstUserAdmin.js.map +1 -1
- package/dist/utils/generateScopes.js +40 -41
- package/dist/utils/generateScopes.js.map +1 -1
- package/dist/utils/session.js +8 -9
- package/dist/utils/session.js.map +1 -1
- package/package.json +97 -26
- package/src/adapter/collections.ts +621 -0
- package/src/adapter/index.ts +712 -0
- package/src/components/BeforeLogin.tsx +39 -0
- package/src/components/LoginView.tsx +1516 -0
- package/src/components/LoginViewWrapper.tsx +35 -0
- package/src/components/LogoutButton.tsx +58 -0
- package/src/components/PasskeyRegisterButton.tsx +105 -0
- package/src/components/PasskeySignInButton.tsx +96 -0
- package/src/components/auth/ForgotPasswordView.tsx +274 -0
- package/src/components/auth/ResetPasswordView.tsx +331 -0
- package/src/components/auth/index.ts +8 -0
- package/src/components/management/ApiKeysManagementClient.tsx +988 -0
- package/src/components/management/PasskeysManagementClient.tsx +409 -0
- package/src/components/management/SecurityNavLinks.tsx +117 -0
- package/src/components/management/TwoFactorManagementClient.tsx +560 -0
- package/src/components/management/index.ts +20 -0
- package/src/components/management/views/ApiKeysView.tsx +57 -0
- package/src/components/management/views/PasskeysView.tsx +42 -0
- package/src/components/management/views/TwoFactorView.tsx +42 -0
- package/src/components/management/views/index.ts +10 -0
- package/src/components/twoFactor/TwoFactorSetupView.tsx +515 -0
- package/src/components/twoFactor/TwoFactorVerifyView.tsx +238 -0
- package/src/components/twoFactor/index.ts +8 -0
- package/src/exports/client.ts +77 -0
- package/src/exports/components.ts +30 -0
- package/src/exports/management.ts +25 -0
- package/src/exports/rsc.ts +11 -0
- package/src/generated-types.ts +269 -0
- package/src/index.ts +135 -0
- package/src/plugin/index.ts +834 -0
- package/src/scripts/generate-types.ts +269 -0
- package/src/types/apiKey.ts +63 -0
- package/src/types/betterAuth.ts +253 -0
- package/src/utils/access.ts +410 -0
- package/src/utils/apiKeyAccess.ts +443 -0
- package/src/utils/betterAuthDefaults.ts +102 -0
- package/src/utils/detectAuthConfig.ts +47 -0
- package/src/utils/detectEnabledPlugins.ts +69 -0
- package/src/utils/firstUserAdmin.ts +164 -0
- package/src/utils/generateScopes.ts +150 -0
- package/src/utils/session.ts +91 -0
package/dist/adapter/index.js
CHANGED
|
@@ -5,13 +5,11 @@
|
|
|
5
5
|
* eliminating hardcoded field mappings and supporting all Better Auth plugins.
|
|
6
6
|
*
|
|
7
7
|
* @packageDocumentation
|
|
8
|
-
*/
|
|
9
|
-
import { createAdapterFactory, } from 'better-auth/adapters';
|
|
8
|
+
*/ import { createAdapterFactory } from 'better-auth/adapters';
|
|
10
9
|
/**
|
|
11
10
|
* Detect ID type from Better Auth options.
|
|
12
11
|
* Defaults to 'number' (SERIAL) since Payload uses SERIAL IDs by default.
|
|
13
|
-
*/
|
|
14
|
-
function detectIdType(options) {
|
|
12
|
+
*/ function detectIdType(options) {
|
|
15
13
|
const generateId = options.advanced?.database?.generateId;
|
|
16
14
|
// If explicitly set to something other than 'serial', use text (UUID)
|
|
17
15
|
if (generateId !== undefined && generateId !== 'serial') {
|
|
@@ -53,49 +51,66 @@ function detectIdType(options) {
|
|
|
53
51
|
* session: { modelName: 'auth_session' }, // → 'auth_sessions' collection
|
|
54
52
|
* })
|
|
55
53
|
* ```
|
|
56
|
-
*/
|
|
57
|
-
export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
54
|
+
*/ export function payloadAdapter({ payloadClient, adapterConfig = {} }) {
|
|
58
55
|
const { enableDebugLogs = false, idFieldsAllowlist = [], idFieldsBlocklist = [] } = adapterConfig;
|
|
59
56
|
const idFieldsAllowlistSet = new Set(idFieldsAllowlist);
|
|
60
57
|
const idFieldsBlocklistSet = new Set(idFieldsBlocklist);
|
|
61
58
|
// Resolve payload client (supports lazy initialization)
|
|
62
59
|
async function resolvePayloadClient() {
|
|
63
|
-
return typeof payloadClient === 'function'
|
|
64
|
-
? await payloadClient()
|
|
65
|
-
: payloadClient;
|
|
60
|
+
return typeof payloadClient === 'function' ? await payloadClient() : payloadClient;
|
|
66
61
|
}
|
|
67
62
|
function convertOperator(operator, value) {
|
|
68
|
-
switch
|
|
63
|
+
switch(operator){
|
|
69
64
|
case 'eq':
|
|
70
|
-
return {
|
|
65
|
+
return {
|
|
66
|
+
equals: value
|
|
67
|
+
};
|
|
71
68
|
case 'ne':
|
|
72
|
-
return {
|
|
69
|
+
return {
|
|
70
|
+
not_equals: value
|
|
71
|
+
};
|
|
73
72
|
case 'gt':
|
|
74
|
-
return {
|
|
73
|
+
return {
|
|
74
|
+
greater_than: value
|
|
75
|
+
};
|
|
75
76
|
case 'gte':
|
|
76
|
-
return {
|
|
77
|
+
return {
|
|
78
|
+
greater_than_equal: value
|
|
79
|
+
};
|
|
77
80
|
case 'lt':
|
|
78
|
-
return {
|
|
81
|
+
return {
|
|
82
|
+
less_than: value
|
|
83
|
+
};
|
|
79
84
|
case 'lte':
|
|
80
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
less_than_equal: value
|
|
87
|
+
};
|
|
81
88
|
case 'in':
|
|
82
|
-
return {
|
|
89
|
+
return {
|
|
90
|
+
in: value
|
|
91
|
+
};
|
|
83
92
|
case 'contains':
|
|
84
|
-
return {
|
|
93
|
+
return {
|
|
94
|
+
contains: value
|
|
95
|
+
};
|
|
85
96
|
case 'starts_with':
|
|
86
|
-
return {
|
|
97
|
+
return {
|
|
98
|
+
like: `${value}%`
|
|
99
|
+
};
|
|
87
100
|
case 'ends_with':
|
|
88
|
-
return {
|
|
101
|
+
return {
|
|
102
|
+
like: `%${value}`
|
|
103
|
+
};
|
|
89
104
|
default:
|
|
90
|
-
return {
|
|
105
|
+
return {
|
|
106
|
+
equals: value
|
|
107
|
+
};
|
|
91
108
|
}
|
|
92
109
|
}
|
|
93
110
|
/**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (where.length !== 1)
|
|
98
|
-
return null;
|
|
111
|
+
* Extract single ID from where clause for optimization
|
|
112
|
+
*/ function extractSingleId(where) {
|
|
113
|
+
if (where.length !== 1) return null;
|
|
99
114
|
const w = where[0];
|
|
100
115
|
if (w.field === 'id' && w.operator === 'eq') {
|
|
101
116
|
const value = w.value;
|
|
@@ -106,7 +121,7 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
106
121
|
return null;
|
|
107
122
|
}
|
|
108
123
|
// Return the adapter factory function
|
|
109
|
-
return (options)
|
|
124
|
+
return (options)=>{
|
|
110
125
|
// Determine ID type: explicit config > auto-detect
|
|
111
126
|
// Defaults to 'number' (SERIAL) since Payload uses SERIAL IDs by default
|
|
112
127
|
const idType = adapterConfig.idType ?? detectIdType(options);
|
|
@@ -115,19 +130,20 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
115
130
|
// This would cause Better Auth to generate UUIDs which won't work with SERIAL columns
|
|
116
131
|
// Don't warn if generateId is undefined - that's the expected default case
|
|
117
132
|
if (idType === 'number' && generateId !== undefined && generateId !== 'serial') {
|
|
118
|
-
console.warn('[payload-adapter] Warning: Using SERIAL (number) IDs but `generateId` is set to a non-serial value. ' +
|
|
119
|
-
'Either set `advanced: { database: { generateId: "serial" } }` to let Payload generate IDs, ' +
|
|
120
|
-
'or set `adapterConfig: { idType: "text" }` if using UUIDs.');
|
|
133
|
+
console.warn('[payload-adapter] Warning: Using SERIAL (number) IDs but `generateId` is set to a non-serial value. ' + 'Either set `advanced: { database: { generateId: "serial" } }` to let Payload generate IDs, ' + 'or set `adapterConfig: { idType: "text" }` if using UUIDs.');
|
|
121
134
|
}
|
|
122
135
|
// Warn if modelName appears to be already plural (ends with 's')
|
|
123
136
|
// With usePlural: true, providing 'users' would become 'userss'
|
|
124
|
-
const coreModels = [
|
|
125
|
-
|
|
137
|
+
const coreModels = [
|
|
138
|
+
'user',
|
|
139
|
+
'session',
|
|
140
|
+
'account',
|
|
141
|
+
'verification'
|
|
142
|
+
];
|
|
143
|
+
for (const model of coreModels){
|
|
126
144
|
const modelName = options[model]?.modelName;
|
|
127
145
|
if (modelName && modelName.endsWith('s')) {
|
|
128
|
-
console.warn(`[payload-adapter] Warning: modelName '${modelName}' for '${model}' appears to be plural. ` +
|
|
129
|
-
`Use singular form (e.g., '${modelName.slice(0, -1)}') - it gets pluralized automatically. ` +
|
|
130
|
-
`Using plural names will result in double-pluralization (e.g., '${modelName}s').`);
|
|
146
|
+
console.warn(`[payload-adapter] Warning: modelName '${modelName}' for '${model}' appears to be plural. ` + `Use singular form (e.g., '${modelName.slice(0, -1)}') - it gets pluralized automatically. ` + `Using plural names will result in double-pluralization (e.g., '${modelName}s').`);
|
|
131
147
|
}
|
|
132
148
|
}
|
|
133
149
|
// Create adapter config for createAdapterFactory
|
|
@@ -148,18 +164,17 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
148
164
|
// Payload doesn't expose transaction API at collection level
|
|
149
165
|
transaction: false,
|
|
150
166
|
// Enable debug logs if configured
|
|
151
|
-
debugLogs: enableDebugLogs
|
|
167
|
+
debugLogs: enableDebugLogs
|
|
152
168
|
};
|
|
153
169
|
// We need to resolve the payload client before creating the adapter
|
|
154
170
|
// The factory pattern requires we return an adapter synchronously,
|
|
155
171
|
// so we'll resolve it lazily on first operation
|
|
156
172
|
let resolvedPayload = null;
|
|
157
173
|
let resolvePromise = null;
|
|
158
|
-
const getPayload = async ()
|
|
159
|
-
if (resolvedPayload)
|
|
160
|
-
return resolvedPayload;
|
|
174
|
+
const getPayload = async ()=>{
|
|
175
|
+
if (resolvedPayload) return resolvedPayload;
|
|
161
176
|
if (!resolvePromise) {
|
|
162
|
-
resolvePromise = resolvePayloadClient().then((p)
|
|
177
|
+
resolvePromise = resolvePayloadClient().then((p)=>{
|
|
163
178
|
resolvedPayload = p;
|
|
164
179
|
return p;
|
|
165
180
|
});
|
|
@@ -167,7 +182,7 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
167
182
|
return resolvePromise;
|
|
168
183
|
};
|
|
169
184
|
// Helper to convert ID based on type
|
|
170
|
-
const convertId = (id)
|
|
185
|
+
const convertId = (id)=>{
|
|
171
186
|
if (idType === 'number' && typeof id === 'string') {
|
|
172
187
|
const num = parseInt(id, 10);
|
|
173
188
|
return isNaN(num) ? id : num;
|
|
@@ -181,41 +196,40 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
181
196
|
// The factory handles all schema-aware transformations for us
|
|
182
197
|
const adapterFactory = createAdapterFactory({
|
|
183
198
|
config: factoryConfig,
|
|
184
|
-
adapter: ({ schema, getModelName, getFieldName, debugLog
|
|
199
|
+
adapter: ({ schema, getModelName, getFieldName, debugLog })=>{
|
|
185
200
|
// Log initialization
|
|
186
201
|
if (enableDebugLogs) {
|
|
187
202
|
debugLog('Adapter initialized', {
|
|
188
203
|
idType,
|
|
189
|
-
schema: Object.keys(schema)
|
|
204
|
+
schema: Object.keys(schema)
|
|
190
205
|
});
|
|
191
206
|
}
|
|
192
207
|
/**
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
function getModelSchema(model) {
|
|
208
|
+
* Get the schema for a model, handling plural/singular lookups.
|
|
209
|
+
* Better Auth queries with plural names when usePlural is true,
|
|
210
|
+
* but schema keys are singular.
|
|
211
|
+
*/ function getModelSchema(model) {
|
|
198
212
|
// First try direct lookup
|
|
199
|
-
if (schema[model])
|
|
200
|
-
return schema[model];
|
|
213
|
+
if (schema[model]) return schema[model];
|
|
201
214
|
// Try singular form (strip trailing 's') for plural model names
|
|
202
215
|
const singular = model.endsWith('s') ? model.slice(0, -1) : model;
|
|
203
|
-
if (schema[singular])
|
|
204
|
-
return schema[singular];
|
|
216
|
+
if (schema[singular]) return schema[singular];
|
|
205
217
|
// Try without 'ies' → 'y' conversion (e.g., 'verifications' → 'verification')
|
|
206
218
|
// This handles edge cases but 'verifications' → 'verification' works with simple 's' strip
|
|
207
219
|
return undefined;
|
|
208
220
|
}
|
|
209
221
|
/**
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
function getPayloadFieldName(model, field) {
|
|
222
|
+
* Transform a Better Auth field name to a Payload field name.
|
|
223
|
+
*
|
|
224
|
+
* For reference fields (those with `references` in schema), Payload collections
|
|
225
|
+
* use the field name without the `Id`/`_id` suffix (e.g., `userId` → `user`).
|
|
226
|
+
* This matches how betterAuthCollections() generates relationship fields.
|
|
227
|
+
*/ function getPayloadFieldName(model, field) {
|
|
217
228
|
// First apply any custom field name mappings from BetterAuthOptions
|
|
218
|
-
const mappedField = getFieldName({
|
|
229
|
+
const mappedField = getFieldName({
|
|
230
|
+
model,
|
|
231
|
+
field
|
|
232
|
+
});
|
|
219
233
|
// Check if this field is a reference field in the schema
|
|
220
234
|
const modelSchema = getModelSchema(model);
|
|
221
235
|
if (modelSchema?.fields?.[field]?.references) {
|
|
@@ -226,16 +240,14 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
226
240
|
return mappedField;
|
|
227
241
|
}
|
|
228
242
|
/**
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
function transformDataForPayload(model, data) {
|
|
243
|
+
* Transform input data from Better Auth format to Payload format.
|
|
244
|
+
* Converts reference field names (e.g., `userId` → `user`) and
|
|
245
|
+
* converts reference field values to the correct ID type.
|
|
246
|
+
*/ function transformDataForPayload(model, data) {
|
|
234
247
|
const modelSchema = getModelSchema(model);
|
|
235
|
-
if (!modelSchema?.fields)
|
|
236
|
-
return data;
|
|
248
|
+
if (!modelSchema?.fields) return data;
|
|
237
249
|
const transformed = {};
|
|
238
|
-
for (const [key, value] of Object.entries(data))
|
|
250
|
+
for (const [key, value] of Object.entries(data)){
|
|
239
251
|
const payloadKey = getPayloadFieldName(model, key);
|
|
240
252
|
let transformedValue = value;
|
|
241
253
|
// If this is a reference field, convert the ID to the correct type
|
|
@@ -247,8 +259,7 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
247
259
|
if (!isNaN(numValue)) {
|
|
248
260
|
transformedValue = numValue;
|
|
249
261
|
}
|
|
250
|
-
}
|
|
251
|
-
else if (idType === 'text' && typeof value === 'number') {
|
|
262
|
+
} else if (idType === 'text' && typeof value === 'number') {
|
|
252
263
|
transformedValue = String(value);
|
|
253
264
|
}
|
|
254
265
|
}
|
|
@@ -259,28 +270,28 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
259
270
|
model,
|
|
260
271
|
inputKeys: Object.keys(data),
|
|
261
272
|
outputKeys: Object.keys(transformed),
|
|
262
|
-
transformedData: transformed
|
|
273
|
+
transformedData: transformed
|
|
263
274
|
});
|
|
264
275
|
}
|
|
265
276
|
return transformed;
|
|
266
277
|
}
|
|
267
278
|
/**
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
function transformDataFromPayload(model, data) {
|
|
279
|
+
* Transform output data from Payload format to Better Auth format.
|
|
280
|
+
* Converts reference field names back (e.g., `user` → `userId`).
|
|
281
|
+
*/ function transformDataFromPayload(model, data) {
|
|
272
282
|
const modelSchema = getModelSchema(model);
|
|
273
|
-
if (!modelSchema?.fields || !data)
|
|
274
|
-
|
|
275
|
-
|
|
283
|
+
if (!modelSchema?.fields || !data) return data;
|
|
284
|
+
const transformed = {
|
|
285
|
+
...data
|
|
286
|
+
};
|
|
276
287
|
// For each field in the schema that has references,
|
|
277
288
|
// check if Payload returned the stripped name and map it back
|
|
278
|
-
for (const [fieldKey, fieldDef] of Object.entries(modelSchema.fields))
|
|
289
|
+
for (const [fieldKey, fieldDef] of Object.entries(modelSchema.fields)){
|
|
279
290
|
if (fieldDef.references) {
|
|
280
291
|
const payloadFieldName = fieldKey.replace(/(_id|Id)$/, '');
|
|
281
292
|
if (payloadFieldName in data && !(fieldKey in transformed)) {
|
|
282
293
|
transformed[fieldKey] = data[payloadFieldName];
|
|
283
|
-
|
|
294
|
+
// Keep both for compatibility - Better Auth expects userId
|
|
284
295
|
}
|
|
285
296
|
}
|
|
286
297
|
}
|
|
@@ -288,10 +299,9 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
288
299
|
// Heuristic: fields ending in 'Id' or '_id' containing numeric strings
|
|
289
300
|
// Modified by allowlist (add) and blocklist (exclude)
|
|
290
301
|
if (idType === 'number') {
|
|
291
|
-
for (const [key, value] of Object.entries(transformed))
|
|
302
|
+
for (const [key, value] of Object.entries(transformed)){
|
|
292
303
|
// Skip if not a string or already processed as a reference
|
|
293
|
-
if (typeof value !== 'string')
|
|
294
|
-
continue;
|
|
304
|
+
if (typeof value !== 'string') continue;
|
|
295
305
|
// Check if field should be converted
|
|
296
306
|
const matchesHeuristic = /(?:Id|_id)$/.test(key);
|
|
297
307
|
const inAllowlist = idFieldsAllowlistSet.has(key);
|
|
@@ -307,36 +317,34 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
307
317
|
return transformed;
|
|
308
318
|
}
|
|
309
319
|
/**
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (!where || where.length === 0)
|
|
315
|
-
return {};
|
|
320
|
+
* Convert Better Auth where clause to Payload where clause.
|
|
321
|
+
* Handles field name transformations for reference fields.
|
|
322
|
+
*/ function convertWhereToPayload(model, where) {
|
|
323
|
+
if (!where || where.length === 0) return {};
|
|
316
324
|
if (where.length === 1) {
|
|
317
325
|
const w = where[0];
|
|
318
326
|
return {
|
|
319
|
-
[getPayloadFieldName(model, w.field)]: convertOperator(w.operator, w.value)
|
|
327
|
+
[getPayloadFieldName(model, w.field)]: convertOperator(w.operator, w.value)
|
|
320
328
|
};
|
|
321
329
|
}
|
|
322
|
-
const andConditions = where.filter((w)
|
|
323
|
-
const orConditions = where.filter((w)
|
|
330
|
+
const andConditions = where.filter((w)=>w.connector !== 'OR');
|
|
331
|
+
const orConditions = where.filter((w)=>w.connector === 'OR');
|
|
324
332
|
const result = {};
|
|
325
333
|
if (andConditions.length > 0) {
|
|
326
|
-
result.and = andConditions.map((w)
|
|
327
|
-
|
|
328
|
-
|
|
334
|
+
result.and = andConditions.map((w)=>({
|
|
335
|
+
[getPayloadFieldName(model, w.field)]: convertOperator(w.operator, w.value)
|
|
336
|
+
}));
|
|
329
337
|
}
|
|
330
338
|
if (orConditions.length > 0) {
|
|
331
|
-
result.or = orConditions.map((w)
|
|
332
|
-
|
|
333
|
-
|
|
339
|
+
result.or = orConditions.map((w)=>({
|
|
340
|
+
[getPayloadFieldName(model, w.field)]: convertOperator(w.operator, w.value)
|
|
341
|
+
}));
|
|
334
342
|
}
|
|
335
343
|
return result;
|
|
336
344
|
}
|
|
337
345
|
// Get Payload collection slug from model name
|
|
338
346
|
// Uses factory's getModelName which respects BetterAuthOptions.modelName config
|
|
339
|
-
const getCollection = (model)
|
|
347
|
+
const getCollection = (model)=>{
|
|
340
348
|
return getModelName(model);
|
|
341
349
|
};
|
|
342
350
|
// The CustomAdapter interface uses generics (T) for return types.
|
|
@@ -345,12 +353,17 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
345
353
|
// when implementing generic interfaces with concrete implementations.
|
|
346
354
|
// The official Better Auth adapters do the same (visible in compiled .mjs).
|
|
347
355
|
return {
|
|
348
|
-
create: async ({ model, data })
|
|
356
|
+
create: async ({ model, data })=>{
|
|
349
357
|
const payload = await getPayload();
|
|
350
358
|
const collection = getCollection(model);
|
|
351
359
|
const payloadData = transformDataForPayload(model, data);
|
|
352
360
|
if (enableDebugLogs) {
|
|
353
|
-
debugLog('create', {
|
|
361
|
+
debugLog('create', {
|
|
362
|
+
collection,
|
|
363
|
+
model,
|
|
364
|
+
data,
|
|
365
|
+
payloadData
|
|
366
|
+
});
|
|
354
367
|
}
|
|
355
368
|
try {
|
|
356
369
|
const result = await payload.create({
|
|
@@ -358,27 +371,34 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
358
371
|
data: payloadData,
|
|
359
372
|
depth: 0,
|
|
360
373
|
// Bypass access control - Better Auth handles its own auth
|
|
361
|
-
overrideAccess: true
|
|
374
|
+
overrideAccess: true
|
|
362
375
|
});
|
|
363
376
|
// Transform back and merge with input data for Better Auth
|
|
364
377
|
// Database result takes precedence (handles hooks that modify data like firstUserAdmin)
|
|
365
378
|
const transformed = transformDataFromPayload(model, result);
|
|
366
|
-
return {
|
|
367
|
-
|
|
368
|
-
|
|
379
|
+
return {
|
|
380
|
+
...data,
|
|
381
|
+
...transformed
|
|
382
|
+
};
|
|
383
|
+
} catch (error) {
|
|
369
384
|
console.error('[payload-adapter] create failed:', {
|
|
370
385
|
collection,
|
|
371
386
|
model,
|
|
372
|
-
error: error instanceof Error ? error.message : error
|
|
387
|
+
error: error instanceof Error ? error.message : error
|
|
373
388
|
});
|
|
374
389
|
throw error;
|
|
375
390
|
}
|
|
376
391
|
},
|
|
377
|
-
findOne: async ({ model, where, select, join })
|
|
392
|
+
findOne: async ({ model, where, select, join })=>{
|
|
378
393
|
const payload = await getPayload();
|
|
379
394
|
const collection = getCollection(model);
|
|
380
395
|
if (enableDebugLogs) {
|
|
381
|
-
debugLog('findOne', {
|
|
396
|
+
debugLog('findOne', {
|
|
397
|
+
collection,
|
|
398
|
+
model,
|
|
399
|
+
where,
|
|
400
|
+
join
|
|
401
|
+
});
|
|
382
402
|
}
|
|
383
403
|
try {
|
|
384
404
|
// Optimize for single ID queries
|
|
@@ -389,14 +409,11 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
389
409
|
collection,
|
|
390
410
|
id: convertId(id),
|
|
391
411
|
depth: join ? 1 : 0,
|
|
392
|
-
overrideAccess: true
|
|
412
|
+
overrideAccess: true
|
|
393
413
|
});
|
|
394
414
|
return transformDataFromPayload(model, result);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
if (error instanceof Error &&
|
|
398
|
-
'status' in error &&
|
|
399
|
-
error.status === 404) {
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (error instanceof Error && 'status' in error && error.status === 404) {
|
|
400
417
|
return null;
|
|
401
418
|
}
|
|
402
419
|
throw error;
|
|
@@ -408,22 +425,20 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
408
425
|
where: payloadWhere,
|
|
409
426
|
limit: 1,
|
|
410
427
|
depth: join ? 1 : 0,
|
|
411
|
-
overrideAccess: true
|
|
428
|
+
overrideAccess: true
|
|
412
429
|
});
|
|
413
|
-
if (!result.docs[0])
|
|
414
|
-
return null;
|
|
430
|
+
if (!result.docs[0]) return null;
|
|
415
431
|
return transformDataFromPayload(model, result.docs[0]);
|
|
416
|
-
}
|
|
417
|
-
catch (error) {
|
|
432
|
+
} catch (error) {
|
|
418
433
|
console.error('[payload-adapter] findOne failed:', {
|
|
419
434
|
model,
|
|
420
435
|
where,
|
|
421
|
-
error
|
|
436
|
+
error
|
|
422
437
|
});
|
|
423
438
|
throw error;
|
|
424
439
|
}
|
|
425
440
|
},
|
|
426
|
-
findMany: async ({ model, where, limit, offset, sortBy, join })
|
|
441
|
+
findMany: async ({ model, where, limit, offset, sortBy, join })=>{
|
|
427
442
|
const payload = await getPayload();
|
|
428
443
|
const collection = getCollection(model);
|
|
429
444
|
if (enableDebugLogs) {
|
|
@@ -433,7 +448,7 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
433
448
|
where,
|
|
434
449
|
limit,
|
|
435
450
|
offset,
|
|
436
|
-
sortBy
|
|
451
|
+
sortBy
|
|
437
452
|
});
|
|
438
453
|
}
|
|
439
454
|
const payloadWhere = where ? convertWhereToPayload(model, where) : {};
|
|
@@ -442,20 +457,24 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
442
457
|
where: payloadWhere,
|
|
443
458
|
limit: limit ?? 100,
|
|
444
459
|
page: offset ? Math.floor(offset / (limit ?? 100)) + 1 : 1,
|
|
445
|
-
sort: sortBy
|
|
446
|
-
? `${sortBy.direction === 'desc' ? '-' : ''}${getPayloadFieldName(model, sortBy.field)}`
|
|
447
|
-
: undefined,
|
|
460
|
+
sort: sortBy ? `${sortBy.direction === 'desc' ? '-' : ''}${getPayloadFieldName(model, sortBy.field)}` : undefined,
|
|
448
461
|
depth: join ? 1 : 0,
|
|
449
|
-
overrideAccess: true
|
|
462
|
+
overrideAccess: true
|
|
450
463
|
});
|
|
451
|
-
return result.docs.map((doc)
|
|
464
|
+
return result.docs.map((doc)=>transformDataFromPayload(model, doc));
|
|
452
465
|
},
|
|
453
|
-
update: async ({ model, where, update: data })
|
|
466
|
+
update: async ({ model, where, update: data })=>{
|
|
454
467
|
const payload = await getPayload();
|
|
455
468
|
const collection = getCollection(model);
|
|
456
469
|
const payloadData = transformDataForPayload(model, data);
|
|
457
470
|
if (enableDebugLogs) {
|
|
458
|
-
debugLog('update', {
|
|
471
|
+
debugLog('update', {
|
|
472
|
+
collection,
|
|
473
|
+
model,
|
|
474
|
+
where,
|
|
475
|
+
data,
|
|
476
|
+
payloadData
|
|
477
|
+
});
|
|
459
478
|
}
|
|
460
479
|
// Optimize for single ID queries
|
|
461
480
|
const id = extractSingleId(where);
|
|
@@ -465,10 +484,13 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
465
484
|
id: convertId(id),
|
|
466
485
|
data: payloadData,
|
|
467
486
|
depth: 0,
|
|
468
|
-
overrideAccess: true
|
|
487
|
+
overrideAccess: true
|
|
469
488
|
});
|
|
470
489
|
const transformed = transformDataFromPayload(model, result);
|
|
471
|
-
return {
|
|
490
|
+
return {
|
|
491
|
+
...data,
|
|
492
|
+
...transformed
|
|
493
|
+
};
|
|
472
494
|
}
|
|
473
495
|
const payloadWhere = convertWhereToPayload(model, where);
|
|
474
496
|
const result = await payload.update({
|
|
@@ -476,19 +498,27 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
476
498
|
where: payloadWhere,
|
|
477
499
|
data: payloadData,
|
|
478
500
|
depth: 0,
|
|
479
|
-
overrideAccess: true
|
|
501
|
+
overrideAccess: true
|
|
480
502
|
});
|
|
481
|
-
if (!result.docs[0])
|
|
482
|
-
return null;
|
|
503
|
+
if (!result.docs[0]) return null;
|
|
483
504
|
const transformed = transformDataFromPayload(model, result.docs[0]);
|
|
484
|
-
return {
|
|
505
|
+
return {
|
|
506
|
+
...data,
|
|
507
|
+
...transformed
|
|
508
|
+
};
|
|
485
509
|
},
|
|
486
|
-
updateMany: async ({ model, where, update: data })
|
|
510
|
+
updateMany: async ({ model, where, update: data })=>{
|
|
487
511
|
const payload = await getPayload();
|
|
488
512
|
const collection = getCollection(model);
|
|
489
513
|
const payloadData = transformDataForPayload(model, data);
|
|
490
514
|
if (enableDebugLogs) {
|
|
491
|
-
debugLog('updateMany', {
|
|
515
|
+
debugLog('updateMany', {
|
|
516
|
+
collection,
|
|
517
|
+
model,
|
|
518
|
+
where,
|
|
519
|
+
data,
|
|
520
|
+
payloadData
|
|
521
|
+
});
|
|
492
522
|
}
|
|
493
523
|
const payloadWhere = convertWhereToPayload(model, where);
|
|
494
524
|
const result = await payload.update({
|
|
@@ -496,15 +526,19 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
496
526
|
where: payloadWhere,
|
|
497
527
|
data: payloadData,
|
|
498
528
|
depth: 0,
|
|
499
|
-
overrideAccess: true
|
|
529
|
+
overrideAccess: true
|
|
500
530
|
});
|
|
501
531
|
return result.docs.length;
|
|
502
532
|
},
|
|
503
|
-
delete: async ({ model, where })
|
|
533
|
+
delete: async ({ model, where })=>{
|
|
504
534
|
const payload = await getPayload();
|
|
505
535
|
const collection = getCollection(model);
|
|
506
536
|
if (enableDebugLogs) {
|
|
507
|
-
debugLog('delete', {
|
|
537
|
+
debugLog('delete', {
|
|
538
|
+
collection,
|
|
539
|
+
model,
|
|
540
|
+
where
|
|
541
|
+
});
|
|
508
542
|
}
|
|
509
543
|
// Optimize for single ID queries
|
|
510
544
|
const id = extractSingleId(where);
|
|
@@ -512,45 +546,58 @@ export function payloadAdapter({ payloadClient, adapterConfig = {}, }) {
|
|
|
512
546
|
await payload.delete({
|
|
513
547
|
collection,
|
|
514
548
|
id: convertId(id),
|
|
515
|
-
overrideAccess: true
|
|
549
|
+
overrideAccess: true
|
|
516
550
|
});
|
|
517
551
|
return;
|
|
518
552
|
}
|
|
519
553
|
const payloadWhere = convertWhereToPayload(model, where);
|
|
520
|
-
await payload.delete({
|
|
554
|
+
await payload.delete({
|
|
555
|
+
collection,
|
|
556
|
+
where: payloadWhere,
|
|
557
|
+
overrideAccess: true
|
|
558
|
+
});
|
|
521
559
|
},
|
|
522
|
-
deleteMany: async ({ model, where })
|
|
560
|
+
deleteMany: async ({ model, where })=>{
|
|
523
561
|
const payload = await getPayload();
|
|
524
562
|
const collection = getCollection(model);
|
|
525
563
|
if (enableDebugLogs) {
|
|
526
|
-
debugLog('deleteMany', {
|
|
564
|
+
debugLog('deleteMany', {
|
|
565
|
+
collection,
|
|
566
|
+
model,
|
|
567
|
+
where
|
|
568
|
+
});
|
|
527
569
|
}
|
|
528
570
|
const payloadWhere = convertWhereToPayload(model, where);
|
|
529
571
|
const result = await payload.delete({
|
|
530
572
|
collection,
|
|
531
573
|
where: payloadWhere,
|
|
532
|
-
overrideAccess: true
|
|
574
|
+
overrideAccess: true
|
|
533
575
|
});
|
|
534
576
|
return result.docs.length;
|
|
535
577
|
},
|
|
536
|
-
count: async ({ model, where })
|
|
578
|
+
count: async ({ model, where })=>{
|
|
537
579
|
const payload = await getPayload();
|
|
538
580
|
const collection = getCollection(model);
|
|
539
581
|
if (enableDebugLogs) {
|
|
540
|
-
debugLog('count', {
|
|
582
|
+
debugLog('count', {
|
|
583
|
+
collection,
|
|
584
|
+
model,
|
|
585
|
+
where
|
|
586
|
+
});
|
|
541
587
|
}
|
|
542
588
|
const payloadWhere = where ? convertWhereToPayload(model, where) : {};
|
|
543
589
|
const result = await payload.count({
|
|
544
590
|
collection,
|
|
545
591
|
where: payloadWhere,
|
|
546
|
-
overrideAccess: true
|
|
592
|
+
overrideAccess: true
|
|
547
593
|
});
|
|
548
594
|
return result.totalDocs;
|
|
549
|
-
}
|
|
595
|
+
}
|
|
550
596
|
};
|
|
551
|
-
}
|
|
597
|
+
}
|
|
552
598
|
});
|
|
553
599
|
return adapterFactory(options);
|
|
554
600
|
};
|
|
555
601
|
}
|
|
602
|
+
|
|
556
603
|
//# sourceMappingURL=index.js.map
|