@hammadj/better-auth-core 1.5.0-beta.9
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 +266 -0
- package/.turbo/turbo-test.log +2 -0
- package/LICENSE.md +20 -0
- package/dist/api/index.d.mts +181 -0
- package/dist/api/index.mjs +34 -0
- package/dist/api/index.mjs.map +1 -0
- package/dist/async_hooks/index.d.mts +7 -0
- package/dist/async_hooks/index.mjs +22 -0
- package/dist/async_hooks/index.mjs.map +1 -0
- package/dist/async_hooks/pure.index.d.mts +7 -0
- package/dist/async_hooks/pure.index.mjs +35 -0
- package/dist/async_hooks/pure.index.mjs.map +1 -0
- package/dist/context/endpoint-context.d.mts +19 -0
- package/dist/context/endpoint-context.mjs +32 -0
- package/dist/context/endpoint-context.mjs.map +1 -0
- package/dist/context/global.d.mts +7 -0
- package/dist/context/global.mjs +38 -0
- package/dist/context/global.mjs.map +1 -0
- package/dist/context/index.d.mts +5 -0
- package/dist/context/index.mjs +6 -0
- package/dist/context/request-state.d.mts +26 -0
- package/dist/context/request-state.mjs +50 -0
- package/dist/context/request-state.mjs.map +1 -0
- package/dist/context/transaction.d.mts +25 -0
- package/dist/context/transaction.mjs +96 -0
- package/dist/context/transaction.mjs.map +1 -0
- package/dist/db/adapter/factory.d.mts +28 -0
- package/dist/db/adapter/factory.mjs +716 -0
- package/dist/db/adapter/factory.mjs.map +1 -0
- package/dist/db/adapter/get-default-field-name.d.mts +19 -0
- package/dist/db/adapter/get-default-field-name.mjs +39 -0
- package/dist/db/adapter/get-default-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-default-model-name.d.mts +13 -0
- package/dist/db/adapter/get-default-model-name.mjs +33 -0
- package/dist/db/adapter/get-default-model-name.mjs.map +1 -0
- package/dist/db/adapter/get-field-attributes.d.mts +30 -0
- package/dist/db/adapter/get-field-attributes.mjs +40 -0
- package/dist/db/adapter/get-field-attributes.mjs.map +1 -0
- package/dist/db/adapter/get-field-name.d.mts +19 -0
- package/dist/db/adapter/get-field-name.mjs +34 -0
- package/dist/db/adapter/get-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-id-field.d.mts +40 -0
- package/dist/db/adapter/get-id-field.mjs +68 -0
- package/dist/db/adapter/get-id-field.mjs.map +1 -0
- package/dist/db/adapter/get-model-name.d.mts +13 -0
- package/dist/db/adapter/get-model-name.mjs +24 -0
- package/dist/db/adapter/get-model-name.mjs.map +1 -0
- package/dist/db/adapter/index.d.mts +515 -0
- package/dist/db/adapter/index.mjs +10 -0
- package/dist/db/adapter/types.d.mts +140 -0
- package/dist/db/adapter/utils.d.mts +8 -0
- package/dist/db/adapter/utils.mjs +39 -0
- package/dist/db/adapter/utils.mjs.map +1 -0
- package/dist/db/get-tables.d.mts +9 -0
- package/dist/db/get-tables.mjs +267 -0
- package/dist/db/get-tables.mjs.map +1 -0
- package/dist/db/index.d.mts +10 -0
- package/dist/db/index.mjs +9 -0
- package/dist/db/plugin.d.mts +13 -0
- package/dist/db/schema/account.d.mts +27 -0
- package/dist/db/schema/account.mjs +20 -0
- package/dist/db/schema/account.mjs.map +1 -0
- package/dist/db/schema/rate-limit.d.mts +15 -0
- package/dist/db/schema/rate-limit.mjs +12 -0
- package/dist/db/schema/rate-limit.mjs.map +1 -0
- package/dist/db/schema/session.d.mts +22 -0
- package/dist/db/schema/session.mjs +15 -0
- package/dist/db/schema/session.mjs.map +1 -0
- package/dist/db/schema/shared.d.mts +11 -0
- package/dist/db/schema/shared.mjs +12 -0
- package/dist/db/schema/shared.mjs.map +1 -0
- package/dist/db/schema/user.d.mts +21 -0
- package/dist/db/schema/user.mjs +14 -0
- package/dist/db/schema/user.mjs.map +1 -0
- package/dist/db/schema/verification.d.mts +20 -0
- package/dist/db/schema/verification.mjs +13 -0
- package/dist/db/schema/verification.mjs.map +1 -0
- package/dist/db/type.d.mts +147 -0
- package/dist/env/color-depth.d.mts +5 -0
- package/dist/env/color-depth.mjs +89 -0
- package/dist/env/color-depth.mjs.map +1 -0
- package/dist/env/env-impl.d.mts +33 -0
- package/dist/env/env-impl.mjs +83 -0
- package/dist/env/env-impl.mjs.map +1 -0
- package/dist/env/index.d.mts +4 -0
- package/dist/env/index.mjs +5 -0
- package/dist/env/logger.d.mts +49 -0
- package/dist/env/logger.mjs +82 -0
- package/dist/env/logger.mjs.map +1 -0
- package/dist/error/codes.d.mts +199 -0
- package/dist/error/codes.mjs +57 -0
- package/dist/error/codes.mjs.map +1 -0
- package/dist/error/index.d.mts +20 -0
- package/dist/error/index.mjs +30 -0
- package/dist/error/index.mjs.map +1 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +1 -0
- package/dist/oauth2/client-credentials-token.d.mts +37 -0
- package/dist/oauth2/client-credentials-token.mjs +55 -0
- package/dist/oauth2/client-credentials-token.mjs.map +1 -0
- package/dist/oauth2/create-authorization-url.d.mts +46 -0
- package/dist/oauth2/create-authorization-url.mjs +43 -0
- package/dist/oauth2/create-authorization-url.mjs.map +1 -0
- package/dist/oauth2/index.d.mts +8 -0
- package/dist/oauth2/index.mjs +8 -0
- package/dist/oauth2/oauth-provider.d.mts +195 -0
- package/dist/oauth2/refresh-access-token.d.mts +36 -0
- package/dist/oauth2/refresh-access-token.mjs +59 -0
- package/dist/oauth2/refresh-access-token.mjs.map +1 -0
- package/dist/oauth2/utils.d.mts +8 -0
- package/dist/oauth2/utils.mjs +28 -0
- package/dist/oauth2/utils.mjs.map +1 -0
- package/dist/oauth2/validate-authorization-code.d.mts +56 -0
- package/dist/oauth2/validate-authorization-code.mjs +72 -0
- package/dist/oauth2/validate-authorization-code.mjs.map +1 -0
- package/dist/oauth2/verify.d.mts +43 -0
- package/dist/oauth2/verify.mjs +96 -0
- package/dist/oauth2/verify.mjs.map +1 -0
- package/dist/social-providers/apple.d.mts +120 -0
- package/dist/social-providers/apple.mjs +105 -0
- package/dist/social-providers/apple.mjs.map +1 -0
- package/dist/social-providers/atlassian.d.mts +73 -0
- package/dist/social-providers/atlassian.mjs +84 -0
- package/dist/social-providers/atlassian.mjs.map +1 -0
- package/dist/social-providers/cognito.d.mts +88 -0
- package/dist/social-providers/cognito.mjs +166 -0
- package/dist/social-providers/cognito.mjs.map +1 -0
- package/dist/social-providers/discord.d.mts +127 -0
- package/dist/social-providers/discord.mjs +65 -0
- package/dist/social-providers/discord.mjs.map +1 -0
- package/dist/social-providers/dropbox.d.mts +72 -0
- package/dist/social-providers/dropbox.mjs +76 -0
- package/dist/social-providers/dropbox.mjs.map +1 -0
- package/dist/social-providers/facebook.d.mts +82 -0
- package/dist/social-providers/facebook.mjs +121 -0
- package/dist/social-providers/facebook.mjs.map +1 -0
- package/dist/social-providers/figma.d.mts +64 -0
- package/dist/social-providers/figma.mjs +87 -0
- package/dist/social-providers/figma.mjs.map +1 -0
- package/dist/social-providers/github.d.mts +105 -0
- package/dist/social-providers/github.mjs +97 -0
- package/dist/social-providers/github.mjs.map +1 -0
- package/dist/social-providers/gitlab.d.mts +126 -0
- package/dist/social-providers/gitlab.mjs +83 -0
- package/dist/social-providers/gitlab.mjs.map +1 -0
- package/dist/social-providers/google.d.mts +100 -0
- package/dist/social-providers/google.mjs +109 -0
- package/dist/social-providers/google.mjs.map +1 -0
- package/dist/social-providers/huggingface.d.mts +86 -0
- package/dist/social-providers/huggingface.mjs +76 -0
- package/dist/social-providers/huggingface.mjs.map +1 -0
- package/dist/social-providers/index.d.mts +1725 -0
- package/dist/social-providers/index.mjs +77 -0
- package/dist/social-providers/index.mjs.map +1 -0
- package/dist/social-providers/kakao.d.mts +164 -0
- package/dist/social-providers/kakao.mjs +73 -0
- package/dist/social-providers/kakao.mjs.map +1 -0
- package/dist/social-providers/kick.d.mts +76 -0
- package/dist/social-providers/kick.mjs +72 -0
- package/dist/social-providers/kick.mjs.map +1 -0
- package/dist/social-providers/line.d.mts +108 -0
- package/dist/social-providers/line.mjs +114 -0
- package/dist/social-providers/line.mjs.map +1 -0
- package/dist/social-providers/linear.d.mts +71 -0
- package/dist/social-providers/linear.mjs +89 -0
- package/dist/social-providers/linear.mjs.map +1 -0
- package/dist/social-providers/linkedin.d.mts +70 -0
- package/dist/social-providers/linkedin.mjs +77 -0
- package/dist/social-providers/linkedin.mjs.map +1 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +175 -0
- package/dist/social-providers/microsoft-entra-id.mjs +107 -0
- package/dist/social-providers/microsoft-entra-id.mjs.map +1 -0
- package/dist/social-providers/naver.d.mts +95 -0
- package/dist/social-providers/naver.mjs +68 -0
- package/dist/social-providers/naver.mjs.map +1 -0
- package/dist/social-providers/notion.d.mts +67 -0
- package/dist/social-providers/notion.mjs +76 -0
- package/dist/social-providers/notion.mjs.map +1 -0
- package/dist/social-providers/paybin.d.mts +74 -0
- package/dist/social-providers/paybin.mjs +86 -0
- package/dist/social-providers/paybin.mjs.map +1 -0
- package/dist/social-providers/paypal.d.mts +132 -0
- package/dist/social-providers/paypal.mjs +145 -0
- package/dist/social-providers/paypal.mjs.map +1 -0
- package/dist/social-providers/polar.d.mts +77 -0
- package/dist/social-providers/polar.mjs +74 -0
- package/dist/social-providers/polar.mjs.map +1 -0
- package/dist/social-providers/reddit.d.mts +65 -0
- package/dist/social-providers/reddit.mjs +84 -0
- package/dist/social-providers/reddit.mjs.map +1 -0
- package/dist/social-providers/roblox.d.mts +73 -0
- package/dist/social-providers/roblox.mjs +60 -0
- package/dist/social-providers/roblox.mjs.map +1 -0
- package/dist/social-providers/salesforce.d.mts +82 -0
- package/dist/social-providers/salesforce.mjs +92 -0
- package/dist/social-providers/salesforce.mjs.map +1 -0
- package/dist/social-providers/slack.d.mts +86 -0
- package/dist/social-providers/slack.mjs +69 -0
- package/dist/social-providers/slack.mjs.map +1 -0
- package/dist/social-providers/spotify.d.mts +66 -0
- package/dist/social-providers/spotify.mjs +72 -0
- package/dist/social-providers/spotify.mjs.map +1 -0
- package/dist/social-providers/tiktok.d.mts +171 -0
- package/dist/social-providers/tiktok.mjs +63 -0
- package/dist/social-providers/tiktok.mjs.map +1 -0
- package/dist/social-providers/twitch.d.mts +82 -0
- package/dist/social-providers/twitch.mjs +79 -0
- package/dist/social-providers/twitch.mjs.map +1 -0
- package/dist/social-providers/twitter.d.mts +129 -0
- package/dist/social-providers/twitter.mjs +88 -0
- package/dist/social-providers/twitter.mjs.map +1 -0
- package/dist/social-providers/vercel.d.mts +65 -0
- package/dist/social-providers/vercel.mjs +62 -0
- package/dist/social-providers/vercel.mjs.map +1 -0
- package/dist/social-providers/vk.d.mts +73 -0
- package/dist/social-providers/vk.mjs +84 -0
- package/dist/social-providers/vk.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +173 -0
- package/dist/social-providers/zoom.mjs +73 -0
- package/dist/social-providers/zoom.mjs.map +1 -0
- package/dist/types/context.d.mts +267 -0
- package/dist/types/cookie.d.mts +16 -0
- package/dist/types/helper.d.mts +10 -0
- package/dist/types/index.d.mts +8 -0
- package/dist/types/init-options.d.mts +1314 -0
- package/dist/types/plugin-client.d.mts +112 -0
- package/dist/types/plugin.d.mts +125 -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 +10 -0
- package/dist/utils/deprecate.mjs +18 -0
- package/dist/utils/deprecate.mjs.map +1 -0
- package/dist/utils/error-codes.d.mts +13 -0
- package/dist/utils/error-codes.mjs +12 -0
- package/dist/utils/error-codes.mjs.map +1 -0
- package/dist/utils/id.d.mts +5 -0
- package/dist/utils/id.mjs +10 -0
- package/dist/utils/id.mjs.map +1 -0
- package/dist/utils/ip.d.mts +55 -0
- package/dist/utils/ip.mjs +119 -0
- package/dist/utils/ip.mjs.map +1 -0
- package/dist/utils/json.d.mts +5 -0
- package/dist/utils/json.mjs +26 -0
- package/dist/utils/json.mjs.map +1 -0
- package/dist/utils/string.d.mts +5 -0
- package/dist/utils/string.mjs +8 -0
- package/dist/utils/string.mjs.map +1 -0
- package/dist/utils/url.d.mts +21 -0
- package/dist/utils/url.mjs +33 -0
- package/dist/utils/url.mjs.map +1 -0
- package/package.json +147 -0
- package/src/api/index.ts +106 -0
- package/src/async_hooks/index.ts +40 -0
- package/src/async_hooks/pure.index.ts +46 -0
- package/src/context/endpoint-context.ts +50 -0
- package/src/context/global.ts +57 -0
- package/src/context/index.ts +23 -0
- package/src/context/request-state.test.ts +94 -0
- package/src/context/request-state.ts +91 -0
- package/src/context/transaction.ts +136 -0
- package/src/db/adapter/factory.ts +1362 -0
- package/src/db/adapter/get-default-field-name.ts +59 -0
- package/src/db/adapter/get-default-model-name.ts +51 -0
- package/src/db/adapter/get-field-attributes.ts +62 -0
- package/src/db/adapter/get-field-name.ts +43 -0
- package/src/db/adapter/get-id-field.ts +141 -0
- package/src/db/adapter/get-model-name.ts +36 -0
- package/src/db/adapter/index.ts +554 -0
- package/src/db/adapter/types.ts +171 -0
- package/src/db/adapter/utils.ts +61 -0
- package/src/db/get-tables.ts +296 -0
- package/src/db/index.ts +18 -0
- package/src/db/plugin.ts +11 -0
- package/src/db/schema/account.ts +34 -0
- package/src/db/schema/rate-limit.ts +21 -0
- package/src/db/schema/session.ts +17 -0
- package/src/db/schema/shared.ts +7 -0
- package/src/db/schema/user.ts +16 -0
- package/src/db/schema/verification.ts +15 -0
- package/src/db/test/get-tables.test.ts +116 -0
- package/src/db/type.ts +180 -0
- package/src/env/color-depth.ts +172 -0
- package/src/env/env-impl.ts +124 -0
- package/src/env/index.ts +23 -0
- package/src/env/logger.test.ts +34 -0
- package/src/env/logger.ts +145 -0
- package/src/error/codes.ts +58 -0
- package/src/error/index.ts +35 -0
- package/src/index.ts +1 -0
- package/src/oauth2/client-credentials-token.ts +102 -0
- package/src/oauth2/create-authorization-url.ts +87 -0
- package/src/oauth2/index.ts +26 -0
- package/src/oauth2/oauth-provider.ts +222 -0
- package/src/oauth2/refresh-access-token.ts +124 -0
- package/src/oauth2/utils.ts +38 -0
- package/src/oauth2/validate-authorization-code.ts +149 -0
- package/src/oauth2/validate-token.test.ts +174 -0
- package/src/oauth2/verify.ts +221 -0
- package/src/social-providers/apple.ts +223 -0
- package/src/social-providers/atlassian.ts +132 -0
- package/src/social-providers/cognito.ts +279 -0
- package/src/social-providers/discord.ts +169 -0
- package/src/social-providers/dropbox.ts +112 -0
- package/src/social-providers/facebook.ts +206 -0
- package/src/social-providers/figma.ts +117 -0
- package/src/social-providers/github.ts +184 -0
- package/src/social-providers/gitlab.ts +155 -0
- package/src/social-providers/google.ts +199 -0
- package/src/social-providers/huggingface.ts +118 -0
- package/src/social-providers/index.ts +127 -0
- package/src/social-providers/kakao.ts +178 -0
- package/src/social-providers/kick.ts +109 -0
- package/src/social-providers/line.ts +169 -0
- package/src/social-providers/linear.ts +121 -0
- package/src/social-providers/linkedin.ts +110 -0
- package/src/social-providers/microsoft-entra-id.ts +259 -0
- package/src/social-providers/naver.ts +112 -0
- package/src/social-providers/notion.ts +108 -0
- package/src/social-providers/paybin.ts +122 -0
- package/src/social-providers/paypal.ts +263 -0
- package/src/social-providers/polar.ts +110 -0
- package/src/social-providers/reddit.ts +122 -0
- package/src/social-providers/roblox.ts +111 -0
- package/src/social-providers/salesforce.ts +159 -0
- package/src/social-providers/slack.ts +111 -0
- package/src/social-providers/spotify.ts +93 -0
- package/src/social-providers/tiktok.ts +209 -0
- package/src/social-providers/twitch.ts +111 -0
- package/src/social-providers/twitter.ts +198 -0
- package/src/social-providers/vercel.ts +87 -0
- package/src/social-providers/vk.ts +124 -0
- package/src/social-providers/zoom.ts +238 -0
- package/src/types/context.ts +396 -0
- package/src/types/cookie.ts +10 -0
- package/src/types/helper.ts +26 -0
- package/src/types/index.ts +32 -0
- package/src/types/init-options.ts +1529 -0
- package/src/types/plugin-client.ts +127 -0
- package/src/types/plugin.ts +157 -0
- package/src/utils/db.ts +20 -0
- package/src/utils/deprecate.test.ts +72 -0
- package/src/utils/deprecate.ts +21 -0
- package/src/utils/error-codes.ts +65 -0
- package/src/utils/id.ts +5 -0
- package/src/utils/ip.test.ts +255 -0
- package/src/utils/ip.ts +211 -0
- package/src/utils/json.ts +25 -0
- package/src/utils/string.ts +3 -0
- package/src/utils/url.ts +43 -0
- package/tsconfig.json +7 -0
- package/tsdown.config.ts +35 -0
- package/vitest.config.ts +3 -0
|
@@ -0,0 +1,33 @@
|
|
|
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 };
|
|
33
|
+
//# sourceMappingURL=url.mjs.map
|
|
@@ -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
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hammadj/better-auth-core",
|
|
3
|
+
"version": "1.5.0-beta.9",
|
|
4
|
+
"description": "The most comprehensive authentication framework for TypeScript.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/META-DREAMER/better-auth.git",
|
|
9
|
+
"directory": "packages/core"
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/index.mjs",
|
|
12
|
+
"module": "./dist/index.mjs",
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"dev-source": "./src/index.ts",
|
|
17
|
+
"types": "./dist/index.d.mts",
|
|
18
|
+
"default": "./dist/index.mjs"
|
|
19
|
+
},
|
|
20
|
+
"./api": {
|
|
21
|
+
"dev-source": "./src/api/index.ts",
|
|
22
|
+
"types": "./dist/api/index.d.mts",
|
|
23
|
+
"default": "./dist/api/index.mjs"
|
|
24
|
+
},
|
|
25
|
+
"./async_hooks": {
|
|
26
|
+
"dev-source": "./src/async_hooks/index.ts",
|
|
27
|
+
"types": "./dist/async_hooks/index.d.mts",
|
|
28
|
+
"node": "./dist/async_hooks/index.mjs",
|
|
29
|
+
"deno": "./dist/async_hooks/index.mjs",
|
|
30
|
+
"bun": "./dist/async_hooks/index.mjs",
|
|
31
|
+
"edge": "./dist/async_hooks/pure.index.mjs",
|
|
32
|
+
"workerd": "./dist/async_hooks/index.mjs",
|
|
33
|
+
"browser": "./dist/async_hooks/pure.index.mjs",
|
|
34
|
+
"default": "./dist/async_hooks/index.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./context": {
|
|
37
|
+
"dev-source": "./src/context/index.ts",
|
|
38
|
+
"types": "./dist/context/index.d.mts",
|
|
39
|
+
"default": "./dist/context/index.mjs"
|
|
40
|
+
},
|
|
41
|
+
"./env": {
|
|
42
|
+
"dev-source": "./src/env/index.ts",
|
|
43
|
+
"types": "./dist/env/index.d.mts",
|
|
44
|
+
"default": "./dist/env/index.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./error": {
|
|
47
|
+
"dev-source": "./src/error/index.ts",
|
|
48
|
+
"types": "./dist/error/index.d.mts",
|
|
49
|
+
"default": "./dist/error/index.mjs"
|
|
50
|
+
},
|
|
51
|
+
"./utils/*": {
|
|
52
|
+
"dev-source": "./src/utils/*.ts",
|
|
53
|
+
"types": "./dist/utils/*.d.mts",
|
|
54
|
+
"default": "./dist/utils/*.mjs"
|
|
55
|
+
},
|
|
56
|
+
"./social-providers": {
|
|
57
|
+
"dev-source": "./src/social-providers/index.ts",
|
|
58
|
+
"types": "./dist/social-providers/index.d.mts",
|
|
59
|
+
"default": "./dist/social-providers/index.mjs"
|
|
60
|
+
},
|
|
61
|
+
"./db": {
|
|
62
|
+
"dev-source": "./src/db/index.ts",
|
|
63
|
+
"types": "./dist/db/index.d.mts",
|
|
64
|
+
"default": "./dist/db/index.mjs"
|
|
65
|
+
},
|
|
66
|
+
"./db/adapter": {
|
|
67
|
+
"dev-source": "./src/db/adapter/index.ts",
|
|
68
|
+
"types": "./dist/db/adapter/index.d.mts",
|
|
69
|
+
"default": "./dist/db/adapter/index.mjs"
|
|
70
|
+
},
|
|
71
|
+
"./oauth2": {
|
|
72
|
+
"dev-source": "./src/oauth2/index.ts",
|
|
73
|
+
"types": "./dist/oauth2/index.d.mts",
|
|
74
|
+
"default": "./dist/oauth2/index.mjs"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"typesVersions": {
|
|
78
|
+
"*": {
|
|
79
|
+
".": [
|
|
80
|
+
"dist/index.d.mts"
|
|
81
|
+
],
|
|
82
|
+
"api": [
|
|
83
|
+
"dist/api/index.d.mts"
|
|
84
|
+
],
|
|
85
|
+
"async_hooks": [
|
|
86
|
+
"dist/async_hooks/index.d.mts"
|
|
87
|
+
],
|
|
88
|
+
"context": [
|
|
89
|
+
"dist/context/index.d.mts"
|
|
90
|
+
],
|
|
91
|
+
"env": [
|
|
92
|
+
"dist/env/index.d.mts"
|
|
93
|
+
],
|
|
94
|
+
"error": [
|
|
95
|
+
"dist/error/index.d.mts"
|
|
96
|
+
],
|
|
97
|
+
"utils": [
|
|
98
|
+
"dist/utils/index.d.mts"
|
|
99
|
+
],
|
|
100
|
+
"utils/*": [
|
|
101
|
+
"dist/utils/*.d.mts"
|
|
102
|
+
],
|
|
103
|
+
"social-providers": [
|
|
104
|
+
"dist/social-providers/index.d.mts"
|
|
105
|
+
],
|
|
106
|
+
"db": [
|
|
107
|
+
"dist/db/index.d.mts"
|
|
108
|
+
],
|
|
109
|
+
"db/adapter": [
|
|
110
|
+
"dist/db/adapter/index.d.mts"
|
|
111
|
+
],
|
|
112
|
+
"oauth2": [
|
|
113
|
+
"dist/oauth2/index.d.mts"
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"devDependencies": {
|
|
118
|
+
"@better-auth/utils": "0.3.1",
|
|
119
|
+
"@better-fetch/fetch": "1.1.21",
|
|
120
|
+
"better-call": "1.2.0",
|
|
121
|
+
"jose": "^6.1.0",
|
|
122
|
+
"kysely": "^0.28.10",
|
|
123
|
+
"nanostores": "^1.1.0",
|
|
124
|
+
"tsdown": "^0.20.1"
|
|
125
|
+
},
|
|
126
|
+
"dependencies": {
|
|
127
|
+
"@standard-schema/spec": "^1.0.0",
|
|
128
|
+
"zod": "^4.3.6"
|
|
129
|
+
},
|
|
130
|
+
"peerDependencies": {
|
|
131
|
+
"@better-auth/utils": "0.3.1",
|
|
132
|
+
"@better-fetch/fetch": "1.1.21",
|
|
133
|
+
"better-call": "1.2.0",
|
|
134
|
+
"jose": "^6.1.0",
|
|
135
|
+
"kysely": "^0.28.5",
|
|
136
|
+
"nanostores": "^1.0.1"
|
|
137
|
+
},
|
|
138
|
+
"scripts": {
|
|
139
|
+
"build": "tsdown",
|
|
140
|
+
"dev": "tsdown --watch",
|
|
141
|
+
"lint:package": "publint run --strict",
|
|
142
|
+
"lint:types": "attw --profile esm-only --pack .",
|
|
143
|
+
"typecheck": "tsc --project tsconfig.json",
|
|
144
|
+
"test": "vitest",
|
|
145
|
+
"coverage": "vitest run --coverage --coverage.provider=istanbul"
|
|
146
|
+
}
|
|
147
|
+
}
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EndpointContext,
|
|
3
|
+
EndpointOptions,
|
|
4
|
+
StrictEndpoint,
|
|
5
|
+
} from "better-call";
|
|
6
|
+
import { createEndpoint, createMiddleware } from "better-call";
|
|
7
|
+
import { runWithEndpointContext } from "../context";
|
|
8
|
+
import type { AuthContext } from "../types";
|
|
9
|
+
|
|
10
|
+
export const optionsMiddleware = createMiddleware(async () => {
|
|
11
|
+
/**
|
|
12
|
+
* This will be passed on the instance of
|
|
13
|
+
* the context. Used to infer the type
|
|
14
|
+
* here.
|
|
15
|
+
*/
|
|
16
|
+
return {} as AuthContext;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const createAuthMiddleware = createMiddleware.create({
|
|
20
|
+
use: [
|
|
21
|
+
optionsMiddleware,
|
|
22
|
+
/**
|
|
23
|
+
* Only use for post hooks
|
|
24
|
+
*/
|
|
25
|
+
createMiddleware(async () => {
|
|
26
|
+
return {} as {
|
|
27
|
+
returned?: unknown | undefined;
|
|
28
|
+
responseHeaders?: Headers | undefined;
|
|
29
|
+
};
|
|
30
|
+
}),
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const use = [optionsMiddleware];
|
|
35
|
+
|
|
36
|
+
type EndpointHandler<
|
|
37
|
+
Path extends string,
|
|
38
|
+
Options extends EndpointOptions,
|
|
39
|
+
R,
|
|
40
|
+
> = (context: EndpointContext<Path, Options, AuthContext>) => Promise<R>;
|
|
41
|
+
|
|
42
|
+
export function createAuthEndpoint<
|
|
43
|
+
Path extends string,
|
|
44
|
+
Options extends EndpointOptions,
|
|
45
|
+
R,
|
|
46
|
+
>(
|
|
47
|
+
path: Path,
|
|
48
|
+
options: Options,
|
|
49
|
+
handler: EndpointHandler<Path, Options, R>,
|
|
50
|
+
): StrictEndpoint<Path, Options, R>;
|
|
51
|
+
|
|
52
|
+
export function createAuthEndpoint<
|
|
53
|
+
Path extends string,
|
|
54
|
+
Options extends EndpointOptions,
|
|
55
|
+
R,
|
|
56
|
+
>(
|
|
57
|
+
options: Options,
|
|
58
|
+
handler: EndpointHandler<Path, Options, R>,
|
|
59
|
+
): StrictEndpoint<Path, Options, R>;
|
|
60
|
+
|
|
61
|
+
export function createAuthEndpoint<
|
|
62
|
+
Path extends string,
|
|
63
|
+
Opts extends EndpointOptions,
|
|
64
|
+
R,
|
|
65
|
+
>(
|
|
66
|
+
pathOrOptions: Path | Opts,
|
|
67
|
+
handlerOrOptions: EndpointHandler<Path, Opts, R> | Opts,
|
|
68
|
+
handlerOrNever?: any,
|
|
69
|
+
) {
|
|
70
|
+
const path: Path | undefined =
|
|
71
|
+
typeof pathOrOptions === "string" ? pathOrOptions : undefined;
|
|
72
|
+
const options: Opts =
|
|
73
|
+
typeof handlerOrOptions === "object"
|
|
74
|
+
? handlerOrOptions
|
|
75
|
+
: (pathOrOptions as Opts);
|
|
76
|
+
const handler: EndpointHandler<Path, Opts, R> =
|
|
77
|
+
typeof handlerOrOptions === "function" ? handlerOrOptions : handlerOrNever;
|
|
78
|
+
|
|
79
|
+
if (path) {
|
|
80
|
+
return createEndpoint(
|
|
81
|
+
path,
|
|
82
|
+
{
|
|
83
|
+
...options,
|
|
84
|
+
use: [...(options?.use || []), ...use],
|
|
85
|
+
},
|
|
86
|
+
// todo: prettify the code, we want to call `runWithEndpointContext` to top level
|
|
87
|
+
async (ctx) => runWithEndpointContext(ctx as any, () => handler(ctx)),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return createEndpoint(
|
|
92
|
+
{
|
|
93
|
+
...options,
|
|
94
|
+
use: [...(options?.use || []), ...use],
|
|
95
|
+
},
|
|
96
|
+
// todo: prettify the code, we want to call `runWithEndpointContext` to top level
|
|
97
|
+
async (ctx) => runWithEndpointContext(ctx as any, () => handler(ctx)),
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type AuthEndpoint<
|
|
102
|
+
Path extends string,
|
|
103
|
+
Opts extends EndpointOptions,
|
|
104
|
+
R,
|
|
105
|
+
> = ReturnType<typeof createAuthEndpoint<Path, Opts, R>>;
|
|
106
|
+
export type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
|
|
3
|
+
export type { AsyncLocalStorage };
|
|
4
|
+
|
|
5
|
+
const AsyncLocalStoragePromise: Promise<typeof AsyncLocalStorage | null> =
|
|
6
|
+
import(
|
|
7
|
+
/* @vite-ignore */
|
|
8
|
+
/* webpackIgnore: true */
|
|
9
|
+
"node:async_hooks"
|
|
10
|
+
)
|
|
11
|
+
.then((mod) => mod.AsyncLocalStorage)
|
|
12
|
+
.catch((err) => {
|
|
13
|
+
if ("AsyncLocalStorage" in globalThis) {
|
|
14
|
+
return (globalThis as any).AsyncLocalStorage;
|
|
15
|
+
}
|
|
16
|
+
if (typeof window !== "undefined") {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
console.warn(
|
|
20
|
+
"[better-auth] Warning: AsyncLocalStorage is not available in this environment. Some features may not work as expected.",
|
|
21
|
+
);
|
|
22
|
+
console.warn(
|
|
23
|
+
"[better-auth] Please read more about this warning at https://better-auth.com/docs/installation#mount-handler",
|
|
24
|
+
);
|
|
25
|
+
console.warn(
|
|
26
|
+
"[better-auth] If you are using Cloudflare Workers, please see: https://developers.cloudflare.com/workers/configuration/compatibility-flags/#nodejs-compatibility-flag",
|
|
27
|
+
);
|
|
28
|
+
throw err;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export async function getAsyncLocalStorage(): Promise<
|
|
32
|
+
typeof AsyncLocalStorage
|
|
33
|
+
> {
|
|
34
|
+
const mod = await AsyncLocalStoragePromise;
|
|
35
|
+
if (mod === null) {
|
|
36
|
+
throw new Error("getAsyncLocalStorage is only available in server code");
|
|
37
|
+
} else {
|
|
38
|
+
return mod;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Due to the lack of AsyncLocalStorage in some environments (like Convex),
|
|
5
|
+
*
|
|
6
|
+
* We assume serverless functions are short-lived and single-threaded, so we can use a simple polyfill.
|
|
7
|
+
*/
|
|
8
|
+
class AsyncLocalStoragePolyfill<T> {
|
|
9
|
+
#current: T | undefined = undefined;
|
|
10
|
+
|
|
11
|
+
run(store: T, fn: () => unknown): unknown {
|
|
12
|
+
const prev = this.#current;
|
|
13
|
+
this.#current = store;
|
|
14
|
+
const result = fn();
|
|
15
|
+
if (result instanceof Promise) {
|
|
16
|
+
return result.finally(() => {
|
|
17
|
+
this.#current = prev;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
this.#current = prev;
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getStore(): T | undefined {
|
|
25
|
+
return this.#current;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const AsyncLocalStoragePromise: Promise<typeof AsyncLocalStorage | null> =
|
|
30
|
+
Promise.resolve().then(() => {
|
|
31
|
+
if ("AsyncLocalStorage" in globalThis) {
|
|
32
|
+
return (globalThis as any).AsyncLocalStorage;
|
|
33
|
+
}
|
|
34
|
+
return AsyncLocalStoragePolyfill;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export async function getAsyncLocalStorage(): Promise<
|
|
38
|
+
typeof AsyncLocalStorage
|
|
39
|
+
> {
|
|
40
|
+
const mod = await AsyncLocalStoragePromise;
|
|
41
|
+
if (mod === null) {
|
|
42
|
+
throw new Error("getAsyncLocalStorage is only available in server code");
|
|
43
|
+
} else {
|
|
44
|
+
return mod;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { AsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
2
|
+
import { getAsyncLocalStorage } from "@better-auth/core/async_hooks";
|
|
3
|
+
import type { EndpointContext, InputContext } from "better-call";
|
|
4
|
+
import type { AuthContext } from "../types";
|
|
5
|
+
import { __getBetterAuthGlobal } from "./global";
|
|
6
|
+
|
|
7
|
+
export type AuthEndpointContext = Partial<
|
|
8
|
+
InputContext<string, any> & EndpointContext<string, any>
|
|
9
|
+
> & {
|
|
10
|
+
context: AuthContext;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const ensureAsyncStorage = async () => {
|
|
14
|
+
const betterAuthGlobal = __getBetterAuthGlobal();
|
|
15
|
+
if (!betterAuthGlobal.context.endpointContextAsyncStorage) {
|
|
16
|
+
const AsyncLocalStorage = await getAsyncLocalStorage();
|
|
17
|
+
betterAuthGlobal.context.endpointContextAsyncStorage =
|
|
18
|
+
new AsyncLocalStorage<AuthEndpointContext>();
|
|
19
|
+
}
|
|
20
|
+
return betterAuthGlobal.context
|
|
21
|
+
.endpointContextAsyncStorage as AsyncLocalStorage<AuthEndpointContext>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This is for internal use only. Most users should use `getCurrentAuthContext` instead.
|
|
26
|
+
*
|
|
27
|
+
* It is exposed for advanced use cases where you need direct access to the AsyncLocalStorage instance.
|
|
28
|
+
*/
|
|
29
|
+
export async function getCurrentAuthContextAsyncLocalStorage() {
|
|
30
|
+
return ensureAsyncStorage();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function getCurrentAuthContext(): Promise<AuthEndpointContext> {
|
|
34
|
+
const als = await ensureAsyncStorage();
|
|
35
|
+
const context = als.getStore();
|
|
36
|
+
if (!context) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"No auth context found. Please make sure you are calling this function within a `runWithEndpointContext` callback.",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return context;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function runWithEndpointContext<T>(
|
|
45
|
+
context: AuthEndpointContext,
|
|
46
|
+
fn: () => T,
|
|
47
|
+
): Promise<T> {
|
|
48
|
+
const als = await ensureAsyncStorage();
|
|
49
|
+
return als.run(context, fn);
|
|
50
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type AuthEndpointContext,
|
|
3
|
+
getCurrentAuthContext,
|
|
4
|
+
getCurrentAuthContextAsyncLocalStorage,
|
|
5
|
+
runWithEndpointContext,
|
|
6
|
+
} from "./endpoint-context";
|
|
7
|
+
export { getBetterAuthVersion } from "./global";
|
|
8
|
+
export {
|
|
9
|
+
defineRequestState,
|
|
10
|
+
getCurrentRequestState,
|
|
11
|
+
getRequestStateAsyncLocalStorage,
|
|
12
|
+
hasRequestState,
|
|
13
|
+
type RequestState,
|
|
14
|
+
type RequestStateWeakMap,
|
|
15
|
+
runWithRequestState,
|
|
16
|
+
} from "./request-state";
|
|
17
|
+
export {
|
|
18
|
+
getCurrentAdapter,
|
|
19
|
+
getCurrentDBAdapterAsyncLocalStorage,
|
|
20
|
+
queueAfterTransactionHook,
|
|
21
|
+
runWithAdapter,
|
|
22
|
+
runWithTransaction,
|
|
23
|
+
} from "./transaction";
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import type { RequestStateWeakMap } from "./request-state";
|
|
3
|
+
import {
|
|
4
|
+
defineRequestState,
|
|
5
|
+
getCurrentRequestState,
|
|
6
|
+
hasRequestState,
|
|
7
|
+
runWithRequestState,
|
|
8
|
+
} from "./request-state";
|
|
9
|
+
|
|
10
|
+
describe("request-state", () => {
|
|
11
|
+
describe("runWithRequestState", () => {
|
|
12
|
+
it("should execute function within request state context", async () => {
|
|
13
|
+
const store: RequestStateWeakMap = new WeakMap();
|
|
14
|
+
const result = await runWithRequestState(store, async () => {
|
|
15
|
+
const hasStore = await hasRequestState();
|
|
16
|
+
expect(hasStore).toBe(true);
|
|
17
|
+
return "success";
|
|
18
|
+
});
|
|
19
|
+
expect(result).toBe("success");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should isolate request states between concurrent requests", async () => {
|
|
23
|
+
const store1: RequestStateWeakMap = new WeakMap();
|
|
24
|
+
const store2: RequestStateWeakMap = new WeakMap();
|
|
25
|
+
|
|
26
|
+
const { get, set } = defineRequestState(() => ({}) as { id: string });
|
|
27
|
+
|
|
28
|
+
const [result1, result2] = await Promise.all([
|
|
29
|
+
runWithRequestState(store1, async () => {
|
|
30
|
+
await set({ id: "store1" });
|
|
31
|
+
// Simulate some async work
|
|
32
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
33
|
+
return await get();
|
|
34
|
+
}),
|
|
35
|
+
runWithRequestState(store2, async () => {
|
|
36
|
+
await set({ id: "store2" });
|
|
37
|
+
// Simulate some async work
|
|
38
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
39
|
+
return await get();
|
|
40
|
+
}),
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
expect(result1).toEqual({ id: "store1" });
|
|
44
|
+
expect(result2).toEqual({ id: "store2" });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should support nested async operations", async () => {
|
|
48
|
+
const store: RequestStateWeakMap = new WeakMap();
|
|
49
|
+
const { get, set } = defineRequestState(() => ({ value: 1 }));
|
|
50
|
+
|
|
51
|
+
await runWithRequestState(store, async () => {
|
|
52
|
+
const nestedResult = await (async () => {
|
|
53
|
+
const current = await get();
|
|
54
|
+
await set({ value: (current?.value || 0) + 1 });
|
|
55
|
+
return await get();
|
|
56
|
+
})();
|
|
57
|
+
|
|
58
|
+
expect(nestedResult).toEqual({ value: 2 });
|
|
59
|
+
expect(await get()).toEqual({ value: 2 });
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("hasRequestState", () => {
|
|
65
|
+
it("should return false when not in request state context", async () => {
|
|
66
|
+
const hasStore = await hasRequestState();
|
|
67
|
+
expect(hasStore).toBe(false);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should return true when in request state context", async () => {
|
|
71
|
+
const store: RequestStateWeakMap = new WeakMap();
|
|
72
|
+
await runWithRequestState(store, async () => {
|
|
73
|
+
const hasStore = await hasRequestState();
|
|
74
|
+
expect(hasStore).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe("getCurrentRequestState", () => {
|
|
80
|
+
it("should throw error when not in request state context", async () => {
|
|
81
|
+
await expect(getCurrentRequestState()).rejects.toThrow(
|
|
82
|
+
"No request state found",
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should return the current store when in context", async () => {
|
|
87
|
+
const store: RequestStateWeakMap = new WeakMap();
|
|
88
|
+
await runWithRequestState(store, async () => {
|
|
89
|
+
const currentStore = await getCurrentRequestState();
|
|
90
|
+
expect(currentStore).toBe(store);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|