@better-auth/core 1.5.0-beta.9 → 1.5.0
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 +17 -0
- package/dist/api/index.d.mts +144 -41
- package/dist/api/index.mjs +2 -1
- package/dist/api/index.mjs.map +1 -0
- package/dist/async_hooks/index.d.mts +2 -1
- package/dist/async_hooks/index.mjs +2 -1
- package/dist/async_hooks/index.mjs.map +1 -0
- package/dist/async_hooks/pure.index.d.mts +2 -1
- package/dist/async_hooks/pure.index.mjs +2 -1
- package/dist/async_hooks/pure.index.mjs.map +1 -0
- package/dist/context/endpoint-context.d.mts +2 -1
- package/dist/context/endpoint-context.mjs +4 -3
- package/dist/context/endpoint-context.mjs.map +1 -0
- package/dist/context/global.d.mts +2 -2
- package/dist/context/global.mjs +3 -2
- package/dist/context/global.mjs.map +1 -0
- package/dist/context/request-state.d.mts +2 -1
- package/dist/context/request-state.mjs +4 -3
- package/dist/context/request-state.mjs.map +1 -0
- package/dist/context/transaction.d.mts +2 -1
- package/dist/context/transaction.mjs +4 -3
- package/dist/context/transaction.mjs.map +1 -0
- package/dist/db/adapter/factory.d.mts +6 -13
- package/dist/db/adapter/factory.mjs +44 -57
- package/dist/db/adapter/factory.mjs.map +1 -0
- package/dist/db/adapter/get-default-field-name.d.mts +2 -1
- package/dist/db/adapter/get-default-field-name.mjs +3 -2
- package/dist/db/adapter/get-default-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-default-model-name.d.mts +2 -1
- package/dist/db/adapter/get-default-model-name.mjs +5 -4
- package/dist/db/adapter/get-default-model-name.mjs.map +1 -0
- package/dist/db/adapter/get-field-attributes.d.mts +3 -2
- package/dist/db/adapter/get-field-attributes.mjs +2 -1
- package/dist/db/adapter/get-field-attributes.mjs.map +1 -0
- package/dist/db/adapter/get-field-name.d.mts +2 -1
- package/dist/db/adapter/get-field-name.mjs +2 -1
- package/dist/db/adapter/get-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-id-field.d.mts +3 -2
- package/dist/db/adapter/get-id-field.mjs +3 -2
- package/dist/db/adapter/get-id-field.mjs.map +1 -0
- package/dist/db/adapter/get-model-name.d.mts +2 -1
- package/dist/db/adapter/get-model-name.mjs +2 -1
- package/dist/db/adapter/get-model-name.mjs.map +1 -0
- package/dist/db/adapter/index.d.mts +10 -4
- package/dist/db/adapter/index.mjs +19 -2
- package/dist/db/adapter/index.mjs.map +1 -0
- package/dist/db/adapter/types.d.mts +3 -34
- package/dist/db/adapter/utils.d.mts +2 -1
- package/dist/db/adapter/utils.mjs +2 -1
- package/dist/db/adapter/utils.mjs.map +1 -0
- package/dist/db/get-tables.d.mts +2 -1
- package/dist/db/get-tables.mjs +46 -39
- package/dist/db/get-tables.mjs.map +1 -0
- package/dist/db/index.d.mts +7 -7
- package/dist/db/plugin.d.mts +2 -1
- package/dist/db/schema/account.d.mts +8 -4
- package/dist/db/schema/account.mjs +2 -1
- package/dist/db/schema/account.mjs.map +1 -0
- package/dist/db/schema/rate-limit.d.mts +8 -2
- package/dist/db/schema/rate-limit.mjs +2 -1
- package/dist/db/schema/rate-limit.mjs.map +1 -0
- package/dist/db/schema/session.d.mts +8 -4
- package/dist/db/schema/session.mjs +2 -1
- package/dist/db/schema/session.mjs.map +1 -0
- package/dist/db/schema/shared.d.mts +2 -1
- package/dist/db/schema/shared.mjs +2 -1
- package/dist/db/schema/shared.mjs.map +1 -0
- package/dist/db/schema/user.d.mts +8 -4
- package/dist/db/schema/user.mjs +2 -1
- package/dist/db/schema/user.mjs.map +1 -0
- package/dist/db/schema/verification.d.mts +8 -4
- package/dist/db/schema/verification.mjs +2 -1
- package/dist/db/schema/verification.mjs.map +1 -0
- package/dist/db/type.d.mts +28 -2
- package/dist/env/color-depth.d.mts +2 -1
- package/dist/env/color-depth.mjs +2 -1
- package/dist/env/color-depth.mjs.map +1 -0
- package/dist/env/env-impl.d.mts +3 -2
- package/dist/env/env-impl.mjs +9 -8
- package/dist/env/env-impl.mjs.map +1 -0
- package/dist/env/logger.d.mts +2 -1
- package/dist/env/logger.mjs +3 -2
- package/dist/env/logger.mjs.map +1 -0
- package/dist/error/codes.d.mts +64 -181
- package/dist/error/codes.mjs +6 -2
- package/dist/error/codes.mjs.map +1 -0
- package/dist/error/index.d.mts +2 -1
- package/dist/error/index.mjs +2 -1
- package/dist/error/index.mjs.map +1 -0
- package/dist/index.d.mts +5 -4
- package/dist/oauth2/client-credentials-token.d.mts +25 -3
- package/dist/oauth2/client-credentials-token.mjs +15 -2
- package/dist/oauth2/client-credentials-token.mjs.map +1 -0
- package/dist/oauth2/create-authorization-url.d.mts +5 -2
- package/dist/oauth2/create-authorization-url.mjs +3 -1
- package/dist/oauth2/create-authorization-url.mjs.map +1 -0
- package/dist/oauth2/index.d.mts +4 -4
- package/dist/oauth2/index.mjs +4 -4
- package/dist/oauth2/oauth-provider.d.mts +3 -2
- package/dist/oauth2/refresh-access-token.d.mts +24 -4
- package/dist/oauth2/refresh-access-token.mjs +20 -2
- package/dist/oauth2/refresh-access-token.mjs.map +1 -0
- package/dist/oauth2/utils.d.mts +2 -1
- package/dist/oauth2/utils.mjs +2 -1
- package/dist/oauth2/utils.mjs.map +1 -0
- package/dist/oauth2/validate-authorization-code.d.mts +37 -4
- package/dist/oauth2/validate-authorization-code.mjs +25 -13
- package/dist/oauth2/validate-authorization-code.mjs.map +1 -0
- package/dist/oauth2/verify.d.mts +7 -13
- package/dist/oauth2/verify.mjs +2 -1
- package/dist/oauth2/verify.mjs.map +1 -0
- package/dist/social-providers/apple.d.mts +2 -1
- package/dist/social-providers/apple.mjs +22 -21
- package/dist/social-providers/apple.mjs.map +1 -0
- package/dist/social-providers/atlassian.d.mts +2 -1
- package/dist/social-providers/atlassian.mjs +2 -1
- package/dist/social-providers/atlassian.mjs.map +1 -0
- package/dist/social-providers/cognito.d.mts +2 -1
- package/dist/social-providers/cognito.mjs +4 -3
- package/dist/social-providers/cognito.mjs.map +1 -0
- package/dist/social-providers/discord.d.mts +2 -1
- package/dist/social-providers/discord.mjs +2 -1
- package/dist/social-providers/discord.mjs.map +1 -0
- package/dist/social-providers/dropbox.d.mts +2 -1
- package/dist/social-providers/dropbox.mjs +2 -1
- package/dist/social-providers/dropbox.mjs.map +1 -0
- package/dist/social-providers/facebook.d.mts +2 -1
- package/dist/social-providers/facebook.mjs +13 -12
- package/dist/social-providers/facebook.mjs.map +1 -0
- package/dist/social-providers/figma.d.mts +2 -1
- package/dist/social-providers/figma.mjs +2 -1
- package/dist/social-providers/figma.mjs.map +1 -0
- package/dist/social-providers/github.d.mts +3 -2
- package/dist/social-providers/github.mjs +23 -6
- package/dist/social-providers/github.mjs.map +1 -0
- package/dist/social-providers/gitlab.d.mts +2 -1
- package/dist/social-providers/gitlab.mjs +3 -2
- package/dist/social-providers/gitlab.mjs.map +1 -0
- package/dist/social-providers/google.d.mts +2 -1
- package/dist/social-providers/google.mjs +18 -13
- package/dist/social-providers/google.mjs.map +1 -0
- package/dist/social-providers/huggingface.d.mts +2 -1
- package/dist/social-providers/huggingface.mjs +3 -2
- package/dist/social-providers/huggingface.mjs.map +1 -0
- package/dist/social-providers/index.d.mts +61 -8
- package/dist/social-providers/index.mjs +5 -2
- package/dist/social-providers/index.mjs.map +1 -0
- package/dist/social-providers/kakao.d.mts +3 -2
- package/dist/social-providers/kakao.mjs +3 -2
- package/dist/social-providers/kakao.mjs.map +1 -0
- package/dist/social-providers/kick.d.mts +2 -1
- package/dist/social-providers/kick.mjs +2 -1
- package/dist/social-providers/kick.mjs.map +1 -0
- package/dist/social-providers/line.d.mts +2 -1
- package/dist/social-providers/line.mjs +3 -2
- package/dist/social-providers/line.mjs.map +1 -0
- package/dist/social-providers/linear.d.mts +2 -1
- package/dist/social-providers/linear.mjs +2 -1
- package/dist/social-providers/linear.mjs.map +1 -0
- package/dist/social-providers/linkedin.d.mts +2 -1
- package/dist/social-providers/linkedin.mjs +2 -1
- package/dist/social-providers/linkedin.mjs.map +1 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +4 -1
- package/dist/social-providers/microsoft-entra-id.mjs +36 -2
- package/dist/social-providers/microsoft-entra-id.mjs.map +1 -0
- package/dist/social-providers/naver.d.mts +11 -20
- package/dist/social-providers/naver.mjs +3 -2
- package/dist/social-providers/naver.mjs.map +1 -0
- package/dist/social-providers/notion.d.mts +2 -1
- package/dist/social-providers/notion.mjs +3 -2
- package/dist/social-providers/notion.mjs.map +1 -0
- package/dist/social-providers/paybin.d.mts +2 -1
- package/dist/social-providers/paybin.mjs +3 -2
- package/dist/social-providers/paybin.mjs.map +1 -0
- package/dist/social-providers/paypal.d.mts +2 -1
- package/dist/social-providers/paypal.mjs +2 -1
- package/dist/social-providers/paypal.mjs.map +1 -0
- package/dist/social-providers/polar.d.mts +2 -1
- package/dist/social-providers/polar.mjs +3 -2
- package/dist/social-providers/polar.mjs.map +1 -0
- package/dist/social-providers/railway.d.mts +68 -0
- package/dist/social-providers/railway.mjs +78 -0
- package/dist/social-providers/railway.mjs.map +1 -0
- package/dist/social-providers/reddit.d.mts +2 -1
- package/dist/social-providers/reddit.mjs +2 -1
- package/dist/social-providers/reddit.mjs.map +1 -0
- package/dist/social-providers/roblox.d.mts +2 -1
- package/dist/social-providers/roblox.mjs +2 -1
- package/dist/social-providers/roblox.mjs.map +1 -0
- package/dist/social-providers/salesforce.d.mts +2 -1
- package/dist/social-providers/salesforce.mjs +2 -1
- package/dist/social-providers/salesforce.mjs.map +1 -0
- package/dist/social-providers/slack.d.mts +2 -1
- package/dist/social-providers/slack.mjs +2 -1
- package/dist/social-providers/slack.mjs.map +1 -0
- package/dist/social-providers/spotify.d.mts +2 -1
- package/dist/social-providers/spotify.mjs +2 -1
- package/dist/social-providers/spotify.mjs.map +1 -0
- package/dist/social-providers/tiktok.d.mts +3 -3
- package/dist/social-providers/tiktok.mjs +3 -2
- package/dist/social-providers/tiktok.mjs.map +1 -0
- package/dist/social-providers/twitch.d.mts +2 -1
- package/dist/social-providers/twitch.mjs +2 -1
- package/dist/social-providers/twitch.mjs.map +1 -0
- package/dist/social-providers/twitter.d.mts +14 -25
- package/dist/social-providers/twitter.mjs +2 -1
- package/dist/social-providers/twitter.mjs.map +1 -0
- package/dist/social-providers/vercel.d.mts +2 -1
- package/dist/social-providers/vercel.mjs +3 -2
- package/dist/social-providers/vercel.mjs.map +1 -0
- package/dist/social-providers/vk.d.mts +2 -1
- package/dist/social-providers/vk.mjs +2 -1
- package/dist/social-providers/vk.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +3 -10
- package/dist/social-providers/zoom.mjs +2 -1
- package/dist/social-providers/zoom.mjs.map +1 -0
- package/dist/types/context.d.mts +53 -21
- package/dist/types/cookie.d.mts +2 -1
- package/dist/types/helper.d.mts +4 -1
- package/dist/types/index.d.mts +4 -3
- package/dist/types/init-options.d.mts +231 -159
- package/dist/types/plugin-client.d.mts +4 -1
- package/dist/types/plugin.d.mts +12 -11
- package/dist/types/secret.d.mts +12 -0
- package/dist/utils/db.d.mts +12 -0
- package/dist/utils/db.mjs +17 -0
- package/dist/utils/db.mjs.map +1 -0
- package/dist/utils/deprecate.d.mts +2 -2
- package/dist/utils/deprecate.mjs +2 -1
- package/dist/utils/deprecate.mjs.map +1 -0
- package/dist/utils/error-codes.d.mts +8 -6
- package/dist/utils/error-codes.mjs +3 -2
- package/dist/utils/error-codes.mjs.map +1 -0
- package/dist/utils/id.d.mts +2 -1
- package/dist/utils/id.mjs +2 -1
- package/dist/utils/id.mjs.map +1 -0
- package/dist/utils/ip.d.mts +2 -1
- package/dist/utils/ip.mjs +2 -1
- package/dist/utils/ip.mjs.map +1 -0
- package/dist/utils/json.d.mts +2 -1
- package/dist/utils/json.mjs +2 -1
- package/dist/utils/json.mjs.map +1 -0
- package/dist/utils/string.d.mts +2 -1
- package/dist/utils/string.mjs +2 -1
- package/dist/utils/string.mjs.map +1 -0
- package/dist/utils/url.d.mts +2 -1
- package/dist/utils/url.mjs +2 -1
- package/dist/utils/url.mjs.map +1 -0
- package/package.json +35 -13
- package/src/db/adapter/factory.ts +41 -73
- package/src/db/adapter/get-id-field.ts +1 -3
- package/src/db/adapter/index.ts +20 -15
- package/src/db/adapter/types.ts +2 -41
- package/src/db/get-tables.ts +48 -37
- package/src/db/index.ts +30 -5
- package/src/db/schema/account.ts +16 -3
- package/src/db/schema/rate-limit.ts +16 -1
- package/src/db/schema/session.ts +15 -3
- package/src/db/schema/user.ts +15 -3
- package/src/db/schema/verification.ts +16 -3
- package/src/db/test/get-tables.test.ts +33 -0
- package/src/db/type.ts +154 -1
- package/src/env/env-impl.ts +2 -2
- package/src/env/logger.ts +1 -1
- package/src/error/codes.ts +17 -0
- package/src/oauth2/client-credentials-token.ts +26 -2
- package/src/oauth2/create-authorization-url.ts +3 -1
- package/src/oauth2/index.ts +3 -0
- package/src/oauth2/oauth-provider.ts +1 -1
- package/src/oauth2/refresh-access-token.test.ts +90 -0
- package/src/oauth2/refresh-access-token.ts +37 -4
- package/src/oauth2/validate-authorization-code.ts +55 -24
- package/src/oauth2/validate-token.test.ts +107 -52
- package/src/social-providers/apple.ts +29 -29
- package/src/social-providers/cognito.ts +6 -5
- package/src/social-providers/facebook.ts +3 -3
- package/src/social-providers/github.ts +26 -4
- package/src/social-providers/gitlab.ts +1 -1
- package/src/social-providers/google.ts +18 -14
- package/src/social-providers/huggingface.ts +1 -1
- package/src/social-providers/index.ts +9 -5
- package/src/social-providers/kakao.ts +1 -1
- package/src/social-providers/line.ts +1 -1
- package/src/social-providers/microsoft-entra-id.ts +84 -1
- package/src/social-providers/naver.ts +1 -1
- package/src/social-providers/notion.ts +1 -1
- package/src/social-providers/paybin.ts +1 -5
- package/src/social-providers/polar.ts +1 -1
- package/src/social-providers/railway.ts +100 -0
- package/src/social-providers/tiktok.ts +2 -1
- package/src/social-providers/vercel.ts +1 -1
- package/src/social-providers/zoom.ts +0 -8
- package/src/types/context.ts +74 -14
- package/src/types/helper.ts +9 -0
- package/src/types/index.ts +14 -2
- package/src/types/init-options.ts +294 -186
- package/src/types/plugin-client.ts +1 -0
- package/src/types/plugin.ts +11 -6
- package/src/types/secret.ts +8 -0
- package/src/utils/db.ts +20 -0
- package/src/utils/deprecate.test.ts +0 -1
- package/src/utils/error-codes.ts +12 -9
- package/.turbo/turbo-build.log +0 -182
- package/tsconfig.json +0 -7
- package/tsdown.config.ts +0 -32
- package/vitest.config.ts +0 -3
package/dist/utils/deprecate.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deprecate.mjs","names":[],"sources":["../../src/utils/deprecate.ts"],"sourcesContent":["import type { InternalLogger } from \"../env\";\n\n/**\n * Wraps a function to log a deprecation warning at once.\n */\nexport function deprecate<T extends (...args: any[]) => any>(\n\tfn: T,\n\tmessage: string,\n\tlogger?: InternalLogger,\n): T {\n\tlet warned = false;\n\n\treturn function (this: any, ...args: Parameters<T>): ReturnType<T> {\n\t\tif (!warned) {\n\t\t\tconst warn = logger?.warn ?? console.warn;\n\t\t\twarn(`[Deprecation] ${message}`);\n\t\t\twarned = true;\n\t\t}\n\t\treturn fn.apply(this, args);\n\t} as T;\n}\n"],"mappings":";;;;AAKA,SAAgB,UACf,IACA,SACA,QACI;CACJ,IAAI,SAAS;AAEb,QAAO,SAAqB,GAAG,MAAoC;AAClE,MAAI,CAAC,QAAQ;AAEZ,IADa,QAAQ,QAAQ,QAAQ,MAChC,iBAAiB,UAAU;AAChC,YAAS;;AAEV,SAAO,GAAG,MAAM,MAAM,KAAK"}
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
type UpperLetter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z";
|
|
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
|
-
type InvalidKeyError<K
|
|
5
|
+
type InvalidKeyError<K extends string> = `Invalid error code key: "${K}" - must only contain uppercase letters (A-Z) and underscores (_)`;
|
|
6
6
|
type ValidateErrorCodes<T> = { [K in keyof T]: K extends string ? IsValidUpperSnakeCase<K> extends false ? InvalidKeyError<K> : T[K] : T[K] };
|
|
7
|
-
|
|
8
|
-
code: K;
|
|
9
|
-
message:
|
|
10
|
-
}
|
|
7
|
+
type RawError<K extends string = string> = {
|
|
8
|
+
readonly code: K;
|
|
9
|
+
message: string;
|
|
10
|
+
};
|
|
11
|
+
declare function defineErrorCodes<const T extends Record<string, string>, R extends { [K in keyof T & string]: RawError<K> }>(codes: ValidateErrorCodes<T>): R;
|
|
11
12
|
//#endregion
|
|
12
|
-
export { defineErrorCodes };
|
|
13
|
+
export { RawError, defineErrorCodes };
|
|
14
|
+
//# sourceMappingURL=error-codes.d.mts.map
|
|
@@ -3,9 +3,10 @@ function defineErrorCodes(codes) {
|
|
|
3
3
|
return Object.fromEntries(Object.entries(codes).map(([key, value]) => [key, {
|
|
4
4
|
code: key,
|
|
5
5
|
message: value,
|
|
6
|
-
toString: () =>
|
|
6
|
+
toString: () => key
|
|
7
7
|
}]));
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
//#endregion
|
|
11
|
-
export { defineErrorCodes };
|
|
11
|
+
export { defineErrorCodes };
|
|
12
|
+
//# sourceMappingURL=error-codes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codes.mjs","names":[],"sources":["../../src/utils/error-codes.ts"],"sourcesContent":["type UpperLetter =\n\t| \"A\"\n\t| \"B\"\n\t| \"C\"\n\t| \"D\"\n\t| \"E\"\n\t| \"F\"\n\t| \"G\"\n\t| \"H\"\n\t| \"I\"\n\t| \"J\"\n\t| \"K\"\n\t| \"L\"\n\t| \"M\"\n\t| \"N\"\n\t| \"O\"\n\t| \"P\"\n\t| \"Q\"\n\t| \"R\"\n\t| \"S\"\n\t| \"T\"\n\t| \"U\"\n\t| \"V\"\n\t| \"W\"\n\t| \"X\"\n\t| \"Y\"\n\t| \"Z\";\ntype SpecialCharacter = \"_\";\n\ntype IsValidUpperSnakeCase<S extends string> = S extends `${infer F}${infer R}`\n\t? F extends UpperLetter | SpecialCharacter\n\t\t? IsValidUpperSnakeCase<R>\n\t\t: false\n\t: true;\n\ntype InvalidKeyError<K extends string> =\n\t`Invalid error code key: \"${K}\" - must only contain uppercase letters (A-Z) and underscores (_)`;\n\ntype ValidateErrorCodes<T> = {\n\t[K in keyof T]: K extends string\n\t\t? IsValidUpperSnakeCase<K> extends false\n\t\t\t? InvalidKeyError<K>\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RawError<K extends string = string> = {\n\treadonly code: K;\n\tmessage: string;\n};\n\nexport function defineErrorCodes<\n\tconst T extends Record<string, string>,\n\tR extends {\n\t\t[K in keyof T & string]: RawError<K>;\n\t},\n>(codes: ValidateErrorCodes<T>): R {\n\treturn Object.fromEntries(\n\t\tObject.entries(codes).map(([key, value]) => [\n\t\t\tkey,\n\t\t\t{\n\t\t\t\tcode: key,\n\t\t\t\tmessage: value,\n\t\t\t\ttoString: () => key,\n\t\t\t},\n\t\t]),\n\t) as any;\n}\n"],"mappings":";AAmDA,SAAgB,iBAKd,OAAiC;AAClC,QAAO,OAAO,YACb,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,KAAK,WAAW,CAC3C,KACA;EACC,MAAM;EACN,SAAS;EACT,gBAAgB;EAChB,CACD,CAAC,CACF"}
|
package/dist/utils/id.d.mts
CHANGED
package/dist/utils/id.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.mjs","names":[],"sources":["../../src/utils/id.ts"],"sourcesContent":["import { createRandomStringGenerator } from \"@better-auth/utils/random\";\n\nexport const generateId = (size?: number) => {\n\treturn createRandomStringGenerator(\"a-z\", \"A-Z\", \"0-9\")(size || 32);\n};\n"],"mappings":";;;AAEA,MAAa,cAAc,SAAkB;AAC5C,QAAO,4BAA4B,OAAO,OAAO,MAAM,CAAC,QAAQ,GAAG"}
|
package/dist/utils/ip.d.mts
CHANGED
|
@@ -51,4 +51,5 @@ declare function normalizeIP(ip: string, options?: NormalizeIPOptions): string;
|
|
|
51
51
|
*/
|
|
52
52
|
declare function createRateLimitKey(ip: string, path: string): string;
|
|
53
53
|
//#endregion
|
|
54
|
-
export { createRateLimitKey, isValidIP, normalizeIP };
|
|
54
|
+
export { createRateLimitKey, isValidIP, normalizeIP };
|
|
55
|
+
//# sourceMappingURL=ip.d.mts.map
|
package/dist/utils/ip.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ip.mjs","names":[],"sources":["../../src/utils/ip.ts"],"sourcesContent":["import * as z from \"zod\";\n\n/**\n * Normalizes an IP address for consistent rate limiting.\n *\n * Features:\n * - Normalizes IPv6 to canonical lowercase form\n * - Converts IPv4-mapped IPv6 to IPv4\n * - Supports IPv6 subnet extraction\n * - Handles all edge cases (::1, ::, etc.)\n */\n\ninterface NormalizeIPOptions {\n\t/**\n\t * For IPv6 addresses, extract the subnet prefix instead of full address.\n\t * Common values: 32, 48, 64, 128 (default: 128 = full address)\n\t *\n\t * @default 128\n\t */\n\tipv6Subnet?: 128 | 64 | 48 | 32;\n}\n\n/**\n * Checks if an IP is valid IPv4 or IPv6\n */\nexport function isValidIP(ip: string): boolean {\n\treturn z.ipv4().safeParse(ip).success || z.ipv6().safeParse(ip).success;\n}\n\n/**\n * Checks if an IP is IPv6\n */\nfunction isIPv6(ip: string): boolean {\n\treturn z.ipv6().safeParse(ip).success;\n}\n\n/**\n * Converts IPv4-mapped IPv6 address to IPv4\n * e.g., \"::ffff:192.0.2.1\" -> \"192.0.2.1\"\n */\nfunction extractIPv4FromMapped(ipv6: string): string | null {\n\tconst lower = ipv6.toLowerCase();\n\n\t// Handle ::ffff:192.0.2.1 format\n\tif (lower.startsWith(\"::ffff:\")) {\n\t\tconst ipv4Part = lower.substring(7);\n\t\t// Check if it's a valid IPv4\n\t\tif (z.ipv4().safeParse(ipv4Part).success) {\n\t\t\treturn ipv4Part;\n\t\t}\n\t}\n\n\t// Handle full form: 0:0:0:0:0:ffff:192.0.2.1\n\tconst parts = ipv6.split(\":\");\n\tif (parts.length === 7 && parts[5]?.toLowerCase() === \"ffff\") {\n\t\tconst ipv4Part = parts[6];\n\t\tif (ipv4Part && z.ipv4().safeParse(ipv4Part).success) {\n\t\t\treturn ipv4Part;\n\t\t}\n\t}\n\n\t// Handle hex-encoded IPv4 in mapped address\n\t// e.g., ::ffff:c000:0201 -> 192.0.2.1\n\tif (lower.includes(\"::ffff:\") || lower.includes(\":ffff:\")) {\n\t\tconst groups = expandIPv6(ipv6);\n\t\tif (\n\t\t\tgroups.length === 8 &&\n\t\t\tgroups[0] === \"0000\" &&\n\t\t\tgroups[1] === \"0000\" &&\n\t\t\tgroups[2] === \"0000\" &&\n\t\t\tgroups[3] === \"0000\" &&\n\t\t\tgroups[4] === \"0000\" &&\n\t\t\tgroups[5] === \"ffff\" &&\n\t\t\tgroups[6] &&\n\t\t\tgroups[7]\n\t\t) {\n\t\t\t// Convert last two groups to IPv4\n\t\t\tconst byte1 = Number.parseInt(groups[6].substring(0, 2), 16);\n\t\t\tconst byte2 = Number.parseInt(groups[6].substring(2, 4), 16);\n\t\t\tconst byte3 = Number.parseInt(groups[7].substring(0, 2), 16);\n\t\t\tconst byte4 = Number.parseInt(groups[7].substring(2, 4), 16);\n\t\t\treturn `${byte1}.${byte2}.${byte3}.${byte4}`;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Expands a compressed IPv6 address to full form\n * e.g., \"2001:db8::1\" -> [\"2001\", \"0db8\", \"0000\", \"0000\", \"0000\", \"0000\", \"0000\", \"0001\"]\n */\nfunction expandIPv6(ipv6: string): string[] {\n\t// Handle :: notation (zero compression)\n\tif (ipv6.includes(\"::\")) {\n\t\tconst sides = ipv6.split(\"::\");\n\t\tconst left = sides[0] ? sides[0].split(\":\") : [];\n\t\tconst right = sides[1] ? sides[1].split(\":\") : [];\n\n\t\t// Calculate missing groups\n\t\tconst totalGroups = 8;\n\t\tconst missingGroups = totalGroups - left.length - right.length;\n\t\tconst zeros = Array(missingGroups).fill(\"0000\");\n\n\t\t// Pad existing groups to 4 digits\n\t\tconst paddedLeft = left.map((g) => g.padStart(4, \"0\"));\n\t\tconst paddedRight = right.map((g) => g.padStart(4, \"0\"));\n\n\t\treturn [...paddedLeft, ...zeros, ...paddedRight];\n\t}\n\n\t// No compression, just pad each group\n\treturn ipv6.split(\":\").map((g) => g.padStart(4, \"0\"));\n}\n\n/**\n * Normalizes an IPv6 address to canonical form\n * e.g., \"2001:DB8::1\" -> \"2001:0db8:0000:0000:0000:0000:0000:0001\"\n */\nfunction normalizeIPv6(\n\tipv6: string,\n\tsubnetPrefix?: 128 | 32 | 48 | 64,\n): string {\n\tconst groups = expandIPv6(ipv6);\n\n\tif (subnetPrefix && subnetPrefix < 128) {\n\t\t// Apply subnet mask\n\t\tconst prefix = subnetPrefix;\n\t\tlet bitsRemaining: number = prefix;\n\n\t\tconst maskedGroups = groups.map((group) => {\n\t\t\tif (bitsRemaining <= 0) {\n\t\t\t\treturn \"0000\";\n\t\t\t}\n\t\t\tif (bitsRemaining >= 16) {\n\t\t\t\tbitsRemaining -= 16;\n\t\t\t\treturn group;\n\t\t\t}\n\n\t\t\t// Partial mask for this group\n\t\t\tconst value = Number.parseInt(group, 16);\n\t\t\tconst mask = (0xffff << (16 - bitsRemaining)) & 0xffff;\n\t\t\tconst masked = value & mask;\n\t\t\tbitsRemaining = 0;\n\t\t\treturn masked.toString(16).padStart(4, \"0\");\n\t\t});\n\n\t\treturn maskedGroups.join(\":\").toLowerCase();\n\t}\n\n\treturn groups.join(\":\").toLowerCase();\n}\n\n/**\n * Normalizes an IP address (IPv4 or IPv6) for consistent rate limiting.\n *\n * @param ip - The IP address to normalize\n * @param options - Normalization options\n * @returns Normalized IP address\n *\n * @example\n * normalizeIP(\"2001:DB8::1\")\n * // -> \"2001:0db8:0000:0000:0000:0000:0000:0000\"\n *\n * @example\n * normalizeIP(\"::ffff:192.0.2.1\")\n * // -> \"192.0.2.1\" (converted to IPv4)\n *\n * @example\n * normalizeIP(\"2001:db8::1\", { ipv6Subnet: 64 })\n * // -> \"2001:0db8:0000:0000:0000:0000:0000:0000\" (subnet /64)\n */\nexport function normalizeIP(\n\tip: string,\n\toptions: NormalizeIPOptions = {},\n): string {\n\t// IPv4 addresses are already normalized\n\tif (z.ipv4().safeParse(ip).success) {\n\t\treturn ip.toLowerCase();\n\t}\n\n\t// Check if it's IPv6\n\tif (!isIPv6(ip)) {\n\t\t// Return as-is if not valid (shouldn't happen due to prior validation)\n\t\treturn ip.toLowerCase();\n\t}\n\n\t// Check for IPv4-mapped IPv6\n\tconst ipv4 = extractIPv4FromMapped(ip);\n\tif (ipv4) {\n\t\treturn ipv4.toLowerCase();\n\t}\n\n\t// Normalize IPv6\n\tconst subnetPrefix = options.ipv6Subnet || 64;\n\treturn normalizeIPv6(ip, subnetPrefix);\n}\n\n/**\n * Creates a rate limit key from IP and path\n * Uses a separator to prevent collision attacks\n *\n * @param ip - The IP address (should be normalized)\n * @param path - The request path\n * @returns Rate limit key\n */\nexport function createRateLimitKey(ip: string, path: string): string {\n\t// Use | as separator to prevent collision attacks\n\t// e.g., \"192.0.2.1\" + \"/sign-in\" vs \"192.0.2\" + \".1/sign-in\"\n\treturn `${ip}|${path}`;\n}\n"],"mappings":"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"}
|
package/dist/utils/json.d.mts
CHANGED
package/dist/utils/json.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.mjs","names":[],"sources":["../../src/utils/json.ts"],"sourcesContent":["import { logger } from \"../env\";\n\nexport function safeJSONParse<T>(data: unknown): T | null {\n\tfunction reviver(_: string, value: any): any {\n\t\tif (typeof value === \"string\") {\n\t\t\tconst iso8601Regex = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z$/;\n\t\t\tif (iso8601Regex.test(value)) {\n\t\t\t\tconst date = new Date(value);\n\t\t\t\tif (!isNaN(date.getTime())) {\n\t\t\t\t\treturn date;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn value;\n\t}\n\ttry {\n\t\tif (typeof data !== \"string\") {\n\t\t\treturn data as T;\n\t\t}\n\t\treturn JSON.parse(data, reviver);\n\t} catch (e) {\n\t\tlogger.error(\"Error parsing JSON\", { error: e });\n\t\treturn null;\n\t}\n}\n"],"mappings":";;;;AAEA,SAAgB,cAAiB,MAAyB;CACzD,SAAS,QAAQ,GAAW,OAAiB;AAC5C,MAAI,OAAO,UAAU,UAEpB;OADqB,mDACJ,KAAK,MAAM,EAAE;IAC7B,MAAM,OAAO,IAAI,KAAK,MAAM;AAC5B,QAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CACzB,QAAO;;;AAIV,SAAO;;AAER,KAAI;AACH,MAAI,OAAO,SAAS,SACnB,QAAO;AAER,SAAO,KAAK,MAAM,MAAM,QAAQ;UACxB,GAAG;AACX,SAAO,MAAM,sBAAsB,EAAE,OAAO,GAAG,CAAC;AAChD,SAAO"}
|
package/dist/utils/string.d.mts
CHANGED
package/dist/utils/string.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string.mjs","names":[],"sources":["../../src/utils/string.ts"],"sourcesContent":["export function capitalizeFirstLetter(str: string) {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":";AAAA,SAAgB,sBAAsB,KAAa;AAClD,QAAO,IAAI,OAAO,EAAE,CAAC,aAAa,GAAG,IAAI,MAAM,EAAE"}
|
package/dist/utils/url.d.mts
CHANGED
package/dist/utils/url.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.mjs","names":[],"sources":["../../src/utils/url.ts"],"sourcesContent":["/**\n * Normalizes a request pathname by removing the basePath prefix and trailing slashes.\n * This is useful for matching paths against configured path lists.\n *\n * @param requestUrl - The full request URL\n * @param basePath - The base path of the auth API (e.g., \"/api/auth\")\n * @returns The normalized path without basePath prefix or trailing slashes,\n * or \"/\" if URL parsing fails\n *\n * @example\n * normalizePathname(\"http://localhost:3000/api/auth/sso/saml2/callback/provider1\", \"/api/auth\")\n * // Returns: \"/sso/saml2/callback/provider1\"\n *\n * normalizePathname(\"http://localhost:3000/sso/saml2/callback/provider1/\", \"/\")\n * // Returns: \"/sso/saml2/callback/provider1\"\n */\nexport function normalizePathname(\n\trequestUrl: string,\n\tbasePath: string,\n): string {\n\tlet pathname: string;\n\ttry {\n\t\tpathname = new URL(requestUrl).pathname.replace(/\\/+$/, \"\") || \"/\";\n\t} catch {\n\t\treturn \"/\";\n\t}\n\n\tif (basePath === \"/\" || basePath === \"\") {\n\t\treturn pathname;\n\t}\n\n\t// Check for exact match or proper path boundary (basePath followed by \"/\" or end)\n\t// This prevents \"/api/auth\" from matching \"/api/authevil/...\"\n\tif (pathname === basePath) {\n\t\treturn \"/\";\n\t}\n\n\tif (pathname.startsWith(basePath + \"/\")) {\n\t\treturn pathname.slice(basePath.length).replace(/\\/+$/, \"\") || \"/\";\n\t}\n\n\treturn pathname;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,SAAgB,kBACf,YACA,UACS;CACT,IAAI;AACJ,KAAI;AACH,aAAW,IAAI,IAAI,WAAW,CAAC,SAAS,QAAQ,QAAQ,GAAG,IAAI;SACxD;AACP,SAAO;;AAGR,KAAI,aAAa,OAAO,aAAa,GACpC,QAAO;AAKR,KAAI,aAAa,SAChB,QAAO;AAGR,KAAI,SAAS,WAAW,WAAW,IAAI,CACtC,QAAO,SAAS,MAAM,SAAS,OAAO,CAAC,QAAQ,QAAQ,GAAG,IAAI;AAG/D,QAAO"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/core",
|
|
3
|
-
"version": "1.5.0
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "The most comprehensive authentication framework for TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://www.better-auth.com",
|
|
6
8
|
"repository": {
|
|
7
9
|
"type": "git",
|
|
8
10
|
"url": "git+https://github.com/better-auth/better-auth.git",
|
|
9
11
|
"directory": "packages/core"
|
|
10
12
|
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"auth",
|
|
15
|
+
"core",
|
|
16
|
+
"typescript",
|
|
17
|
+
"better-auth"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src"
|
|
25
|
+
],
|
|
11
26
|
"main": "./dist/index.mjs",
|
|
12
27
|
"module": "./dist/index.mjs",
|
|
13
28
|
"types": "./dist/index.d.mts",
|
|
@@ -114,27 +129,34 @@
|
|
|
114
129
|
]
|
|
115
130
|
}
|
|
116
131
|
},
|
|
132
|
+
"dependencies": {
|
|
133
|
+
"@standard-schema/spec": "^1.1.0",
|
|
134
|
+
"zod": "^4.3.6"
|
|
135
|
+
},
|
|
117
136
|
"devDependencies": {
|
|
118
|
-
"@better-auth/utils": "0.3.
|
|
137
|
+
"@better-auth/utils": "0.3.1",
|
|
119
138
|
"@better-fetch/fetch": "1.1.21",
|
|
120
|
-
"better-call": "1.2
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
|
|
126
|
-
"dependencies": {
|
|
127
|
-
"@standard-schema/spec": "^1.0.0",
|
|
128
|
-
"zod": "^4.3.5"
|
|
139
|
+
"better-call": "1.3.2",
|
|
140
|
+
"@cloudflare/workers-types": "^4.20250121.0",
|
|
141
|
+
"jose": "^6.1.3",
|
|
142
|
+
"kysely": "^0.28.11",
|
|
143
|
+
"nanostores": "^1.1.1",
|
|
144
|
+
"tsdown": "^0.20.3"
|
|
129
145
|
},
|
|
130
146
|
"peerDependencies": {
|
|
131
|
-
"@better-auth/utils": "0.3.
|
|
147
|
+
"@better-auth/utils": "0.3.1",
|
|
132
148
|
"@better-fetch/fetch": "1.1.21",
|
|
133
|
-
"better-call": "1.2
|
|
149
|
+
"better-call": "1.3.2",
|
|
150
|
+
"@cloudflare/workers-types": ">=4",
|
|
134
151
|
"jose": "^6.1.0",
|
|
135
152
|
"kysely": "^0.28.5",
|
|
136
153
|
"nanostores": "^1.0.1"
|
|
137
154
|
},
|
|
155
|
+
"peerDependenciesMeta": {
|
|
156
|
+
"@cloudflare/workers-types": {
|
|
157
|
+
"optional": true
|
|
158
|
+
}
|
|
159
|
+
},
|
|
138
160
|
"scripts": {
|
|
139
161
|
"build": "tsdown",
|
|
140
162
|
"dev": "tsdown --watch",
|
|
@@ -38,20 +38,20 @@ let debugLogs: { instance: string; args: any[] }[] = [];
|
|
|
38
38
|
let transactionId = -1;
|
|
39
39
|
|
|
40
40
|
const createAsIsTransaction =
|
|
41
|
-
(adapter: DBAdapter<
|
|
42
|
-
<R>(fn: (trx: DBTransactionAdapter<
|
|
41
|
+
<Options extends BetterAuthOptions>(adapter: DBAdapter<Options>) =>
|
|
42
|
+
<R>(fn: (trx: DBTransactionAdapter<Options>) => Promise<R>) =>
|
|
43
43
|
fn(adapter);
|
|
44
44
|
|
|
45
|
-
export type AdapterFactory = (
|
|
46
|
-
options:
|
|
47
|
-
) => DBAdapter<
|
|
45
|
+
export type AdapterFactory<Options extends BetterAuthOptions> = (
|
|
46
|
+
options: Options,
|
|
47
|
+
) => DBAdapter<Options>;
|
|
48
48
|
|
|
49
49
|
export const createAdapterFactory =
|
|
50
|
-
({
|
|
50
|
+
<Options extends BetterAuthOptions>({
|
|
51
51
|
adapter: customAdapter,
|
|
52
52
|
config: cfg,
|
|
53
|
-
}: AdapterFactoryOptions): AdapterFactory =>
|
|
54
|
-
(options:
|
|
53
|
+
}: AdapterFactoryOptions): AdapterFactory<Options> =>
|
|
54
|
+
(options: Options): DBAdapter<Options> => {
|
|
55
55
|
const uniqueAdapterFactoryInstanceId = Math.random()
|
|
56
56
|
.toString(36)
|
|
57
57
|
.substring(2, 15);
|
|
@@ -71,9 +71,7 @@ export const createAdapterFactory =
|
|
|
71
71
|
disableTransformJoin: cfg.disableTransformJoin ?? false,
|
|
72
72
|
} satisfies AdapterFactoryConfig;
|
|
73
73
|
|
|
74
|
-
const useNumberId =
|
|
75
|
-
options.advanced?.database?.useNumberId === true ||
|
|
76
|
-
options.advanced?.database?.generateId === "serial";
|
|
74
|
+
const useNumberId = options.advanced?.database?.generateId === "serial";
|
|
77
75
|
if (useNumberId && config.supportsNumericIds === false) {
|
|
78
76
|
throw new BetterAuthError(
|
|
79
77
|
`[${config.adapterName}] Your database or database adapter does not support numeric ids. Please disable "useNumberId" in your config.`,
|
|
@@ -189,9 +187,7 @@ export const createAdapterFactory =
|
|
|
189
187
|
const fields = schema[defaultModelName]!.fields;
|
|
190
188
|
|
|
191
189
|
const newMappedKeys = config.mapKeysTransformInput ?? {};
|
|
192
|
-
const useNumberId =
|
|
193
|
-
options.advanced?.database?.useNumberId ||
|
|
194
|
-
options.advanced?.database?.generateId === "serial";
|
|
190
|
+
const useNumberId = options.advanced?.database?.generateId === "serial";
|
|
195
191
|
fields.id = idField({
|
|
196
192
|
customModelName: defaultModelName,
|
|
197
193
|
forceAllowId: forceAllowId && "id" in data,
|
|
@@ -309,9 +305,7 @@ export const createAdapterFactory =
|
|
|
309
305
|
const idKey = Object.entries(newMappedKeys).find(
|
|
310
306
|
([_, v]) => v === "id",
|
|
311
307
|
)?.[0];
|
|
312
|
-
const useNumberId =
|
|
313
|
-
options.advanced?.database?.useNumberId ||
|
|
314
|
-
options.advanced?.database?.generateId === "serial";
|
|
308
|
+
const useNumberId = options.advanced?.database?.generateId === "serial";
|
|
315
309
|
tableSchema[idKey ?? "id"] = {
|
|
316
310
|
type: useNumberId ? "number" : "string",
|
|
317
311
|
};
|
|
@@ -523,9 +517,7 @@ export const createAdapterFactory =
|
|
|
523
517
|
model: defaultModelName,
|
|
524
518
|
});
|
|
525
519
|
|
|
526
|
-
const useNumberId =
|
|
527
|
-
options.advanced?.database?.useNumberId ||
|
|
528
|
-
options.advanced?.database?.generateId === "serial";
|
|
520
|
+
const useNumberId = options.advanced?.database?.generateId === "serial";
|
|
529
521
|
|
|
530
522
|
if (
|
|
531
523
|
defaultFieldName === "id" ||
|
|
@@ -548,12 +540,32 @@ export const createAdapterFactory =
|
|
|
548
540
|
newValue = value.toISOString();
|
|
549
541
|
}
|
|
550
542
|
|
|
543
|
+
if (fieldAttr.type === "boolean" && typeof newValue === "string") {
|
|
544
|
+
newValue = newValue === "true";
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (fieldAttr.type === "number") {
|
|
548
|
+
if (typeof newValue === "string" && newValue.trim() !== "") {
|
|
549
|
+
const parsed = Number(newValue);
|
|
550
|
+
if (!Number.isNaN(parsed)) {
|
|
551
|
+
newValue = parsed;
|
|
552
|
+
}
|
|
553
|
+
} else if (Array.isArray(newValue)) {
|
|
554
|
+
const parsed = newValue.map((v) =>
|
|
555
|
+
typeof v === "string" && v.trim() !== "" ? Number(v) : NaN,
|
|
556
|
+
);
|
|
557
|
+
if (parsed.every((n) => !Number.isNaN(n))) {
|
|
558
|
+
newValue = parsed;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
551
563
|
if (
|
|
552
564
|
fieldAttr.type === "boolean" &&
|
|
553
|
-
typeof
|
|
565
|
+
typeof newValue === "boolean" &&
|
|
554
566
|
!config.supportsBooleans
|
|
555
567
|
) {
|
|
556
|
-
newValue =
|
|
568
|
+
newValue = newValue ? 1 : 0;
|
|
557
569
|
}
|
|
558
570
|
|
|
559
571
|
if (
|
|
@@ -793,10 +805,8 @@ export const createAdapterFactory =
|
|
|
793
805
|
transformWhereClause,
|
|
794
806
|
});
|
|
795
807
|
|
|
796
|
-
let lazyLoadTransaction:
|
|
797
|
-
|
|
798
|
-
| null = null;
|
|
799
|
-
const adapter: DBAdapter<BetterAuthOptions> = {
|
|
808
|
+
let lazyLoadTransaction: DBAdapter<Options>["transaction"] | null = null;
|
|
809
|
+
const adapter: DBAdapter<Options> = {
|
|
800
810
|
transaction: async (cb) => {
|
|
801
811
|
if (!lazyLoadTransaction) {
|
|
802
812
|
if (!config.transaction) {
|
|
@@ -1083,6 +1093,7 @@ export const createAdapterFactory =
|
|
|
1083
1093
|
model: unsafeModel,
|
|
1084
1094
|
where: unsafeWhere,
|
|
1085
1095
|
limit: unsafeLimit,
|
|
1096
|
+
select,
|
|
1086
1097
|
sortBy,
|
|
1087
1098
|
offset,
|
|
1088
1099
|
join: unsafeJoin,
|
|
@@ -1090,6 +1101,7 @@ export const createAdapterFactory =
|
|
|
1090
1101
|
model: string;
|
|
1091
1102
|
where?: Where[];
|
|
1092
1103
|
limit?: number;
|
|
1104
|
+
select?: string[] | undefined;
|
|
1093
1105
|
sortBy?: { field: string; direction: "asc" | "desc" };
|
|
1094
1106
|
offset?: number;
|
|
1095
1107
|
join?: JoinOption;
|
|
@@ -1110,13 +1122,10 @@ export const createAdapterFactory =
|
|
|
1110
1122
|
let join: JoinConfig | undefined;
|
|
1111
1123
|
let passJoinToAdapter = true;
|
|
1112
1124
|
if (!config.disableTransformJoin) {
|
|
1113
|
-
const result = transformJoinClause(
|
|
1114
|
-
unsafeModel,
|
|
1115
|
-
unsafeJoin,
|
|
1116
|
-
undefined,
|
|
1117
|
-
);
|
|
1125
|
+
const result = transformJoinClause(unsafeModel, unsafeJoin, select);
|
|
1118
1126
|
if (result) {
|
|
1119
1127
|
join = result.join;
|
|
1128
|
+
select = result.select;
|
|
1120
1129
|
}
|
|
1121
1130
|
// If adapter doesn't support joins and we have joins, don't pass them to the adapter
|
|
1122
1131
|
const experimentalJoins = options.experimental?.joins;
|
|
@@ -1137,6 +1146,7 @@ export const createAdapterFactory =
|
|
|
1137
1146
|
model,
|
|
1138
1147
|
where,
|
|
1139
1148
|
limit: limit,
|
|
1149
|
+
select,
|
|
1140
1150
|
sortBy,
|
|
1141
1151
|
offset,
|
|
1142
1152
|
join: passJoinToAdapter ? join : undefined,
|
|
@@ -1284,42 +1294,6 @@ export const createAdapterFactory =
|
|
|
1284
1294
|
delete tables.session;
|
|
1285
1295
|
}
|
|
1286
1296
|
|
|
1287
|
-
if (
|
|
1288
|
-
options.rateLimit &&
|
|
1289
|
-
options.rateLimit.storage === "database" &&
|
|
1290
|
-
// rate-limit will default to enabled in production,
|
|
1291
|
-
// and given storage is database, it will try to use the rate-limit table,
|
|
1292
|
-
// so we should make sure to generate rate-limit table schema
|
|
1293
|
-
(typeof options.rateLimit.enabled === "undefined" ||
|
|
1294
|
-
// and of course if they forcefully set to true, then they want rate-limit,
|
|
1295
|
-
// thus we should also generate rate-limit table schema
|
|
1296
|
-
options.rateLimit.enabled === true)
|
|
1297
|
-
) {
|
|
1298
|
-
tables.ratelimit = {
|
|
1299
|
-
modelName: options.rateLimit.modelName ?? "ratelimit",
|
|
1300
|
-
fields: {
|
|
1301
|
-
key: {
|
|
1302
|
-
type: "string",
|
|
1303
|
-
unique: true,
|
|
1304
|
-
required: true,
|
|
1305
|
-
fieldName: options.rateLimit.fields?.key ?? "key",
|
|
1306
|
-
},
|
|
1307
|
-
count: {
|
|
1308
|
-
type: "number",
|
|
1309
|
-
required: true,
|
|
1310
|
-
fieldName: options.rateLimit.fields?.count ?? "count",
|
|
1311
|
-
},
|
|
1312
|
-
lastRequest: {
|
|
1313
|
-
type: "number",
|
|
1314
|
-
required: true,
|
|
1315
|
-
bigint: true,
|
|
1316
|
-
defaultValue: () => Date.now(),
|
|
1317
|
-
fieldName:
|
|
1318
|
-
options.rateLimit.fields?.lastRequest ?? "lastRequest",
|
|
1319
|
-
},
|
|
1320
|
-
},
|
|
1321
|
-
};
|
|
1322
|
-
}
|
|
1323
1297
|
return adapterInstance.createSchema!({ file, tables });
|
|
1324
1298
|
}
|
|
1325
1299
|
: undefined,
|
|
@@ -1390,9 +1364,3 @@ function formatMethod(method: string) {
|
|
|
1390
1364
|
function formatAction(action: string) {
|
|
1391
1365
|
return `${TTY_COLORS.dim}(${action})${TTY_COLORS.reset}`;
|
|
1392
1366
|
}
|
|
1393
|
-
|
|
1394
|
-
/**
|
|
1395
|
-
* @deprecated Use `createAdapterFactory` instead. This export will be removed in a future version.
|
|
1396
|
-
* @alias
|
|
1397
|
-
*/
|
|
1398
|
-
export const createAdapter = createAdapterFactory;
|
|
@@ -31,9 +31,7 @@ export const initGetIdField = ({
|
|
|
31
31
|
customModelName?: string;
|
|
32
32
|
forceAllowId?: boolean;
|
|
33
33
|
}) => {
|
|
34
|
-
const useNumberId =
|
|
35
|
-
options.advanced?.database?.useNumberId ||
|
|
36
|
-
options.advanced?.database?.generateId === "serial";
|
|
34
|
+
const useNumberId = options.advanced?.database?.generateId === "serial";
|
|
37
35
|
const useUUIDs = options.advanced?.database?.generateId === "uuid";
|
|
38
36
|
|
|
39
37
|
const shouldGenerateId: boolean = (() => {
|
package/src/db/adapter/index.ts
CHANGED
|
@@ -301,25 +301,27 @@ export interface DBAdapterFactoryConfig<
|
|
|
301
301
|
disableTransformJoin?: boolean | undefined;
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
export const whereOperators = [
|
|
305
|
+
"eq",
|
|
306
|
+
"ne",
|
|
307
|
+
"lt",
|
|
308
|
+
"lte",
|
|
309
|
+
"gt",
|
|
310
|
+
"gte",
|
|
311
|
+
"in",
|
|
312
|
+
"not_in",
|
|
313
|
+
"contains",
|
|
314
|
+
"starts_with",
|
|
315
|
+
"ends_with",
|
|
316
|
+
] as const;
|
|
317
|
+
|
|
318
|
+
export type WhereOperator = (typeof whereOperators)[number];
|
|
319
|
+
|
|
304
320
|
export type Where = {
|
|
305
321
|
/**
|
|
306
322
|
* @default eq
|
|
307
323
|
*/
|
|
308
|
-
operator?:
|
|
309
|
-
| (
|
|
310
|
-
| "eq"
|
|
311
|
-
| "ne"
|
|
312
|
-
| "lt"
|
|
313
|
-
| "lte"
|
|
314
|
-
| "gt"
|
|
315
|
-
| "gte"
|
|
316
|
-
| "in"
|
|
317
|
-
| "not_in"
|
|
318
|
-
| "contains"
|
|
319
|
-
| "starts_with"
|
|
320
|
-
| "ends_with"
|
|
321
|
-
)
|
|
322
|
-
| undefined;
|
|
324
|
+
operator?: WhereOperator | undefined;
|
|
323
325
|
value: string | number | boolean | string[] | number[] | Date | null;
|
|
324
326
|
field: string;
|
|
325
327
|
/**
|
|
@@ -405,6 +407,7 @@ export type DBAdapter<Options extends BetterAuthOptions = BetterAuthOptions> = {
|
|
|
405
407
|
model: string;
|
|
406
408
|
where?: Where[] | undefined;
|
|
407
409
|
limit?: number | undefined;
|
|
410
|
+
select?: string[] | undefined;
|
|
408
411
|
sortBy?:
|
|
409
412
|
| {
|
|
410
413
|
field: string;
|
|
@@ -493,6 +496,7 @@ export interface CustomAdapter {
|
|
|
493
496
|
model,
|
|
494
497
|
where,
|
|
495
498
|
limit,
|
|
499
|
+
select,
|
|
496
500
|
sortBy,
|
|
497
501
|
offset,
|
|
498
502
|
join,
|
|
@@ -500,6 +504,7 @@ export interface CustomAdapter {
|
|
|
500
504
|
model: string;
|
|
501
505
|
where?: CleanedWhere[] | undefined;
|
|
502
506
|
limit: number;
|
|
507
|
+
select?: string[] | undefined;
|
|
503
508
|
sortBy?: { field: string; direction: "asc" | "desc" } | undefined;
|
|
504
509
|
offset?: number | undefined;
|
|
505
510
|
join?: JoinConfig | undefined;
|
package/src/db/adapter/types.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { BetterAuthOptions } from "../../types";
|
|
2
|
-
import type { Prettify } from "../../types/helper";
|
|
3
2
|
import type { BetterAuthDBSchema, DBFieldAttribute } from "../type";
|
|
4
3
|
import type {
|
|
5
|
-
|
|
6
|
-
CustomAdapter
|
|
4
|
+
CleanedWhere,
|
|
5
|
+
CustomAdapter,
|
|
7
6
|
DBAdapterFactoryConfig,
|
|
8
7
|
JoinConfig,
|
|
9
8
|
DBTransactionAdapter as TransactionAdapter,
|
|
@@ -127,45 +126,7 @@ export type AdapterFactoryCustomizeAdapterCreator = (config: {
|
|
|
127
126
|
}) => W extends undefined ? undefined : CleanedWhere[];
|
|
128
127
|
}) => CustomAdapter;
|
|
129
128
|
|
|
130
|
-
/**
|
|
131
|
-
* @deprecated Use `CustomAdapter` from `@better-auth/core/db/adapter` instead.
|
|
132
|
-
*/
|
|
133
|
-
export interface CustomAdapter extends Omit<CoreCustomAdapter, "createSchema"> {
|
|
134
|
-
createSchema?:
|
|
135
|
-
| ((props: {
|
|
136
|
-
/**
|
|
137
|
-
* The file the user may have passed in to the `generate` command as the expected schema file output path.
|
|
138
|
-
*/
|
|
139
|
-
file?: string;
|
|
140
|
-
/**
|
|
141
|
-
* The tables from the user's Better-Auth instance schema.
|
|
142
|
-
*/
|
|
143
|
-
tables: BetterAuthDBSchema;
|
|
144
|
-
}) => Promise<AdapterSchemaCreation>)
|
|
145
|
-
| undefined;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* @deprecated Use `CleanedWhere` from `@better-auth/core/db/adapter` instead.
|
|
150
|
-
*/
|
|
151
|
-
export type CleanedWhere = Prettify<Required<Where>>;
|
|
152
|
-
|
|
153
129
|
export type AdapterTestDebugLogs = {
|
|
154
130
|
resetDebugLogs: () => void;
|
|
155
131
|
printDebugLogs: () => void;
|
|
156
132
|
};
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* @deprecated Use `AdapterFactoryOptions` instead. This export will be removed in a future version.
|
|
160
|
-
*/
|
|
161
|
-
export type CreateAdapterOptions = AdapterFactoryOptions;
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* @deprecated Use `AdapterFactoryConfig` instead. This export will be removed in a future version.
|
|
165
|
-
*/
|
|
166
|
-
export type AdapterConfig = AdapterFactoryConfig;
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @deprecated Use `AdapterFactoryCustomizeAdapterCreator` instead. This export will be removed in a future version.
|
|
170
|
-
*/
|
|
171
|
-
export type CreateCustomAdapter = AdapterFactoryCustomizeAdapterCreator;
|