@better-auth/core 1.7.0-rc.1 → 1.7.0-rc.2
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 +28 -28
- package/dist/async_hooks/index.d.mts +0 -1
- package/dist/async_hooks/pure.index.d.mts +0 -1
- package/dist/context/endpoint-context.d.mts +1 -1
- package/dist/context/global.d.mts +0 -1
- package/dist/context/global.mjs +1 -1
- package/dist/context/request-state.d.mts +0 -1
- package/dist/context/request-state.mjs +8 -5
- package/dist/context/transaction.d.mts +8 -3
- package/dist/context/transaction.mjs +27 -10
- package/dist/db/adapter/factory.d.mts +3 -5
- package/dist/db/adapter/factory.mjs +7 -5
- package/dist/db/adapter/get-default-field-name.d.mts +2 -9
- package/dist/db/adapter/get-default-model-name.d.mts +1 -5
- package/dist/db/adapter/get-default-model-name.mjs +6 -5
- package/dist/db/adapter/get-field-attributes.d.mts +4 -11
- package/dist/db/adapter/get-field-name.d.mts +2 -9
- package/dist/db/adapter/get-id-field.d.mts +4 -12
- package/dist/db/adapter/get-model-name.d.mts +1 -5
- package/dist/db/adapter/index.d.mts +7 -32
- package/dist/db/adapter/types.d.mts +5 -17
- package/dist/db/adapter/utils.d.mts +0 -1
- package/dist/db/database-index.d.mts +44 -0
- package/dist/db/database-index.mjs +168 -0
- package/dist/db/get-tables.d.mts +7 -1
- package/dist/db/get-tables.mjs +47 -6
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/internal.d.mts +3 -0
- package/dist/db/internal.mjs +3 -0
- package/dist/db/plugin.d.mts +4 -3
- package/dist/db/schema/account.d.mts +16 -3
- package/dist/db/schema/account.mjs +35 -2
- package/dist/db/schema/rate-limit.d.mts +1 -1
- package/dist/db/schema/rate-limit.mjs +9 -0
- package/dist/db/schema/session.d.mts +1 -1
- package/dist/db/schema/shared.d.mts +0 -1
- package/dist/db/schema/user.d.mts +1 -1
- package/dist/db/schema/verification.d.mts +1 -1
- package/dist/db/type.d.mts +17 -9
- package/dist/env/logger.d.mts +25 -25
- package/dist/error/codes.d.mts +0 -1
- package/dist/error/index.d.mts +0 -1
- package/dist/index.d.mts +1 -1
- package/dist/instrumentation/attributes.d.mts +0 -1
- package/dist/instrumentation/pure.index.d.mts +0 -1
- package/dist/instrumentation/tracer.mjs +1 -1
- package/dist/oauth2/authorization-params.d.mts +0 -1
- package/dist/oauth2/client-assertion.d.mts +3 -13
- package/dist/oauth2/client-credentials-token.d.mts +3 -17
- package/dist/oauth2/client-credentials-token.mjs +1 -4
- package/dist/oauth2/create-authorization-url.d.mts +3 -21
- package/dist/oauth2/dpop.d.mts +2 -23
- package/dist/oauth2/dpop.mjs +1 -1
- package/dist/oauth2/index.d.mts +2 -2
- package/dist/oauth2/oauth-provider.d.mts +85 -36
- package/dist/oauth2/refresh-access-token.d.mts +3 -19
- package/dist/oauth2/refresh-access-token.mjs +3 -9
- package/dist/oauth2/reject-redirects.mjs +1 -1
- package/dist/oauth2/token-endpoint-auth.d.mts +0 -1
- package/dist/oauth2/utils.d.mts +0 -1
- package/dist/oauth2/utils.mjs +2 -3
- package/dist/oauth2/validate-authorization-code.d.mts +5 -29
- package/dist/oauth2/verify-id-token.d.mts +3 -2
- package/dist/oauth2/verify-id-token.mjs +3 -3
- package/dist/oauth2/verify.d.mts +5 -7
- package/dist/oauth2/verify.mjs +2 -2
- package/dist/social-providers/apple.d.mts +9 -24
- package/dist/social-providers/apple.mjs +2 -1
- package/dist/social-providers/atlassian.d.mts +18 -19
- package/dist/social-providers/atlassian.mjs +1 -1
- package/dist/social-providers/cognito.d.mts +33 -22
- package/dist/social-providers/cognito.mjs +2 -2
- package/dist/social-providers/discord.d.mts +7 -20
- package/dist/social-providers/discord.mjs +1 -1
- package/dist/social-providers/dropbox.d.mts +7 -22
- package/dist/social-providers/dropbox.mjs +1 -1
- package/dist/social-providers/facebook.d.mts +19 -27
- package/dist/social-providers/facebook.mjs +6 -17
- package/dist/social-providers/figma.d.mts +7 -22
- package/dist/social-providers/figma.mjs +1 -1
- package/dist/social-providers/github.d.mts +7 -23
- package/dist/social-providers/github.mjs +1 -1
- package/dist/social-providers/gitlab.d.mts +6 -43
- package/dist/social-providers/gitlab.mjs +1 -1
- package/dist/social-providers/google.d.mts +10 -32
- package/dist/social-providers/google.mjs +2 -1
- package/dist/social-providers/huggingface.d.mts +7 -22
- package/dist/social-providers/huggingface.mjs +1 -1
- package/dist/social-providers/index.d.mts +229 -787
- package/dist/social-providers/kakao.d.mts +8 -33
- package/dist/social-providers/kakao.mjs +1 -1
- package/dist/social-providers/kick.d.mts +7 -22
- package/dist/social-providers/kick.mjs +1 -1
- package/dist/social-providers/line.d.mts +8 -44
- package/dist/social-providers/line.mjs +4 -6
- package/dist/social-providers/linear.d.mts +7 -21
- package/dist/social-providers/linear.mjs +1 -1
- package/dist/social-providers/linkedin.d.mts +7 -21
- package/dist/social-providers/linkedin.mjs +1 -1
- package/dist/social-providers/microsoft-entra-id.d.mts +8 -18
- package/dist/social-providers/microsoft-entra-id.mjs +18 -2
- package/dist/social-providers/naver.d.mts +27 -42
- package/dist/social-providers/naver.mjs +1 -1
- package/dist/social-providers/notion.d.mts +7 -21
- package/dist/social-providers/notion.mjs +1 -1
- package/dist/social-providers/paybin.d.mts +8 -23
- package/dist/social-providers/paybin.mjs +2 -1
- package/dist/social-providers/paypal.d.mts +8 -33
- package/dist/social-providers/paypal.mjs +1 -1
- package/dist/social-providers/polar.d.mts +7 -22
- package/dist/social-providers/polar.mjs +1 -1
- package/dist/social-providers/railway.d.mts +7 -22
- package/dist/social-providers/railway.mjs +1 -1
- package/dist/social-providers/reddit.d.mts +7 -20
- package/dist/social-providers/reddit.mjs +1 -1
- package/dist/social-providers/roblox.d.mts +7 -20
- package/dist/social-providers/roblox.mjs +1 -1
- package/dist/social-providers/salesforce.d.mts +7 -22
- package/dist/social-providers/salesforce.mjs +1 -1
- package/dist/social-providers/slack.d.mts +7 -20
- package/dist/social-providers/slack.mjs +1 -1
- package/dist/social-providers/spotify.d.mts +7 -22
- package/dist/social-providers/spotify.mjs +1 -1
- package/dist/social-providers/tiktok.d.mts +10 -22
- package/dist/social-providers/tiktok.mjs +1 -1
- package/dist/social-providers/twitch.d.mts +7 -20
- package/dist/social-providers/twitch.mjs +1 -1
- package/dist/social-providers/twitter.d.mts +29 -26
- package/dist/social-providers/twitter.mjs +1 -1
- package/dist/social-providers/vercel.d.mts +7 -22
- package/dist/social-providers/vercel.mjs +1 -1
- package/dist/social-providers/vk.d.mts +8 -24
- package/dist/social-providers/vk.mjs +5 -6
- package/dist/social-providers/wechat.d.mts +7 -19
- package/dist/social-providers/wechat.mjs +1 -1
- package/dist/social-providers/zoom.d.mts +9 -25
- package/dist/social-providers/zoom.mjs +1 -1
- package/dist/types/context.d.mts +16 -9
- package/dist/types/cookie.d.mts +0 -1
- package/dist/types/helper.d.mts +1 -1
- package/dist/types/index.d.mts +1 -1
- package/dist/types/init-options.d.mts +37 -26
- package/dist/types/plugin-client.d.mts +1 -3
- package/dist/types/plugin.d.mts +2 -2
- package/dist/utils/async.d.mts +0 -1
- package/dist/utils/db.d.mts +1 -0
- package/dist/utils/deprecate.d.mts +0 -1
- package/dist/utils/error-codes.d.mts +2 -2
- package/dist/utils/host.d.mts +27 -1
- package/dist/utils/host.mjs +1 -1
- package/dist/utils/ip.d.mts +1 -0
- package/dist/utils/ip.mjs +1 -1
- package/dist/utils/is-api-error.d.mts +0 -1
- package/dist/utils/redirect-uri.d.mts +0 -1
- package/package.json +10 -2
- package/src/context/request-state.ts +26 -6
- package/src/context/transaction.ts +37 -18
- package/src/db/adapter/factory.ts +24 -18
- package/src/db/adapter/get-default-model-name.ts +23 -14
- package/src/db/database-index.ts +351 -0
- package/src/db/get-tables.ts +89 -9
- package/src/db/index.ts +4 -0
- package/src/db/internal.ts +12 -0
- package/src/db/plugin.ts +3 -1
- package/src/db/schema/account.ts +27 -1
- package/src/db/schema/user.ts +1 -1
- package/src/db/type.ts +12 -0
- package/src/oauth2/index.ts +3 -0
- package/src/oauth2/oauth-provider.ts +94 -36
- package/src/oauth2/verify-id-token.ts +4 -2
- package/src/social-providers/apple.ts +2 -1
- package/src/social-providers/atlassian.ts +1 -1
- package/src/social-providers/cognito.ts +2 -2
- package/src/social-providers/discord.ts +1 -1
- package/src/social-providers/dropbox.ts +1 -1
- package/src/social-providers/facebook.ts +21 -28
- package/src/social-providers/figma.ts +1 -1
- package/src/social-providers/github.ts +1 -1
- package/src/social-providers/gitlab.ts +1 -1
- package/src/social-providers/google.ts +2 -1
- package/src/social-providers/huggingface.ts +1 -1
- package/src/social-providers/kakao.ts +1 -1
- package/src/social-providers/kick.ts +1 -1
- package/src/social-providers/line.ts +7 -12
- package/src/social-providers/linear.ts +1 -1
- package/src/social-providers/linkedin.ts +1 -1
- package/src/social-providers/microsoft-entra-id.ts +3 -2
- package/src/social-providers/naver.ts +1 -1
- package/src/social-providers/notion.ts +1 -1
- package/src/social-providers/paybin.ts +2 -1
- package/src/social-providers/paypal.ts +1 -1
- package/src/social-providers/polar.ts +1 -1
- package/src/social-providers/railway.ts +1 -1
- package/src/social-providers/reddit.ts +1 -1
- package/src/social-providers/roblox.ts +1 -1
- package/src/social-providers/salesforce.ts +1 -1
- package/src/social-providers/slack.ts +1 -1
- package/src/social-providers/spotify.ts +1 -1
- package/src/social-providers/tiktok.ts +2 -2
- package/src/social-providers/twitch.ts +1 -1
- package/src/social-providers/twitter.ts +1 -1
- package/src/social-providers/vercel.ts +1 -1
- package/src/social-providers/vk.ts +2 -2
- package/src/social-providers/wechat.ts +1 -1
- package/src/social-providers/zoom.ts +1 -1
- package/src/types/context.ts +21 -14
- package/src/types/init-options.ts +15 -14
package/dist/types/helper.d.mts
CHANGED
|
@@ -4,7 +4,7 @@ type Awaitable<T> = T | Promise<T>;
|
|
|
4
4
|
type AwaitableFunction<T> = T | (() => Awaitable<T>);
|
|
5
5
|
type LiteralString = "" | (string & Record<never, never>);
|
|
6
6
|
type LiteralUnion<LiteralType, BaseType extends Primitive> = LiteralType | (BaseType & Record<never, never>);
|
|
7
|
-
type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
|
7
|
+
type Prettify<T> = { [K in keyof T]: T[K]; } & {};
|
|
8
8
|
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
9
9
|
//#endregion
|
|
10
10
|
export { Awaitable, AwaitableFunction, LiteralString, LiteralUnion, Prettify, Primitive, UnionToIntersection };
|
package/dist/types/index.d.mts
CHANGED
|
@@ -6,4 +6,4 @@ import { SecretConfig } from "./secret.mjs";
|
|
|
6
6
|
import { AuthContext, BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, GenericEndpointContext, InfoContext, InternalAdapter, PluginContext } from "./context.mjs";
|
|
7
7
|
import { BetterAuthClientOptions, BetterAuthClientPlugin, ClientAtomListener, ClientFetchOption, ClientStore } from "./plugin-client.mjs";
|
|
8
8
|
import { StandardSchemaV1 as StandardSchemaV1$1 } from "@standard-schema/spec";
|
|
9
|
-
export {
|
|
9
|
+
export type { AuthContext, Awaitable, AwaitableFunction, BaseURLConfig, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookie, BetterAuthCookies, BetterAuthDBOptions, BetterAuthOptions, BetterAuthPlugin, BetterAuthPluginErrorCodePart, BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, BetterAuthRateLimitOptions, BetterAuthRateLimitRule, BetterAuthRateLimitStorage, ClientAtomListener, ClientFetchOption, ClientStore, DynamicBaseURLConfig, GenerateIdFn, GenericEndpointContext, HookEndpointContext, InfoContext, InternalAdapter, LiteralString, LiteralUnion, PluginContext, Prettify, Primitive, SecretConfig, StandardSchemaV1$1 as StandardSchemaV1, StoreIdentifierOption, UnionToIntersection, UserProvisioningSource, ValidateUserInfoAction, ValidateUserInfoMethod, ValidateUserInfoOAuthInfo, ValidateUserInfoResult, ValidateUserInfoSSOInfo, ValidateUserInfoSource };
|
|
@@ -9,6 +9,7 @@ import { SocialProviderList, SocialProviders } from "../social-providers/index.m
|
|
|
9
9
|
import { Awaitable, LiteralString, LiteralUnion } from "./helper.mjs";
|
|
10
10
|
import { BetterAuthPlugin } from "./plugin.mjs";
|
|
11
11
|
import { Account, BaseAccount } from "../db/schema/account.mjs";
|
|
12
|
+
import "../db/index.mjs";
|
|
12
13
|
import { AuthContext, GenericEndpointContext } from "./context.mjs";
|
|
13
14
|
import { AuthMiddleware } from "../api/index.mjs";
|
|
14
15
|
import { CookieOptions } from "better-call";
|
|
@@ -16,10 +17,9 @@ import { Database } from "bun:sqlite";
|
|
|
16
17
|
import { DatabaseSync } from "node:sqlite";
|
|
17
18
|
import { D1Database } from "@cloudflare/workers-types";
|
|
18
19
|
import { Dialect, Kysely, MysqlPool, PostgresPool, SqliteDatabase } from "kysely";
|
|
19
|
-
|
|
20
20
|
//#region src/types/init-options.d.ts
|
|
21
21
|
type KyselyDatabaseType = "postgres" | "mysql" | "sqlite" | "mssql";
|
|
22
|
-
type Optional<T> = { [P in keyof T]?: T[P] | undefined };
|
|
22
|
+
type Optional<T> = { [P in keyof T]?: T[P] | undefined; };
|
|
23
23
|
type StoreIdentifierOption = "plain" | "hashed" | {
|
|
24
24
|
hash: (identifier: string) => Promise<string>;
|
|
25
25
|
};
|
|
@@ -53,18 +53,24 @@ type ValidateUserInfoAction = "create-user" | "link-account" | "sign-in";
|
|
|
53
53
|
type ValidateUserInfoMethod = "oauth" | "sso-oidc" | "sso-saml" | "email-password" | "magic-link" | "email-otp" | "anonymous" | "siwe" | "phone-number" | "admin" | (string & {});
|
|
54
54
|
/** OAuth-specific provisioning context; present only when `method` is `"oauth"`. */
|
|
55
55
|
type ValidateUserInfoOAuthInfo = {
|
|
56
|
-
/** The social or generic OAuth provider id (e.g. `"google"`). */
|
|
56
|
+
/** The social or generic OAuth provider id (e.g. `"google"`). */
|
|
57
|
+
providerId: string;
|
|
58
|
+
/** The raw provider profile (userinfo or id-token claims), unmapped. */
|
|
57
59
|
profile?: Record<string, unknown> | undefined;
|
|
58
60
|
};
|
|
59
61
|
/** SSO-specific provisioning context; present for OIDC and SAML SSO methods. */
|
|
60
62
|
type ValidateUserInfoSSOInfo = {
|
|
61
|
-
/** The configured SSO provider id. */
|
|
63
|
+
/** The configured SSO provider id. */
|
|
64
|
+
providerId: string;
|
|
65
|
+
/** The raw OIDC claims or SAML assertion attributes, unmapped. */
|
|
62
66
|
profile?: Record<string, unknown> | undefined;
|
|
63
67
|
};
|
|
64
68
|
/** Provisioning origin passed to `createUser`; the creation seam adds `action: "create-user"` to build {@link ValidateUserInfoSource}. */
|
|
65
69
|
type UserProvisioningSource = {
|
|
66
|
-
method: ValidateUserInfoMethod;
|
|
67
|
-
|
|
70
|
+
method: ValidateUserInfoMethod;
|
|
71
|
+
/** Provider id and raw profile; present iff `method` is `"oauth"`. */
|
|
72
|
+
oauth?: ValidateUserInfoOAuthInfo | undefined;
|
|
73
|
+
/** Provider id and raw profile; present iff `method` is `"sso-oidc"` or `"sso-saml"`. */
|
|
68
74
|
sso?: ValidateUserInfoSSOInfo | undefined;
|
|
69
75
|
};
|
|
70
76
|
/**
|
|
@@ -87,7 +93,8 @@ type ValidateUserInfoSource = UserProvisioningSource & {
|
|
|
87
93
|
action: ValidateUserInfoAction;
|
|
88
94
|
};
|
|
89
95
|
type ValidateUserInfoResult = {
|
|
90
|
-
/** A short, machine-readable rejection code, surfaced to the client. */
|
|
96
|
+
/** A short, machine-readable rejection code, surfaced to the client. */
|
|
97
|
+
error: string;
|
|
91
98
|
/**
|
|
92
99
|
* A human-readable reason, surfaced to the client. Do not put sensitive
|
|
93
100
|
* details here.
|
|
@@ -190,7 +197,7 @@ type BetterAuthDBOptions<ModelName extends string, Keys extends string = string>
|
|
|
190
197
|
/**
|
|
191
198
|
* Additional fields for the model
|
|
192
199
|
*/
|
|
193
|
-
additionalFields?: { [Key in Exclude<string, Keys | "id">]: DBFieldAttribute };
|
|
200
|
+
additionalFields?: { [Key in Exclude<string, Keys | "id">]: DBFieldAttribute; };
|
|
194
201
|
};
|
|
195
202
|
type BetterAuthRateLimitOptions = Optional<BetterAuthRateLimitRule> & Omit<BetterAuthDBOptions<"rateLimit", keyof BaseRateLimit>, "additionalFields"> & {
|
|
196
203
|
/**
|
|
@@ -370,11 +377,26 @@ type BetterAuthAdvancedOptions = {
|
|
|
370
377
|
* function.
|
|
371
378
|
*/
|
|
372
379
|
generateId?: GenerateIdFn | false | "serial" | "uuid";
|
|
380
|
+
/**
|
|
381
|
+
* Enable database joins for adapters that support them.
|
|
382
|
+
*
|
|
383
|
+
* When disabled (default), related data is fetched via
|
|
384
|
+
* separate queries. When enabled, adapters that support
|
|
385
|
+
* native joins use them; otherwise Better Auth falls back
|
|
386
|
+
* to separate queries.
|
|
387
|
+
*
|
|
388
|
+
* Please read the adapter documentation for more
|
|
389
|
+
* information regarding joins before enabling this.
|
|
390
|
+
* Not all adapters support joins.
|
|
391
|
+
*
|
|
392
|
+
* @default false
|
|
393
|
+
*/
|
|
394
|
+
joins?: boolean;
|
|
373
395
|
} | undefined;
|
|
374
396
|
/**
|
|
375
397
|
* Trusted proxy headers
|
|
376
398
|
*
|
|
377
|
-
|
|
399
|
+
* - `x-forwarded-host`
|
|
378
400
|
* - `x-forwarded-proto`
|
|
379
401
|
*
|
|
380
402
|
* If set to `true` and no `baseURL` option is provided, we will use the headers to infer the
|
|
@@ -764,15 +786,18 @@ type BetterAuthOptions = {
|
|
|
764
786
|
* ```
|
|
765
787
|
*/
|
|
766
788
|
customSyntheticUser?: (params: {
|
|
767
|
-
/** Core user fields: name, email, emailVerified, image, createdAt, updatedAt */
|
|
789
|
+
/** Core user fields: name, email, emailVerified, image, createdAt, updatedAt */
|
|
790
|
+
coreFields: {
|
|
768
791
|
name: string;
|
|
769
792
|
email: string;
|
|
770
793
|
emailVerified: boolean;
|
|
771
794
|
image: string | null;
|
|
772
795
|
createdAt: Date;
|
|
773
796
|
updatedAt: Date;
|
|
774
|
-
};
|
|
775
|
-
|
|
797
|
+
};
|
|
798
|
+
/** Processed additional fields from options.user.additionalFields (with defaults applied) */
|
|
799
|
+
additionalFields: Record<string, unknown>;
|
|
800
|
+
/** Generated user ID */
|
|
776
801
|
id: string;
|
|
777
802
|
}) => Record<string, unknown>;
|
|
778
803
|
} | undefined;
|
|
@@ -1509,20 +1534,6 @@ type BetterAuthOptions = {
|
|
|
1509
1534
|
*/
|
|
1510
1535
|
debug?: boolean;
|
|
1511
1536
|
} | undefined;
|
|
1512
|
-
/**
|
|
1513
|
-
* Experimental features
|
|
1514
|
-
*/
|
|
1515
|
-
experimental?: {
|
|
1516
|
-
/**
|
|
1517
|
-
* Enable experimental joins for your database adapter.
|
|
1518
|
-
*
|
|
1519
|
-
* Please read the adapter documentation for more information regarding joins before enabling this.
|
|
1520
|
-
* Not all adapters support joins.
|
|
1521
|
-
*
|
|
1522
|
-
* @default false
|
|
1523
|
-
*/
|
|
1524
|
-
joins?: boolean;
|
|
1525
|
-
};
|
|
1526
1537
|
};
|
|
1527
1538
|
//#endregion
|
|
1528
1539
|
export { BaseURLConfig, BetterAuthAdvancedOptions, BetterAuthDBOptions, BetterAuthOptions, BetterAuthRateLimitOptions, BetterAuthRateLimitRule, BetterAuthRateLimitStorage, DynamicBaseURLConfig, GenerateIdFn, StoreIdentifierOption, UserProvisioningSource, ValidateUserInfoAction, ValidateUserInfoMethod, ValidateUserInfoOAuthInfo, ValidateUserInfoResult, ValidateUserInfoSSOInfo, ValidateUserInfoSource };
|
|
@@ -2,7 +2,6 @@ import { LiteralString } from "./helper.mjs";
|
|
|
2
2
|
import { BetterAuthOptions } from "./init-options.mjs";
|
|
3
3
|
import { BetterFetch, BetterFetchOption, BetterFetchPlugin } from "@better-fetch/fetch";
|
|
4
4
|
import { Atom, WritableAtom } from "nanostores";
|
|
5
|
-
|
|
6
5
|
//#region src/types/plugin-client.d.ts
|
|
7
6
|
type InferableServerPlugin = {
|
|
8
7
|
id?: LiteralString | undefined;
|
|
@@ -89,7 +88,6 @@ interface BetterAuthClientPlugin {
|
|
|
89
88
|
/**
|
|
90
89
|
* better-auth client options
|
|
91
90
|
*/
|
|
92
|
-
|
|
93
91
|
options: BetterAuthClientOptions | undefined) => Record<string, any>;
|
|
94
92
|
/**
|
|
95
93
|
* State atoms that'll be resolved by each framework
|
|
@@ -120,4 +118,4 @@ interface BetterAuthClientPlugin {
|
|
|
120
118
|
}>;
|
|
121
119
|
}
|
|
122
120
|
//#endregion
|
|
123
|
-
export { BetterAuthClientOptions, BetterAuthClientPlugin, ClientAtomListener, ClientFetchOption, ClientStore };
|
|
121
|
+
export { BetterAuthClientOptions, BetterAuthClientPlugin, ClientAtomListener, ClientFetchOption, ClientStore, RevalidateOptions };
|
package/dist/types/plugin.d.mts
CHANGED
|
@@ -2,13 +2,13 @@ import { BetterAuthPluginDBSchema } from "../db/plugin.mjs";
|
|
|
2
2
|
import { Awaitable, LiteralString } from "./helper.mjs";
|
|
3
3
|
import { RawError } from "../utils/error-codes.mjs";
|
|
4
4
|
import { BetterAuthOptions } from "./init-options.mjs";
|
|
5
|
+
import "../db/index.mjs";
|
|
5
6
|
import { AuthContext } from "./context.mjs";
|
|
6
7
|
import { AuthMiddleware } from "../api/index.mjs";
|
|
7
8
|
import { Endpoint, EndpointContext, InputContext, Middleware } from "better-call";
|
|
8
9
|
import { Migration } from "kysely";
|
|
9
|
-
|
|
10
10
|
//#region src/types/plugin.d.ts
|
|
11
|
-
type DeepPartial<T> = T extends Function ? T : T extends object ? { [K in keyof T]?: DeepPartial<T[K]
|
|
11
|
+
type DeepPartial<T> = T extends Function ? T : T extends object ? { [K in keyof T]?: DeepPartial<T[K]>; } : T;
|
|
12
12
|
type HookEndpointContext = Partial<EndpointContext<string, any> & Omit<InputContext<string, any>, "method">> & {
|
|
13
13
|
path?: string;
|
|
14
14
|
context: AuthContext & {
|
package/dist/utils/async.d.mts
CHANGED
package/dist/utils/db.d.mts
CHANGED
|
@@ -3,11 +3,11 @@ type UpperLetter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "
|
|
|
3
3
|
type SpecialCharacter = "_";
|
|
4
4
|
type IsValidUpperSnakeCase<S extends string> = S extends `${infer F}${infer R}` ? F extends UpperLetter | SpecialCharacter ? IsValidUpperSnakeCase<R> : false : true;
|
|
5
5
|
type InvalidKeyError<K extends string> = `Invalid error code key: "${K}" - must only contain uppercase letters (A-Z) and underscores (_)`;
|
|
6
|
-
type ValidateErrorCodes<T> = { [K in keyof T]: K extends string ? IsValidUpperSnakeCase<K> extends false ? InvalidKeyError<K> : T[K] : T[K] };
|
|
6
|
+
type ValidateErrorCodes<T> = { [K in keyof T]: K extends string ? IsValidUpperSnakeCase<K> extends false ? InvalidKeyError<K> : T[K] : T[K]; };
|
|
7
7
|
type RawError<K extends string = string> = {
|
|
8
8
|
readonly code: K;
|
|
9
9
|
message: string;
|
|
10
10
|
};
|
|
11
|
-
declare function defineErrorCodes<const T extends Record<string, string>, R extends { [K in keyof T & string]: RawError<K
|
|
11
|
+
declare function defineErrorCodes<const T extends Record<string, string>, R extends { [K in keyof T & string]: RawError<K>; }>(codes: ValidateErrorCodes<T>): R;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { RawError, defineErrorCodes };
|
package/dist/utils/host.d.mts
CHANGED
|
@@ -26,7 +26,33 @@
|
|
|
26
26
|
* The semantic kind of a host, derived from RFC 6890 special-purpose registries
|
|
27
27
|
* plus a few domain-name categories (localhost, cloud metadata FQDNs).
|
|
28
28
|
*/
|
|
29
|
-
type HostKind =
|
|
29
|
+
type HostKind =
|
|
30
|
+
/** IPv4 `127.0.0.0/8` or IPv6 `::1`. */
|
|
31
|
+
"loopback" |
|
|
32
|
+
/** DNS name `localhost` or RFC 6761 `.localhost` TLD. */
|
|
33
|
+
"localhost" |
|
|
34
|
+
/** IPv4 `0.0.0.0` or IPv6 `::` — "this host on this network", not loopback. */
|
|
35
|
+
"unspecified" |
|
|
36
|
+
/** RFC 1918 `10/8`, `172.16/12`, `192.168/16`, or IPv6 ULA `fc00::/7`. */
|
|
37
|
+
"private" |
|
|
38
|
+
/** IPv4 `169.254/16` or IPv6 `fe80::/10`. Includes AWS IMDS `169.254.169.254`. */
|
|
39
|
+
"linkLocal" |
|
|
40
|
+
/** RFC 6598 carrier-grade NAT `100.64.0.0/10`. */
|
|
41
|
+
"sharedAddressSpace" |
|
|
42
|
+
/** RFC 5737 `192.0.2/24`, `198.51.100/24`, `203.0.113/24`, or RFC 3849 `2001:db8::/32`. */
|
|
43
|
+
"documentation" |
|
|
44
|
+
/** RFC 2544 `198.18.0.0/15`. */
|
|
45
|
+
"benchmarking" |
|
|
46
|
+
/** IPv4 `224.0.0.0/4` or IPv6 `ff00::/8`. */
|
|
47
|
+
"multicast" |
|
|
48
|
+
/** IPv4 limited broadcast `255.255.255.255`. */
|
|
49
|
+
"broadcast" |
|
|
50
|
+
/** Other RFC 6890 special-purpose ranges (0.0.0.0/8, 192.0.0.0/24, 192.88.99.0/24, 240.0.0.0/4, 2001::/32, etc.). */
|
|
51
|
+
"reserved" |
|
|
52
|
+
/** Cloud metadata service FQDN (e.g. `metadata.google.internal`). */
|
|
53
|
+
"cloudMetadata" |
|
|
54
|
+
/** Any host not matching a special-purpose range above. */
|
|
55
|
+
"public";
|
|
30
56
|
/**
|
|
31
57
|
* The syntactic form of the input host: an IPv4 literal, an IPv6 literal, or
|
|
32
58
|
* a domain name. IPv4-mapped IPv6 (`::ffff:192.0.2.1`) is reported as `ipv4`
|
package/dist/utils/host.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { isValidIP, normalizeIP } from "./ip.mjs";
|
|
|
9
9
|
* only exists for the FQDN form that a naive server-side fetch might resolve
|
|
10
10
|
* via its own resolver.
|
|
11
11
|
*/
|
|
12
|
-
const CLOUD_METADATA_HOSTS = new Set([
|
|
12
|
+
const CLOUD_METADATA_HOSTS = /* @__PURE__ */ new Set([
|
|
13
13
|
"metadata.google.internal",
|
|
14
14
|
"metadata.goog",
|
|
15
15
|
"metadata",
|
package/dist/utils/ip.d.mts
CHANGED
package/dist/utils/ip.mjs
CHANGED
|
@@ -111,7 +111,7 @@ function ipToBytes(ip) {
|
|
|
111
111
|
const mapped = extractIPv4FromMapped(ip);
|
|
112
112
|
if (mapped) return Uint8Array.from(mapped.split(".").map((octet) => Number(octet)));
|
|
113
113
|
const groups = expandIPv6(ip);
|
|
114
|
-
const bytes = new Uint8Array(16);
|
|
114
|
+
const bytes = /* @__PURE__ */ new Uint8Array(16);
|
|
115
115
|
for (let i = 0; i < 8; i++) {
|
|
116
116
|
const group = Number.parseInt(groups[i] ?? "0", 16);
|
|
117
117
|
bytes[i * 2] = group >> 8 & 255;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/core",
|
|
3
|
-
"version": "1.7.0-rc.
|
|
3
|
+
"version": "1.7.0-rc.2",
|
|
4
4
|
"description": "The most comprehensive authentication framework for TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -80,6 +80,11 @@
|
|
|
80
80
|
"types": "./dist/db/index.d.mts",
|
|
81
81
|
"default": "./dist/db/index.mjs"
|
|
82
82
|
},
|
|
83
|
+
"./db/internal": {
|
|
84
|
+
"dev-source": "./src/db/internal.ts",
|
|
85
|
+
"types": "./dist/db/internal.d.mts",
|
|
86
|
+
"default": "./dist/db/internal.mjs"
|
|
87
|
+
},
|
|
83
88
|
"./db/adapter": {
|
|
84
89
|
"dev-source": "./src/db/adapter/index.ts",
|
|
85
90
|
"types": "./dist/db/adapter/index.d.mts",
|
|
@@ -135,6 +140,9 @@
|
|
|
135
140
|
"db": [
|
|
136
141
|
"dist/db/index.d.mts"
|
|
137
142
|
],
|
|
143
|
+
"db/internal": [
|
|
144
|
+
"dist/db/internal.d.mts"
|
|
145
|
+
],
|
|
138
146
|
"db/adapter": [
|
|
139
147
|
"dist/db/adapter/index.d.mts"
|
|
140
148
|
],
|
|
@@ -162,7 +170,7 @@
|
|
|
162
170
|
"jose": "^6.2.3",
|
|
163
171
|
"kysely": "^0.28.17 || ^0.29.0",
|
|
164
172
|
"nanostores": "^1.3.0",
|
|
165
|
-
"tsdown": "0.
|
|
173
|
+
"tsdown": "0.22.7"
|
|
166
174
|
},
|
|
167
175
|
"peerDependencies": {
|
|
168
176
|
"@better-auth/utils": "0.4.2",
|
|
@@ -4,15 +4,35 @@ import { __getBetterAuthGlobal } from "./global";
|
|
|
4
4
|
|
|
5
5
|
export type RequestStateWeakMap = WeakMap<object, any>;
|
|
6
6
|
|
|
7
|
+
// Memoizes the in-flight AsyncLocalStorage initialization so concurrent
|
|
8
|
+
// first-callers share a single instance instead of each constructing one.
|
|
9
|
+
let asyncStorageInit: Promise<AsyncLocalStorage<RequestStateWeakMap>> | null =
|
|
10
|
+
null;
|
|
11
|
+
|
|
7
12
|
const ensureAsyncStorage = async () => {
|
|
8
13
|
const betterAuthGlobal = __getBetterAuthGlobal();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
const existing = betterAuthGlobal.context.requestStateAsyncStorage;
|
|
15
|
+
if (existing) {
|
|
16
|
+
return existing as AsyncLocalStorage<RequestStateWeakMap>;
|
|
17
|
+
}
|
|
18
|
+
// Without memoizing the init, several concurrent callers can each pass the
|
|
19
|
+
// check above, each `await getAsyncLocalStorage()`, and each assign a fresh
|
|
20
|
+
// instance — last write wins. `runWithRequestState().run()` then executes on
|
|
21
|
+
// one instance while a nested `getCurrentRequestState()` reads the
|
|
22
|
+
// overwritten one, throwing "No request state found". This shows up
|
|
23
|
+
// intermittently on serverless cold start (e.g. Cloudflare Workers), where
|
|
24
|
+
// the first requests hit before the lazy `node:async_hooks` import settles.
|
|
25
|
+
// The idempotent `??=` keeps the global singleton stable even if multiple
|
|
26
|
+
// BetterAuth copies (Dual Module Hazard) race here.
|
|
27
|
+
if (!asyncStorageInit) {
|
|
28
|
+
asyncStorageInit = getAsyncLocalStorage().then((AsyncLocalStorage) => {
|
|
29
|
+
betterAuthGlobal.context.requestStateAsyncStorage ??=
|
|
30
|
+
new AsyncLocalStorage<RequestStateWeakMap>();
|
|
31
|
+
return betterAuthGlobal.context
|
|
32
|
+
.requestStateAsyncStorage as AsyncLocalStorage<RequestStateWeakMap>;
|
|
33
|
+
});
|
|
13
34
|
}
|
|
14
|
-
return
|
|
15
|
-
.requestStateAsyncStorage as AsyncLocalStorage<RequestStateWeakMap>;
|
|
35
|
+
return asyncStorageInit;
|
|
16
36
|
};
|
|
17
37
|
|
|
18
38
|
export async function getRequestStateAsyncLocalStorage() {
|
|
@@ -100,6 +100,9 @@ export const runWithTransaction = async <
|
|
|
100
100
|
>(
|
|
101
101
|
adapter: DBAdapter<Options>,
|
|
102
102
|
fn: () => R,
|
|
103
|
+
options?: {
|
|
104
|
+
onAfterCommitHookError?: (error: unknown) => void | Promise<void>;
|
|
105
|
+
},
|
|
103
106
|
): Promise<R> => {
|
|
104
107
|
let called = false;
|
|
105
108
|
return ensureAsyncStorage()
|
|
@@ -128,12 +131,21 @@ export const runWithTransaction = async <
|
|
|
128
131
|
hasError = true;
|
|
129
132
|
error = e;
|
|
130
133
|
}
|
|
131
|
-
for (const hook of pendingHooks) {
|
|
132
|
-
await hook();
|
|
133
|
-
}
|
|
134
134
|
if (hasError) {
|
|
135
135
|
throw error;
|
|
136
136
|
}
|
|
137
|
+
for (const hook of pendingHooks) {
|
|
138
|
+
try {
|
|
139
|
+
await hook();
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (!options?.onAfterCommitHookError) throw error;
|
|
142
|
+
try {
|
|
143
|
+
await options.onAfterCommitHookError(error);
|
|
144
|
+
} catch {
|
|
145
|
+
// Reporting cannot roll back committed work or suppress later hooks.
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
137
149
|
return result!;
|
|
138
150
|
})
|
|
139
151
|
.catch((err) => {
|
|
@@ -150,20 +162,27 @@ export const runWithTransaction = async <
|
|
|
150
162
|
*/
|
|
151
163
|
export const queueAfterTransactionHook = async (
|
|
152
164
|
hook: () => Promise<void>,
|
|
165
|
+
options?: {
|
|
166
|
+
/** Handles a queued hook failure after the surrounding work has committed. */
|
|
167
|
+
onError?: (error: unknown) => void | Promise<void>;
|
|
168
|
+
},
|
|
153
169
|
): Promise<void> => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
170
|
+
const executeHook = async () => {
|
|
171
|
+
try {
|
|
172
|
+
await hook();
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (!options?.onError) throw error;
|
|
175
|
+
await options.onError(error);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
let storage: Awaited<ReturnType<typeof ensureAsyncStorage>>;
|
|
179
|
+
try {
|
|
180
|
+
storage = await ensureAsyncStorage();
|
|
181
|
+
} catch {
|
|
182
|
+
return executeHook();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const store = storage.getStore();
|
|
186
|
+
if (!store?.isTransactionActive) return executeHook();
|
|
187
|
+
store.pendingHooks.push(executeHook);
|
|
169
188
|
};
|
|
@@ -425,19 +425,19 @@ export const createAdapterFactory =
|
|
|
425
425
|
joinConfig,
|
|
426
426
|
} of requiredModels) {
|
|
427
427
|
let joinedData = await (async () => {
|
|
428
|
-
if (options.
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
baseModel: unsafe_model,
|
|
435
|
-
baseData: transformedData,
|
|
436
|
-
joinModel: modelName,
|
|
437
|
-
specificJoinConfig: joinConfig,
|
|
438
|
-
});
|
|
439
|
-
return result;
|
|
428
|
+
if (options.advanced?.database?.joins) {
|
|
429
|
+
// Use native joined data when the adapter included the key;
|
|
430
|
+
// otherwise fall back to separate queries.
|
|
431
|
+
if (modelName in data) {
|
|
432
|
+
return data[modelName];
|
|
433
|
+
}
|
|
440
434
|
}
|
|
435
|
+
return await handleFallbackJoin({
|
|
436
|
+
baseModel: unsafe_model,
|
|
437
|
+
baseData: transformedData,
|
|
438
|
+
joinModel: modelName,
|
|
439
|
+
specificJoinConfig: joinConfig,
|
|
440
|
+
});
|
|
441
441
|
})();
|
|
442
442
|
|
|
443
443
|
// If joinedData is undefined, initialize it based on relationship type
|
|
@@ -1118,9 +1118,12 @@ export const createAdapterFactory =
|
|
|
1118
1118
|
join = result.join;
|
|
1119
1119
|
select = result.select;
|
|
1120
1120
|
}
|
|
1121
|
-
// If
|
|
1122
|
-
|
|
1123
|
-
|
|
1121
|
+
// If joins are disabled and we have joins, don't pass them to the adapter
|
|
1122
|
+
if (
|
|
1123
|
+
!options.advanced?.database?.joins &&
|
|
1124
|
+
join &&
|
|
1125
|
+
Object.keys(join).length > 0
|
|
1126
|
+
) {
|
|
1124
1127
|
passJoinToAdapter = false;
|
|
1125
1128
|
}
|
|
1126
1129
|
} else {
|
|
@@ -1206,9 +1209,12 @@ export const createAdapterFactory =
|
|
|
1206
1209
|
join = result.join;
|
|
1207
1210
|
select = result.select;
|
|
1208
1211
|
}
|
|
1209
|
-
// If
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
+
// If joins are disabled and we have joins, don't pass them to the adapter
|
|
1213
|
+
if (
|
|
1214
|
+
!options.advanced?.database?.joins &&
|
|
1215
|
+
join &&
|
|
1216
|
+
Object.keys(join).length > 0
|
|
1217
|
+
) {
|
|
1212
1218
|
passJoinToAdapter = false;
|
|
1213
1219
|
}
|
|
1214
1220
|
} else {
|
|
@@ -20,26 +20,35 @@ export const initGetDefaultModelName = ({
|
|
|
20
20
|
* 3. Using this function helps us get the actual model name based on the user's defined custom modelName.
|
|
21
21
|
*/
|
|
22
22
|
const getDefaultModelName = (model: string) => {
|
|
23
|
+
// Resolve a model string (either a schema key or a user-defined
|
|
24
|
+
// `modelName`) back to its canonical schema key.
|
|
25
|
+
//
|
|
26
|
+
// An exact schema-key match must win over a `modelName` match.
|
|
27
|
+
// Better-auth internals (and `references.model`, see get-tables.ts)
|
|
28
|
+
// always pass canonical schema keys, so when a user remaps a
|
|
29
|
+
// built-in table onto another table's schema key (e.g.
|
|
30
|
+
// `user.modelName = "account"`), preferring the modelName alias
|
|
31
|
+
// would silently reroute every internal "account" query to the
|
|
32
|
+
// user table. The modelName lookup is only a fallback for
|
|
33
|
+
// externally supplied physical table names.
|
|
34
|
+
// @see https://github.com/better-auth/better-auth/issues/8111
|
|
35
|
+
// @see https://github.com/better-auth/better-auth/issues/10136
|
|
36
|
+
const resolve = (candidate: string): string | undefined => {
|
|
37
|
+
if (schema[candidate]) return candidate;
|
|
38
|
+
return Object.entries(schema).find(
|
|
39
|
+
([_, f]) => f.modelName === candidate,
|
|
40
|
+
)?.[0];
|
|
41
|
+
};
|
|
42
|
+
|
|
23
43
|
// It's possible this `model` could had applied `usePlural`.
|
|
24
44
|
// Thus we'll try the search but without the trailing `s`.
|
|
25
45
|
if (usePlural && model.charAt(model.length - 1) === "s") {
|
|
26
46
|
const pluralessModel = model.slice(0, -1);
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
m = Object.entries(schema).find(
|
|
30
|
-
([_, f]) => f.modelName === pluralessModel,
|
|
31
|
-
)?.[0];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (m) {
|
|
35
|
-
return m;
|
|
36
|
-
}
|
|
47
|
+
const m = resolve(pluralessModel);
|
|
48
|
+
if (m) return m;
|
|
37
49
|
}
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
if (!m) {
|
|
41
|
-
m = Object.entries(schema).find(([_, f]) => f.modelName === model)?.[0];
|
|
42
|
-
}
|
|
51
|
+
const m = resolve(model);
|
|
43
52
|
|
|
44
53
|
if (!m) {
|
|
45
54
|
throw new BetterAuthError(`Model "${model}" not found in schema`);
|