better-auth 1.6.9 → 1.6.11
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/dist/api/index.d.mts +0 -2
- package/dist/api/routes/callback.mjs +6 -5
- package/dist/api/routes/email-verification.mjs +2 -2
- package/dist/api/routes/error.mjs +1 -1
- package/dist/api/routes/sign-in.d.mts +0 -1
- package/dist/api/routes/sign-in.mjs +4 -11
- package/dist/api/routes/sign-up.mjs +1 -1
- package/dist/api/routes/update-user.mjs +1 -1
- package/dist/api/to-auth-endpoints.mjs +7 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/plugins/index.d.mts +2 -1
- package/dist/cookies/cookie-utils.d.mts +10 -1
- package/dist/cookies/cookie-utils.mjs +19 -1
- package/dist/cookies/index.d.mts +2 -2
- package/dist/cookies/index.mjs +2 -2
- package/dist/db/internal-adapter.mjs +103 -7
- package/dist/db/with-hooks.d.mts +1 -0
- package/dist/db/with-hooks.mjs +58 -1
- package/dist/integrations/cookie-plugin-guard.mjs +18 -0
- package/dist/integrations/next-js.mjs +6 -0
- package/dist/integrations/svelte-kit.mjs +6 -0
- package/dist/integrations/tanstack-start-solid.mjs +6 -0
- package/dist/integrations/tanstack-start.mjs +6 -0
- package/dist/oauth2/link-account.mjs +3 -1
- package/dist/package.mjs +1 -1
- package/dist/plugins/access/access.d.mts +3 -15
- package/dist/plugins/access/index.d.mts +2 -2
- package/dist/plugins/access/types.d.mts +11 -4
- package/dist/plugins/admin/access/statement.d.mts +29 -93
- package/dist/plugins/admin/client.d.mts +5 -0
- package/dist/plugins/admin/client.mjs +5 -0
- package/dist/plugins/admin/routes.mjs +1 -0
- package/dist/plugins/anonymous/client.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.mjs +1 -0
- package/dist/plugins/anonymous/index.d.mts +1 -0
- package/dist/plugins/anonymous/index.mjs +16 -2
- package/dist/plugins/bearer/index.mjs +2 -4
- package/dist/plugins/captcha/index.mjs +14 -1
- package/dist/plugins/device-authorization/error-codes.mjs +1 -0
- package/dist/plugins/device-authorization/index.d.mts +1 -0
- package/dist/plugins/device-authorization/routes.mjs +34 -3
- package/dist/plugins/email-otp/routes.mjs +3 -3
- package/dist/plugins/generic-oauth/routes.mjs +3 -3
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/magic-link/index.d.mts +8 -1
- package/dist/plugins/magic-link/index.mjs +5 -17
- package/dist/plugins/mcp/authorize.mjs +8 -2
- package/dist/plugins/mcp/index.mjs +73 -30
- package/dist/plugins/oidc-provider/authorize.mjs +8 -2
- package/dist/plugins/oidc-provider/index.mjs +63 -33
- package/dist/plugins/one-tap/index.mjs +16 -10
- package/dist/plugins/organization/access/statement.d.mts +68 -201
- package/dist/plugins/organization/client.d.mts +1 -0
- package/dist/plugins/organization/client.mjs +1 -1
- package/dist/plugins/organization/error-codes.d.mts +1 -0
- package/dist/plugins/organization/error-codes.mjs +1 -0
- package/dist/plugins/organization/routes/crud-access-control.d.mts +2 -2
- package/dist/plugins/organization/routes/crud-invites.d.mts +8 -1
- package/dist/plugins/organization/routes/crud-invites.mjs +5 -3
- package/dist/plugins/organization/routes/crud-team.mjs +7 -2
- package/dist/plugins/organization/types.d.mts +12 -2
- package/dist/plugins/siwe/client.d.mts +4 -0
- package/dist/plugins/siwe/client.mjs +5 -1
- package/dist/plugins/siwe/index.d.mts +13 -2
- package/dist/plugins/siwe/index.mjs +179 -165
- package/dist/plugins/username/index.d.mts +11 -0
- package/dist/plugins/username/index.mjs +18 -2
- package/dist/test-utils/test-instance.d.mts +1 -6
- package/dist/test-utils/test-instance.mjs +11 -2
- package/package.json +10 -10
|
@@ -9,195 +9,209 @@ import { schema } from "./schema.mjs";
|
|
|
9
9
|
import { createAuthEndpoint } from "@better-auth/core/api";
|
|
10
10
|
import * as z from "zod";
|
|
11
11
|
//#region src/plugins/siwe/index.ts
|
|
12
|
+
const walletAddressInputSchema = z.string().regex(/^0[xX][a-fA-F0-9]{40}$/i).length(42);
|
|
12
13
|
const getSiweNonceBodySchema = z.object({
|
|
13
|
-
walletAddress:
|
|
14
|
+
walletAddress: walletAddressInputSchema.optional(),
|
|
15
|
+
address: walletAddressInputSchema.optional(),
|
|
14
16
|
chainId: z.number().int().positive().optional().default(1)
|
|
17
|
+
}).refine((body) => body.walletAddress || body.address, {
|
|
18
|
+
message: "walletAddress or address is required",
|
|
19
|
+
path: ["walletAddress"]
|
|
15
20
|
});
|
|
16
|
-
const siwe = (options) =>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
21
|
+
const siwe = (options) => {
|
|
22
|
+
const createSiweNonceEndpoint = (path) => createAuthEndpoint(path, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
body: getSiweNonceBodySchema
|
|
25
|
+
}, async (ctx) => {
|
|
26
|
+
const rawWalletAddress = ctx.body.walletAddress ?? ctx.body.address;
|
|
27
|
+
if (!rawWalletAddress) throw APIError.fromStatus("BAD_REQUEST", {
|
|
28
|
+
message: "walletAddress or address is required",
|
|
29
|
+
status: 400
|
|
30
|
+
});
|
|
31
|
+
const { chainId } = ctx.body;
|
|
32
|
+
const walletAddress = toChecksumAddress(rawWalletAddress);
|
|
33
|
+
const nonce = await options.getNonce();
|
|
34
|
+
await ctx.context.internalAdapter.createVerificationValue({
|
|
35
|
+
identifier: `siwe:${walletAddress}:${chainId}`,
|
|
36
|
+
value: nonce,
|
|
37
|
+
expiresAt: new Date(Date.now() + 900 * 1e3)
|
|
38
|
+
});
|
|
39
|
+
return ctx.json({ nonce });
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
id: "siwe",
|
|
43
|
+
version: PACKAGE_VERSION,
|
|
44
|
+
schema: mergeSchema(schema, options?.schema),
|
|
45
|
+
endpoints: {
|
|
46
|
+
getSiweNonce: createSiweNonceEndpoint("/siwe/nonce"),
|
|
47
|
+
getNonce: createSiweNonceEndpoint("/siwe/get-nonce"),
|
|
48
|
+
verifySiweMessage: createAuthEndpoint("/siwe/verify", {
|
|
49
|
+
method: "POST",
|
|
50
|
+
body: z.object({
|
|
51
|
+
message: z.string().min(1),
|
|
52
|
+
signature: z.string().min(1),
|
|
53
|
+
walletAddress: z.string().regex(/^0[xX][a-fA-F0-9]{40}$/i).length(42),
|
|
54
|
+
chainId: z.number().int().positive().optional().default(1),
|
|
55
|
+
email: z.email().optional()
|
|
56
|
+
}).refine((data) => options.anonymous !== false || !!data.email, {
|
|
57
|
+
message: "Email is required when the anonymous plugin option is disabled.",
|
|
58
|
+
path: ["email"]
|
|
59
|
+
}),
|
|
60
|
+
requireRequest: true
|
|
61
|
+
}, async (ctx) => {
|
|
62
|
+
const { message, signature, walletAddress: rawWalletAddress, chainId, email } = ctx.body;
|
|
63
|
+
const walletAddress = toChecksumAddress(rawWalletAddress);
|
|
64
|
+
const isAnon = options.anonymous ?? true;
|
|
65
|
+
if (!isAnon && !email) throw APIError.fromStatus("BAD_REQUEST", {
|
|
66
|
+
message: "Email is required when anonymous is disabled.",
|
|
67
|
+
status: 400
|
|
62
68
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
try {
|
|
70
|
+
const verification = await ctx.context.internalAdapter.findVerificationValue(`siwe:${walletAddress}:${chainId}`);
|
|
71
|
+
if (!verification || /* @__PURE__ */ new Date() > verification.expiresAt) throw APIError.fromStatus("UNAUTHORIZED", {
|
|
72
|
+
message: "Unauthorized: Invalid or expired nonce",
|
|
73
|
+
status: 401,
|
|
74
|
+
code: "UNAUTHORIZED_INVALID_OR_EXPIRED_NONCE"
|
|
75
|
+
});
|
|
76
|
+
const { value: nonce } = verification;
|
|
77
|
+
if (!await options.verifyMessage({
|
|
78
|
+
message,
|
|
79
|
+
signature,
|
|
80
|
+
address: walletAddress,
|
|
81
|
+
chainId,
|
|
82
|
+
cacao: {
|
|
83
|
+
h: { t: "caip122" },
|
|
84
|
+
p: {
|
|
85
|
+
domain: options.domain,
|
|
86
|
+
aud: options.domain,
|
|
87
|
+
nonce,
|
|
88
|
+
iss: options.domain,
|
|
89
|
+
version: "1"
|
|
90
|
+
},
|
|
91
|
+
s: {
|
|
92
|
+
t: "eip191",
|
|
93
|
+
s: signature
|
|
94
|
+
}
|
|
81
95
|
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const existingWalletAddress = await ctx.context.adapter.findOne({
|
|
90
|
-
model: "walletAddress",
|
|
91
|
-
where: [{
|
|
92
|
-
field: "address",
|
|
93
|
-
operator: "eq",
|
|
94
|
-
value: walletAddress
|
|
95
|
-
}, {
|
|
96
|
-
field: "chainId",
|
|
97
|
-
operator: "eq",
|
|
98
|
-
value: chainId
|
|
99
|
-
}]
|
|
100
|
-
});
|
|
101
|
-
if (existingWalletAddress) user = await ctx.context.adapter.findOne({
|
|
102
|
-
model: "user",
|
|
103
|
-
where: [{
|
|
104
|
-
field: "id",
|
|
105
|
-
operator: "eq",
|
|
106
|
-
value: existingWalletAddress.userId
|
|
107
|
-
}]
|
|
108
|
-
});
|
|
109
|
-
else {
|
|
110
|
-
const anyWalletAddress = await ctx.context.adapter.findOne({
|
|
96
|
+
})) throw APIError.fromStatus("UNAUTHORIZED", {
|
|
97
|
+
message: "Unauthorized: Invalid SIWE signature",
|
|
98
|
+
status: 401
|
|
99
|
+
});
|
|
100
|
+
await ctx.context.internalAdapter.deleteVerificationByIdentifier(`siwe:${walletAddress}:${chainId}`);
|
|
101
|
+
let user = null;
|
|
102
|
+
const existingWalletAddress = await ctx.context.adapter.findOne({
|
|
111
103
|
model: "walletAddress",
|
|
112
104
|
where: [{
|
|
113
105
|
field: "address",
|
|
114
106
|
operator: "eq",
|
|
115
107
|
value: walletAddress
|
|
108
|
+
}, {
|
|
109
|
+
field: "chainId",
|
|
110
|
+
operator: "eq",
|
|
111
|
+
value: chainId
|
|
116
112
|
}]
|
|
117
113
|
});
|
|
118
|
-
if (
|
|
114
|
+
if (existingWalletAddress) user = await ctx.context.adapter.findOne({
|
|
119
115
|
model: "user",
|
|
120
116
|
where: [{
|
|
121
117
|
field: "id",
|
|
122
118
|
operator: "eq",
|
|
123
|
-
value:
|
|
119
|
+
value: existingWalletAddress.userId
|
|
124
120
|
}]
|
|
125
121
|
});
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
122
|
+
else {
|
|
123
|
+
const anyWalletAddress = await ctx.context.adapter.findOne({
|
|
124
|
+
model: "walletAddress",
|
|
125
|
+
where: [{
|
|
126
|
+
field: "address",
|
|
127
|
+
operator: "eq",
|
|
128
|
+
value: walletAddress
|
|
129
|
+
}]
|
|
130
|
+
});
|
|
131
|
+
if (anyWalletAddress) user = await ctx.context.adapter.findOne({
|
|
132
|
+
model: "user",
|
|
133
|
+
where: [{
|
|
134
|
+
field: "id",
|
|
135
|
+
operator: "eq",
|
|
136
|
+
value: anyWalletAddress.userId
|
|
137
|
+
}]
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (!user) {
|
|
141
|
+
const domain = options.emailDomainName ?? getOrigin(ctx.context.baseURL);
|
|
142
|
+
const userEmail = !isAnon && email ? email : `${walletAddress}@${domain}`;
|
|
143
|
+
const { name, avatar } = await options.ensLookup?.({ walletAddress }) ?? {};
|
|
144
|
+
user = await ctx.context.internalAdapter.createUser({
|
|
145
|
+
name: name ?? walletAddress,
|
|
146
|
+
email: userEmail,
|
|
147
|
+
image: avatar ?? ""
|
|
148
|
+
});
|
|
149
|
+
await ctx.context.adapter.create({
|
|
150
|
+
model: "walletAddress",
|
|
151
|
+
data: {
|
|
152
|
+
userId: user.id,
|
|
153
|
+
address: walletAddress,
|
|
154
|
+
chainId,
|
|
155
|
+
isPrimary: true,
|
|
156
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
await ctx.context.internalAdapter.createAccount({
|
|
139
160
|
userId: user.id,
|
|
140
|
-
|
|
141
|
-
chainId
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
161
|
+
providerId: "siwe",
|
|
162
|
+
accountId: `${walletAddress}:${chainId}`,
|
|
163
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
164
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
165
|
+
});
|
|
166
|
+
} else if (!existingWalletAddress) {
|
|
167
|
+
await ctx.context.adapter.create({
|
|
168
|
+
model: "walletAddress",
|
|
169
|
+
data: {
|
|
170
|
+
userId: user.id,
|
|
171
|
+
address: walletAddress,
|
|
172
|
+
chainId,
|
|
173
|
+
isPrimary: false,
|
|
174
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
await ctx.context.internalAdapter.createAccount({
|
|
178
|
+
userId: user.id,
|
|
179
|
+
providerId: "siwe",
|
|
180
|
+
accountId: `${walletAddress}:${chainId}`,
|
|
181
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
182
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const session = await ctx.context.internalAdapter.createSession(user.id);
|
|
186
|
+
if (!session) throw APIError.fromStatus("INTERNAL_SERVER_ERROR", {
|
|
187
|
+
message: "Internal Server Error",
|
|
188
|
+
status: 500
|
|
145
189
|
});
|
|
146
|
-
await ctx
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
accountId: `${walletAddress}:${chainId}`,
|
|
150
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
151
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
190
|
+
await setSessionCookie(ctx, {
|
|
191
|
+
session,
|
|
192
|
+
user
|
|
152
193
|
});
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
chainId
|
|
160
|
-
isPrimary: false,
|
|
161
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
194
|
+
return ctx.json({
|
|
195
|
+
token: session.token,
|
|
196
|
+
success: true,
|
|
197
|
+
user: {
|
|
198
|
+
id: user.id,
|
|
199
|
+
walletAddress,
|
|
200
|
+
chainId
|
|
162
201
|
}
|
|
163
202
|
});
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (isAPIError(error)) throw error;
|
|
205
|
+
throw APIError.fromStatus("UNAUTHORIZED", {
|
|
206
|
+
message: "Something went wrong. Please try again later.",
|
|
207
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
208
|
+
status: 401
|
|
170
209
|
});
|
|
171
210
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
await setSessionCookie(ctx, {
|
|
178
|
-
session,
|
|
179
|
-
user
|
|
180
|
-
});
|
|
181
|
-
return ctx.json({
|
|
182
|
-
token: session.token,
|
|
183
|
-
success: true,
|
|
184
|
-
user: {
|
|
185
|
-
id: user.id,
|
|
186
|
-
walletAddress,
|
|
187
|
-
chainId
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
} catch (error) {
|
|
191
|
-
if (isAPIError(error)) throw error;
|
|
192
|
-
throw APIError.fromStatus("UNAUTHORIZED", {
|
|
193
|
-
message: "Something went wrong. Please try again later.",
|
|
194
|
-
error: error instanceof Error ? error.message : "Unknown error",
|
|
195
|
-
status: 401
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
})
|
|
199
|
-
},
|
|
200
|
-
options
|
|
201
|
-
});
|
|
211
|
+
})
|
|
212
|
+
},
|
|
213
|
+
options
|
|
214
|
+
};
|
|
215
|
+
};
|
|
202
216
|
//#endregion
|
|
203
217
|
export { siwe };
|
|
@@ -151,10 +151,19 @@ declare const username: (options?: UsernameOptions | undefined) => {
|
|
|
151
151
|
schema: {
|
|
152
152
|
type: "object";
|
|
153
153
|
properties: {
|
|
154
|
+
redirect: {
|
|
155
|
+
type: string;
|
|
156
|
+
description: string;
|
|
157
|
+
};
|
|
154
158
|
token: {
|
|
155
159
|
type: string;
|
|
156
160
|
description: string;
|
|
157
161
|
};
|
|
162
|
+
url: {
|
|
163
|
+
type: string;
|
|
164
|
+
nullable: boolean;
|
|
165
|
+
description: string;
|
|
166
|
+
};
|
|
158
167
|
user: {
|
|
159
168
|
$ref: string;
|
|
160
169
|
};
|
|
@@ -183,7 +192,9 @@ declare const username: (options?: UsernameOptions | undefined) => {
|
|
|
183
192
|
};
|
|
184
193
|
};
|
|
185
194
|
}, {
|
|
195
|
+
redirect: boolean;
|
|
186
196
|
token: string;
|
|
197
|
+
url: string | undefined;
|
|
187
198
|
user: {
|
|
188
199
|
id: string;
|
|
189
200
|
createdAt: Date;
|
|
@@ -16,7 +16,7 @@ const signInUsernameBodySchema = z.object({
|
|
|
16
16
|
username: z.string().meta({ description: "The username of the user" }),
|
|
17
17
|
password: z.string().meta({ description: "The password of the user" }),
|
|
18
18
|
rememberMe: z.boolean().meta({ description: "Remember the user session" }).optional(),
|
|
19
|
-
callbackURL: z.string().meta({ description: "
|
|
19
|
+
callbackURL: z.string().meta({ description: "URL to redirect to after sign in (also used as the redirect target for email verification when required)" }).optional()
|
|
20
20
|
});
|
|
21
21
|
const isUsernameAvailableBodySchema = z.object({ username: z.string().meta({ description: "The username to check" }) });
|
|
22
22
|
const username = (options) => {
|
|
@@ -66,13 +66,26 @@ const username = (options) => {
|
|
|
66
66
|
content: { "application/json": { schema: {
|
|
67
67
|
type: "object",
|
|
68
68
|
properties: {
|
|
69
|
+
redirect: {
|
|
70
|
+
type: "boolean",
|
|
71
|
+
description: "Whether the client should follow the Location header. True when callbackURL was provided."
|
|
72
|
+
},
|
|
69
73
|
token: {
|
|
70
74
|
type: "string",
|
|
71
75
|
description: "Session token for the authenticated session"
|
|
72
76
|
},
|
|
77
|
+
url: {
|
|
78
|
+
type: "string",
|
|
79
|
+
nullable: true,
|
|
80
|
+
description: "The callbackURL echoed back so the client can redirect."
|
|
81
|
+
},
|
|
73
82
|
user: { $ref: "#/components/schemas/User" }
|
|
74
83
|
},
|
|
75
|
-
required: [
|
|
84
|
+
required: [
|
|
85
|
+
"redirect",
|
|
86
|
+
"token",
|
|
87
|
+
"user"
|
|
88
|
+
]
|
|
76
89
|
} } }
|
|
77
90
|
},
|
|
78
91
|
422: {
|
|
@@ -155,8 +168,11 @@ const username = (options) => {
|
|
|
155
168
|
session,
|
|
156
169
|
user
|
|
157
170
|
}, ctx.body.rememberMe === false);
|
|
171
|
+
if (ctx.body.callbackURL) ctx.setHeader("Location", ctx.body.callbackURL);
|
|
158
172
|
return ctx.json({
|
|
173
|
+
redirect: !!ctx.body.callbackURL,
|
|
159
174
|
token: session.token,
|
|
175
|
+
url: ctx.body.callbackURL,
|
|
160
176
|
user: parseUserOutput(ctx.context.options, user)
|
|
161
177
|
});
|
|
162
178
|
}),
|
|
@@ -190,7 +190,6 @@ declare function getTestInstance<O extends Partial<BetterAuthOptions>, C extends
|
|
|
190
190
|
};
|
|
191
191
|
redirect: {
|
|
192
192
|
type: string;
|
|
193
|
-
enum: boolean[];
|
|
194
193
|
};
|
|
195
194
|
};
|
|
196
195
|
required: string[];
|
|
@@ -2193,7 +2192,6 @@ declare function getTestInstance<O extends Partial<BetterAuthOptions>, C extends
|
|
|
2193
2192
|
};
|
|
2194
2193
|
redirect: {
|
|
2195
2194
|
type: string;
|
|
2196
|
-
enum: boolean[];
|
|
2197
2195
|
};
|
|
2198
2196
|
};
|
|
2199
2197
|
required: string[];
|
|
@@ -4199,7 +4197,6 @@ declare function getTestInstance<O extends Partial<BetterAuthOptions>, C extends
|
|
|
4199
4197
|
};
|
|
4200
4198
|
redirect: {
|
|
4201
4199
|
type: string;
|
|
4202
|
-
enum: boolean[];
|
|
4203
4200
|
};
|
|
4204
4201
|
};
|
|
4205
4202
|
required: string[];
|
|
@@ -6202,7 +6199,6 @@ declare function getTestInstance<O extends Partial<BetterAuthOptions>, C extends
|
|
|
6202
6199
|
};
|
|
6203
6200
|
redirect: {
|
|
6204
6201
|
type: string;
|
|
6205
|
-
enum: boolean[];
|
|
6206
6202
|
};
|
|
6207
6203
|
};
|
|
6208
6204
|
required: string[];
|
|
@@ -8279,7 +8275,6 @@ declare function getTestInstance<O extends Partial<BetterAuthOptions>, C extends
|
|
|
8279
8275
|
};
|
|
8280
8276
|
redirect: {
|
|
8281
8277
|
type: string;
|
|
8282
|
-
enum: boolean[];
|
|
8283
8278
|
};
|
|
8284
8279
|
};
|
|
8285
8280
|
required: string[];
|
|
@@ -10282,7 +10277,6 @@ declare function getTestInstance<O extends Partial<BetterAuthOptions>, C extends
|
|
|
10282
10277
|
};
|
|
10283
10278
|
redirect: {
|
|
10284
10279
|
type: string;
|
|
10285
|
-
enum: boolean[];
|
|
10286
10280
|
};
|
|
10287
10281
|
};
|
|
10288
10282
|
required: string[];
|
|
@@ -12157,6 +12151,7 @@ declare function getTestInstance<O extends Partial<BetterAuthOptions>, C extends
|
|
|
12157
12151
|
USER_ALREADY_EXISTS: _better_auth_core_utils_error_codes0.RawError<"USER_ALREADY_EXISTS">;
|
|
12158
12152
|
USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL: _better_auth_core_utils_error_codes0.RawError<"USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL">;
|
|
12159
12153
|
EMAIL_CAN_NOT_BE_UPDATED: _better_auth_core_utils_error_codes0.RawError<"EMAIL_CAN_NOT_BE_UPDATED">;
|
|
12154
|
+
CHANGE_EMAIL_DISABLED: _better_auth_core_utils_error_codes0.RawError<"CHANGE_EMAIL_DISABLED">;
|
|
12160
12155
|
CREDENTIAL_ACCOUNT_NOT_FOUND: _better_auth_core_utils_error_codes0.RawError<"CREDENTIAL_ACCOUNT_NOT_FOUND">;
|
|
12161
12156
|
ACCOUNT_NOT_FOUND: _better_auth_core_utils_error_codes0.RawError<"ACCOUNT_NOT_FOUND">;
|
|
12162
12157
|
SESSION_EXPIRED: _better_auth_core_utils_error_codes0.RawError<"SESSION_EXPIRED">;
|
|
@@ -7,6 +7,7 @@ import { createAuthClient } from "../client/vanilla.mjs";
|
|
|
7
7
|
import { bearer } from "../plugins/bearer/index.mjs";
|
|
8
8
|
import { sql } from "kysely";
|
|
9
9
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10
|
+
import { randomUUID } from "node:crypto";
|
|
10
11
|
import { afterAll } from "vitest";
|
|
11
12
|
//#region src/test-utils/test-instance.ts
|
|
12
13
|
const cleanupSet = /* @__PURE__ */ new Set();
|
|
@@ -19,10 +20,17 @@ afterAll(async () => {
|
|
|
19
20
|
});
|
|
20
21
|
async function getTestInstance(options, config) {
|
|
21
22
|
const testWith = config?.testWith || "sqlite";
|
|
23
|
+
const postgresSchema = testWith === "postgres" ? `ba_test_${randomUUID().replaceAll("-", "_")}` : void 0;
|
|
24
|
+
const quotePostgresIdentifier = (identifier) => `"${identifier.replaceAll("\"", "\"\"")}"`;
|
|
22
25
|
async function getPostgres() {
|
|
23
26
|
const { Kysely, PostgresDialect } = await import("kysely");
|
|
24
27
|
const { Pool } = await import("pg");
|
|
25
|
-
|
|
28
|
+
const pool = new Pool({
|
|
29
|
+
connectionString: "postgres://user:password@localhost:5432/better_auth",
|
|
30
|
+
options: postgresSchema ? `-c search_path=${postgresSchema},public` : void 0
|
|
31
|
+
});
|
|
32
|
+
if (postgresSchema) await pool.query(`CREATE SCHEMA IF NOT EXISTS ${quotePostgresIdentifier(postgresSchema)}`);
|
|
33
|
+
return new Kysely({ dialect: new PostgresDialect({ pool }) });
|
|
26
34
|
}
|
|
27
35
|
async function getSqlite() {
|
|
28
36
|
const { DatabaseSync } = await import("node:sqlite");
|
|
@@ -103,7 +111,8 @@ async function getTestInstance(options, config) {
|
|
|
103
111
|
}
|
|
104
112
|
if (testWith === "postgres") {
|
|
105
113
|
const postgres = await getPostgres();
|
|
106
|
-
await sql`DROP SCHEMA
|
|
114
|
+
if (postgresSchema) await sql.raw(`DROP SCHEMA IF EXISTS ${quotePostgresIdentifier(postgresSchema)} CASCADE`).execute(postgres);
|
|
115
|
+
else await sql`DROP SCHEMA public CASCADE; CREATE SCHEMA public;`.execute(postgres);
|
|
107
116
|
await postgres.destroy();
|
|
108
117
|
return;
|
|
109
118
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-auth",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.11",
|
|
4
4
|
"description": "The most comprehensive authentication framework for TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -486,16 +486,16 @@
|
|
|
486
486
|
"better-call": "1.3.5",
|
|
487
487
|
"defu": "^6.1.4",
|
|
488
488
|
"jose": "^6.1.3",
|
|
489
|
-
"kysely": "^0.28.
|
|
489
|
+
"kysely": "^0.28.17",
|
|
490
490
|
"nanostores": "^1.1.1",
|
|
491
491
|
"zod": "^4.3.6",
|
|
492
|
-
"@better-auth/core": "1.6.
|
|
493
|
-
"@better-auth/drizzle-adapter": "1.6.
|
|
494
|
-
"@better-auth/kysely-adapter": "1.6.
|
|
495
|
-
"@better-auth/memory-adapter": "1.6.
|
|
496
|
-
"@better-auth/mongo-adapter": "1.6.
|
|
497
|
-
"@better-auth/prisma-adapter": "1.6.
|
|
498
|
-
"@better-auth/telemetry": "1.6.
|
|
492
|
+
"@better-auth/core": "1.6.11",
|
|
493
|
+
"@better-auth/drizzle-adapter": "1.6.11",
|
|
494
|
+
"@better-auth/kysely-adapter": "1.6.11",
|
|
495
|
+
"@better-auth/memory-adapter": "1.6.11",
|
|
496
|
+
"@better-auth/mongo-adapter": "1.6.11",
|
|
497
|
+
"@better-auth/prisma-adapter": "1.6.11",
|
|
498
|
+
"@better-auth/telemetry": "1.6.11"
|
|
499
499
|
},
|
|
500
500
|
"devDependencies": {
|
|
501
501
|
"@lynx-js/react": "^0.116.3",
|
|
@@ -520,7 +520,7 @@
|
|
|
520
520
|
"tsdown": "0.21.1",
|
|
521
521
|
"type-fest": "^5.4.4",
|
|
522
522
|
"typescript": "^5.9.3",
|
|
523
|
-
"vitest": "^4.
|
|
523
|
+
"vitest": "^4.1.5",
|
|
524
524
|
"vue": "^3.5.29"
|
|
525
525
|
},
|
|
526
526
|
"peerDependencies": {
|