@better-auth/core 1.5.0-beta.6 → 1.5.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +26 -22
- package/dist/api/index.d.mts +10 -20
- package/dist/context/endpoint-context.mjs +6 -6
- package/dist/context/global.d.mts +7 -0
- package/dist/context/global.mjs +37 -0
- package/dist/context/index.d.mts +2 -1
- package/dist/context/index.mjs +2 -1
- package/dist/context/request-state.mjs +6 -6
- package/dist/context/transaction.d.mts +1 -1
- package/dist/context/transaction.mjs +6 -6
- package/dist/db/adapter/factory.mjs +13 -13
- package/dist/db/adapter/get-default-model-name.mjs +1 -1
- package/dist/db/adapter/get-id-field.d.mts +1 -1
- package/dist/db/adapter/get-id-field.mjs +2 -2
- package/dist/error/index.d.mts +3 -1
- package/dist/error/index.mjs +2 -3
- package/dist/index.d.mts +4 -4
- package/dist/social-providers/apple.mjs +3 -1
- package/dist/social-providers/gitlab.mjs +1 -1
- package/dist/types/context.d.mts +17 -16
- package/dist/types/cookie.d.mts +9 -17
- package/dist/types/index.d.mts +3 -3
- package/dist/types/init-options.d.mts +17 -29
- package/dist/utils/url.d.mts +20 -0
- package/dist/utils/url.mjs +32 -0
- package/package.json +1 -1
- package/src/context/endpoint-context.ts +7 -15
- package/src/context/global.ts +57 -0
- package/src/context/index.ts +1 -0
- package/src/context/request-state.ts +7 -12
- package/src/context/transaction.ts +7 -16
- package/src/db/adapter/factory.ts +13 -13
- package/src/db/adapter/get-default-model-name.ts +1 -1
- package/src/db/adapter/get-id-field.ts +2 -2
- package/src/error/index.ts +2 -3
- package/src/social-providers/apple.ts +12 -3
- package/src/social-providers/gitlab.ts +1 -1
- package/src/types/context.ts +137 -131
- package/src/types/cookie.ts +6 -4
- package/src/types/index.ts +4 -1
- package/src/types/init-options.ts +26 -32
- package/src/utils/url.ts +43 -0
- package/tsdown.config.ts +8 -0
package/dist/types/context.d.mts
CHANGED
|
@@ -9,7 +9,7 @@ import { DBAdapter, Where } from "../db/adapter/index.mjs";
|
|
|
9
9
|
import { createLogger } from "../env/logger.mjs";
|
|
10
10
|
import { OAuthProvider } from "../oauth2/oauth-provider.mjs";
|
|
11
11
|
import "../oauth2/index.mjs";
|
|
12
|
-
import { BetterAuthCookies } from "./cookie.mjs";
|
|
12
|
+
import { BetterAuthCookie, BetterAuthCookies } from "./cookie.mjs";
|
|
13
13
|
import { BetterAuthPlugin } from "./plugin.mjs";
|
|
14
14
|
import { BetterAuthOptions, BetterAuthRateLimitOptions } from "./init-options.mjs";
|
|
15
15
|
import { CookieOptions, EndpointContext } from "better-call";
|
|
@@ -89,10 +89,7 @@ interface InternalAdapter<_Options extends BetterAuthOptions = BetterAuthOptions
|
|
|
89
89
|
deleteVerificationByIdentifier(identifier: string): Promise<void>;
|
|
90
90
|
updateVerificationValue(id: string, data: Partial<Verification>): Promise<Verification>;
|
|
91
91
|
}
|
|
92
|
-
type CreateCookieGetterFn = (cookieName: string, overrideAttributes?: Partial<CookieOptions> | undefined) =>
|
|
93
|
-
name: string;
|
|
94
|
-
attributes: CookieOptions;
|
|
95
|
-
};
|
|
92
|
+
type CreateCookieGetterFn = (cookieName: string, overrideAttributes?: Partial<CookieOptions> | undefined) => BetterAuthCookie;
|
|
96
93
|
type CheckPasswordFn<Options extends BetterAuthOptions = BetterAuthOptions> = (userId: string, ctx: GenericEndpointContext<Options>) => Promise<boolean>;
|
|
97
94
|
type PluginContext = {
|
|
98
95
|
getPlugin: <ID extends BetterAuthPluginRegistryIdentifier | LiteralString>(pluginId: ID) => (ID extends BetterAuthPluginRegistryIdentifier ? ReturnType<BetterAuthPluginRegistry<unknown, unknown>[ID]["creator"]> : BetterAuthPlugin) | null;
|
|
@@ -111,10 +108,13 @@ type PluginContext = {
|
|
|
111
108
|
*/
|
|
112
109
|
hasPlugin: <ID extends BetterAuthPluginRegistryIdentifier | LiteralString>(pluginId: ID) => boolean;
|
|
113
110
|
};
|
|
114
|
-
type
|
|
115
|
-
options: Options;
|
|
111
|
+
type InfoContext = {
|
|
116
112
|
appName: string;
|
|
117
113
|
baseURL: string;
|
|
114
|
+
version: string;
|
|
115
|
+
};
|
|
116
|
+
type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> = PluginContext & InfoContext & {
|
|
117
|
+
options: Options;
|
|
118
118
|
trustedOrigins: string[];
|
|
119
119
|
/**
|
|
120
120
|
* Verifies whether url is a trusted origin according to the "trustedOrigins" configuration
|
|
@@ -166,7 +166,7 @@ type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> = Plugin
|
|
|
166
166
|
window: number;
|
|
167
167
|
max: number;
|
|
168
168
|
storage: "memory" | "database" | "secondary-storage";
|
|
169
|
-
} & BetterAuthRateLimitOptions
|
|
169
|
+
} & Omit<BetterAuthRateLimitOptions, "enabled" | "window" | "max" | "storage">;
|
|
170
170
|
adapter: DBAdapter<Options>;
|
|
171
171
|
internalAdapter: InternalAdapter<Options>;
|
|
172
172
|
createAuthCookie: CreateCookieGetterFn;
|
|
@@ -205,17 +205,18 @@ type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> = Plugin
|
|
|
205
205
|
payload: Record<string, any>;
|
|
206
206
|
}) => Promise<void>;
|
|
207
207
|
/**
|
|
208
|
-
*
|
|
208
|
+
* Skip origin check for requests.
|
|
209
209
|
*
|
|
210
|
-
*
|
|
211
|
-
* for
|
|
210
|
+
* - `true`: Skip for ALL requests (DANGEROUS - disables CSRF protection)
|
|
211
|
+
* - `string[]`: Skip only for specific paths (e.g., SAML callbacks)
|
|
212
|
+
* - `false`: Enable origin check (default)
|
|
212
213
|
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
214
|
+
* Paths support prefix matching (e.g., "/sso/saml2/callback" matches
|
|
215
|
+
* "/sso/saml2/callback/provider-name").
|
|
215
216
|
*
|
|
216
|
-
* @default false
|
|
217
|
+
* @default false (true in test environments)
|
|
217
218
|
*/
|
|
218
|
-
skipOriginCheck: boolean;
|
|
219
|
+
skipOriginCheck: boolean | string[];
|
|
219
220
|
/**
|
|
220
221
|
* This skips the CSRF check for all requests.
|
|
221
222
|
*
|
|
@@ -243,4 +244,4 @@ type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> = Plugin
|
|
|
243
244
|
runInBackgroundOrAwait: (promise: Promise<unknown> | Promise<void> | void | unknown) => Promise<unknown>;
|
|
244
245
|
};
|
|
245
246
|
//#endregion
|
|
246
|
-
export { AuthContext, BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, GenericEndpointContext, InternalAdapter, PluginContext };
|
|
247
|
+
export { AuthContext, BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, GenericEndpointContext, InfoContext, InternalAdapter, PluginContext };
|
package/dist/types/cookie.d.mts
CHANGED
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
import { CookieOptions } from "better-call";
|
|
2
2
|
|
|
3
3
|
//#region src/types/cookie.d.ts
|
|
4
|
+
type BetterAuthCookie = {
|
|
5
|
+
name: string;
|
|
6
|
+
attributes: CookieOptions;
|
|
7
|
+
};
|
|
4
8
|
type BetterAuthCookies = {
|
|
5
|
-
sessionToken:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
sessionData: {
|
|
10
|
-
name: string;
|
|
11
|
-
options: CookieOptions;
|
|
12
|
-
};
|
|
13
|
-
accountData: {
|
|
14
|
-
name: string;
|
|
15
|
-
options: CookieOptions;
|
|
16
|
-
};
|
|
17
|
-
dontRememberToken: {
|
|
18
|
-
name: string;
|
|
19
|
-
options: CookieOptions;
|
|
20
|
-
};
|
|
9
|
+
sessionToken: BetterAuthCookie;
|
|
10
|
+
sessionData: BetterAuthCookie;
|
|
11
|
+
accountData: BetterAuthCookie;
|
|
12
|
+
dontRememberToken: BetterAuthCookie;
|
|
21
13
|
};
|
|
22
14
|
//#endregion
|
|
23
|
-
export { BetterAuthCookies };
|
|
15
|
+
export { BetterAuthCookie, BetterAuthCookies };
|
package/dist/types/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Awaitable, LiteralString, LiteralUnion, Prettify, Primitive } from "./helper.mjs";
|
|
2
|
-
import { BetterAuthCookies } from "./cookie.mjs";
|
|
2
|
+
import { BetterAuthCookie, BetterAuthCookies } from "./cookie.mjs";
|
|
3
3
|
import { BetterAuthPlugin, HookEndpointContext } from "./plugin.mjs";
|
|
4
|
-
import { BetterAuthAdvancedOptions, BetterAuthOptions, BetterAuthRateLimitOptions, GenerateIdFn } from "./init-options.mjs";
|
|
5
|
-
import { AuthContext, BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, GenericEndpointContext, InternalAdapter, PluginContext } from "./context.mjs";
|
|
4
|
+
import { BetterAuthAdvancedOptions, BetterAuthOptions, BetterAuthRateLimitOptions, BetterAuthRateLimitRule, BetterAuthRateLimitStorage, GenerateIdFn } from "./init-options.mjs";
|
|
5
|
+
import { AuthContext, BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, GenericEndpointContext, InfoContext, InternalAdapter, PluginContext } from "./context.mjs";
|
|
6
6
|
import { BetterAuthClientOptions, BetterAuthClientPlugin, ClientAtomListener, ClientFetchOption, ClientStore } from "./plugin-client.mjs";
|
|
7
7
|
import { StandardSchemaV1 as StandardSchemaV1$1 } from "@standard-schema/spec";
|
|
8
8
|
export { type StandardSchemaV1$1 as StandardSchemaV1 };
|
|
@@ -27,46 +27,37 @@ type GenerateIdFn = (options: {
|
|
|
27
27
|
model: ModelNames;
|
|
28
28
|
size?: number | undefined;
|
|
29
29
|
}) => string | false;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
enabled?: boolean | undefined;
|
|
30
|
+
interface BetterAuthRateLimitStorage {
|
|
31
|
+
get: (key: string) => Promise<RateLimit | null | undefined>;
|
|
32
|
+
set: (key: string, value: RateLimit, update?: boolean | undefined) => Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
type BetterAuthRateLimitRule = {
|
|
36
35
|
/**
|
|
37
36
|
* Default window to use for rate limiting. The value
|
|
38
37
|
* should be in seconds.
|
|
39
38
|
*
|
|
40
39
|
* @default 10 seconds
|
|
41
40
|
*/
|
|
42
|
-
window
|
|
41
|
+
window: number;
|
|
43
42
|
/**
|
|
44
43
|
* The default maximum number of requests allowed within the window.
|
|
45
44
|
*
|
|
46
45
|
* @default 100 requests
|
|
47
46
|
*/
|
|
48
|
-
max
|
|
47
|
+
max: number;
|
|
48
|
+
};
|
|
49
|
+
type BetterAuthRateLimitOptions = Optional<BetterAuthRateLimitRule> & {
|
|
50
|
+
/**
|
|
51
|
+
* By default, rate limiting is only
|
|
52
|
+
* enabled on production.
|
|
53
|
+
*/
|
|
54
|
+
enabled?: boolean | undefined;
|
|
49
55
|
/**
|
|
50
56
|
* Custom rate limit rules to apply to
|
|
51
57
|
* specific paths.
|
|
52
58
|
*/
|
|
53
59
|
customRules?: {
|
|
54
|
-
[key: string]:
|
|
55
|
-
/**
|
|
56
|
-
* The window to use for the custom rule.
|
|
57
|
-
*/
|
|
58
|
-
window: number;
|
|
59
|
-
/**
|
|
60
|
-
* The maximum number of requests allowed within the window.
|
|
61
|
-
*/
|
|
62
|
-
max: number;
|
|
63
|
-
} | false | ((request: Request) => {
|
|
64
|
-
window: number;
|
|
65
|
-
max: number;
|
|
66
|
-
} | false | Promise<{
|
|
67
|
-
window: number;
|
|
68
|
-
max: number;
|
|
69
|
-
} | false>);
|
|
60
|
+
[key: string]: BetterAuthRateLimitRule | false | ((request: Request, currentRule: BetterAuthRateLimitRule) => Awaitable<false | BetterAuthRateLimitRule>);
|
|
70
61
|
} | undefined;
|
|
71
62
|
/**
|
|
72
63
|
* Storage configuration
|
|
@@ -95,10 +86,7 @@ type BetterAuthRateLimitOptions = {
|
|
|
95
86
|
* NOTE: If custom storage is used storage
|
|
96
87
|
* is ignored
|
|
97
88
|
*/
|
|
98
|
-
customStorage?:
|
|
99
|
-
get: (key: string) => Promise<RateLimit | undefined>;
|
|
100
|
-
set: (key: string, value: RateLimit) => Promise<void>;
|
|
101
|
-
};
|
|
89
|
+
customStorage?: BetterAuthRateLimitStorage;
|
|
102
90
|
};
|
|
103
91
|
type BetterAuthAdvancedOptions = {
|
|
104
92
|
/**
|
|
@@ -1263,4 +1251,4 @@ type BetterAuthOptions = {
|
|
|
1263
1251
|
};
|
|
1264
1252
|
};
|
|
1265
1253
|
//#endregion
|
|
1266
|
-
export { BetterAuthAdvancedOptions, BetterAuthOptions, BetterAuthRateLimitOptions, GenerateIdFn };
|
|
1254
|
+
export { BetterAuthAdvancedOptions, BetterAuthOptions, BetterAuthRateLimitOptions, BetterAuthRateLimitRule, BetterAuthRateLimitStorage, GenerateIdFn };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/utils/url.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a request pathname by removing the basePath prefix and trailing slashes.
|
|
4
|
+
* This is useful for matching paths against configured path lists.
|
|
5
|
+
*
|
|
6
|
+
* @param requestUrl - The full request URL
|
|
7
|
+
* @param basePath - The base path of the auth API (e.g., "/api/auth")
|
|
8
|
+
* @returns The normalized path without basePath prefix or trailing slashes,
|
|
9
|
+
* or "/" if URL parsing fails
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* normalizePathname("http://localhost:3000/api/auth/sso/saml2/callback/provider1", "/api/auth")
|
|
13
|
+
* // Returns: "/sso/saml2/callback/provider1"
|
|
14
|
+
*
|
|
15
|
+
* normalizePathname("http://localhost:3000/sso/saml2/callback/provider1/", "/")
|
|
16
|
+
* // Returns: "/sso/saml2/callback/provider1"
|
|
17
|
+
*/
|
|
18
|
+
declare function normalizePathname(requestUrl: string, basePath: string): string;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { normalizePathname };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/utils/url.ts
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a request pathname by removing the basePath prefix and trailing slashes.
|
|
4
|
+
* This is useful for matching paths against configured path lists.
|
|
5
|
+
*
|
|
6
|
+
* @param requestUrl - The full request URL
|
|
7
|
+
* @param basePath - The base path of the auth API (e.g., "/api/auth")
|
|
8
|
+
* @returns The normalized path without basePath prefix or trailing slashes,
|
|
9
|
+
* or "/" if URL parsing fails
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* normalizePathname("http://localhost:3000/api/auth/sso/saml2/callback/provider1", "/api/auth")
|
|
13
|
+
* // Returns: "/sso/saml2/callback/provider1"
|
|
14
|
+
*
|
|
15
|
+
* normalizePathname("http://localhost:3000/sso/saml2/callback/provider1/", "/")
|
|
16
|
+
* // Returns: "/sso/saml2/callback/provider1"
|
|
17
|
+
*/
|
|
18
|
+
function normalizePathname(requestUrl, basePath) {
|
|
19
|
+
let pathname;
|
|
20
|
+
try {
|
|
21
|
+
pathname = new URL(requestUrl).pathname.replace(/\/+$/, "") || "/";
|
|
22
|
+
} catch {
|
|
23
|
+
return "/";
|
|
24
|
+
}
|
|
25
|
+
if (basePath === "/" || basePath === "") return pathname;
|
|
26
|
+
if (pathname === basePath) return "/";
|
|
27
|
+
if (pathname.startsWith(basePath + "/")) return pathname.slice(basePath.length).replace(/\/+$/, "") || "/";
|
|
28
|
+
return pathname;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { normalizePathname };
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import type { AsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
|
2
2
|
import { getAsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
3
3
|
import type { EndpointContext, InputContext } from "better-call";
|
|
4
4
|
import type { AuthContext } from "../types";
|
|
5
|
+
import { __getBetterAuthGlobal } from "./global";
|
|
5
6
|
|
|
6
7
|
export type AuthEndpointContext = Partial<
|
|
7
8
|
InputContext<string, any> & EndpointContext<string, any>
|
|
@@ -9,24 +10,15 @@ export type AuthEndpointContext = Partial<
|
|
|
9
10
|
context: AuthContext;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
const symbol = Symbol.for("better-auth:endpoint-context-async-storage");
|
|
13
|
-
|
|
14
|
-
let currentContextAsyncStorage: AsyncLocalStorage<AuthEndpointContext> | null =
|
|
15
|
-
null;
|
|
16
|
-
|
|
17
13
|
const ensureAsyncStorage = async () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
(globalThis as any)[symbol] === undefined
|
|
21
|
-
) {
|
|
14
|
+
const betterAuthGlobal = __getBetterAuthGlobal();
|
|
15
|
+
if (!betterAuthGlobal.context.endpointContextAsyncStorage) {
|
|
22
16
|
const AsyncLocalStorage = await getAsyncLocalStorage();
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
betterAuthGlobal.context.endpointContextAsyncStorage =
|
|
18
|
+
new AsyncLocalStorage<AuthEndpointContext>();
|
|
25
19
|
}
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
((globalThis as any)[symbol] as AsyncLocalStorage<AuthEndpointContext>)
|
|
29
|
-
);
|
|
20
|
+
return betterAuthGlobal.context
|
|
21
|
+
.endpointContextAsyncStorage as AsyncLocalStorage<AuthEndpointContext>;
|
|
30
22
|
};
|
|
31
23
|
|
|
32
24
|
/**
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { AsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
2
|
+
|
|
3
|
+
interface BetterAuthGlobal {
|
|
4
|
+
/**
|
|
5
|
+
* The version of BetterAuth.
|
|
6
|
+
*/
|
|
7
|
+
version: string;
|
|
8
|
+
/**
|
|
9
|
+
* Used to track the number of BetterAuth instances in the same process.
|
|
10
|
+
*
|
|
11
|
+
* Debugging purposes only.
|
|
12
|
+
*/
|
|
13
|
+
epoch: number;
|
|
14
|
+
/**
|
|
15
|
+
* Stores the AsyncLocalStorage instances for each context.
|
|
16
|
+
*/
|
|
17
|
+
context: Record<string, AsyncLocalStorage<unknown>>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const symbol = Symbol.for("better-auth:global");
|
|
21
|
+
let bind: BetterAuthGlobal | null = null;
|
|
22
|
+
|
|
23
|
+
const __context: Record<string, AsyncLocalStorage<unknown>> = {};
|
|
24
|
+
const __betterAuthVersion: string = import.meta.env
|
|
25
|
+
.BETTER_AUTH_VERSION as string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* We store context instance in the globalThis.
|
|
29
|
+
*
|
|
30
|
+
* The reason we do this is that some bundlers, web framework, or package managers might
|
|
31
|
+
* create multiple copies of BetterAuth in the same process intentionally or unintentionally.
|
|
32
|
+
*
|
|
33
|
+
* For example, yarn v1, Next.js, SSR, Vite...
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export function __getBetterAuthGlobal(): BetterAuthGlobal {
|
|
38
|
+
if (!(globalThis as any)[symbol]) {
|
|
39
|
+
(globalThis as any)[symbol] = {
|
|
40
|
+
version: __betterAuthVersion,
|
|
41
|
+
epoch: 1,
|
|
42
|
+
context: __context,
|
|
43
|
+
};
|
|
44
|
+
bind = (globalThis as any)[symbol] as BetterAuthGlobal;
|
|
45
|
+
}
|
|
46
|
+
bind = (globalThis as any)[symbol] as BetterAuthGlobal;
|
|
47
|
+
if (bind.version !== __betterAuthVersion) {
|
|
48
|
+
bind.version = __betterAuthVersion;
|
|
49
|
+
// Different versions of BetterAuth are loaded in the same process.
|
|
50
|
+
bind.epoch++;
|
|
51
|
+
}
|
|
52
|
+
return (globalThis as any)[symbol] as BetterAuthGlobal;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getBetterAuthVersion(): string {
|
|
56
|
+
return __getBetterAuthGlobal().version;
|
|
57
|
+
}
|
package/src/context/index.ts
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import type { AsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
2
2
|
import { getAsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
3
|
+
import { __getBetterAuthGlobal } from "./global";
|
|
3
4
|
|
|
4
5
|
export type RequestStateWeakMap = WeakMap<object, any>;
|
|
5
6
|
|
|
6
|
-
const symbol = Symbol.for("better-auth:request-state-async-storage");
|
|
7
|
-
|
|
8
|
-
let requestStateAsyncStorage: AsyncLocalStorage<RequestStateWeakMap> | null =
|
|
9
|
-
null;
|
|
10
|
-
|
|
11
7
|
const ensureAsyncStorage = async () => {
|
|
12
|
-
|
|
8
|
+
const betterAuthGlobal = __getBetterAuthGlobal();
|
|
9
|
+
if (!betterAuthGlobal.context.requestStateAsyncStorage) {
|
|
13
10
|
const AsyncLocalStorage = await getAsyncLocalStorage();
|
|
14
|
-
requestStateAsyncStorage =
|
|
15
|
-
|
|
11
|
+
betterAuthGlobal.context.requestStateAsyncStorage =
|
|
12
|
+
new AsyncLocalStorage<RequestStateWeakMap>();
|
|
16
13
|
}
|
|
17
|
-
return
|
|
18
|
-
requestStateAsyncStorage
|
|
19
|
-
((globalThis as any)[symbol] as AsyncLocalStorage<RequestStateWeakMap>)
|
|
20
|
-
);
|
|
14
|
+
return betterAuthGlobal.context
|
|
15
|
+
.requestStateAsyncStorage as AsyncLocalStorage<RequestStateWeakMap>;
|
|
21
16
|
};
|
|
22
17
|
|
|
23
18
|
export async function getRequestStateAsyncLocalStorage() {
|
|
@@ -1,25 +1,16 @@
|
|
|
1
|
-
import type { AsyncLocalStorage } from "
|
|
1
|
+
import type { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import { getAsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
3
3
|
import type { DBAdapter, DBTransactionAdapter } from "../db/adapter";
|
|
4
|
-
|
|
5
|
-
const symbol = Symbol.for("better-auth:transaction-adapter-async-storage");
|
|
6
|
-
|
|
7
|
-
let currentAdapterAsyncStorage: AsyncLocalStorage<DBTransactionAdapter> | null =
|
|
8
|
-
null;
|
|
4
|
+
import { __getBetterAuthGlobal } from "./global";
|
|
9
5
|
|
|
10
6
|
const ensureAsyncStorage = async () => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
(globalThis as any)[symbol] === undefined
|
|
14
|
-
) {
|
|
7
|
+
const betterAuthGlobal = __getBetterAuthGlobal();
|
|
8
|
+
if (!betterAuthGlobal.context.adapterAsyncStorage) {
|
|
15
9
|
const AsyncLocalStorage = await getAsyncLocalStorage();
|
|
16
|
-
|
|
17
|
-
(globalThis as any)[symbol] = currentAdapterAsyncStorage;
|
|
10
|
+
betterAuthGlobal.context.adapterAsyncStorage = new AsyncLocalStorage();
|
|
18
11
|
}
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
((globalThis as any)[symbol] as AsyncLocalStorage<DBTransactionAdapter>)
|
|
22
|
-
);
|
|
12
|
+
return betterAuthGlobal.context
|
|
13
|
+
.adapterAsyncStorage as AsyncLocalStorage<DBTransactionAdapter>;
|
|
23
14
|
};
|
|
24
15
|
|
|
25
16
|
/**
|
|
@@ -200,7 +200,7 @@ export const createAdapterFactory =
|
|
|
200
200
|
let value = data[field];
|
|
201
201
|
const fieldAttributes = fields[field];
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
const newFieldName: string =
|
|
204
204
|
newMappedKeys[field] || fields[field]!.fieldName || field;
|
|
205
205
|
if (
|
|
206
206
|
value === undefined &&
|
|
@@ -335,7 +335,7 @@ export const createAdapterFactory =
|
|
|
335
335
|
newValue = await field.transform.output(newValue);
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
-
|
|
338
|
+
const newFieldName: string = newMappedKeys[key] || key;
|
|
339
339
|
|
|
340
340
|
if (originalKey === "id" || field.references?.field === "id") {
|
|
341
341
|
// Even if `useNumberId` is true, we must always return a string `id` output.
|
|
@@ -392,7 +392,7 @@ export const createAdapterFactory =
|
|
|
392
392
|
unsafe_model = getDefaultModelName(unsafe_model);
|
|
393
393
|
// for now we just transform the base model
|
|
394
394
|
// later we append the joined models to this object.
|
|
395
|
-
|
|
395
|
+
const transformedData: Record<string, any> = await transformSingleOutput(
|
|
396
396
|
data,
|
|
397
397
|
unsafe_model,
|
|
398
398
|
select,
|
|
@@ -443,7 +443,7 @@ export const createAdapterFactory =
|
|
|
443
443
|
joinedData = [joinedData];
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
-
|
|
446
|
+
const transformed = [];
|
|
447
447
|
|
|
448
448
|
if (Array.isArray(joinedData)) {
|
|
449
449
|
for (const item of joinedData) {
|
|
@@ -822,7 +822,7 @@ export const createAdapterFactory =
|
|
|
822
822
|
forceAllowId?: boolean;
|
|
823
823
|
}): Promise<R> => {
|
|
824
824
|
transactionId++;
|
|
825
|
-
|
|
825
|
+
const thisTransactionId = transactionId;
|
|
826
826
|
const model = getModelName(unsafeModel);
|
|
827
827
|
unsafeModel = getDefaultModelName(unsafeModel);
|
|
828
828
|
if (
|
|
@@ -903,7 +903,7 @@ export const createAdapterFactory =
|
|
|
903
903
|
update: Record<string, any>;
|
|
904
904
|
}): Promise<T | null> => {
|
|
905
905
|
transactionId++;
|
|
906
|
-
|
|
906
|
+
const thisTransactionId = transactionId;
|
|
907
907
|
unsafeModel = getDefaultModelName(unsafeModel);
|
|
908
908
|
const model = getModelName(unsafeModel);
|
|
909
909
|
const where = transformWhereClause({
|
|
@@ -965,7 +965,7 @@ export const createAdapterFactory =
|
|
|
965
965
|
update: Record<string, any>;
|
|
966
966
|
}) => {
|
|
967
967
|
transactionId++;
|
|
968
|
-
|
|
968
|
+
const thisTransactionId = transactionId;
|
|
969
969
|
const model = getModelName(unsafeModel);
|
|
970
970
|
const where = transformWhereClause({
|
|
971
971
|
model: unsafeModel,
|
|
@@ -1021,7 +1021,7 @@ export const createAdapterFactory =
|
|
|
1021
1021
|
join?: JoinOption;
|
|
1022
1022
|
}) => {
|
|
1023
1023
|
transactionId++;
|
|
1024
|
-
|
|
1024
|
+
const thisTransactionId = transactionId;
|
|
1025
1025
|
const model = getModelName(unsafeModel);
|
|
1026
1026
|
const where = transformWhereClause({
|
|
1027
1027
|
model: unsafeModel,
|
|
@@ -1095,7 +1095,7 @@ export const createAdapterFactory =
|
|
|
1095
1095
|
join?: JoinOption;
|
|
1096
1096
|
}) => {
|
|
1097
1097
|
transactionId++;
|
|
1098
|
-
|
|
1098
|
+
const thisTransactionId = transactionId;
|
|
1099
1099
|
const limit =
|
|
1100
1100
|
unsafeLimit ??
|
|
1101
1101
|
options.advanced?.database?.defaultFindManyLimit ??
|
|
@@ -1173,7 +1173,7 @@ export const createAdapterFactory =
|
|
|
1173
1173
|
where: Where[];
|
|
1174
1174
|
}) => {
|
|
1175
1175
|
transactionId++;
|
|
1176
|
-
|
|
1176
|
+
const thisTransactionId = transactionId;
|
|
1177
1177
|
const model = getModelName(unsafeModel);
|
|
1178
1178
|
const where = transformWhereClause({
|
|
1179
1179
|
model: unsafeModel,
|
|
@@ -1206,7 +1206,7 @@ export const createAdapterFactory =
|
|
|
1206
1206
|
where: Where[];
|
|
1207
1207
|
}) => {
|
|
1208
1208
|
transactionId++;
|
|
1209
|
-
|
|
1209
|
+
const thisTransactionId = transactionId;
|
|
1210
1210
|
const model = getModelName(unsafeModel);
|
|
1211
1211
|
const where = transformWhereClause({
|
|
1212
1212
|
model: unsafeModel,
|
|
@@ -1240,7 +1240,7 @@ export const createAdapterFactory =
|
|
|
1240
1240
|
where?: Where[];
|
|
1241
1241
|
}) => {
|
|
1242
1242
|
transactionId++;
|
|
1243
|
-
|
|
1243
|
+
const thisTransactionId = transactionId;
|
|
1244
1244
|
const model = getModelName(unsafeModel);
|
|
1245
1245
|
const where = transformWhereClause({
|
|
1246
1246
|
model: unsafeModel,
|
|
@@ -1350,7 +1350,7 @@ export const createAdapterFactory =
|
|
|
1350
1350
|
}
|
|
1351
1351
|
|
|
1352
1352
|
//`${colors.fg.blue}|${colors.reset} `,
|
|
1353
|
-
|
|
1353
|
+
const log: any[] = logs
|
|
1354
1354
|
.reverse()
|
|
1355
1355
|
.map((log) => {
|
|
1356
1356
|
log.args[0] = `\n${log.args[0]}`;
|
|
@@ -23,7 +23,7 @@ export const initGetDefaultModelName = ({
|
|
|
23
23
|
// It's possible this `model` could had applied `usePlural`.
|
|
24
24
|
// Thus we'll try the search but without the trailing `s`.
|
|
25
25
|
if (usePlural && model.charAt(model.length - 1) === "s") {
|
|
26
|
-
|
|
26
|
+
const pluralessModel = model.slice(0, -1);
|
|
27
27
|
let m = schema[pluralessModel] ? pluralessModel : undefined;
|
|
28
28
|
if (!m) {
|
|
29
29
|
m = Object.entries(schema).find(
|
|
@@ -36,7 +36,7 @@ export const initGetIdField = ({
|
|
|
36
36
|
options.advanced?.database?.generateId === "serial";
|
|
37
37
|
const useUUIDs = options.advanced?.database?.generateId === "uuid";
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
const shouldGenerateId: boolean = (() => {
|
|
40
40
|
if (disableIdGeneration) {
|
|
41
41
|
return false;
|
|
42
42
|
} else if (useNumberId && !forceAllowId) {
|
|
@@ -58,7 +58,7 @@ export const initGetIdField = ({
|
|
|
58
58
|
? {
|
|
59
59
|
defaultValue() {
|
|
60
60
|
if (disableIdGeneration) return undefined;
|
|
61
|
-
|
|
61
|
+
const generateId = options.advanced?.database?.generateId;
|
|
62
62
|
if (generateId === false || useNumberId) return undefined;
|
|
63
63
|
if (typeof generateId === "function") {
|
|
64
64
|
return generateId({
|
package/src/error/index.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { APIError as BaseAPIError } from "better-call/error";
|
|
2
2
|
|
|
3
3
|
export class BetterAuthError extends Error {
|
|
4
|
-
constructor(message: string, cause?:
|
|
5
|
-
super(message);
|
|
4
|
+
constructor(message: string, options?: { cause?: unknown | undefined }) {
|
|
5
|
+
super(message, options);
|
|
6
6
|
this.name = "BetterAuthError";
|
|
7
7
|
this.message = message;
|
|
8
|
-
this.cause = cause;
|
|
9
8
|
this.stack = "";
|
|
10
9
|
}
|
|
11
10
|
}
|
|
@@ -161,9 +161,18 @@ export const apple = (options: AppleOptions) => {
|
|
|
161
161
|
if (!profile) {
|
|
162
162
|
return null;
|
|
163
163
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
|
|
165
|
+
// TODO: " " masking will be removed when the name field is made optional
|
|
166
|
+
let name: string;
|
|
167
|
+
if (token.user?.name) {
|
|
168
|
+
const firstName = token.user.name.firstName || "";
|
|
169
|
+
const lastName = token.user.name.lastName || "";
|
|
170
|
+
const fullName = `${firstName} ${lastName}`.trim();
|
|
171
|
+
name = fullName || " ";
|
|
172
|
+
} else {
|
|
173
|
+
name = profile.name || " ";
|
|
174
|
+
}
|
|
175
|
+
|
|
167
176
|
const emailVerified =
|
|
168
177
|
typeof profile.email_verified === "boolean"
|
|
169
178
|
? profile.email_verified
|
|
@@ -65,7 +65,7 @@ const cleanDoubleSlashes = (input: string = "") => {
|
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
const issuerToEndpoints = (issuer?: string | undefined) => {
|
|
68
|
-
|
|
68
|
+
const baseUrl = issuer || "https://gitlab.com";
|
|
69
69
|
return {
|
|
70
70
|
authorizationEndpoint: cleanDoubleSlashes(`${baseUrl}/oauth/authorize`),
|
|
71
71
|
tokenEndpoint: cleanDoubleSlashes(`${baseUrl}/oauth/token`),
|