better-auth 1.5.0-beta.1 → 1.5.0-beta.3
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/LICENSE.md +15 -12
- package/README.md +19 -9
- package/dist/adapters/memory-adapter/memory-adapter.mjs +1 -0
- package/dist/adapters/memory-adapter/memory-adapter.mjs.map +1 -1
- package/dist/adapters/mongodb-adapter/mongodb-adapter.mjs +11 -3
- package/dist/adapters/mongodb-adapter/mongodb-adapter.mjs.map +1 -1
- package/dist/adapters/prisma-adapter/prisma-adapter.mjs +15 -0
- package/dist/adapters/prisma-adapter/prisma-adapter.mjs.map +1 -1
- package/dist/api/index.d.mts +212 -94
- package/dist/api/index.mjs +10 -10
- package/dist/api/index.mjs.map +1 -1
- package/dist/api/middlewares/index.d.mts +1 -1
- package/dist/api/middlewares/index.mjs +1 -1
- package/dist/api/middlewares/origin-check.d.mts +11 -6
- package/dist/api/middlewares/origin-check.mjs +56 -10
- package/dist/api/middlewares/origin-check.mjs.map +1 -1
- package/dist/api/rate-limiter/index.mjs +13 -2
- package/dist/api/rate-limiter/index.mjs.map +1 -1
- package/dist/api/routes/account.d.mts +13 -13
- package/dist/api/routes/account.mjs +3 -2
- package/dist/api/routes/account.mjs.map +1 -1
- package/dist/api/routes/callback.d.mts +2 -2
- package/dist/api/routes/email-verification.d.mts +4 -4
- package/dist/api/routes/email-verification.mjs +4 -1
- package/dist/api/routes/email-verification.mjs.map +1 -1
- package/dist/api/routes/error.d.mts +2 -2
- package/dist/api/routes/index.d.mts +1 -1
- package/dist/api/routes/index.mjs +1 -1
- package/dist/api/routes/ok.d.mts +2 -2
- package/dist/api/routes/{reset-password.d.mts → password.d.mts} +63 -8
- package/dist/api/routes/{reset-password.mjs → password.mjs} +32 -3
- package/dist/api/routes/password.mjs.map +1 -0
- package/dist/api/routes/session.d.mts +14 -14
- package/dist/api/routes/sign-in.d.mts +5 -3
- package/dist/api/routes/sign-in.mjs +5 -0
- package/dist/api/routes/sign-in.mjs.map +1 -1
- package/dist/api/routes/sign-out.d.mts +2 -2
- package/dist/api/routes/sign-up.d.mts +4 -2
- package/dist/api/routes/sign-up.mjs +4 -0
- package/dist/api/routes/sign-up.mjs.map +1 -1
- package/dist/api/routes/update-user.d.mts +13 -13
- package/dist/api/to-auth-endpoints.mjs +48 -32
- package/dist/api/to-auth-endpoints.mjs.map +1 -1
- package/dist/auth/base.mjs +1 -1
- package/dist/auth/trusted-origins.mjs +1 -1
- package/dist/client/index.d.mts +2 -3
- package/dist/client/plugins/index.d.mts +4 -3
- package/dist/client/proxy.mjs +3 -0
- package/dist/client/proxy.mjs.map +1 -1
- package/dist/client/react/index.d.mts +13 -13
- package/dist/client/session-refresh.mjs +2 -2
- package/dist/client/session-refresh.mjs.map +1 -1
- package/dist/client/vue/index.d.mts +13 -13
- package/dist/context/create-context.mjs +17 -11
- package/dist/context/create-context.mjs.map +1 -1
- package/dist/context/helpers.mjs +5 -4
- package/dist/context/helpers.mjs.map +1 -1
- package/dist/cookies/cookie-utils.d.mts +7 -1
- package/dist/cookies/cookie-utils.mjs +11 -1
- package/dist/cookies/cookie-utils.mjs.map +1 -1
- package/dist/cookies/index.d.mts +2 -2
- package/dist/cookies/index.mjs +5 -5
- package/dist/cookies/index.mjs.map +1 -1
- package/dist/db/field.d.mts +6 -6
- package/dist/db/internal-adapter.mjs +30 -12
- package/dist/db/internal-adapter.mjs.map +1 -1
- package/dist/integrations/next-js.d.mts +4 -4
- package/dist/integrations/svelte-kit.d.mts +2 -2
- package/dist/integrations/tanstack-start.d.mts +4 -4
- package/dist/oauth2/link-account.mjs +13 -15
- package/dist/oauth2/link-account.mjs.map +1 -1
- package/dist/oauth2/utils.mjs +13 -4
- package/dist/oauth2/utils.mjs.map +1 -1
- package/dist/plugins/admin/access/statement.d.mts +17 -17
- package/dist/plugins/admin/admin.d.mts +125 -118
- package/dist/plugins/admin/admin.mjs +2 -2
- package/dist/plugins/admin/admin.mjs.map +1 -1
- package/dist/plugins/admin/routes.mjs +1 -1
- package/dist/plugins/admin/routes.mjs.map +1 -1
- package/dist/plugins/anonymous/client.d.mts +13 -1
- package/dist/plugins/anonymous/error-codes.d.mts +12 -0
- package/dist/plugins/anonymous/error-codes.mjs +4 -1
- package/dist/plugins/anonymous/error-codes.mjs.map +1 -1
- package/dist/plugins/anonymous/index.d.mts +104 -3
- package/dist/plugins/anonymous/index.mjs +109 -50
- package/dist/plugins/anonymous/index.mjs.map +1 -1
- package/dist/plugins/anonymous/types.d.mts +10 -2
- package/dist/plugins/api-key/index.d.mts +146 -59
- package/dist/plugins/api-key/index.mjs.map +1 -1
- package/dist/plugins/api-key/routes/verify-api-key.mjs +0 -8
- package/dist/plugins/api-key/routes/verify-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/schema.d.mts +3 -3
- package/dist/plugins/bearer/index.d.mts +13 -6
- package/dist/plugins/bearer/index.mjs.map +1 -1
- package/dist/plugins/captcha/index.d.mts +11 -4
- package/dist/plugins/captcha/index.mjs.map +1 -1
- package/dist/plugins/captcha/types.d.mts +2 -1
- package/dist/plugins/custom-session/index.d.mts +9 -2
- package/dist/plugins/custom-session/index.mjs.map +1 -1
- package/dist/plugins/device-authorization/index.d.mts +7 -0
- package/dist/plugins/device-authorization/index.mjs.map +1 -1
- package/dist/plugins/email-otp/index.d.mts +55 -48
- package/dist/plugins/email-otp/index.mjs.map +1 -1
- package/dist/plugins/email-otp/routes.mjs +3 -1
- package/dist/plugins/email-otp/routes.mjs.map +1 -1
- package/dist/plugins/generic-oauth/client.d.mts +1 -0
- package/dist/plugins/generic-oauth/index.d.mts +33 -25
- package/dist/plugins/generic-oauth/index.mjs +2 -1
- package/dist/plugins/generic-oauth/index.mjs.map +1 -1
- package/dist/plugins/generic-oauth/providers/gumroad.d.mts +32 -0
- package/dist/plugins/generic-oauth/providers/gumroad.mjs +60 -0
- package/dist/plugins/generic-oauth/providers/gumroad.mjs.map +1 -0
- package/dist/plugins/generic-oauth/providers/index.d.mts +1 -0
- package/dist/plugins/generic-oauth/providers/index.mjs +1 -0
- package/dist/plugins/haveibeenpwned/index.d.mts +11 -4
- package/dist/plugins/haveibeenpwned/index.mjs +1 -1
- package/dist/plugins/haveibeenpwned/index.mjs.map +1 -1
- package/dist/plugins/index.d.mts +7 -6
- package/dist/plugins/index.mjs +2 -1
- package/dist/plugins/jwt/index.d.mts +16 -9
- package/dist/plugins/jwt/index.mjs.map +1 -1
- package/dist/plugins/last-login-method/index.d.mts +11 -4
- package/dist/plugins/last-login-method/index.mjs.map +1 -1
- package/dist/plugins/magic-link/index.d.mts +11 -4
- package/dist/plugins/magic-link/index.mjs.map +1 -1
- package/dist/plugins/mcp/index.d.mts +17 -10
- package/dist/plugins/mcp/index.mjs +5 -1
- package/dist/plugins/mcp/index.mjs.map +1 -1
- package/dist/plugins/multi-session/index.d.mts +21 -14
- package/dist/plugins/multi-session/index.mjs.map +1 -1
- package/dist/plugins/oauth-proxy/index.d.mts +15 -8
- package/dist/plugins/oauth-proxy/index.mjs +23 -11
- package/dist/plugins/oauth-proxy/index.mjs.map +1 -1
- package/dist/plugins/oauth-proxy/utils.mjs +8 -1
- package/dist/plugins/oauth-proxy/utils.mjs.map +1 -1
- package/dist/plugins/oidc-provider/index.d.mts +23 -16
- package/dist/plugins/oidc-provider/index.mjs +4 -7
- package/dist/plugins/oidc-provider/index.mjs.map +1 -1
- package/dist/plugins/one-tap/client.d.mts +4 -2
- package/dist/plugins/one-tap/client.mjs +29 -8
- package/dist/plugins/one-tap/client.mjs.map +1 -1
- package/dist/plugins/one-tap/index.d.mts +9 -2
- package/dist/plugins/one-tap/index.mjs +1 -1
- package/dist/plugins/one-tap/index.mjs.map +1 -1
- package/dist/plugins/one-time-token/index.d.mts +12 -5
- package/dist/plugins/one-time-token/index.mjs.map +1 -1
- package/dist/plugins/open-api/generator.mjs +11 -2
- package/dist/plugins/open-api/generator.mjs.map +1 -1
- package/dist/plugins/open-api/index.d.mts +10 -3
- package/dist/plugins/open-api/index.mjs.map +1 -1
- package/dist/plugins/organization/access/statement.d.mts +25 -25
- package/dist/plugins/organization/adapter.d.mts +1 -1
- package/dist/plugins/organization/client.d.mts +3 -3
- package/dist/plugins/organization/index.d.mts +2 -4
- package/dist/plugins/organization/organization.d.mts +48 -37
- package/dist/plugins/organization/organization.mjs +86 -85
- package/dist/plugins/organization/organization.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-access-control.d.mts +23 -23
- package/dist/plugins/organization/routes/crud-invites.d.mts +61 -61
- package/dist/plugins/organization/routes/crud-members.d.mts +66 -66
- package/dist/plugins/organization/routes/crud-org.d.mts +54 -54
- package/dist/plugins/organization/routes/crud-team.d.mts +79 -79
- package/dist/plugins/organization/schema.d.mts +2 -2
- package/dist/plugins/phone-number/index.d.mts +40 -33
- package/dist/plugins/phone-number/index.mjs.map +1 -1
- package/dist/plugins/siwe/index.d.mts +7 -0
- package/dist/plugins/siwe/index.mjs +1 -1
- package/dist/plugins/siwe/index.mjs.map +1 -1
- package/dist/plugins/two-factor/backup-codes/index.d.mts +5 -5
- package/dist/plugins/two-factor/client.d.mts +2 -2
- package/dist/plugins/two-factor/index.d.mts +25 -18
- package/dist/plugins/two-factor/index.mjs +1 -1
- package/dist/plugins/two-factor/index.mjs.map +1 -1
- package/dist/plugins/two-factor/otp/index.d.mts +3 -3
- package/dist/plugins/two-factor/totp/index.d.mts +5 -5
- package/dist/plugins/username/index.d.mts +18 -11
- package/dist/plugins/username/index.mjs.map +1 -1
- package/dist/plugins/username/schema.d.mts +3 -3
- package/dist/test-utils/test-instance.d.mts +1546 -1188
- package/dist/test-utils/test-instance.mjs +1 -1
- package/package.json +5 -5
- package/dist/api/routes/reset-password.mjs.map +0 -1
package/LICENSE.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
Copyright (c) 2024 - present, Bereket Engida
|
|
3
3
|
|
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
5
|
-
and associated documentation files (the
|
|
6
|
-
including without limitation the rights to
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
5
|
+
this software and associated documentation files (the “Software”), to deal in
|
|
6
|
+
the Software without restriction, including without limitation the rights to
|
|
7
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
8
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
9
|
+
subject to the following conditions:
|
|
9
10
|
|
|
10
|
-
The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
substantial portions of the Software.
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
12
13
|
|
|
13
|
-
THE SOFTWARE IS PROVIDED
|
|
14
|
-
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
16
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
18
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
19
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
20
|
+
DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
+
{/* lint disable maximum-line-length */}
|
|
3
|
+
|
|
2
4
|
<picture>
|
|
3
|
-
<source srcset="https://github.com/better-auth/better-auth/blob/main/banner-dark.png?raw=true"
|
|
4
|
-
|
|
5
|
-
<
|
|
5
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/better-auth/better-auth/blob/main/banner-dark.png?raw=true" />
|
|
6
|
+
|
|
7
|
+
<source media="(prefers-color-scheme: light)" srcset="https://github.com/better-auth/better-auth/blob/main/banner.png?raw=true" />
|
|
8
|
+
|
|
9
|
+
<img alt="Better Auth Logo" src="https://github.com/better-auth/better-auth/blob/main/banner.png?raw=true" />
|
|
6
10
|
</picture>
|
|
7
|
-
|
|
11
|
+
|
|
12
|
+
{/* lint enable maximum-line-length */}
|
|
13
|
+
|
|
14
|
+
<h1 align="center">
|
|
8
15
|
Better Auth
|
|
9
|
-
</
|
|
16
|
+
</h1>
|
|
10
17
|
|
|
11
18
|
<p align="center">
|
|
12
19
|
The most comprehensive authentication framework for TypeScript
|
|
20
|
+
|
|
13
21
|
<br />
|
|
22
|
+
|
|
14
23
|
<a href="https://better-auth.com"><strong>Learn more »</strong></a>
|
|
24
|
+
|
|
15
25
|
<br />
|
|
26
|
+
|
|
16
27
|
<br />
|
|
28
|
+
|
|
17
29
|
<a href="https://discord.gg/better-auth">Discord</a>
|
|
18
30
|
·
|
|
19
31
|
<a href="https://better-auth.com">Website</a>
|
|
@@ -22,13 +34,11 @@
|
|
|
22
34
|
</p>
|
|
23
35
|
</p>
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
37
|
## Getting Started
|
|
29
38
|
|
|
30
39
|
```bash
|
|
31
40
|
pnpm install better-auth
|
|
32
41
|
```
|
|
33
42
|
|
|
34
|
-
Read the [Installation Guide](https://better-auth.com/docs/installation) to
|
|
43
|
+
Read the [Installation Guide](https://better-auth.com/docs/installation) to
|
|
44
|
+
learn more.
|
|
@@ -10,6 +10,7 @@ const memoryAdapter = (db, config) => {
|
|
|
10
10
|
adapterName: "Memory Adapter",
|
|
11
11
|
usePlural: false,
|
|
12
12
|
debugLogs: config?.debugLogs || false,
|
|
13
|
+
supportsArrays: true,
|
|
13
14
|
customTransformInput(props) {
|
|
14
15
|
if ((props.options.advanced?.database?.useNumberId || props.options.advanced?.database?.generateId === "serial") && props.field === "id" && props.action === "create") return db[props.model].length + 1;
|
|
15
16
|
return props.data;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-adapter.mjs","names":["lazyOptions: BetterAuthOptions | null","model","where","nested: Record<string, any>"],"sources":["../../../src/adapters/memory-adapter/memory-adapter.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport type {\n\tCleanedWhere,\n\tDBAdapterDebugLogOption,\n\tJoinConfig,\n} from \"@better-auth/core/db/adapter\";\nimport { createAdapterFactory } from \"@better-auth/core/db/adapter\";\nimport { logger } from \"@better-auth/core/env\";\n\nexport interface MemoryDB {\n\t[key: string]: any[];\n}\n\nexport interface MemoryAdapterConfig {\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n}\n\nexport const memoryAdapter = (\n\tdb: MemoryDB,\n\tconfig?: MemoryAdapterConfig | undefined,\n) => {\n\tlet lazyOptions: BetterAuthOptions | null = null;\n\tlet adapterCreator = createAdapterFactory({\n\t\tconfig: {\n\t\t\tadapterId: \"memory\",\n\t\t\tadapterName: \"Memory Adapter\",\n\t\t\tusePlural: false,\n\t\t\tdebugLogs: config?.debugLogs || false,\n\t\t\tcustomTransformInput(props) {\n\t\t\t\tconst useNumberId =\n\t\t\t\t\tprops.options.advanced?.database?.useNumberId ||\n\t\t\t\t\tprops.options.advanced?.database?.generateId === \"serial\";\n\t\t\t\tif (useNumberId && props.field === \"id\" && props.action === \"create\") {\n\t\t\t\t\treturn db[props.model]!.length + 1;\n\t\t\t\t}\n\t\t\t\treturn props.data;\n\t\t\t},\n\t\t\ttransaction: async (cb) => {\n\t\t\t\tlet clone = structuredClone(db);\n\t\t\t\ttry {\n\t\t\t\t\tconst r = await cb(adapterCreator(lazyOptions!));\n\t\t\t\t\treturn r;\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Rollback changes\n\t\t\t\t\tObject.keys(db).forEach((key) => {\n\t\t\t\t\t\tdb[key] = clone[key]!;\n\t\t\t\t\t});\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tadapter: ({ getFieldName, options, getModelName }) => {\n\t\t\tconst applySortToRecords = (\n\t\t\t\trecords: any[],\n\t\t\t\tsortBy: { field: string; direction: \"asc\" | \"desc\" } | undefined,\n\t\t\t\tmodel: string,\n\t\t\t) => {\n\t\t\t\tif (!sortBy) return records;\n\t\t\t\treturn records.sort((a: any, b: any) => {\n\t\t\t\t\tconst field = getFieldName({ model, field: sortBy.field });\n\t\t\t\t\tconst aValue = a[field];\n\t\t\t\t\tconst bValue = b[field];\n\n\t\t\t\t\tlet comparison = 0;\n\n\t\t\t\t\t// Handle null/undefined values\n\t\t\t\t\tif (aValue == null && bValue == null) {\n\t\t\t\t\t\tcomparison = 0;\n\t\t\t\t\t} else if (aValue == null) {\n\t\t\t\t\t\tcomparison = -1;\n\t\t\t\t\t} else if (bValue == null) {\n\t\t\t\t\t\tcomparison = 1;\n\t\t\t\t\t}\n\t\t\t\t\t// Handle string comparison\n\t\t\t\t\telse if (typeof aValue === \"string\" && typeof bValue === \"string\") {\n\t\t\t\t\t\tcomparison = aValue.localeCompare(bValue);\n\t\t\t\t\t}\n\t\t\t\t\t// Handle date comparison\n\t\t\t\t\telse if (aValue instanceof Date && bValue instanceof Date) {\n\t\t\t\t\t\tcomparison = aValue.getTime() - bValue.getTime();\n\t\t\t\t\t}\n\t\t\t\t\t// Handle numeric comparison\n\t\t\t\t\telse if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n\t\t\t\t\t\tcomparison = aValue - bValue;\n\t\t\t\t\t}\n\t\t\t\t\t// Handle boolean comparison\n\t\t\t\t\telse if (typeof aValue === \"boolean\" && typeof bValue === \"boolean\") {\n\t\t\t\t\t\tcomparison = aValue === bValue ? 0 : aValue ? 1 : -1;\n\t\t\t\t\t}\n\t\t\t\t\t// Fallback to string comparison\n\t\t\t\t\telse {\n\t\t\t\t\t\tcomparison = String(aValue).localeCompare(String(bValue));\n\t\t\t\t\t}\n\n\t\t\t\t\treturn sortBy.direction === \"asc\" ? comparison : -comparison;\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tfunction convertWhereClause(\n\t\t\t\twhere: CleanedWhere[],\n\t\t\t\tmodel: string,\n\t\t\t\tjoin?: JoinConfig,\n\t\t\t): any[] {\n\t\t\t\tconst execute = (where: CleanedWhere[], model: string) => {\n\t\t\t\t\tconst table = db[model];\n\t\t\t\t\tif (!table) {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t`[MemoryAdapter] Model ${model} not found in the DB`,\n\t\t\t\t\t\t\tObject.keys(db),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthrow new Error(`Model ${model} not found`);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst evalClause = (record: any, clause: CleanedWhere): boolean => {\n\t\t\t\t\t\tconst { field, value, operator } = clause;\n\t\t\t\t\t\tswitch (operator) {\n\t\t\t\t\t\t\tcase \"in\":\n\t\t\t\t\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\t\t\t\t\tthrow new Error(\"Value must be an array\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t\t\treturn value.includes(record[field]);\n\t\t\t\t\t\t\tcase \"not_in\":\n\t\t\t\t\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\t\t\t\t\tthrow new Error(\"Value must be an array\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t\t\treturn !value.includes(record[field]);\n\t\t\t\t\t\t\tcase \"contains\":\n\t\t\t\t\t\t\t\treturn record[field].includes(value);\n\t\t\t\t\t\t\tcase \"starts_with\":\n\t\t\t\t\t\t\t\treturn record[field].startsWith(value);\n\t\t\t\t\t\t\tcase \"ends_with\":\n\t\t\t\t\t\t\t\treturn record[field].endsWith(value);\n\t\t\t\t\t\t\tcase \"ne\":\n\t\t\t\t\t\t\t\treturn record[field] !== value;\n\t\t\t\t\t\t\tcase \"gt\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] > value);\n\t\t\t\t\t\t\tcase \"gte\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] >= value);\n\t\t\t\t\t\t\tcase \"lt\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] < value);\n\t\t\t\t\t\t\tcase \"lte\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] <= value);\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\treturn record[field] === value;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\treturn table.filter((record: any) => {\n\t\t\t\t\t\tif (!where.length || where.length === 0) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet result = evalClause(record, where[0]!);\n\t\t\t\t\t\tfor (const clause of where) {\n\t\t\t\t\t\t\tconst clauseResult = evalClause(record, clause);\n\n\t\t\t\t\t\t\tif (clause.connector === \"OR\") {\n\t\t\t\t\t\t\t\tresult = result || clauseResult;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresult = result && clauseResult;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\tif (!join) return execute(where, model);\n\n\t\t\t\tconst baseRecords = execute(where, model);\n\n\t\t\t\t// Group results by base model and nest joined data as arrays\n\t\t\t\tconst grouped = new Map<string, any>();\n\t\t\t\t// Track seen IDs per joined model for O(1) deduplication\n\t\t\t\tconst seenIds = new Map<string, Set<string>>();\n\n\t\t\t\tfor (const baseRecord of baseRecords) {\n\t\t\t\t\tconst baseId = String(baseRecord.id);\n\n\t\t\t\t\tif (!grouped.has(baseId)) {\n\t\t\t\t\t\tconst nested: Record<string, any> = { ...baseRecord };\n\n\t\t\t\t\t\t// Initialize joined data structures based on isUnique\n\t\t\t\t\t\tfor (const [joinModel, joinAttr] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst joinModelName = getModelName(joinModel);\n\t\t\t\t\t\t\tif (joinAttr.relation === \"one-to-one\") {\n\t\t\t\t\t\t\t\tnested[joinModelName] = null;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnested[joinModelName] = [];\n\t\t\t\t\t\t\t\tseenIds.set(`${baseId}-${joinModel}`, new Set());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tgrouped.set(baseId, nested);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nestedEntry = grouped.get(baseId)!;\n\n\t\t\t\t\t// Add joined data\n\t\t\t\t\tfor (const [joinModel, joinAttr] of Object.entries(join)) {\n\t\t\t\t\t\tconst joinModelName = getModelName(joinModel);\n\t\t\t\t\t\tconst joinTable = db[joinModelName];\n\t\t\t\t\t\tif (!joinTable) {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t`[MemoryAdapter] JoinOption model ${joinModelName} not found in the DB`,\n\t\t\t\t\t\t\t\tObject.keys(db),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tthrow new Error(`JoinOption model ${joinModelName} not found`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst matchingRecords = joinTable.filter(\n\t\t\t\t\t\t\t(joinRecord: any) =>\n\t\t\t\t\t\t\t\tjoinRecord[joinAttr.on.to] === baseRecord[joinAttr.on.from],\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (joinAttr.relation === \"one-to-one\") {\n\t\t\t\t\t\t\t// For unique relationships, store a single object (or null)\n\t\t\t\t\t\t\tnestedEntry[joinModelName] = matchingRecords[0] || null;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// For non-unique relationships, store array with limit\n\t\t\t\t\t\t\tconst seenSet = seenIds.get(`${baseId}-${joinModel}`)!;\n\t\t\t\t\t\t\tconst limit = joinAttr.limit ?? 100;\n\t\t\t\t\t\t\tlet count = 0;\n\n\t\t\t\t\t\t\tfor (const matchingRecord of matchingRecords) {\n\t\t\t\t\t\t\t\tif (count >= limit) break;\n\t\t\t\t\t\t\t\tif (!seenSet.has(matchingRecord.id)) {\n\t\t\t\t\t\t\t\t\tnestedEntry[joinModelName].push(matchingRecord);\n\t\t\t\t\t\t\t\t\tseenSet.add(matchingRecord.id);\n\t\t\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn Array.from(grouped.values());\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcreate: async ({ model, data }) => {\n\t\t\t\t\tconst useNumberId =\n\t\t\t\t\t\toptions.advanced?.database?.useNumberId ||\n\t\t\t\t\t\toptions.advanced?.database?.generateId === \"serial\";\n\t\t\t\t\tif (useNumberId) {\n\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\tdata.id = db[getModelName(model)]!.length + 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tdb[model] = [];\n\t\t\t\t\t}\n\t\t\t\t\tdb[model]!.push(data);\n\t\t\t\t\treturn data;\n\t\t\t\t},\n\t\t\t\tfindOne: async ({ model, where, join }) => {\n\t\t\t\t\tconst res = convertWhereClause(where, model, join);\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\t// When join is present, res is an array of nested objects\n\t\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\t\tif (!resArray.length) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Return the first nested object\n\t\t\t\t\t\treturn resArray[0];\n\t\t\t\t\t}\n\t\t\t\t\t// Without join, res is an array\n\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\tconst record = resArray[0] || null;\n\t\t\t\t\treturn record;\n\t\t\t\t},\n\t\t\t\tfindMany: async ({ model, where, sortBy, limit, offset, join }) => {\n\t\t\t\t\tlet res = convertWhereClause(where || [], model, join);\n\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\t// When join is present, res is an array of nested objects\n\t\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\t\tif (!resArray.length) {\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Apply sorting to nested objects\n\t\t\t\t\t\tapplySortToRecords(resArray, sortBy, model);\n\n\t\t\t\t\t\t// Apply offset and limit\n\t\t\t\t\t\tlet paginatedRecords = resArray;\n\t\t\t\t\t\tif (offset !== undefined) {\n\t\t\t\t\t\t\tpaginatedRecords = paginatedRecords.slice(offset);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\t\tpaginatedRecords = paginatedRecords.slice(0, limit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn paginatedRecords;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Without join - original logic\n\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\tlet table = applySortToRecords(resArray, sortBy, model);\n\t\t\t\t\tif (offset !== undefined) {\n\t\t\t\t\t\ttable = table!.slice(offset);\n\t\t\t\t\t}\n\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\ttable = table!.slice(0, limit);\n\t\t\t\t\t}\n\t\t\t\t\treturn table || [];\n\t\t\t\t},\n\t\t\t\tcount: async ({ model, where }) => {\n\t\t\t\t\tif (where) {\n\t\t\t\t\t\tconst filteredRecords = convertWhereClause(where, model);\n\t\t\t\t\t\treturn filteredRecords.length;\n\t\t\t\t\t}\n\t\t\t\t\treturn db[model]!.length;\n\t\t\t\t},\n\t\t\t\tupdate: async ({ model, where, update }) => {\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tres.forEach((record) => {\n\t\t\t\t\t\tObject.assign(record, update);\n\t\t\t\t\t});\n\t\t\t\t\treturn res[0] || null;\n\t\t\t\t},\n\t\t\t\tdelete: async ({ model, where }) => {\n\t\t\t\t\tconst table = db[model]!;\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tdb[model] = table.filter((record) => !res.includes(record));\n\t\t\t\t},\n\t\t\t\tdeleteMany: async ({ model, where }) => {\n\t\t\t\t\tconst table = db[model]!;\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tlet count = 0;\n\t\t\t\t\tdb[model] = table.filter((record) => {\n\t\t\t\t\t\tif (res.includes(record)) {\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn !res.includes(record);\n\t\t\t\t\t});\n\t\t\t\t\treturn count;\n\t\t\t\t},\n\t\t\t\tupdateMany({ model, where, update }) {\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tres.forEach((record) => {\n\t\t\t\t\t\tObject.assign(record, update);\n\t\t\t\t\t});\n\t\t\t\t\treturn res[0] || null;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t});\n\treturn (options: BetterAuthOptions) => {\n\t\tlazyOptions = options;\n\t\treturn adapterCreator(options);\n\t};\n};\n"],"mappings":";;;;AAiBA,MAAa,iBACZ,IACA,WACI;CACJ,IAAIA,cAAwC;CAC5C,IAAI,iBAAiB,qBAAqB;EACzC,QAAQ;GACP,WAAW;GACX,aAAa;GACb,WAAW;GACX,WAAW,QAAQ,aAAa;GAChC,qBAAqB,OAAO;AAI3B,SAFC,MAAM,QAAQ,UAAU,UAAU,eAClC,MAAM,QAAQ,UAAU,UAAU,eAAe,aAC/B,MAAM,UAAU,QAAQ,MAAM,WAAW,SAC3D,QAAO,GAAG,MAAM,OAAQ,SAAS;AAElC,WAAO,MAAM;;GAEd,aAAa,OAAO,OAAO;IAC1B,IAAI,QAAQ,gBAAgB,GAAG;AAC/B,QAAI;AAEH,YADU,MAAM,GAAG,eAAe,YAAa,CAAC;aAExC,OAAO;AAEf,YAAO,KAAK,GAAG,CAAC,SAAS,QAAQ;AAChC,SAAG,OAAO,MAAM;OACf;AACF,WAAM;;;GAGR;EACD,UAAU,EAAE,cAAc,SAAS,mBAAmB;GACrD,MAAM,sBACL,SACA,QACA,UACI;AACJ,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,QAAQ,MAAM,GAAQ,MAAW;KACvC,MAAM,QAAQ,aAAa;MAAE;MAAO,OAAO,OAAO;MAAO,CAAC;KAC1D,MAAM,SAAS,EAAE;KACjB,MAAM,SAAS,EAAE;KAEjB,IAAI,aAAa;AAGjB,SAAI,UAAU,QAAQ,UAAU,KAC/B,cAAa;cACH,UAAU,KACpB,cAAa;cACH,UAAU,KACpB,cAAa;cAGL,OAAO,WAAW,YAAY,OAAO,WAAW,SACxD,cAAa,OAAO,cAAc,OAAO;cAGjC,kBAAkB,QAAQ,kBAAkB,KACpD,cAAa,OAAO,SAAS,GAAG,OAAO,SAAS;cAGxC,OAAO,WAAW,YAAY,OAAO,WAAW,SACxD,cAAa,SAAS;cAGd,OAAO,WAAW,aAAa,OAAO,WAAW,UACzD,cAAa,WAAW,SAAS,IAAI,SAAS,IAAI;SAIlD,cAAa,OAAO,OAAO,CAAC,cAAc,OAAO,OAAO,CAAC;AAG1D,YAAO,OAAO,cAAc,QAAQ,aAAa,CAAC;MACjD;;GAGH,SAAS,mBACR,OACA,OACA,MACQ;IACR,MAAM,WAAW,SAAuB,YAAkB;KACzD,MAAM,QAAQ,GAAGC;AACjB,SAAI,CAAC,OAAO;AACX,aAAO,MACN,yBAAyBA,QAAM,uBAC/B,OAAO,KAAK,GAAG,CACf;AACD,YAAM,IAAI,MAAM,SAASA,QAAM,YAAY;;KAG5C,MAAM,cAAc,QAAa,WAAkC;MAClE,MAAM,EAAE,OAAO,OAAO,aAAa;AACnC,cAAQ,UAAR;OACC,KAAK;AACJ,YAAI,CAAC,MAAM,QAAQ,MAAM,CACxB,OAAM,IAAI,MAAM,yBAAyB;AAG1C,eAAO,MAAM,SAAS,OAAO,OAAO;OACrC,KAAK;AACJ,YAAI,CAAC,MAAM,QAAQ,MAAM,CACxB,OAAM,IAAI,MAAM,yBAAyB;AAG1C,eAAO,CAAC,MAAM,SAAS,OAAO,OAAO;OACtC,KAAK,WACJ,QAAO,OAAO,OAAO,SAAS,MAAM;OACrC,KAAK,cACJ,QAAO,OAAO,OAAO,WAAW,MAAM;OACvC,KAAK,YACJ,QAAO,OAAO,OAAO,SAAS,MAAM;OACrC,KAAK,KACJ,QAAO,OAAO,WAAW;OAC1B,KAAK,KACJ,QAAO,SAAS,QAAQ,QAAQ,OAAO,SAAS,MAAM;OACvD,KAAK,MACJ,QAAO,SAAS,QAAQ,QAAQ,OAAO,UAAU,MAAM;OACxD,KAAK,KACJ,QAAO,SAAS,QAAQ,QAAQ,OAAO,SAAS,MAAM;OACvD,KAAK,MACJ,QAAO,SAAS,QAAQ,QAAQ,OAAO,UAAU,MAAM;OACxD,QACC,QAAO,OAAO,WAAW;;;AAI5B,YAAO,MAAM,QAAQ,WAAgB;AACpC,UAAI,CAACC,QAAM,UAAUA,QAAM,WAAW,EACrC,QAAO;MAGR,IAAI,SAAS,WAAW,QAAQA,QAAM,GAAI;AAC1C,WAAK,MAAM,UAAUA,SAAO;OAC3B,MAAM,eAAe,WAAW,QAAQ,OAAO;AAE/C,WAAI,OAAO,cAAc,KACxB,UAAS,UAAU;WAEnB,UAAS,UAAU;;AAIrB,aAAO;OACN;;AAGH,QAAI,CAAC,KAAM,QAAO,QAAQ,OAAO,MAAM;IAEvC,MAAM,cAAc,QAAQ,OAAO,MAAM;IAGzC,MAAM,0BAAU,IAAI,KAAkB;IAEtC,MAAM,0BAAU,IAAI,KAA0B;AAE9C,SAAK,MAAM,cAAc,aAAa;KACrC,MAAM,SAAS,OAAO,WAAW,GAAG;AAEpC,SAAI,CAAC,QAAQ,IAAI,OAAO,EAAE;MACzB,MAAMC,SAA8B,EAAE,GAAG,YAAY;AAGrD,WAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,KAAK,EAAE;OACzD,MAAM,gBAAgB,aAAa,UAAU;AAC7C,WAAI,SAAS,aAAa,aACzB,QAAO,iBAAiB;YAClB;AACN,eAAO,iBAAiB,EAAE;AAC1B,gBAAQ,IAAI,GAAG,OAAO,GAAG,6BAAa,IAAI,KAAK,CAAC;;;AAIlD,cAAQ,IAAI,QAAQ,OAAO;;KAG5B,MAAM,cAAc,QAAQ,IAAI,OAAO;AAGvC,UAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,KAAK,EAAE;MACzD,MAAM,gBAAgB,aAAa,UAAU;MAC7C,MAAM,YAAY,GAAG;AACrB,UAAI,CAAC,WAAW;AACf,cAAO,MACN,oCAAoC,cAAc,uBAClD,OAAO,KAAK,GAAG,CACf;AACD,aAAM,IAAI,MAAM,oBAAoB,cAAc,YAAY;;MAG/D,MAAM,kBAAkB,UAAU,QAChC,eACA,WAAW,SAAS,GAAG,QAAQ,WAAW,SAAS,GAAG,MACvD;AAED,UAAI,SAAS,aAAa,aAEzB,aAAY,iBAAiB,gBAAgB,MAAM;WAC7C;OAEN,MAAM,UAAU,QAAQ,IAAI,GAAG,OAAO,GAAG,YAAY;OACrD,MAAM,QAAQ,SAAS,SAAS;OAChC,IAAI,QAAQ;AAEZ,YAAK,MAAM,kBAAkB,iBAAiB;AAC7C,YAAI,SAAS,MAAO;AACpB,YAAI,CAAC,QAAQ,IAAI,eAAe,GAAG,EAAE;AACpC,qBAAY,eAAe,KAAK,eAAe;AAC/C,iBAAQ,IAAI,eAAe,GAAG;AAC9B;;;;;;AAOL,WAAO,MAAM,KAAK,QAAQ,QAAQ,CAAC;;AAEpC,UAAO;IACN,QAAQ,OAAO,EAAE,OAAO,WAAW;AAIlC,SAFC,QAAQ,UAAU,UAAU,eAC5B,QAAQ,UAAU,UAAU,eAAe,SAG3C,MAAK,KAAK,GAAG,aAAa,MAAM,EAAG,SAAS;AAE7C,SAAI,CAAC,GAAG,OACP,IAAG,SAAS,EAAE;AAEf,QAAG,OAAQ,KAAK,KAAK;AACrB,YAAO;;IAER,SAAS,OAAO,EAAE,OAAO,OAAO,WAAW;KAC1C,MAAM,MAAM,mBAAmB,OAAO,OAAO,KAAK;AAClD,SAAI,MAAM;MAET,MAAM,WAAW;AACjB,UAAI,CAAC,SAAS,OACb,QAAO;AAGR,aAAO,SAAS;;AAKjB,YAFiB,IACO,MAAM;;IAG/B,UAAU,OAAO,EAAE,OAAO,OAAO,QAAQ,OAAO,QAAQ,WAAW;KAClE,IAAI,MAAM,mBAAmB,SAAS,EAAE,EAAE,OAAO,KAAK;AAEtD,SAAI,MAAM;MAET,MAAM,WAAW;AACjB,UAAI,CAAC,SAAS,OACb,QAAO,EAAE;AAIV,yBAAmB,UAAU,QAAQ,MAAM;MAG3C,IAAI,mBAAmB;AACvB,UAAI,WAAW,OACd,oBAAmB,iBAAiB,MAAM,OAAO;AAElD,UAAI,UAAU,OACb,oBAAmB,iBAAiB,MAAM,GAAG,MAAM;AAGpD,aAAO;;KAKR,IAAI,QAAQ,mBADK,KACwB,QAAQ,MAAM;AACvD,SAAI,WAAW,OACd,SAAQ,MAAO,MAAM,OAAO;AAE7B,SAAI,UAAU,OACb,SAAQ,MAAO,MAAM,GAAG,MAAM;AAE/B,YAAO,SAAS,EAAE;;IAEnB,OAAO,OAAO,EAAE,OAAO,YAAY;AAClC,SAAI,MAEH,QADwB,mBAAmB,OAAO,MAAM,CACjC;AAExB,YAAO,GAAG,OAAQ;;IAEnB,QAAQ,OAAO,EAAE,OAAO,OAAO,aAAa;KAC3C,MAAM,MAAM,mBAAmB,OAAO,MAAM;AAC5C,SAAI,SAAS,WAAW;AACvB,aAAO,OAAO,QAAQ,OAAO;OAC5B;AACF,YAAO,IAAI,MAAM;;IAElB,QAAQ,OAAO,EAAE,OAAO,YAAY;KACnC,MAAM,QAAQ,GAAG;KACjB,MAAM,MAAM,mBAAmB,OAAO,MAAM;AAC5C,QAAG,SAAS,MAAM,QAAQ,WAAW,CAAC,IAAI,SAAS,OAAO,CAAC;;IAE5D,YAAY,OAAO,EAAE,OAAO,YAAY;KACvC,MAAM,QAAQ,GAAG;KACjB,MAAM,MAAM,mBAAmB,OAAO,MAAM;KAC5C,IAAI,QAAQ;AACZ,QAAG,SAAS,MAAM,QAAQ,WAAW;AACpC,UAAI,IAAI,SAAS,OAAO,EAAE;AACzB;AACA,cAAO;;AAER,aAAO,CAAC,IAAI,SAAS,OAAO;OAC3B;AACF,YAAO;;IAER,WAAW,EAAE,OAAO,OAAO,UAAU;KACpC,MAAM,MAAM,mBAAmB,OAAO,MAAM;AAC5C,SAAI,SAAS,WAAW;AACvB,aAAO,OAAO,QAAQ,OAAO;OAC5B;AACF,YAAO,IAAI,MAAM;;IAElB;;EAEF,CAAC;AACF,SAAQ,YAA+B;AACtC,gBAAc;AACd,SAAO,eAAe,QAAQ"}
|
|
1
|
+
{"version":3,"file":"memory-adapter.mjs","names":["lazyOptions: BetterAuthOptions | null","model","where","nested: Record<string, any>"],"sources":["../../../src/adapters/memory-adapter/memory-adapter.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport type {\n\tCleanedWhere,\n\tDBAdapterDebugLogOption,\n\tJoinConfig,\n} from \"@better-auth/core/db/adapter\";\nimport { createAdapterFactory } from \"@better-auth/core/db/adapter\";\nimport { logger } from \"@better-auth/core/env\";\n\nexport interface MemoryDB {\n\t[key: string]: any[];\n}\n\nexport interface MemoryAdapterConfig {\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n}\n\nexport const memoryAdapter = (\n\tdb: MemoryDB,\n\tconfig?: MemoryAdapterConfig | undefined,\n) => {\n\tlet lazyOptions: BetterAuthOptions | null = null;\n\tlet adapterCreator = createAdapterFactory({\n\t\tconfig: {\n\t\t\tadapterId: \"memory\",\n\t\t\tadapterName: \"Memory Adapter\",\n\t\t\tusePlural: false,\n\t\t\tdebugLogs: config?.debugLogs || false,\n\t\t\tsupportsArrays: true,\n\t\t\tcustomTransformInput(props) {\n\t\t\t\tconst useNumberId =\n\t\t\t\t\tprops.options.advanced?.database?.useNumberId ||\n\t\t\t\t\tprops.options.advanced?.database?.generateId === \"serial\";\n\t\t\t\tif (useNumberId && props.field === \"id\" && props.action === \"create\") {\n\t\t\t\t\treturn db[props.model]!.length + 1;\n\t\t\t\t}\n\t\t\t\treturn props.data;\n\t\t\t},\n\t\t\ttransaction: async (cb) => {\n\t\t\t\tlet clone = structuredClone(db);\n\t\t\t\ttry {\n\t\t\t\t\tconst r = await cb(adapterCreator(lazyOptions!));\n\t\t\t\t\treturn r;\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Rollback changes\n\t\t\t\t\tObject.keys(db).forEach((key) => {\n\t\t\t\t\t\tdb[key] = clone[key]!;\n\t\t\t\t\t});\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tadapter: ({ getFieldName, options, getModelName }) => {\n\t\t\tconst applySortToRecords = (\n\t\t\t\trecords: any[],\n\t\t\t\tsortBy: { field: string; direction: \"asc\" | \"desc\" } | undefined,\n\t\t\t\tmodel: string,\n\t\t\t) => {\n\t\t\t\tif (!sortBy) return records;\n\t\t\t\treturn records.sort((a: any, b: any) => {\n\t\t\t\t\tconst field = getFieldName({ model, field: sortBy.field });\n\t\t\t\t\tconst aValue = a[field];\n\t\t\t\t\tconst bValue = b[field];\n\n\t\t\t\t\tlet comparison = 0;\n\n\t\t\t\t\t// Handle null/undefined values\n\t\t\t\t\tif (aValue == null && bValue == null) {\n\t\t\t\t\t\tcomparison = 0;\n\t\t\t\t\t} else if (aValue == null) {\n\t\t\t\t\t\tcomparison = -1;\n\t\t\t\t\t} else if (bValue == null) {\n\t\t\t\t\t\tcomparison = 1;\n\t\t\t\t\t}\n\t\t\t\t\t// Handle string comparison\n\t\t\t\t\telse if (typeof aValue === \"string\" && typeof bValue === \"string\") {\n\t\t\t\t\t\tcomparison = aValue.localeCompare(bValue);\n\t\t\t\t\t}\n\t\t\t\t\t// Handle date comparison\n\t\t\t\t\telse if (aValue instanceof Date && bValue instanceof Date) {\n\t\t\t\t\t\tcomparison = aValue.getTime() - bValue.getTime();\n\t\t\t\t\t}\n\t\t\t\t\t// Handle numeric comparison\n\t\t\t\t\telse if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n\t\t\t\t\t\tcomparison = aValue - bValue;\n\t\t\t\t\t}\n\t\t\t\t\t// Handle boolean comparison\n\t\t\t\t\telse if (typeof aValue === \"boolean\" && typeof bValue === \"boolean\") {\n\t\t\t\t\t\tcomparison = aValue === bValue ? 0 : aValue ? 1 : -1;\n\t\t\t\t\t}\n\t\t\t\t\t// Fallback to string comparison\n\t\t\t\t\telse {\n\t\t\t\t\t\tcomparison = String(aValue).localeCompare(String(bValue));\n\t\t\t\t\t}\n\n\t\t\t\t\treturn sortBy.direction === \"asc\" ? comparison : -comparison;\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tfunction convertWhereClause(\n\t\t\t\twhere: CleanedWhere[],\n\t\t\t\tmodel: string,\n\t\t\t\tjoin?: JoinConfig,\n\t\t\t): any[] {\n\t\t\t\tconst execute = (where: CleanedWhere[], model: string) => {\n\t\t\t\t\tconst table = db[model];\n\t\t\t\t\tif (!table) {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t`[MemoryAdapter] Model ${model} not found in the DB`,\n\t\t\t\t\t\t\tObject.keys(db),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthrow new Error(`Model ${model} not found`);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst evalClause = (record: any, clause: CleanedWhere): boolean => {\n\t\t\t\t\t\tconst { field, value, operator } = clause;\n\t\t\t\t\t\tswitch (operator) {\n\t\t\t\t\t\t\tcase \"in\":\n\t\t\t\t\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\t\t\t\t\tthrow new Error(\"Value must be an array\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t\t\treturn value.includes(record[field]);\n\t\t\t\t\t\t\tcase \"not_in\":\n\t\t\t\t\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\t\t\t\t\tthrow new Error(\"Value must be an array\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t\t\treturn !value.includes(record[field]);\n\t\t\t\t\t\t\tcase \"contains\":\n\t\t\t\t\t\t\t\treturn record[field].includes(value);\n\t\t\t\t\t\t\tcase \"starts_with\":\n\t\t\t\t\t\t\t\treturn record[field].startsWith(value);\n\t\t\t\t\t\t\tcase \"ends_with\":\n\t\t\t\t\t\t\t\treturn record[field].endsWith(value);\n\t\t\t\t\t\t\tcase \"ne\":\n\t\t\t\t\t\t\t\treturn record[field] !== value;\n\t\t\t\t\t\t\tcase \"gt\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] > value);\n\t\t\t\t\t\t\tcase \"gte\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] >= value);\n\t\t\t\t\t\t\tcase \"lt\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] < value);\n\t\t\t\t\t\t\tcase \"lte\":\n\t\t\t\t\t\t\t\treturn value != null && Boolean(record[field] <= value);\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\treturn record[field] === value;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\treturn table.filter((record: any) => {\n\t\t\t\t\t\tif (!where.length || where.length === 0) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet result = evalClause(record, where[0]!);\n\t\t\t\t\t\tfor (const clause of where) {\n\t\t\t\t\t\t\tconst clauseResult = evalClause(record, clause);\n\n\t\t\t\t\t\t\tif (clause.connector === \"OR\") {\n\t\t\t\t\t\t\t\tresult = result || clauseResult;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresult = result && clauseResult;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\tif (!join) return execute(where, model);\n\n\t\t\t\tconst baseRecords = execute(where, model);\n\n\t\t\t\t// Group results by base model and nest joined data as arrays\n\t\t\t\tconst grouped = new Map<string, any>();\n\t\t\t\t// Track seen IDs per joined model for O(1) deduplication\n\t\t\t\tconst seenIds = new Map<string, Set<string>>();\n\n\t\t\t\tfor (const baseRecord of baseRecords) {\n\t\t\t\t\tconst baseId = String(baseRecord.id);\n\n\t\t\t\t\tif (!grouped.has(baseId)) {\n\t\t\t\t\t\tconst nested: Record<string, any> = { ...baseRecord };\n\n\t\t\t\t\t\t// Initialize joined data structures based on isUnique\n\t\t\t\t\t\tfor (const [joinModel, joinAttr] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst joinModelName = getModelName(joinModel);\n\t\t\t\t\t\t\tif (joinAttr.relation === \"one-to-one\") {\n\t\t\t\t\t\t\t\tnested[joinModelName] = null;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnested[joinModelName] = [];\n\t\t\t\t\t\t\t\tseenIds.set(`${baseId}-${joinModel}`, new Set());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tgrouped.set(baseId, nested);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nestedEntry = grouped.get(baseId)!;\n\n\t\t\t\t\t// Add joined data\n\t\t\t\t\tfor (const [joinModel, joinAttr] of Object.entries(join)) {\n\t\t\t\t\t\tconst joinModelName = getModelName(joinModel);\n\t\t\t\t\t\tconst joinTable = db[joinModelName];\n\t\t\t\t\t\tif (!joinTable) {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t`[MemoryAdapter] JoinOption model ${joinModelName} not found in the DB`,\n\t\t\t\t\t\t\t\tObject.keys(db),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tthrow new Error(`JoinOption model ${joinModelName} not found`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst matchingRecords = joinTable.filter(\n\t\t\t\t\t\t\t(joinRecord: any) =>\n\t\t\t\t\t\t\t\tjoinRecord[joinAttr.on.to] === baseRecord[joinAttr.on.from],\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (joinAttr.relation === \"one-to-one\") {\n\t\t\t\t\t\t\t// For unique relationships, store a single object (or null)\n\t\t\t\t\t\t\tnestedEntry[joinModelName] = matchingRecords[0] || null;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// For non-unique relationships, store array with limit\n\t\t\t\t\t\t\tconst seenSet = seenIds.get(`${baseId}-${joinModel}`)!;\n\t\t\t\t\t\t\tconst limit = joinAttr.limit ?? 100;\n\t\t\t\t\t\t\tlet count = 0;\n\n\t\t\t\t\t\t\tfor (const matchingRecord of matchingRecords) {\n\t\t\t\t\t\t\t\tif (count >= limit) break;\n\t\t\t\t\t\t\t\tif (!seenSet.has(matchingRecord.id)) {\n\t\t\t\t\t\t\t\t\tnestedEntry[joinModelName].push(matchingRecord);\n\t\t\t\t\t\t\t\t\tseenSet.add(matchingRecord.id);\n\t\t\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn Array.from(grouped.values());\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcreate: async ({ model, data }) => {\n\t\t\t\t\tconst useNumberId =\n\t\t\t\t\t\toptions.advanced?.database?.useNumberId ||\n\t\t\t\t\t\toptions.advanced?.database?.generateId === \"serial\";\n\t\t\t\t\tif (useNumberId) {\n\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\tdata.id = db[getModelName(model)]!.length + 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tdb[model] = [];\n\t\t\t\t\t}\n\t\t\t\t\tdb[model]!.push(data);\n\t\t\t\t\treturn data;\n\t\t\t\t},\n\t\t\t\tfindOne: async ({ model, where, join }) => {\n\t\t\t\t\tconst res = convertWhereClause(where, model, join);\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\t// When join is present, res is an array of nested objects\n\t\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\t\tif (!resArray.length) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Return the first nested object\n\t\t\t\t\t\treturn resArray[0];\n\t\t\t\t\t}\n\t\t\t\t\t// Without join, res is an array\n\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\tconst record = resArray[0] || null;\n\t\t\t\t\treturn record;\n\t\t\t\t},\n\t\t\t\tfindMany: async ({ model, where, sortBy, limit, offset, join }) => {\n\t\t\t\t\tlet res = convertWhereClause(where || [], model, join);\n\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\t// When join is present, res is an array of nested objects\n\t\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\t\tif (!resArray.length) {\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Apply sorting to nested objects\n\t\t\t\t\t\tapplySortToRecords(resArray, sortBy, model);\n\n\t\t\t\t\t\t// Apply offset and limit\n\t\t\t\t\t\tlet paginatedRecords = resArray;\n\t\t\t\t\t\tif (offset !== undefined) {\n\t\t\t\t\t\t\tpaginatedRecords = paginatedRecords.slice(offset);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\t\tpaginatedRecords = paginatedRecords.slice(0, limit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn paginatedRecords;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Without join - original logic\n\t\t\t\t\tconst resArray = res as any[];\n\t\t\t\t\tlet table = applySortToRecords(resArray, sortBy, model);\n\t\t\t\t\tif (offset !== undefined) {\n\t\t\t\t\t\ttable = table!.slice(offset);\n\t\t\t\t\t}\n\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\ttable = table!.slice(0, limit);\n\t\t\t\t\t}\n\t\t\t\t\treturn table || [];\n\t\t\t\t},\n\t\t\t\tcount: async ({ model, where }) => {\n\t\t\t\t\tif (where) {\n\t\t\t\t\t\tconst filteredRecords = convertWhereClause(where, model);\n\t\t\t\t\t\treturn filteredRecords.length;\n\t\t\t\t\t}\n\t\t\t\t\treturn db[model]!.length;\n\t\t\t\t},\n\t\t\t\tupdate: async ({ model, where, update }) => {\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tres.forEach((record) => {\n\t\t\t\t\t\tObject.assign(record, update);\n\t\t\t\t\t});\n\t\t\t\t\treturn res[0] || null;\n\t\t\t\t},\n\t\t\t\tdelete: async ({ model, where }) => {\n\t\t\t\t\tconst table = db[model]!;\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tdb[model] = table.filter((record) => !res.includes(record));\n\t\t\t\t},\n\t\t\t\tdeleteMany: async ({ model, where }) => {\n\t\t\t\t\tconst table = db[model]!;\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tlet count = 0;\n\t\t\t\t\tdb[model] = table.filter((record) => {\n\t\t\t\t\t\tif (res.includes(record)) {\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn !res.includes(record);\n\t\t\t\t\t});\n\t\t\t\t\treturn count;\n\t\t\t\t},\n\t\t\t\tupdateMany({ model, where, update }) {\n\t\t\t\t\tconst res = convertWhereClause(where, model);\n\t\t\t\t\tres.forEach((record) => {\n\t\t\t\t\t\tObject.assign(record, update);\n\t\t\t\t\t});\n\t\t\t\t\treturn res[0] || null;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t});\n\treturn (options: BetterAuthOptions) => {\n\t\tlazyOptions = options;\n\t\treturn adapterCreator(options);\n\t};\n};\n"],"mappings":"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"}
|
|
@@ -2,6 +2,13 @@ import { createAdapterFactory } from "@better-auth/core/db/adapter";
|
|
|
2
2
|
import { ObjectId } from "mongodb";
|
|
3
3
|
|
|
4
4
|
//#region src/adapters/mongodb-adapter/mongodb-adapter.ts
|
|
5
|
+
var MongoAdapterError = class extends Error {
|
|
6
|
+
constructor(code, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.name = "MongoAdapterError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
5
12
|
const mongodbAdapter = (db, config) => {
|
|
6
13
|
let lazyOptions;
|
|
7
14
|
const getCustomIdGenerator = (options) => {
|
|
@@ -25,9 +32,9 @@ const mongodbAdapter = (db, config) => {
|
|
|
25
32
|
return v;
|
|
26
33
|
}
|
|
27
34
|
if (v instanceof ObjectId) return v;
|
|
28
|
-
throw new
|
|
35
|
+
throw new MongoAdapterError("INVALID_ID", "Invalid id value");
|
|
29
36
|
});
|
|
30
|
-
throw new
|
|
37
|
+
throw new MongoAdapterError("INVALID_ID", "Invalid id value");
|
|
31
38
|
}
|
|
32
39
|
try {
|
|
33
40
|
return new ObjectId(value);
|
|
@@ -121,7 +128,7 @@ const mongodbAdapter = (db, config) => {
|
|
|
121
128
|
case "ends_with":
|
|
122
129
|
condition = { [field]: { $regex: `${escapeForMongoRegex(value)}$` } };
|
|
123
130
|
break;
|
|
124
|
-
default: throw new
|
|
131
|
+
default: throw new MongoAdapterError("UNSUPPORTED_OPERATOR", `Unsupported operator: ${operator}`);
|
|
125
132
|
}
|
|
126
133
|
return {
|
|
127
134
|
condition,
|
|
@@ -307,6 +314,7 @@ const mongodbAdapter = (db, config) => {
|
|
|
307
314
|
debugLogs: config?.debugLogs ?? false,
|
|
308
315
|
mapKeysTransformInput: { id: "_id" },
|
|
309
316
|
mapKeysTransformOutput: { _id: "id" },
|
|
317
|
+
supportsArrays: true,
|
|
310
318
|
supportsNumericIds: false,
|
|
311
319
|
transaction: config?.client && (config?.transaction ?? true) ? async (cb) => {
|
|
312
320
|
if (!config.client) return cb(lazyAdapter(lazyOptions));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongodb-adapter.mjs","names":["lazyOptions: BetterAuthOptions | null","condition: any","db","pipeline: any[]","projection: any","limit","lazyAdapter:\n\t\t| ((options: BetterAuthOptions) => DBAdapter<BetterAuthOptions>)\n\t\t| null","adapterOptions: AdapterFactoryOptions | null"],"sources":["../../../src/adapters/mongodb-adapter/mongodb-adapter.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport type {\n\tAdapterFactoryCustomizeAdapterCreator,\n\tAdapterFactoryOptions,\n\tDBAdapter,\n\tDBAdapterDebugLogOption,\n\tWhere,\n} from \"@better-auth/core/db/adapter\";\nimport { createAdapterFactory } from \"@better-auth/core/db/adapter\";\nimport type { ClientSession, Db, MongoClient } from \"mongodb\";\nimport { ObjectId } from \"mongodb\";\n\nexport interface MongoDBAdapterConfig {\n\t/**\n\t * MongoDB client instance\n\t * If not provided, Database transactions won't be enabled.\n\t */\n\tclient?: MongoClient | undefined;\n\t/**\n\t * Enable debug logs for the adapter\n\t *\n\t * @default false\n\t */\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n\t/**\n\t * Use plural table names\n\t *\n\t * @default false\n\t */\n\tusePlural?: boolean | undefined;\n\t/**\n\t * Whether to execute multiple operations in a transaction.\n\t *\n\t * If the database doesn't support transactions,\n\t * set this to `false` and operations will be executed sequentially.\n\t * @default false\n\t */\n\ttransaction?: boolean | undefined;\n}\n\nexport const mongodbAdapter = (\n\tdb: Db,\n\tconfig?: MongoDBAdapterConfig | undefined,\n) => {\n\tlet lazyOptions: BetterAuthOptions | null;\n\n\tconst getCustomIdGenerator = (options: BetterAuthOptions) => {\n\t\tconst generator = options.advanced?.database?.generateId;\n\t\tif (typeof generator === \"function\") {\n\t\t\treturn generator;\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tconst createCustomAdapter =\n\t\t(\n\t\t\tdb: Db,\n\t\t\tsession?: ClientSession | undefined,\n\t\t): AdapterFactoryCustomizeAdapterCreator =>\n\t\t({\n\t\t\tgetFieldAttributes,\n\t\t\tgetFieldName,\n\t\t\tschema,\n\t\t\tgetDefaultModelName,\n\t\t\toptions,\n\t\t}) => {\n\t\t\tconst customIdGen = getCustomIdGenerator(options);\n\n\t\t\tfunction serializeID({\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tmodel,\n\t\t\t}: {\n\t\t\t\tfield: string;\n\t\t\t\tvalue: any;\n\t\t\t\tmodel: string;\n\t\t\t}) {\n\t\t\t\tif (customIdGen) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t\tmodel = getDefaultModelName(model);\n\t\t\t\tif (\n\t\t\t\t\tfield === \"id\" ||\n\t\t\t\t\tfield === \"_id\" ||\n\t\t\t\t\tschema[model]!.fields[field]?.references?.field === \"id\"\n\t\t\t\t) {\n\t\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof value !== \"string\") {\n\t\t\t\t\t\tif (value instanceof ObjectId) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\treturn value.map((v) => {\n\t\t\t\t\t\t\t\tif (v === null || v === undefined) {\n\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (typeof v === \"string\") {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\treturn new ObjectId(v);\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (v instanceof ObjectId) {\n\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t\"Invalid id value, received: \" + JSON.stringify(v),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Invalid id value, received: \" + JSON.stringify(value),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn new ObjectId(value);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\tfunction convertWhereClause({\n\t\t\t\twhere,\n\t\t\t\tmodel,\n\t\t\t}: {\n\t\t\t\twhere: Where[];\n\t\t\t\tmodel: string;\n\t\t\t}) {\n\t\t\t\tif (!where.length) return {};\n\t\t\t\tconst conditions = where.map((w) => {\n\t\t\t\t\tconst {\n\t\t\t\t\t\tfield: field_,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\toperator = \"eq\",\n\t\t\t\t\t\tconnector = \"AND\",\n\t\t\t\t\t} = w;\n\t\t\t\t\tlet condition: any;\n\t\t\t\t\tlet field = getFieldName({ model, field: field_ });\n\t\t\t\t\tif (field === \"id\") field = \"_id\";\n\t\t\t\t\tswitch (operator.toLowerCase()) {\n\t\t\t\t\t\tcase \"eq\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: serializeID({\n\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"in\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$in: Array.isArray(value)\n\t\t\t\t\t\t\t\t\t\t? value.map((v) => serializeID({ field, value: v, model }))\n\t\t\t\t\t\t\t\t\t\t: [serializeID({ field, value, model })],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"not_in\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$nin: Array.isArray(value)\n\t\t\t\t\t\t\t\t\t\t? value.map((v) => serializeID({ field, value: v, model }))\n\t\t\t\t\t\t\t\t\t\t: [serializeID({ field, value, model })],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"gt\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$gt: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"gte\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$gte: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"lt\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$lt: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"lte\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$lte: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"ne\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$ne: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"contains\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$regex: `.*${escapeForMongoRegex(value as string)}.*`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"starts_with\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: { $regex: `^${escapeForMongoRegex(value as string)}` },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"ends_with\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: { $regex: `${escapeForMongoRegex(value as string)}$` },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow new Error(`Unsupported operator: ${operator}`);\n\t\t\t\t\t}\n\t\t\t\t\treturn { condition, connector };\n\t\t\t\t});\n\t\t\t\tif (conditions.length === 1) {\n\t\t\t\t\treturn conditions[0]!.condition;\n\t\t\t\t}\n\t\t\t\tconst andConditions = conditions\n\t\t\t\t\t.filter((c) => c.connector === \"AND\")\n\t\t\t\t\t.map((c) => c.condition);\n\t\t\t\tconst orConditions = conditions\n\t\t\t\t\t.filter((c) => c.connector === \"OR\")\n\t\t\t\t\t.map((c) => c.condition);\n\n\t\t\t\tlet clause = {};\n\t\t\t\tif (andConditions.length) {\n\t\t\t\t\tclause = { ...clause, $and: andConditions };\n\t\t\t\t}\n\t\t\t\tif (orConditions.length) {\n\t\t\t\t\tclause = { ...clause, $or: orConditions };\n\t\t\t\t}\n\t\t\t\treturn clause;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tasync create({ model, data: values }) {\n\t\t\t\t\tconst res = await db.collection(model).insertOne(values, { session });\n\t\t\t\t\tconst insertedData = { _id: res.insertedId.toString(), ...values };\n\t\t\t\t\treturn insertedData as any;\n\t\t\t\t},\n\t\t\t\tasync findOne({ model, where, select, join }) {\n\t\t\t\t\tconst matchStage = where\n\t\t\t\t\t\t? { $match: convertWhereClause({ where, model }) }\n\t\t\t\t\t\t: { $match: {} };\n\t\t\t\t\tconst pipeline: any[] = [matchStage];\n\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\tfor (const [joinedModel, joinConfig] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst localField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.from,\n\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst foreignField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.to,\n\t\t\t\t\t\t\t\tmodel: joinedModel,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst localFieldName = localField === \"id\" ? \"_id\" : localField;\n\t\t\t\t\t\t\tconst foreignFieldName =\n\t\t\t\t\t\t\t\tforeignField === \"id\" ? \"_id\" : foreignField;\n\n\t\t\t\t\t\t\t// Only unwind if the foreign field has a unique constraint (one-to-one relationship)\n\t\t\t\t\t\t\tconst joinedModelSchema =\n\t\t\t\t\t\t\t\tschema[getDefaultModelName(joinedModel)];\n\t\t\t\t\t\t\tconst foreignFieldAttribute =\n\t\t\t\t\t\t\t\tjoinedModelSchema?.fields[joinConfig.on.to];\n\t\t\t\t\t\t\tconst isUnique = foreignFieldAttribute?.unique === true;\n\n\t\t\t\t\t\t\t// For unique relationships, limit is ignored (as per JoinConfig type)\n\t\t\t\t\t\t\t// For non-unique relationships, apply limit if specified\n\t\t\t\t\t\t\tconst shouldLimit = !isUnique && joinConfig.limit !== undefined;\n\t\t\t\t\t\t\tlet limit =\n\t\t\t\t\t\t\t\tjoinConfig.limit ??\n\t\t\t\t\t\t\t\toptions.advanced?.database?.defaultFindManyLimit ??\n\t\t\t\t\t\t\t\t100;\n\t\t\t\t\t\t\tif (shouldLimit && limit > 0) {\n\t\t\t\t\t\t\t\t// Use pipeline syntax to support limit\n\t\t\t\t\t\t\t\t// Construct the field reference string for the foreign field\n\t\t\t\t\t\t\t\tconst foreignFieldRef = `$${foreignFieldName}`;\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlet: { localFieldValue: `$${localFieldName}` },\n\t\t\t\t\t\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$eq: [foreignFieldRef, \"$$localFieldValue\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ $limit: limit },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Use simple syntax when no limit is needed\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlocalField: localFieldName,\n\t\t\t\t\t\t\t\t\t\tforeignField: foreignFieldName,\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (isUnique) {\n\t\t\t\t\t\t\t\t// For one-to-one relationships, unwind to flatten to a single object\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$unwind: {\n\t\t\t\t\t\t\t\t\t\tpath: `$${joinedModel}`,\n\t\t\t\t\t\t\t\t\t\tpreserveNullAndEmptyArrays: true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// For one-to-many, keep as array - no unwind\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (select) {\n\t\t\t\t\t\tconst projection: any = {};\n\t\t\t\t\t\tselect.forEach((field) => {\n\t\t\t\t\t\t\tprojection[getFieldName({ field, model })] = 1;\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Include joined collections in projection\n\t\t\t\t\t\tif (join) {\n\t\t\t\t\t\t\tfor (const joinedModel of Object.keys(join)) {\n\t\t\t\t\t\t\t\tprojection[joinedModel] = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpipeline.push({ $project: projection });\n\t\t\t\t\t}\n\n\t\t\t\t\tpipeline.push({ $limit: 1 });\n\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.aggregate(pipeline, { session })\n\t\t\t\t\t\t.toArray();\n\n\t\t\t\t\tif (!res || res.length === 0) return null;\n\t\t\t\t\treturn res[0] as any;\n\t\t\t\t},\n\t\t\t\tasync findMany({ model, where, limit, offset, sortBy, join }) {\n\t\t\t\t\tconst matchStage = where\n\t\t\t\t\t\t? { $match: convertWhereClause({ where, model }) }\n\t\t\t\t\t\t: { $match: {} };\n\t\t\t\t\tconst pipeline: any[] = [matchStage];\n\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\tfor (const [joinedModel, joinConfig] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst localField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.from,\n\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst foreignField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.to,\n\t\t\t\t\t\t\t\tmodel: joinedModel,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst localFieldName = localField === \"id\" ? \"_id\" : localField;\n\t\t\t\t\t\t\tconst foreignFieldName =\n\t\t\t\t\t\t\t\tforeignField === \"id\" ? \"_id\" : foreignField;\n\n\t\t\t\t\t\t\t// Only unwind if the foreign field has a unique constraint (one-to-one relationship)\n\t\t\t\t\t\t\tconst foreignFieldAttribute = getFieldAttributes({\n\t\t\t\t\t\t\t\tmodel: joinedModel,\n\t\t\t\t\t\t\t\tfield: joinConfig.on.to,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst isUnique = foreignFieldAttribute?.unique === true;\n\n\t\t\t\t\t\t\t// For unique relationships, limit is ignored (as per JoinConfig type)\n\t\t\t\t\t\t\t// For non-unique relationships, apply limit if specified\n\t\t\t\t\t\t\tconst shouldLimit =\n\t\t\t\t\t\t\t\tjoinConfig.relation !== \"one-to-one\" &&\n\t\t\t\t\t\t\t\tjoinConfig.limit !== undefined;\n\n\t\t\t\t\t\t\tlet limit =\n\t\t\t\t\t\t\t\tjoinConfig.limit ??\n\t\t\t\t\t\t\t\toptions.advanced?.database?.defaultFindManyLimit ??\n\t\t\t\t\t\t\t\t100;\n\t\t\t\t\t\t\tif (shouldLimit && limit > 0) {\n\t\t\t\t\t\t\t\t// Use pipeline syntax to support limit\n\t\t\t\t\t\t\t\t// Construct the field reference string for the foreign field\n\t\t\t\t\t\t\t\tconst foreignFieldRef = `$${foreignFieldName}`;\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlet: { localFieldValue: `$${localFieldName}` },\n\t\t\t\t\t\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$eq: [foreignFieldRef, \"$$localFieldValue\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ $limit: limit },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Use simple syntax when no limit is needed\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlocalField: localFieldName,\n\t\t\t\t\t\t\t\t\t\tforeignField: foreignFieldName,\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (isUnique) {\n\t\t\t\t\t\t\t\t// For one-to-one relationships, unwind to flatten to a single object\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$unwind: {\n\t\t\t\t\t\t\t\t\t\tpath: `$${joinedModel}`,\n\t\t\t\t\t\t\t\t\t\tpreserveNullAndEmptyArrays: true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// For one-to-many, keep as array - no unwind\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (sortBy) {\n\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t$sort: {\n\t\t\t\t\t\t\t\t[getFieldName({ field: sortBy.field, model })]:\n\t\t\t\t\t\t\t\t\tsortBy.direction === \"desc\" ? -1 : 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (offset) {\n\t\t\t\t\t\tpipeline.push({ $skip: offset });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (limit) {\n\t\t\t\t\t\tpipeline.push({ $limit: limit });\n\t\t\t\t\t}\n\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.aggregate(pipeline, { session })\n\t\t\t\t\t\t.toArray();\n\n\t\t\t\t\treturn res as any;\n\t\t\t\t},\n\t\t\t\tasync count({ model, where }) {\n\t\t\t\t\tconst matchStage = where\n\t\t\t\t\t\t? { $match: convertWhereClause({ where, model }) }\n\t\t\t\t\t\t: { $match: {} };\n\t\t\t\t\tconst pipeline: any[] = [matchStage, { $count: \"total\" }];\n\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.aggregate(pipeline, { session })\n\t\t\t\t\t\t.toArray();\n\n\t\t\t\t\tif (!res || res.length === 0) return 0;\n\t\t\t\t\treturn res[0]?.total ?? 0;\n\t\t\t\t},\n\t\t\t\tasync update({ model, where, update: values }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\n\t\t\t\t\tconst res = await db.collection(model).findOneAndUpdate(\n\t\t\t\t\t\tclause,\n\t\t\t\t\t\t{ $set: values as any },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\treturnDocument: \"after\",\n\t\t\t\t\t\t\tincludeResultMetadata: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tconst doc = (res as any)?.value ?? null;\n\t\t\t\t\tif (!doc) return null;\n\t\t\t\t\treturn doc as any;\n\t\t\t\t},\n\t\t\t\tasync updateMany({ model, where, update: values }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\n\t\t\t\t\tconst res = await db.collection(model).updateMany(\n\t\t\t\t\t\tclause,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$set: values as any,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ session },\n\t\t\t\t\t);\n\t\t\t\t\treturn res.modifiedCount;\n\t\t\t\t},\n\t\t\t\tasync delete({ model, where }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\t\t\t\t\tawait db.collection(model).deleteOne(clause, { session });\n\t\t\t\t},\n\t\t\t\tasync deleteMany({ model, where }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.deleteMany(clause, { session });\n\t\t\t\t\treturn res.deletedCount;\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\tlet lazyAdapter:\n\t\t| ((options: BetterAuthOptions) => DBAdapter<BetterAuthOptions>)\n\t\t| null = null;\n\tlet adapterOptions: AdapterFactoryOptions | null = null;\n\tadapterOptions = {\n\t\tconfig: {\n\t\t\tadapterId: \"mongodb-adapter\",\n\t\t\tadapterName: \"MongoDB Adapter\",\n\t\t\tusePlural: config?.usePlural ?? false,\n\t\t\tdebugLogs: config?.debugLogs ?? false,\n\t\t\tmapKeysTransformInput: {\n\t\t\t\tid: \"_id\",\n\t\t\t},\n\t\t\tmapKeysTransformOutput: {\n\t\t\t\t_id: \"id\",\n\t\t\t},\n\t\t\tsupportsNumericIds: false,\n\t\t\ttransaction:\n\t\t\t\tconfig?.client && (config?.transaction ?? true)\n\t\t\t\t\t? async (cb) => {\n\t\t\t\t\t\t\tif (!config.client) {\n\t\t\t\t\t\t\t\treturn cb(lazyAdapter!(lazyOptions!));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst session = config.client.startSession();\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tsession.startTransaction();\n\n\t\t\t\t\t\t\t\tconst adapter = createAdapterFactory({\n\t\t\t\t\t\t\t\t\tconfig: adapterOptions!.config,\n\t\t\t\t\t\t\t\t\tadapter: createCustomAdapter(db, session),\n\t\t\t\t\t\t\t\t})(lazyOptions!);\n\n\t\t\t\t\t\t\t\tconst result = await cb(adapter);\n\n\t\t\t\t\t\t\t\tawait session.commitTransaction();\n\t\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tawait session.abortTransaction();\n\t\t\t\t\t\t\t\tthrow err;\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tawait session.endSession();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t: false,\n\t\t\tcustomTransformInput({\n\t\t\t\taction,\n\t\t\t\tdata,\n\t\t\t\tfield,\n\t\t\t\tfieldAttributes,\n\t\t\t\tschema,\n\t\t\t\tmodel,\n\t\t\t\toptions,\n\t\t\t}) {\n\t\t\t\tconst customIdGen = getCustomIdGenerator(options);\n\t\t\t\tif (field === \"_id\" || fieldAttributes.references?.field === \"id\") {\n\t\t\t\t\tif (customIdGen) {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\t\t\t\t\tif (action !== \"create\") {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\t\t\t\t\tif (Array.isArray(data)) {\n\t\t\t\t\t\treturn data.map((v) => {\n\t\t\t\t\t\t\tif (typeof v === \"string\") {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst oid = new ObjectId(v);\n\t\t\t\t\t\t\t\t\treturn oid;\n\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof data === \"string\") {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst oid = new ObjectId(data);\n\t\t\t\t\t\t\treturn oid;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn data;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tfieldAttributes?.references?.field === \"id\" &&\n\t\t\t\t\t\t!fieldAttributes?.required &&\n\t\t\t\t\t\tdata === null\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tconst oid = new ObjectId();\n\t\t\t\t\treturn oid;\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t},\n\t\t\tcustomTransformOutput({ data, field, fieldAttributes }) {\n\t\t\t\tif (field === \"id\" || fieldAttributes.references?.field === \"id\") {\n\t\t\t\t\tif (data instanceof ObjectId) {\n\t\t\t\t\t\treturn data.toHexString();\n\t\t\t\t\t}\n\t\t\t\t\tif (Array.isArray(data)) {\n\t\t\t\t\t\treturn data.map((v) => {\n\t\t\t\t\t\t\tif (v instanceof ObjectId) {\n\t\t\t\t\t\t\t\treturn v.toHexString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t},\n\t\t\tcustomIdGenerator() {\n\t\t\t\treturn new ObjectId().toString();\n\t\t\t},\n\t\t},\n\t\tadapter: createCustomAdapter(db),\n\t};\n\tlazyAdapter = createAdapterFactory(adapterOptions);\n\n\treturn (options: BetterAuthOptions): DBAdapter<BetterAuthOptions> => {\n\t\tlazyOptions = options;\n\t\treturn lazyAdapter(options);\n\t};\n};\n\n/**\n * Safely escape user input for use in a MongoDB regex.\n * This ensures the resulting pattern is treated as literal text,\n * and not as a regex with special syntax.\n *\n * @param input - The input string to escape. Any type that isn't a string will be converted to an empty string.\n * @param maxLength - The maximum length of the input string to escape. Defaults to 256. This is to prevent DOS attacks.\n * @returns The escaped string.\n */\nfunction escapeForMongoRegex(input: string, maxLength = 256): string {\n\tif (typeof input !== \"string\") return \"\";\n\n\t// Escape all PCRE special characters\n\t// Source: PCRE docs — https://www.pcre.org/original/doc/html/pcrepattern.html\n\treturn input.slice(0, maxLength).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mongodb-adapter.mjs","names":["code: \"INVALID_ID\" | \"UNSUPPORTED_OPERATOR\"","lazyOptions: BetterAuthOptions | null","condition: any","db","pipeline: any[]","projection: any","limit","lazyAdapter:\n\t\t| ((options: BetterAuthOptions) => DBAdapter<BetterAuthOptions>)\n\t\t| null","adapterOptions: AdapterFactoryOptions | null"],"sources":["../../../src/adapters/mongodb-adapter/mongodb-adapter.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport type {\n\tAdapterFactoryCustomizeAdapterCreator,\n\tAdapterFactoryOptions,\n\tDBAdapter,\n\tDBAdapterDebugLogOption,\n\tWhere,\n} from \"@better-auth/core/db/adapter\";\nimport { createAdapterFactory } from \"@better-auth/core/db/adapter\";\nimport type { ClientSession, Db, MongoClient } from \"mongodb\";\nimport { ObjectId } from \"mongodb\";\n\nclass MongoAdapterError extends Error {\n\tconstructor(\n\t\tpublic code: \"INVALID_ID\" | \"UNSUPPORTED_OPERATOR\",\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"MongoAdapterError\";\n\t}\n}\n\nexport interface MongoDBAdapterConfig {\n\t/**\n\t * MongoDB client instance\n\t * If not provided, Database transactions won't be enabled.\n\t */\n\tclient?: MongoClient | undefined;\n\t/**\n\t * Enable debug logs for the adapter\n\t *\n\t * @default false\n\t */\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n\t/**\n\t * Use plural table names\n\t *\n\t * @default false\n\t */\n\tusePlural?: boolean | undefined;\n\t/**\n\t * Whether to execute multiple operations in a transaction.\n\t *\n\t * If the database doesn't support transactions,\n\t * set this to `false` and operations will be executed sequentially.\n\t * @default false\n\t */\n\ttransaction?: boolean | undefined;\n}\n\nexport const mongodbAdapter = (\n\tdb: Db,\n\tconfig?: MongoDBAdapterConfig | undefined,\n) => {\n\tlet lazyOptions: BetterAuthOptions | null;\n\n\tconst getCustomIdGenerator = (options: BetterAuthOptions) => {\n\t\tconst generator = options.advanced?.database?.generateId;\n\t\tif (typeof generator === \"function\") {\n\t\t\treturn generator;\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tconst createCustomAdapter =\n\t\t(\n\t\t\tdb: Db,\n\t\t\tsession?: ClientSession | undefined,\n\t\t): AdapterFactoryCustomizeAdapterCreator =>\n\t\t({\n\t\t\tgetFieldAttributes,\n\t\t\tgetFieldName,\n\t\t\tschema,\n\t\t\tgetDefaultModelName,\n\t\t\toptions,\n\t\t}) => {\n\t\t\tconst customIdGen = getCustomIdGenerator(options);\n\n\t\t\tfunction serializeID({\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tmodel,\n\t\t\t}: {\n\t\t\t\tfield: string;\n\t\t\t\tvalue: any;\n\t\t\t\tmodel: string;\n\t\t\t}) {\n\t\t\t\tif (customIdGen) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t\tmodel = getDefaultModelName(model);\n\t\t\t\tif (\n\t\t\t\t\tfield === \"id\" ||\n\t\t\t\t\tfield === \"_id\" ||\n\t\t\t\t\tschema[model]!.fields[field]?.references?.field === \"id\"\n\t\t\t\t) {\n\t\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof value !== \"string\") {\n\t\t\t\t\t\tif (value instanceof ObjectId) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\treturn value.map((v) => {\n\t\t\t\t\t\t\t\tif (v === null || v === undefined) {\n\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (typeof v === \"string\") {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\treturn new ObjectId(v);\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (v instanceof ObjectId) {\n\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthrow new MongoAdapterError(\"INVALID_ID\", \"Invalid id value\");\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new MongoAdapterError(\"INVALID_ID\", \"Invalid id value\");\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn new ObjectId(value);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\tfunction convertWhereClause({\n\t\t\t\twhere,\n\t\t\t\tmodel,\n\t\t\t}: {\n\t\t\t\twhere: Where[];\n\t\t\t\tmodel: string;\n\t\t\t}) {\n\t\t\t\tif (!where.length) return {};\n\t\t\t\tconst conditions = where.map((w) => {\n\t\t\t\t\tconst {\n\t\t\t\t\t\tfield: field_,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\toperator = \"eq\",\n\t\t\t\t\t\tconnector = \"AND\",\n\t\t\t\t\t} = w;\n\t\t\t\t\tlet condition: any;\n\t\t\t\t\tlet field = getFieldName({ model, field: field_ });\n\t\t\t\t\tif (field === \"id\") field = \"_id\";\n\t\t\t\t\tswitch (operator.toLowerCase()) {\n\t\t\t\t\t\tcase \"eq\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: serializeID({\n\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"in\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$in: Array.isArray(value)\n\t\t\t\t\t\t\t\t\t\t? value.map((v) => serializeID({ field, value: v, model }))\n\t\t\t\t\t\t\t\t\t\t: [serializeID({ field, value, model })],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"not_in\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$nin: Array.isArray(value)\n\t\t\t\t\t\t\t\t\t\t? value.map((v) => serializeID({ field, value: v, model }))\n\t\t\t\t\t\t\t\t\t\t: [serializeID({ field, value, model })],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"gt\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$gt: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"gte\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$gte: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"lt\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$lt: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"lte\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$lte: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"ne\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$ne: serializeID({\n\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"contains\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: {\n\t\t\t\t\t\t\t\t\t$regex: `.*${escapeForMongoRegex(value as string)}.*`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"starts_with\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: { $regex: `^${escapeForMongoRegex(value as string)}` },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"ends_with\":\n\t\t\t\t\t\t\tcondition = {\n\t\t\t\t\t\t\t\t[field]: { $regex: `${escapeForMongoRegex(value as string)}$` },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow new MongoAdapterError(\n\t\t\t\t\t\t\t\t\"UNSUPPORTED_OPERATOR\",\n\t\t\t\t\t\t\t\t`Unsupported operator: ${operator}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn { condition, connector };\n\t\t\t\t});\n\t\t\t\tif (conditions.length === 1) {\n\t\t\t\t\treturn conditions[0]!.condition;\n\t\t\t\t}\n\t\t\t\tconst andConditions = conditions\n\t\t\t\t\t.filter((c) => c.connector === \"AND\")\n\t\t\t\t\t.map((c) => c.condition);\n\t\t\t\tconst orConditions = conditions\n\t\t\t\t\t.filter((c) => c.connector === \"OR\")\n\t\t\t\t\t.map((c) => c.condition);\n\n\t\t\t\tlet clause = {};\n\t\t\t\tif (andConditions.length) {\n\t\t\t\t\tclause = { ...clause, $and: andConditions };\n\t\t\t\t}\n\t\t\t\tif (orConditions.length) {\n\t\t\t\t\tclause = { ...clause, $or: orConditions };\n\t\t\t\t}\n\t\t\t\treturn clause;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tasync create({ model, data: values }) {\n\t\t\t\t\tconst res = await db.collection(model).insertOne(values, { session });\n\t\t\t\t\tconst insertedData = { _id: res.insertedId.toString(), ...values };\n\t\t\t\t\treturn insertedData as any;\n\t\t\t\t},\n\t\t\t\tasync findOne({ model, where, select, join }) {\n\t\t\t\t\tconst matchStage = where\n\t\t\t\t\t\t? { $match: convertWhereClause({ where, model }) }\n\t\t\t\t\t\t: { $match: {} };\n\t\t\t\t\tconst pipeline: any[] = [matchStage];\n\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\tfor (const [joinedModel, joinConfig] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst localField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.from,\n\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst foreignField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.to,\n\t\t\t\t\t\t\t\tmodel: joinedModel,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst localFieldName = localField === \"id\" ? \"_id\" : localField;\n\t\t\t\t\t\t\tconst foreignFieldName =\n\t\t\t\t\t\t\t\tforeignField === \"id\" ? \"_id\" : foreignField;\n\n\t\t\t\t\t\t\t// Only unwind if the foreign field has a unique constraint (one-to-one relationship)\n\t\t\t\t\t\t\tconst joinedModelSchema =\n\t\t\t\t\t\t\t\tschema[getDefaultModelName(joinedModel)];\n\t\t\t\t\t\t\tconst foreignFieldAttribute =\n\t\t\t\t\t\t\t\tjoinedModelSchema?.fields[joinConfig.on.to];\n\t\t\t\t\t\t\tconst isUnique = foreignFieldAttribute?.unique === true;\n\n\t\t\t\t\t\t\t// For unique relationships, limit is ignored (as per JoinConfig type)\n\t\t\t\t\t\t\t// For non-unique relationships, apply limit if specified\n\t\t\t\t\t\t\tconst shouldLimit = !isUnique && joinConfig.limit !== undefined;\n\t\t\t\t\t\t\tlet limit =\n\t\t\t\t\t\t\t\tjoinConfig.limit ??\n\t\t\t\t\t\t\t\toptions.advanced?.database?.defaultFindManyLimit ??\n\t\t\t\t\t\t\t\t100;\n\t\t\t\t\t\t\tif (shouldLimit && limit > 0) {\n\t\t\t\t\t\t\t\t// Use pipeline syntax to support limit\n\t\t\t\t\t\t\t\t// Construct the field reference string for the foreign field\n\t\t\t\t\t\t\t\tconst foreignFieldRef = `$${foreignFieldName}`;\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlet: { localFieldValue: `$${localFieldName}` },\n\t\t\t\t\t\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$eq: [foreignFieldRef, \"$$localFieldValue\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ $limit: limit },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Use simple syntax when no limit is needed\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlocalField: localFieldName,\n\t\t\t\t\t\t\t\t\t\tforeignField: foreignFieldName,\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (isUnique) {\n\t\t\t\t\t\t\t\t// For one-to-one relationships, unwind to flatten to a single object\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$unwind: {\n\t\t\t\t\t\t\t\t\t\tpath: `$${joinedModel}`,\n\t\t\t\t\t\t\t\t\t\tpreserveNullAndEmptyArrays: true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// For one-to-many, keep as array - no unwind\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (select) {\n\t\t\t\t\t\tconst projection: any = {};\n\t\t\t\t\t\tselect.forEach((field) => {\n\t\t\t\t\t\t\tprojection[getFieldName({ field, model })] = 1;\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Include joined collections in projection\n\t\t\t\t\t\tif (join) {\n\t\t\t\t\t\t\tfor (const joinedModel of Object.keys(join)) {\n\t\t\t\t\t\t\t\tprojection[joinedModel] = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpipeline.push({ $project: projection });\n\t\t\t\t\t}\n\n\t\t\t\t\tpipeline.push({ $limit: 1 });\n\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.aggregate(pipeline, { session })\n\t\t\t\t\t\t.toArray();\n\n\t\t\t\t\tif (!res || res.length === 0) return null;\n\t\t\t\t\treturn res[0] as any;\n\t\t\t\t},\n\t\t\t\tasync findMany({ model, where, limit, offset, sortBy, join }) {\n\t\t\t\t\tconst matchStage = where\n\t\t\t\t\t\t? { $match: convertWhereClause({ where, model }) }\n\t\t\t\t\t\t: { $match: {} };\n\t\t\t\t\tconst pipeline: any[] = [matchStage];\n\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\tfor (const [joinedModel, joinConfig] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst localField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.from,\n\t\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst foreignField = getFieldName({\n\t\t\t\t\t\t\t\tfield: joinConfig.on.to,\n\t\t\t\t\t\t\t\tmodel: joinedModel,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst localFieldName = localField === \"id\" ? \"_id\" : localField;\n\t\t\t\t\t\t\tconst foreignFieldName =\n\t\t\t\t\t\t\t\tforeignField === \"id\" ? \"_id\" : foreignField;\n\n\t\t\t\t\t\t\t// Only unwind if the foreign field has a unique constraint (one-to-one relationship)\n\t\t\t\t\t\t\tconst foreignFieldAttribute = getFieldAttributes({\n\t\t\t\t\t\t\t\tmodel: joinedModel,\n\t\t\t\t\t\t\t\tfield: joinConfig.on.to,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst isUnique = foreignFieldAttribute?.unique === true;\n\n\t\t\t\t\t\t\t// For unique relationships, limit is ignored (as per JoinConfig type)\n\t\t\t\t\t\t\t// For non-unique relationships, apply limit if specified\n\t\t\t\t\t\t\tconst shouldLimit =\n\t\t\t\t\t\t\t\tjoinConfig.relation !== \"one-to-one\" &&\n\t\t\t\t\t\t\t\tjoinConfig.limit !== undefined;\n\n\t\t\t\t\t\t\tlet limit =\n\t\t\t\t\t\t\t\tjoinConfig.limit ??\n\t\t\t\t\t\t\t\toptions.advanced?.database?.defaultFindManyLimit ??\n\t\t\t\t\t\t\t\t100;\n\t\t\t\t\t\t\tif (shouldLimit && limit > 0) {\n\t\t\t\t\t\t\t\t// Use pipeline syntax to support limit\n\t\t\t\t\t\t\t\t// Construct the field reference string for the foreign field\n\t\t\t\t\t\t\t\tconst foreignFieldRef = `$${foreignFieldName}`;\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlet: { localFieldValue: `$${localFieldName}` },\n\t\t\t\t\t\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$eq: [foreignFieldRef, \"$$localFieldValue\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ $limit: limit },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Use simple syntax when no limit is needed\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\t\t\tfrom: joinedModel,\n\t\t\t\t\t\t\t\t\t\tlocalField: localFieldName,\n\t\t\t\t\t\t\t\t\t\tforeignField: foreignFieldName,\n\t\t\t\t\t\t\t\t\t\tas: joinedModel,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (isUnique) {\n\t\t\t\t\t\t\t\t// For one-to-one relationships, unwind to flatten to a single object\n\t\t\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t\t\t$unwind: {\n\t\t\t\t\t\t\t\t\t\tpath: `$${joinedModel}`,\n\t\t\t\t\t\t\t\t\t\tpreserveNullAndEmptyArrays: true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// For one-to-many, keep as array - no unwind\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (sortBy) {\n\t\t\t\t\t\tpipeline.push({\n\t\t\t\t\t\t\t$sort: {\n\t\t\t\t\t\t\t\t[getFieldName({ field: sortBy.field, model })]:\n\t\t\t\t\t\t\t\t\tsortBy.direction === \"desc\" ? -1 : 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (offset) {\n\t\t\t\t\t\tpipeline.push({ $skip: offset });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (limit) {\n\t\t\t\t\t\tpipeline.push({ $limit: limit });\n\t\t\t\t\t}\n\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.aggregate(pipeline, { session })\n\t\t\t\t\t\t.toArray();\n\n\t\t\t\t\treturn res as any;\n\t\t\t\t},\n\t\t\t\tasync count({ model, where }) {\n\t\t\t\t\tconst matchStage = where\n\t\t\t\t\t\t? { $match: convertWhereClause({ where, model }) }\n\t\t\t\t\t\t: { $match: {} };\n\t\t\t\t\tconst pipeline: any[] = [matchStage, { $count: \"total\" }];\n\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.aggregate(pipeline, { session })\n\t\t\t\t\t\t.toArray();\n\n\t\t\t\t\tif (!res || res.length === 0) return 0;\n\t\t\t\t\treturn res[0]?.total ?? 0;\n\t\t\t\t},\n\t\t\t\tasync update({ model, where, update: values }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\n\t\t\t\t\tconst res = await db.collection(model).findOneAndUpdate(\n\t\t\t\t\t\tclause,\n\t\t\t\t\t\t{ $set: values as any },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\treturnDocument: \"after\",\n\t\t\t\t\t\t\tincludeResultMetadata: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tconst doc = (res as any)?.value ?? null;\n\t\t\t\t\tif (!doc) return null;\n\t\t\t\t\treturn doc as any;\n\t\t\t\t},\n\t\t\t\tasync updateMany({ model, where, update: values }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\n\t\t\t\t\tconst res = await db.collection(model).updateMany(\n\t\t\t\t\t\tclause,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$set: values as any,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ session },\n\t\t\t\t\t);\n\t\t\t\t\treturn res.modifiedCount;\n\t\t\t\t},\n\t\t\t\tasync delete({ model, where }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\t\t\t\t\tawait db.collection(model).deleteOne(clause, { session });\n\t\t\t\t},\n\t\t\t\tasync deleteMany({ model, where }) {\n\t\t\t\t\tconst clause = convertWhereClause({ where, model });\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.collection(model)\n\t\t\t\t\t\t.deleteMany(clause, { session });\n\t\t\t\t\treturn res.deletedCount;\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\tlet lazyAdapter:\n\t\t| ((options: BetterAuthOptions) => DBAdapter<BetterAuthOptions>)\n\t\t| null = null;\n\tlet adapterOptions: AdapterFactoryOptions | null = null;\n\tadapterOptions = {\n\t\tconfig: {\n\t\t\tadapterId: \"mongodb-adapter\",\n\t\t\tadapterName: \"MongoDB Adapter\",\n\t\t\tusePlural: config?.usePlural ?? false,\n\t\t\tdebugLogs: config?.debugLogs ?? false,\n\t\t\tmapKeysTransformInput: {\n\t\t\t\tid: \"_id\",\n\t\t\t},\n\t\t\tmapKeysTransformOutput: {\n\t\t\t\t_id: \"id\",\n\t\t\t},\n\t\t\tsupportsArrays: true,\n\t\t\tsupportsNumericIds: false,\n\t\t\ttransaction:\n\t\t\t\tconfig?.client && (config?.transaction ?? true)\n\t\t\t\t\t? async (cb) => {\n\t\t\t\t\t\t\tif (!config.client) {\n\t\t\t\t\t\t\t\treturn cb(lazyAdapter!(lazyOptions!));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst session = config.client.startSession();\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tsession.startTransaction();\n\n\t\t\t\t\t\t\t\tconst adapter = createAdapterFactory({\n\t\t\t\t\t\t\t\t\tconfig: adapterOptions!.config,\n\t\t\t\t\t\t\t\t\tadapter: createCustomAdapter(db, session),\n\t\t\t\t\t\t\t\t})(lazyOptions!);\n\n\t\t\t\t\t\t\t\tconst result = await cb(adapter);\n\n\t\t\t\t\t\t\t\tawait session.commitTransaction();\n\t\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tawait session.abortTransaction();\n\t\t\t\t\t\t\t\tthrow err;\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tawait session.endSession();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t: false,\n\t\t\tcustomTransformInput({\n\t\t\t\taction,\n\t\t\t\tdata,\n\t\t\t\tfield,\n\t\t\t\tfieldAttributes,\n\t\t\t\tschema,\n\t\t\t\tmodel,\n\t\t\t\toptions,\n\t\t\t}) {\n\t\t\t\tconst customIdGen = getCustomIdGenerator(options);\n\t\t\t\tif (field === \"_id\" || fieldAttributes.references?.field === \"id\") {\n\t\t\t\t\tif (customIdGen) {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\t\t\t\t\tif (action !== \"create\") {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\t\t\t\t\tif (Array.isArray(data)) {\n\t\t\t\t\t\treturn data.map((v) => {\n\t\t\t\t\t\t\tif (typeof v === \"string\") {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst oid = new ObjectId(v);\n\t\t\t\t\t\t\t\t\treturn oid;\n\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof data === \"string\") {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst oid = new ObjectId(data);\n\t\t\t\t\t\t\treturn oid;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn data;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tfieldAttributes?.references?.field === \"id\" &&\n\t\t\t\t\t\t!fieldAttributes?.required &&\n\t\t\t\t\t\tdata === null\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tconst oid = new ObjectId();\n\t\t\t\t\treturn oid;\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t},\n\t\t\tcustomTransformOutput({ data, field, fieldAttributes }) {\n\t\t\t\tif (field === \"id\" || fieldAttributes.references?.field === \"id\") {\n\t\t\t\t\tif (data instanceof ObjectId) {\n\t\t\t\t\t\treturn data.toHexString();\n\t\t\t\t\t}\n\t\t\t\t\tif (Array.isArray(data)) {\n\t\t\t\t\t\treturn data.map((v) => {\n\t\t\t\t\t\t\tif (v instanceof ObjectId) {\n\t\t\t\t\t\t\t\treturn v.toHexString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn v;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t},\n\t\t\tcustomIdGenerator() {\n\t\t\t\treturn new ObjectId().toString();\n\t\t\t},\n\t\t},\n\t\tadapter: createCustomAdapter(db),\n\t};\n\tlazyAdapter = createAdapterFactory(adapterOptions);\n\n\treturn (options: BetterAuthOptions): DBAdapter<BetterAuthOptions> => {\n\t\tlazyOptions = options;\n\t\treturn lazyAdapter(options);\n\t};\n};\n\n/**\n * Safely escape user input for use in a MongoDB regex.\n * This ensures the resulting pattern is treated as literal text,\n * and not as a regex with special syntax.\n *\n * @param input - The input string to escape. Any type that isn't a string will be converted to an empty string.\n * @param maxLength - The maximum length of the input string to escape. Defaults to 256. This is to prevent DOS attacks.\n * @returns The escaped string.\n */\nfunction escapeForMongoRegex(input: string, maxLength = 256): string {\n\tif (typeof input !== \"string\") return \"\";\n\n\t// Escape all PCRE special characters\n\t// Source: PCRE docs — https://www.pcre.org/original/doc/html/pcrepattern.html\n\treturn input.slice(0, maxLength).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"],"mappings":"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"}
|
|
@@ -76,6 +76,20 @@ const prismaAdapter = (prisma, config) => {
|
|
|
76
76
|
if (w.operator === "eq" || !w.operator) return { [fieldName]: w.value };
|
|
77
77
|
return { [fieldName]: { [operatorToPrismaOperator(w.operator)]: w.value } };
|
|
78
78
|
};
|
|
79
|
+
if (action === "update") {
|
|
80
|
+
const and$1 = where.filter((w) => w.connector === "AND" || !w.connector);
|
|
81
|
+
const or$1 = where.filter((w) => w.connector === "OR");
|
|
82
|
+
const andSimple = and$1.filter((w) => w.operator === "eq" || !w.operator);
|
|
83
|
+
const andComplex = and$1.filter((w) => w.operator !== "eq" && w.operator !== void 0);
|
|
84
|
+
const andSimpleClause = andSimple.map((w) => buildSingleCondition(w));
|
|
85
|
+
const andComplexClause = andComplex.map((w) => buildSingleCondition(w));
|
|
86
|
+
const orClause$1 = or$1.map((w) => buildSingleCondition(w));
|
|
87
|
+
const result = {};
|
|
88
|
+
for (const clause of andSimpleClause) Object.assign(result, clause);
|
|
89
|
+
if (andComplexClause.length > 0) result.AND = andComplexClause;
|
|
90
|
+
if (orClause$1.length > 0) result.OR = orClause$1;
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
79
93
|
if (action === "delete") {
|
|
80
94
|
const idCondition = where.find((w) => w.field === "id");
|
|
81
95
|
if (idCondition) {
|
|
@@ -223,6 +237,7 @@ const prismaAdapter = (prisma, config) => {
|
|
|
223
237
|
await db[model].delete({ where: whereClause });
|
|
224
238
|
} catch (e) {
|
|
225
239
|
if (e?.meta?.cause === "Record to delete does not exist.") return;
|
|
240
|
+
if (e?.code === "P2025") return;
|
|
226
241
|
console.log(e);
|
|
227
242
|
}
|
|
228
243
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-adapter.mjs","names":["lazyOptions: BetterAuthOptions | null","prisma","result: Record<string, Record<string, any> | boolean>","schema","and","or","andClause","orClause","result: Record<string, any>","e: any","adapterOptions: AdapterFactoryOptions | null"],"sources":["../../../src/adapters/prisma-adapter/prisma-adapter.ts"],"sourcesContent":["import type { Awaitable, BetterAuthOptions } from \"@better-auth/core\";\nimport type {\n\tAdapterFactoryCustomizeAdapterCreator,\n\tAdapterFactoryOptions,\n\tDBAdapter,\n\tDBAdapterDebugLogOption,\n\tJoinConfig,\n\tWhere,\n} from \"@better-auth/core/db/adapter\";\nimport { createAdapterFactory } from \"@better-auth/core/db/adapter\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\n\nexport interface PrismaConfig {\n\t/**\n\t * Database provider.\n\t */\n\tprovider:\n\t\t| \"sqlite\"\n\t\t| \"cockroachdb\"\n\t\t| \"mysql\"\n\t\t| \"postgresql\"\n\t\t| \"sqlserver\"\n\t\t| \"mongodb\";\n\n\t/**\n\t * Enable debug logs for the adapter\n\t *\n\t * @default false\n\t */\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n\n\t/**\n\t * Use plural table names\n\t *\n\t * @default false\n\t */\n\tusePlural?: boolean | undefined;\n\n\t/**\n\t * Whether to execute multiple operations in a transaction.\n\t *\n\t * If the database doesn't support transactions,\n\t * set this to `false` and operations will be executed sequentially.\n\t * @default false\n\t */\n\ttransaction?: boolean | undefined;\n}\n\ninterface PrismaClient {}\n\ntype PrismaClientInternal = {\n\t$transaction: (\n\t\tcallback: (db: PrismaClient) => Awaitable<any>,\n\t) => Promise<any>;\n} & {\n\t[model: string]: {\n\t\tcreate: (data: any) => Promise<any>;\n\t\tfindFirst: (data: any) => Promise<any>;\n\t\tfindMany: (data: any) => Promise<any>;\n\t\tupdate: (data: any) => Promise<any>;\n\t\tupdateMany: (data: any) => Promise<any>;\n\t\tdelete: (data: any) => Promise<any>;\n\t\t[key: string]: any;\n\t};\n};\n\nexport const prismaAdapter = (prisma: PrismaClient, config: PrismaConfig) => {\n\tlet lazyOptions: BetterAuthOptions | null = null;\n\tconst createCustomAdapter =\n\t\t(prisma: PrismaClient): AdapterFactoryCustomizeAdapterCreator =>\n\t\t({\n\t\t\tgetFieldName,\n\t\t\tgetModelName,\n\t\t\tgetFieldAttributes,\n\t\t\tgetDefaultModelName,\n\t\t\tschema,\n\t\t}) => {\n\t\t\tconst db = prisma as PrismaClientInternal;\n\n\t\t\tconst convertSelect = (\n\t\t\t\tselect: string[] | undefined,\n\t\t\t\tmodel: string,\n\t\t\t\tjoin?: JoinConfig | undefined,\n\t\t\t) => {\n\t\t\t\tif (!select && !join) return undefined;\n\n\t\t\t\tlet result: Record<string, Record<string, any> | boolean> = {};\n\n\t\t\t\tif (select) {\n\t\t\t\t\tfor (const field of select) {\n\t\t\t\t\t\tresult[getFieldName({ model, field })] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (join) {\n\t\t\t\t\t// when joining that has a limit, we need to use Prisma's `select` syntax to append the limit to the field\n\t\t\t\t\t// because of such, it also means we need to select all base-model fields as well\n\t\t\t\t\t// should check if `select` is not provided, because then we should select all base-model fields\n\t\t\t\t\tif (!select) {\n\t\t\t\t\t\tconst fields = schema[getDefaultModelName(model)]?.fields || {};\n\t\t\t\t\t\tfields.id = { type: \"string\" }; // make sure there is at least an id field\n\t\t\t\t\t\tfor (const field of Object.keys(fields)) {\n\t\t\t\t\t\t\tresult[getFieldName({ model, field })] = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const [joinModel, joinAttr] of Object.entries(join)) {\n\t\t\t\t\t\tconst key = getJoinKeyName(model, getModelName(joinModel), schema);\n\t\t\t\t\t\tif (joinAttr.relation === \"one-to-one\") {\n\t\t\t\t\t\t\tresult[key] = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult[key] = { take: joinAttr.limit };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * Build the join key name based on whether the foreign field is unique or not.\n\t\t\t * If unique, use singular. Otherwise, pluralize (add 's').\n\t\t\t */\n\t\t\tconst getJoinKeyName = (\n\t\t\t\tbaseModel: string,\n\t\t\t\tjoinedModel: string,\n\t\t\t\tschema: any,\n\t\t\t): string => {\n\t\t\t\ttry {\n\t\t\t\t\tconst defaultBaseModelName = getDefaultModelName(baseModel);\n\t\t\t\t\tconst defaultJoinedModelName = getDefaultModelName(joinedModel);\n\t\t\t\t\tconst key = getModelName(joinedModel).toLowerCase();\n\n\t\t\t\t\t// First, check if the joined model has FKs to the base model (forward join)\n\t\t\t\t\tlet foreignKeys = Object.entries(\n\t\t\t\t\t\tschema[defaultJoinedModelName]?.fields || {},\n\t\t\t\t\t).filter(\n\t\t\t\t\t\t([_field, fieldAttributes]: any) =>\n\t\t\t\t\t\t\tfieldAttributes.references &&\n\t\t\t\t\t\t\tgetDefaultModelName(fieldAttributes.references.model) ===\n\t\t\t\t\t\t\t\tdefaultBaseModelName,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (foreignKeys.length > 0) {\n\t\t\t\t\t\t// Forward join: joined model has FK to base model\n\t\t\t\t\t\t// This is typically a one-to-many relationship (plural)\n\t\t\t\t\t\t// Unless the FK is unique, then it's one-to-one (singular)\n\t\t\t\t\t\tconst [_foreignKey, foreignKeyAttributes] = foreignKeys[0] as any;\n\t\t\t\t\t\t// Only check if field is explicitly marked as unique\n\t\t\t\t\t\tconst isUnique = foreignKeyAttributes?.unique === true;\n\t\t\t\t\t\treturn isUnique || config.usePlural === true ? key : `${key}s`;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check backwards: does the base model have FKs to the joined model?\n\t\t\t\t\tforeignKeys = Object.entries(\n\t\t\t\t\t\tschema[defaultBaseModelName]?.fields || {},\n\t\t\t\t\t).filter(\n\t\t\t\t\t\t([_field, fieldAttributes]: any) =>\n\t\t\t\t\t\t\tfieldAttributes.references &&\n\t\t\t\t\t\t\tgetDefaultModelName(fieldAttributes.references.model) ===\n\t\t\t\t\t\t\t\tdefaultJoinedModelName,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (foreignKeys.length > 0) {\n\t\t\t\t\t\treturn key;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Fallback to pluralizing if we can't determine uniqueness\n\t\t\t\t}\n\t\t\t\treturn `${getModelName(joinedModel).toLowerCase()}s`;\n\t\t\t};\n\t\t\tfunction operatorToPrismaOperator(operator: string) {\n\t\t\t\tswitch (operator) {\n\t\t\t\t\tcase \"starts_with\":\n\t\t\t\t\t\treturn \"startsWith\";\n\t\t\t\t\tcase \"ends_with\":\n\t\t\t\t\t\treturn \"endsWith\";\n\t\t\t\t\tcase \"ne\":\n\t\t\t\t\t\treturn \"not\";\n\t\t\t\t\tcase \"not_in\":\n\t\t\t\t\t\treturn \"notIn\";\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn operator;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst convertWhereClause = ({\n\t\t\t\taction,\n\t\t\t\tmodel,\n\t\t\t\twhere,\n\t\t\t}: {\n\t\t\t\tmodel: string;\n\t\t\t\twhere?: Where[] | undefined;\n\t\t\t\taction:\n\t\t\t\t\t| \"create\"\n\t\t\t\t\t| \"update\"\n\t\t\t\t\t| \"delete\"\n\t\t\t\t\t| \"findOne\"\n\t\t\t\t\t| \"findMany\"\n\t\t\t\t\t| \"count\"\n\t\t\t\t\t| \"updateMany\"\n\t\t\t\t\t| \"deleteMany\";\n\t\t\t}) => {\n\t\t\t\tif (!where || !where.length) return {};\n\t\t\t\tconst buildSingleCondition = (w: Where) => {\n\t\t\t\t\tconst fieldName = getFieldName({ model, field: w.field });\n\t\t\t\t\t// Special handling for Prisma null semantics, for non-nullable fields this is a tautology. Skip condition.\n\t\t\t\t\tif (w.operator === \"ne\" && w.value === null) {\n\t\t\t\t\t\treturn {};\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\t(w.operator === \"in\" || w.operator === \"not_in\") &&\n\t\t\t\t\t\tArray.isArray(w.value)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst filtered = w.value.filter((v) => v != null);\n\t\t\t\t\t\tif (filtered.length === 0) {\n\t\t\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tAND: [\n\t\t\t\t\t\t\t\t\t\t{ [fieldName]: { equals: \"__never__\" } },\n\t\t\t\t\t\t\t\t\t\t{ [fieldName]: { not: \"__never__\" } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn {};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prismaOp = operatorToPrismaOperator(w.operator);\n\t\t\t\t\t\treturn { [fieldName]: { [prismaOp]: filtered } };\n\t\t\t\t\t}\n\t\t\t\t\tif (w.operator === \"eq\" || !w.operator) {\n\t\t\t\t\t\treturn { [fieldName]: w.value };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t[fieldName]: {\n\t\t\t\t\t\t\t[operatorToPrismaOperator(w.operator)]: w.value,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Special handling for delete actions: extract id to root level\n\t\t\t\tif (action === \"delete\") {\n\t\t\t\t\tconst idCondition = where.find((w) => w.field === \"id\");\n\t\t\t\t\tif (idCondition) {\n\t\t\t\t\t\tconst idFieldName = getFieldName({ model, field: \"id\" });\n\t\t\t\t\t\tconst idClause = buildSingleCondition(idCondition);\n\t\t\t\t\t\tconst remainingWhere = where.filter((w) => w.field !== \"id\");\n\n\t\t\t\t\t\tif (remainingWhere.length === 0) {\n\t\t\t\t\t\t\treturn idClause;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst and = remainingWhere.filter(\n\t\t\t\t\t\t\t(w) => w.connector === \"AND\" || !w.connector,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst or = remainingWhere.filter((w) => w.connector === \"OR\");\n\t\t\t\t\t\tconst andClause = and.map((w) => buildSingleCondition(w));\n\t\t\t\t\t\tconst orClause = or.map((w) => buildSingleCondition(w));\n\n\t\t\t\t\t\t// Extract id to root level, put other conditions in AND array\n\t\t\t\t\t\tconst result: Record<string, any> = {};\n\t\t\t\t\t\tif (idFieldName in idClause) {\n\t\t\t\t\t\t\tresult[idFieldName] = (idClause as Record<string, any>)[\n\t\t\t\t\t\t\t\tidFieldName\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Handle edge case where idClause might have special structure\n\t\t\t\t\t\t\tObject.assign(result, idClause);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (andClause.length > 0) {\n\t\t\t\t\t\t\tresult.AND = andClause;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (orClause.length > 0) {\n\t\t\t\t\t\t\tresult.OR = orClause;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (where.length === 1) {\n\t\t\t\t\tconst w = where[0]!;\n\t\t\t\t\tif (!w) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\treturn buildSingleCondition(w);\n\t\t\t\t}\n\t\t\t\tconst and = where.filter((w) => w.connector === \"AND\" || !w.connector);\n\t\t\t\tconst or = where.filter((w) => w.connector === \"OR\");\n\t\t\t\tconst andClause = and.map((w) => buildSingleCondition(w));\n\t\t\t\tconst orClause = or.map((w) => buildSingleCondition(w));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(andClause.length ? { AND: andClause } : {}),\n\t\t\t\t\t...(orClause.length ? { OR: orClause } : {}),\n\t\t\t\t};\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tasync create({ model, data: values, select }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst result = await db[model]!.create({\n\t\t\t\t\t\tdata: values,\n\t\t\t\t\t\tselect: convertSelect(select, model),\n\t\t\t\t\t});\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\tasync findOne({ model, where, select, join }) {\n\t\t\t\t\t// this is just \"JoinOption\" type because we disabled join transformation in adapter config\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"findOne\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// transform join keys to use Prisma expected field names\n\t\t\t\t\tlet map = new Map<string, string>();\n\t\t\t\t\tfor (const joinModel of Object.keys(join ?? {})) {\n\t\t\t\t\t\tconst key = getJoinKeyName(model, joinModel, schema);\n\t\t\t\t\t\tmap.set(key, getModelName(joinModel));\n\t\t\t\t\t}\n\n\t\t\t\t\tconst selects = convertSelect(select, model, join);\n\n\t\t\t\t\tlet result = await db[model]!.findFirst({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\tselect: selects,\n\t\t\t\t\t});\n\n\t\t\t\t\t// transform the resulting `include` items to use better-auth expected field names\n\t\t\t\t\tif (join && result) {\n\t\t\t\t\t\tfor (const [includeKey, originalKey] of map.entries()) {\n\t\t\t\t\t\t\tif (includeKey === originalKey) continue;\n\t\t\t\t\t\t\tif (includeKey in result) {\n\t\t\t\t\t\t\t\tresult[originalKey] = result[includeKey];\n\t\t\t\t\t\t\t\tdelete result[includeKey];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\tasync findMany({ model, where, limit, offset, sortBy, join }) {\n\t\t\t\t\t// this is just \"JoinOption\" type because we disabled join transformation in adapter config\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"findMany\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// transform join keys to use Prisma expected field names\n\t\t\t\t\tlet map = new Map<string, string>();\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\tfor (const [joinModel, _value] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst key = getJoinKeyName(model, joinModel, schema);\n\t\t\t\t\t\t\tmap.set(key, getModelName(joinModel));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst selects = convertSelect(undefined, model, join);\n\n\t\t\t\t\tconst result = await db[model]!.findMany({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\ttake: limit || 100,\n\t\t\t\t\t\tskip: offset || 0,\n\t\t\t\t\t\t...(sortBy?.field\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\torderBy: {\n\t\t\t\t\t\t\t\t\t\t[getFieldName({ model, field: sortBy.field })]:\n\t\t\t\t\t\t\t\t\t\t\tsortBy.direction === \"desc\" ? \"desc\" : \"asc\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\tselect: selects,\n\t\t\t\t\t});\n\n\t\t\t\t\t// transform the resulting join items to use better-auth expected field names\n\t\t\t\t\tif (join && Array.isArray(result)) {\n\t\t\t\t\t\tfor (const item of result) {\n\t\t\t\t\t\t\tfor (const [includeKey, originalKey] of map.entries()) {\n\t\t\t\t\t\t\t\tif (includeKey === originalKey) continue;\n\t\t\t\t\t\t\t\tif (includeKey in item) {\n\t\t\t\t\t\t\t\t\titem[originalKey] = item[includeKey];\n\t\t\t\t\t\t\t\t\tdelete item[includeKey];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\tasync count({ model, where }) {\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"count\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn await db[model]!.count({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tasync update({ model, where, update }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"update\",\n\t\t\t\t\t});\n\t\t\t\t\treturn await db[model]!.update({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\tdata: update,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tasync updateMany({ model, where, update }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"updateMany\",\n\t\t\t\t\t});\n\t\t\t\t\tconst result = await db[model]!.updateMany({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\tdata: update,\n\t\t\t\t\t});\n\t\t\t\t\treturn result ? (result.count as number) : 0;\n\t\t\t\t},\n\t\t\t\tasync delete({ model, where }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"delete\",\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait db[model]!.delete({\n\t\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\t// If the record doesn't exist, we don't want to throw an error\n\t\t\t\t\t\tif (e?.meta?.cause === \"Record to delete does not exist.\") return;\n\t\t\t\t\t\t// otherwise if it's an unknown error, we want to just log it for debugging.\n\t\t\t\t\t\tconsole.log(e);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tasync deleteMany({ model, where }) {\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"deleteMany\",\n\t\t\t\t\t});\n\t\t\t\t\tconst result = await db[model]!.deleteMany({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t});\n\t\t\t\t\treturn result ? (result.count as number) : 0;\n\t\t\t\t},\n\t\t\t\toptions: config,\n\t\t\t};\n\t\t};\n\n\tlet adapterOptions: AdapterFactoryOptions | null = null;\n\tadapterOptions = {\n\t\tconfig: {\n\t\t\tadapterId: \"prisma\",\n\t\t\tadapterName: \"Prisma Adapter\",\n\t\t\tusePlural: config.usePlural ?? false,\n\t\t\tdebugLogs: config.debugLogs ?? false,\n\t\t\tsupportsUUIDs: config.provider === \"postgresql\" ? true : false,\n\t\t\tsupportsArrays:\n\t\t\t\tconfig.provider === \"postgresql\" || config.provider === \"mongodb\"\n\t\t\t\t\t? true\n\t\t\t\t\t: false,\n\t\t\ttransaction:\n\t\t\t\t(config.transaction ?? false)\n\t\t\t\t\t? (cb) =>\n\t\t\t\t\t\t\t(prisma as PrismaClientInternal).$transaction((tx) => {\n\t\t\t\t\t\t\t\tconst adapter = createAdapterFactory({\n\t\t\t\t\t\t\t\t\tconfig: adapterOptions!.config,\n\t\t\t\t\t\t\t\t\tadapter: createCustomAdapter(tx),\n\t\t\t\t\t\t\t\t})(lazyOptions!);\n\t\t\t\t\t\t\t\treturn cb(adapter);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t: false,\n\t\t},\n\t\tadapter: createCustomAdapter(prisma),\n\t};\n\n\tconst adapter = createAdapterFactory(adapterOptions);\n\treturn (options: BetterAuthOptions): DBAdapter<BetterAuthOptions> => {\n\t\tlazyOptions = options;\n\t\treturn adapter(options);\n\t};\n};\n"],"mappings":";;;;AAkEA,MAAa,iBAAiB,QAAsB,WAAyB;CAC5E,IAAIA,cAAwC;CAC5C,MAAM,uBACJ,cACA,EACA,cACA,cACA,oBACA,qBACA,aACK;EACL,MAAM,KAAKC;EAEX,MAAM,iBACL,QACA,OACA,SACI;AACJ,OAAI,CAAC,UAAU,CAAC,KAAM,QAAO;GAE7B,IAAIC,SAAwD,EAAE;AAE9D,OAAI,OACH,MAAK,MAAM,SAAS,OACnB,QAAO,aAAa;IAAE;IAAO;IAAO,CAAC,IAAI;AAI3C,OAAI,MAAM;AAIT,QAAI,CAAC,QAAQ;KACZ,MAAM,SAAS,OAAO,oBAAoB,MAAM,GAAG,UAAU,EAAE;AAC/D,YAAO,KAAK,EAAE,MAAM,UAAU;AAC9B,UAAK,MAAM,SAAS,OAAO,KAAK,OAAO,CACtC,QAAO,aAAa;MAAE;MAAO;MAAO,CAAC,IAAI;;AAI3C,SAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,KAAK,EAAE;KACzD,MAAM,MAAM,eAAe,OAAO,aAAa,UAAU,EAAE,OAAO;AAClE,SAAI,SAAS,aAAa,aACzB,QAAO,OAAO;SAEd,QAAO,OAAO,EAAE,MAAM,SAAS,OAAO;;;AAKzC,UAAO;;;;;;EAOR,MAAM,kBACL,WACA,aACA,aACY;AACZ,OAAI;IACH,MAAM,uBAAuB,oBAAoB,UAAU;IAC3D,MAAM,yBAAyB,oBAAoB,YAAY;IAC/D,MAAM,MAAM,aAAa,YAAY,CAAC,aAAa;IAGnD,IAAI,cAAc,OAAO,QACxBC,SAAO,yBAAyB,UAAU,EAAE,CAC5C,CAAC,QACA,CAAC,QAAQ,qBACT,gBAAgB,cAChB,oBAAoB,gBAAgB,WAAW,MAAM,KACpD,qBACF;AAED,QAAI,YAAY,SAAS,GAAG;KAI3B,MAAM,CAAC,aAAa,wBAAwB,YAAY;AAGxD,YADiB,sBAAsB,WAAW,QAC/B,OAAO,cAAc,OAAO,MAAM,GAAG,IAAI;;AAI7D,kBAAc,OAAO,QACpBA,SAAO,uBAAuB,UAAU,EAAE,CAC1C,CAAC,QACA,CAAC,QAAQ,qBACT,gBAAgB,cAChB,oBAAoB,gBAAgB,WAAW,MAAM,KACpD,uBACF;AAED,QAAI,YAAY,SAAS,EACxB,QAAO;WAED;AAGR,UAAO,GAAG,aAAa,YAAY,CAAC,aAAa,CAAC;;EAEnD,SAAS,yBAAyB,UAAkB;AACnD,WAAQ,UAAR;IACC,KAAK,cACJ,QAAO;IACR,KAAK,YACJ,QAAO;IACR,KAAK,KACJ,QAAO;IACR,KAAK,SACJ,QAAO;IACR,QACC,QAAO;;;EAGV,MAAM,sBAAsB,EAC3B,QACA,OACA,YAaK;AACL,OAAI,CAAC,SAAS,CAAC,MAAM,OAAQ,QAAO,EAAE;GACtC,MAAM,wBAAwB,MAAa;IAC1C,MAAM,YAAY,aAAa;KAAE;KAAO,OAAO,EAAE;KAAO,CAAC;AAEzD,QAAI,EAAE,aAAa,QAAQ,EAAE,UAAU,KACtC,QAAO,EAAE;AAEV,SACE,EAAE,aAAa,QAAQ,EAAE,aAAa,aACvC,MAAM,QAAQ,EAAE,MAAM,EACrB;KACD,MAAM,WAAW,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK;AACjD,SAAI,SAAS,WAAW,EACvB,KAAI,EAAE,aAAa,KAClB,QAAO,EACN,KAAK,CACJ,GAAG,YAAY,EAAE,QAAQ,aAAa,EAAE,EACxC,GAAG,YAAY,EAAE,KAAK,aAAa,EAAE,CACrC,EACD;SAED,QAAO,EAAE;KAGX,MAAM,WAAW,yBAAyB,EAAE,SAAS;AACrD,YAAO,GAAG,YAAY,GAAG,WAAW,UAAU,EAAE;;AAEjD,QAAI,EAAE,aAAa,QAAQ,CAAC,EAAE,SAC7B,QAAO,GAAG,YAAY,EAAE,OAAO;AAEhC,WAAO,GACL,YAAY,GACX,yBAAyB,EAAE,SAAS,GAAG,EAAE,OAC1C,EACD;;AAIF,OAAI,WAAW,UAAU;IACxB,MAAM,cAAc,MAAM,MAAM,MAAM,EAAE,UAAU,KAAK;AACvD,QAAI,aAAa;KAChB,MAAM,cAAc,aAAa;MAAE;MAAO,OAAO;MAAM,CAAC;KACxD,MAAM,WAAW,qBAAqB,YAAY;KAClD,MAAM,iBAAiB,MAAM,QAAQ,MAAM,EAAE,UAAU,KAAK;AAE5D,SAAI,eAAe,WAAW,EAC7B,QAAO;KAGR,MAAMC,QAAM,eAAe,QACzB,MAAM,EAAE,cAAc,SAAS,CAAC,EAAE,UACnC;KACD,MAAMC,OAAK,eAAe,QAAQ,MAAM,EAAE,cAAc,KAAK;KAC7D,MAAMC,cAAYF,MAAI,KAAK,MAAM,qBAAqB,EAAE,CAAC;KACzD,MAAMG,aAAWF,KAAG,KAAK,MAAM,qBAAqB,EAAE,CAAC;KAGvD,MAAMG,SAA8B,EAAE;AACtC,SAAI,eAAe,SAClB,QAAO,eAAgB,SACtB;SAID,QAAO,OAAO,QAAQ,SAAS;AAEhC,SAAIF,YAAU,SAAS,EACtB,QAAO,MAAMA;AAEd,SAAIC,WAAS,SAAS,EACrB,QAAO,KAAKA;AAEb,YAAO;;;AAIT,OAAI,MAAM,WAAW,GAAG;IACvB,MAAM,IAAI,MAAM;AAChB,QAAI,CAAC,EACJ;AAED,WAAO,qBAAqB,EAAE;;GAE/B,MAAM,MAAM,MAAM,QAAQ,MAAM,EAAE,cAAc,SAAS,CAAC,EAAE,UAAU;GACtE,MAAM,KAAK,MAAM,QAAQ,MAAM,EAAE,cAAc,KAAK;GACpD,MAAM,YAAY,IAAI,KAAK,MAAM,qBAAqB,EAAE,CAAC;GACzD,MAAM,WAAW,GAAG,KAAK,MAAM,qBAAqB,EAAE,CAAC;AAEvD,UAAO;IACN,GAAI,UAAU,SAAS,EAAE,KAAK,WAAW,GAAG,EAAE;IAC9C,GAAI,SAAS,SAAS,EAAE,IAAI,UAAU,GAAG,EAAE;IAC3C;;AAGF,SAAO;GACN,MAAM,OAAO,EAAE,OAAO,MAAM,QAAQ,UAAU;AAC7C,QAAI,CAAC,GAAG,OACP,OAAM,IAAI,gBACT,SAAS,MAAM,oHACf;AAMF,WAJe,MAAM,GAAG,OAAQ,OAAO;KACtC,MAAM;KACN,QAAQ,cAAc,QAAQ,MAAM;KACpC,CAAC;;GAGH,MAAM,QAAQ,EAAE,OAAO,OAAO,QAAQ,QAAQ;IAE7C,MAAM,cAAc,mBAAmB;KACtC;KACA;KACA,QAAQ;KACR,CAAC;AACF,QAAI,CAAC,GAAG,OACP,OAAM,IAAI,gBACT,SAAS,MAAM,oHACf;IAIF,IAAI,sBAAM,IAAI,KAAqB;AACnC,SAAK,MAAM,aAAa,OAAO,KAAK,QAAQ,EAAE,CAAC,EAAE;KAChD,MAAM,MAAM,eAAe,OAAO,WAAW,OAAO;AACpD,SAAI,IAAI,KAAK,aAAa,UAAU,CAAC;;IAGtC,MAAM,UAAU,cAAc,QAAQ,OAAO,KAAK;IAElD,IAAI,SAAS,MAAM,GAAG,OAAQ,UAAU;KACvC,OAAO;KACP,QAAQ;KACR,CAAC;AAGF,QAAI,QAAQ,OACX,MAAK,MAAM,CAAC,YAAY,gBAAgB,IAAI,SAAS,EAAE;AACtD,SAAI,eAAe,YAAa;AAChC,SAAI,cAAc,QAAQ;AACzB,aAAO,eAAe,OAAO;AAC7B,aAAO,OAAO;;;AAIjB,WAAO;;GAER,MAAM,SAAS,EAAE,OAAO,OAAO,OAAO,QAAQ,QAAQ,QAAQ;IAE7D,MAAM,cAAc,mBAAmB;KACtC;KACA;KACA,QAAQ;KACR,CAAC;AACF,QAAI,CAAC,GAAG,OACP,OAAM,IAAI,gBACT,SAAS,MAAM,oHACf;IAGF,IAAI,sBAAM,IAAI,KAAqB;AACnC,QAAI,KACH,MAAK,MAAM,CAAC,WAAW,WAAW,OAAO,QAAQ,KAAK,EAAE;KACvD,MAAM,MAAM,eAAe,OAAO,WAAW,OAAO;AACpD,SAAI,IAAI,KAAK,aAAa,UAAU,CAAC;;IAIvC,MAAM,UAAU,cAAc,QAAW,OAAO,KAAK;IAErD,MAAM,SAAS,MAAM,GAAG,OAAQ,SAAS;KACxC,OAAO;KACP,MAAM,SAAS;KACf,MAAM,UAAU;KAChB,GAAI,QAAQ,QACT,EACA,SAAS,GACP,aAAa;MAAE;MAAO,OAAO,OAAO;MAAO,CAAC,GAC5C,OAAO,cAAc,SAAS,SAAS,OACxC,EACD,GACA,EAAE;KACL,QAAQ;KACR,CAAC;AAGF,QAAI,QAAQ,MAAM,QAAQ,OAAO,CAChC,MAAK,MAAM,QAAQ,OAClB,MAAK,MAAM,CAAC,YAAY,gBAAgB,IAAI,SAAS,EAAE;AACtD,SAAI,eAAe,YAAa;AAChC,SAAI,cAAc,MAAM;AACvB,WAAK,eAAe,KAAK;AACzB,aAAO,KAAK;;;AAMhB,WAAO;;GAER,MAAM,MAAM,EAAE,OAAO,SAAS;IAC7B,MAAM,cAAc,mBAAmB;KACtC;KACA;KACA,QAAQ;KACR,CAAC;AACF,QAAI,CAAC,GAAG,OACP,OAAM,IAAI,gBACT,SAAS,MAAM,oHACf;AAEF,WAAO,MAAM,GAAG,OAAQ,MAAM,EAC7B,OAAO,aACP,CAAC;;GAEH,MAAM,OAAO,EAAE,OAAO,OAAO,UAAU;AACtC,QAAI,CAAC,GAAG,OACP,OAAM,IAAI,gBACT,SAAS,MAAM,oHACf;IAEF,MAAM,cAAc,mBAAmB;KACtC;KACA;KACA,QAAQ;KACR,CAAC;AACF,WAAO,MAAM,GAAG,OAAQ,OAAO;KAC9B,OAAO;KACP,MAAM;KACN,CAAC;;GAEH,MAAM,WAAW,EAAE,OAAO,OAAO,UAAU;AAC1C,QAAI,CAAC,GAAG,OACP,OAAM,IAAI,gBACT,SAAS,MAAM,oHACf;IAEF,MAAM,cAAc,mBAAmB;KACtC;KACA;KACA,QAAQ;KACR,CAAC;IACF,MAAM,SAAS,MAAM,GAAG,OAAQ,WAAW;KAC1C,OAAO;KACP,MAAM;KACN,CAAC;AACF,WAAO,SAAU,OAAO,QAAmB;;GAE5C,MAAM,OAAO,EAAE,OAAO,SAAS;AAC9B,QAAI,CAAC,GAAG,OACP,OAAM,IAAI,gBACT,SAAS,MAAM,oHACf;IAEF,MAAM,cAAc,mBAAmB;KACtC;KACA;KACA,QAAQ;KACR,CAAC;AACF,QAAI;AACH,WAAM,GAAG,OAAQ,OAAO,EACvB,OAAO,aACP,CAAC;aACME,GAAQ;AAEhB,SAAI,GAAG,MAAM,UAAU,mCAAoC;AAE3D,aAAQ,IAAI,EAAE;;;GAGhB,MAAM,WAAW,EAAE,OAAO,SAAS;IAClC,MAAM,cAAc,mBAAmB;KACtC;KACA;KACA,QAAQ;KACR,CAAC;IACF,MAAM,SAAS,MAAM,GAAG,OAAQ,WAAW,EAC1C,OAAO,aACP,CAAC;AACF,WAAO,SAAU,OAAO,QAAmB;;GAE5C,SAAS;GACT;;CAGH,IAAIC,iBAA+C;AACnD,kBAAiB;EAChB,QAAQ;GACP,WAAW;GACX,aAAa;GACb,WAAW,OAAO,aAAa;GAC/B,WAAW,OAAO,aAAa;GAC/B,eAAe,OAAO,aAAa,eAAe,OAAO;GACzD,gBACC,OAAO,aAAa,gBAAgB,OAAO,aAAa,YACrD,OACA;GACJ,aACE,OAAO,eAAe,SACnB,OACA,OAAgC,cAAc,OAAO;AAKrD,WAAO,GAJS,qBAAqB;KACpC,QAAQ,eAAgB;KACxB,SAAS,oBAAoB,GAAG;KAChC,CAAC,CAAC,YAAa,CACE;KACjB,GACF;GACJ;EACD,SAAS,oBAAoB,OAAO;EACpC;CAED,MAAM,UAAU,qBAAqB,eAAe;AACpD,SAAQ,YAA6D;AACpE,gBAAc;AACd,SAAO,QAAQ,QAAQ"}
|
|
1
|
+
{"version":3,"file":"prisma-adapter.mjs","names":["lazyOptions: BetterAuthOptions | null","prisma","result: Record<string, Record<string, any> | boolean>","schema","and","or","orClause","result: Record<string, any>","andClause","e: any","adapterOptions: AdapterFactoryOptions | null"],"sources":["../../../src/adapters/prisma-adapter/prisma-adapter.ts"],"sourcesContent":["import type { Awaitable, BetterAuthOptions } from \"@better-auth/core\";\nimport type {\n\tAdapterFactoryCustomizeAdapterCreator,\n\tAdapterFactoryOptions,\n\tDBAdapter,\n\tDBAdapterDebugLogOption,\n\tJoinConfig,\n\tWhere,\n} from \"@better-auth/core/db/adapter\";\nimport { createAdapterFactory } from \"@better-auth/core/db/adapter\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\n\nexport interface PrismaConfig {\n\t/**\n\t * Database provider.\n\t */\n\tprovider:\n\t\t| \"sqlite\"\n\t\t| \"cockroachdb\"\n\t\t| \"mysql\"\n\t\t| \"postgresql\"\n\t\t| \"sqlserver\"\n\t\t| \"mongodb\";\n\n\t/**\n\t * Enable debug logs for the adapter\n\t *\n\t * @default false\n\t */\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n\n\t/**\n\t * Use plural table names\n\t *\n\t * @default false\n\t */\n\tusePlural?: boolean | undefined;\n\n\t/**\n\t * Whether to execute multiple operations in a transaction.\n\t *\n\t * If the database doesn't support transactions,\n\t * set this to `false` and operations will be executed sequentially.\n\t * @default false\n\t */\n\ttransaction?: boolean | undefined;\n}\n\ninterface PrismaClient {}\n\ntype PrismaClientInternal = {\n\t$transaction: (\n\t\tcallback: (db: PrismaClient) => Awaitable<any>,\n\t) => Promise<any>;\n} & {\n\t[model: string]: {\n\t\tcreate: (data: any) => Promise<any>;\n\t\tfindFirst: (data: any) => Promise<any>;\n\t\tfindMany: (data: any) => Promise<any>;\n\t\tupdate: (data: any) => Promise<any>;\n\t\tupdateMany: (data: any) => Promise<any>;\n\t\tdelete: (data: any) => Promise<any>;\n\t\t[key: string]: any;\n\t};\n};\n\nexport const prismaAdapter = (prisma: PrismaClient, config: PrismaConfig) => {\n\tlet lazyOptions: BetterAuthOptions | null = null;\n\tconst createCustomAdapter =\n\t\t(prisma: PrismaClient): AdapterFactoryCustomizeAdapterCreator =>\n\t\t({\n\t\t\tgetFieldName,\n\t\t\tgetModelName,\n\t\t\tgetFieldAttributes,\n\t\t\tgetDefaultModelName,\n\t\t\tschema,\n\t\t}) => {\n\t\t\tconst db = prisma as PrismaClientInternal;\n\n\t\t\tconst convertSelect = (\n\t\t\t\tselect: string[] | undefined,\n\t\t\t\tmodel: string,\n\t\t\t\tjoin?: JoinConfig | undefined,\n\t\t\t) => {\n\t\t\t\tif (!select && !join) return undefined;\n\n\t\t\t\tlet result: Record<string, Record<string, any> | boolean> = {};\n\n\t\t\t\tif (select) {\n\t\t\t\t\tfor (const field of select) {\n\t\t\t\t\t\tresult[getFieldName({ model, field })] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (join) {\n\t\t\t\t\t// when joining that has a limit, we need to use Prisma's `select` syntax to append the limit to the field\n\t\t\t\t\t// because of such, it also means we need to select all base-model fields as well\n\t\t\t\t\t// should check if `select` is not provided, because then we should select all base-model fields\n\t\t\t\t\tif (!select) {\n\t\t\t\t\t\tconst fields = schema[getDefaultModelName(model)]?.fields || {};\n\t\t\t\t\t\tfields.id = { type: \"string\" }; // make sure there is at least an id field\n\t\t\t\t\t\tfor (const field of Object.keys(fields)) {\n\t\t\t\t\t\t\tresult[getFieldName({ model, field })] = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const [joinModel, joinAttr] of Object.entries(join)) {\n\t\t\t\t\t\tconst key = getJoinKeyName(model, getModelName(joinModel), schema);\n\t\t\t\t\t\tif (joinAttr.relation === \"one-to-one\") {\n\t\t\t\t\t\t\tresult[key] = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult[key] = { take: joinAttr.limit };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * Build the join key name based on whether the foreign field is unique or not.\n\t\t\t * If unique, use singular. Otherwise, pluralize (add 's').\n\t\t\t */\n\t\t\tconst getJoinKeyName = (\n\t\t\t\tbaseModel: string,\n\t\t\t\tjoinedModel: string,\n\t\t\t\tschema: any,\n\t\t\t): string => {\n\t\t\t\ttry {\n\t\t\t\t\tconst defaultBaseModelName = getDefaultModelName(baseModel);\n\t\t\t\t\tconst defaultJoinedModelName = getDefaultModelName(joinedModel);\n\t\t\t\t\tconst key = getModelName(joinedModel).toLowerCase();\n\n\t\t\t\t\t// First, check if the joined model has FKs to the base model (forward join)\n\t\t\t\t\tlet foreignKeys = Object.entries(\n\t\t\t\t\t\tschema[defaultJoinedModelName]?.fields || {},\n\t\t\t\t\t).filter(\n\t\t\t\t\t\t([_field, fieldAttributes]: any) =>\n\t\t\t\t\t\t\tfieldAttributes.references &&\n\t\t\t\t\t\t\tgetDefaultModelName(fieldAttributes.references.model) ===\n\t\t\t\t\t\t\t\tdefaultBaseModelName,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (foreignKeys.length > 0) {\n\t\t\t\t\t\t// Forward join: joined model has FK to base model\n\t\t\t\t\t\t// This is typically a one-to-many relationship (plural)\n\t\t\t\t\t\t// Unless the FK is unique, then it's one-to-one (singular)\n\t\t\t\t\t\tconst [_foreignKey, foreignKeyAttributes] = foreignKeys[0] as any;\n\t\t\t\t\t\t// Only check if field is explicitly marked as unique\n\t\t\t\t\t\tconst isUnique = foreignKeyAttributes?.unique === true;\n\t\t\t\t\t\treturn isUnique || config.usePlural === true ? key : `${key}s`;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check backwards: does the base model have FKs to the joined model?\n\t\t\t\t\tforeignKeys = Object.entries(\n\t\t\t\t\t\tschema[defaultBaseModelName]?.fields || {},\n\t\t\t\t\t).filter(\n\t\t\t\t\t\t([_field, fieldAttributes]: any) =>\n\t\t\t\t\t\t\tfieldAttributes.references &&\n\t\t\t\t\t\t\tgetDefaultModelName(fieldAttributes.references.model) ===\n\t\t\t\t\t\t\t\tdefaultJoinedModelName,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (foreignKeys.length > 0) {\n\t\t\t\t\t\treturn key;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Fallback to pluralizing if we can't determine uniqueness\n\t\t\t\t}\n\t\t\t\treturn `${getModelName(joinedModel).toLowerCase()}s`;\n\t\t\t};\n\t\t\tfunction operatorToPrismaOperator(operator: string) {\n\t\t\t\tswitch (operator) {\n\t\t\t\t\tcase \"starts_with\":\n\t\t\t\t\t\treturn \"startsWith\";\n\t\t\t\t\tcase \"ends_with\":\n\t\t\t\t\t\treturn \"endsWith\";\n\t\t\t\t\tcase \"ne\":\n\t\t\t\t\t\treturn \"not\";\n\t\t\t\t\tcase \"not_in\":\n\t\t\t\t\t\treturn \"notIn\";\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn operator;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst convertWhereClause = ({\n\t\t\t\taction,\n\t\t\t\tmodel,\n\t\t\t\twhere,\n\t\t\t}: {\n\t\t\t\tmodel: string;\n\t\t\t\twhere?: Where[] | undefined;\n\t\t\t\taction:\n\t\t\t\t\t| \"create\"\n\t\t\t\t\t| \"update\"\n\t\t\t\t\t| \"delete\"\n\t\t\t\t\t| \"findOne\"\n\t\t\t\t\t| \"findMany\"\n\t\t\t\t\t| \"count\"\n\t\t\t\t\t| \"updateMany\"\n\t\t\t\t\t| \"deleteMany\";\n\t\t\t}) => {\n\t\t\t\tif (!where || !where.length) return {};\n\t\t\t\tconst buildSingleCondition = (w: Where) => {\n\t\t\t\t\tconst fieldName = getFieldName({ model, field: w.field });\n\t\t\t\t\t// Special handling for Prisma null semantics, for non-nullable fields this is a tautology. Skip condition.\n\t\t\t\t\tif (w.operator === \"ne\" && w.value === null) {\n\t\t\t\t\t\treturn {};\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\t(w.operator === \"in\" || w.operator === \"not_in\") &&\n\t\t\t\t\t\tArray.isArray(w.value)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst filtered = w.value.filter((v) => v != null);\n\t\t\t\t\t\tif (filtered.length === 0) {\n\t\t\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tAND: [\n\t\t\t\t\t\t\t\t\t\t{ [fieldName]: { equals: \"__never__\" } },\n\t\t\t\t\t\t\t\t\t\t{ [fieldName]: { not: \"__never__\" } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn {};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prismaOp = operatorToPrismaOperator(w.operator);\n\t\t\t\t\t\treturn { [fieldName]: { [prismaOp]: filtered } };\n\t\t\t\t\t}\n\t\t\t\t\tif (w.operator === \"eq\" || !w.operator) {\n\t\t\t\t\t\treturn { [fieldName]: w.value };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t[fieldName]: {\n\t\t\t\t\t\t\t[operatorToPrismaOperator(w.operator)]: w.value,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Special handling for update actions: extract AND conditions with eq operator to root level\n\t\t\t\t// Prisma requires unique fields to be at root level, not nested in AND arrays\n\t\t\t\t// Only simple equality conditions can be at root level; complex operators must stay in AND array\n\t\t\t\tif (action === \"update\") {\n\t\t\t\t\tconst and = where.filter(\n\t\t\t\t\t\t(w) => w.connector === \"AND\" || !w.connector,\n\t\t\t\t\t);\n\t\t\t\t\tconst or = where.filter((w) => w.connector === \"OR\");\n\n\t\t\t\t\t// Separate AND conditions into simple eq (can extract) and complex (must stay in AND)\n\t\t\t\t\tconst andSimple = and.filter(\n\t\t\t\t\t\t(w) => w.operator === \"eq\" || !w.operator,\n\t\t\t\t\t);\n\t\t\t\t\tconst andComplex = and.filter(\n\t\t\t\t\t\t(w) => w.operator !== \"eq\" && w.operator !== undefined,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst andSimpleClause = andSimple.map((w) => buildSingleCondition(w));\n\t\t\t\t\tconst andComplexClause = andComplex.map((w) =>\n\t\t\t\t\t\tbuildSingleCondition(w),\n\t\t\t\t\t);\n\t\t\t\t\tconst orClause = or.map((w) => buildSingleCondition(w));\n\n\t\t\t\t\t// Extract simple equality AND conditions to root level\n\t\t\t\t\tconst result: Record<string, any> = {};\n\t\t\t\t\tfor (const clause of andSimpleClause) {\n\t\t\t\t\t\tObject.assign(result, clause);\n\t\t\t\t\t}\n\t\t\t\t\t// Keep complex AND conditions in AND array\n\t\t\t\t\tif (andComplexClause.length > 0) {\n\t\t\t\t\t\tresult.AND = andComplexClause;\n\t\t\t\t\t}\n\t\t\t\t\tif (orClause.length > 0) {\n\t\t\t\t\t\tresult.OR = orClause;\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\t// Special handling for delete actions: extract id to root level\n\t\t\t\tif (action === \"delete\") {\n\t\t\t\t\tconst idCondition = where.find((w) => w.field === \"id\");\n\t\t\t\t\tif (idCondition) {\n\t\t\t\t\t\tconst idFieldName = getFieldName({ model, field: \"id\" });\n\t\t\t\t\t\tconst idClause = buildSingleCondition(idCondition);\n\t\t\t\t\t\tconst remainingWhere = where.filter((w) => w.field !== \"id\");\n\n\t\t\t\t\t\tif (remainingWhere.length === 0) {\n\t\t\t\t\t\t\treturn idClause;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst and = remainingWhere.filter(\n\t\t\t\t\t\t\t(w) => w.connector === \"AND\" || !w.connector,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst or = remainingWhere.filter((w) => w.connector === \"OR\");\n\t\t\t\t\t\tconst andClause = and.map((w) => buildSingleCondition(w));\n\t\t\t\t\t\tconst orClause = or.map((w) => buildSingleCondition(w));\n\n\t\t\t\t\t\t// Extract id to root level, put other conditions in AND array\n\t\t\t\t\t\tconst result: Record<string, any> = {};\n\t\t\t\t\t\tif (idFieldName in idClause) {\n\t\t\t\t\t\t\tresult[idFieldName] = (idClause as Record<string, any>)[\n\t\t\t\t\t\t\t\tidFieldName\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Handle edge case where idClause might have special structure\n\t\t\t\t\t\t\tObject.assign(result, idClause);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (andClause.length > 0) {\n\t\t\t\t\t\t\tresult.AND = andClause;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (orClause.length > 0) {\n\t\t\t\t\t\t\tresult.OR = orClause;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (where.length === 1) {\n\t\t\t\t\tconst w = where[0]!;\n\t\t\t\t\tif (!w) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\treturn buildSingleCondition(w);\n\t\t\t\t}\n\t\t\t\tconst and = where.filter((w) => w.connector === \"AND\" || !w.connector);\n\t\t\t\tconst or = where.filter((w) => w.connector === \"OR\");\n\t\t\t\tconst andClause = and.map((w) => buildSingleCondition(w));\n\t\t\t\tconst orClause = or.map((w) => buildSingleCondition(w));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(andClause.length ? { AND: andClause } : {}),\n\t\t\t\t\t...(orClause.length ? { OR: orClause } : {}),\n\t\t\t\t};\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tasync create({ model, data: values, select }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst result = await db[model]!.create({\n\t\t\t\t\t\tdata: values,\n\t\t\t\t\t\tselect: convertSelect(select, model),\n\t\t\t\t\t});\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\tasync findOne({ model, where, select, join }) {\n\t\t\t\t\t// this is just \"JoinOption\" type because we disabled join transformation in adapter config\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"findOne\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// transform join keys to use Prisma expected field names\n\t\t\t\t\tlet map = new Map<string, string>();\n\t\t\t\t\tfor (const joinModel of Object.keys(join ?? {})) {\n\t\t\t\t\t\tconst key = getJoinKeyName(model, joinModel, schema);\n\t\t\t\t\t\tmap.set(key, getModelName(joinModel));\n\t\t\t\t\t}\n\n\t\t\t\t\tconst selects = convertSelect(select, model, join);\n\n\t\t\t\t\tlet result = await db[model]!.findFirst({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\tselect: selects,\n\t\t\t\t\t});\n\n\t\t\t\t\t// transform the resulting `include` items to use better-auth expected field names\n\t\t\t\t\tif (join && result) {\n\t\t\t\t\t\tfor (const [includeKey, originalKey] of map.entries()) {\n\t\t\t\t\t\t\tif (includeKey === originalKey) continue;\n\t\t\t\t\t\t\tif (includeKey in result) {\n\t\t\t\t\t\t\t\tresult[originalKey] = result[includeKey];\n\t\t\t\t\t\t\t\tdelete result[includeKey];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\tasync findMany({ model, where, limit, offset, sortBy, join }) {\n\t\t\t\t\t// this is just \"JoinOption\" type because we disabled join transformation in adapter config\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"findMany\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// transform join keys to use Prisma expected field names\n\t\t\t\t\tlet map = new Map<string, string>();\n\t\t\t\t\tif (join) {\n\t\t\t\t\t\tfor (const [joinModel, _value] of Object.entries(join)) {\n\t\t\t\t\t\t\tconst key = getJoinKeyName(model, joinModel, schema);\n\t\t\t\t\t\t\tmap.set(key, getModelName(joinModel));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst selects = convertSelect(undefined, model, join);\n\n\t\t\t\t\tconst result = await db[model]!.findMany({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\ttake: limit || 100,\n\t\t\t\t\t\tskip: offset || 0,\n\t\t\t\t\t\t...(sortBy?.field\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\torderBy: {\n\t\t\t\t\t\t\t\t\t\t[getFieldName({ model, field: sortBy.field })]:\n\t\t\t\t\t\t\t\t\t\t\tsortBy.direction === \"desc\" ? \"desc\" : \"asc\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\tselect: selects,\n\t\t\t\t\t});\n\n\t\t\t\t\t// transform the resulting join items to use better-auth expected field names\n\t\t\t\t\tif (join && Array.isArray(result)) {\n\t\t\t\t\t\tfor (const item of result) {\n\t\t\t\t\t\t\tfor (const [includeKey, originalKey] of map.entries()) {\n\t\t\t\t\t\t\t\tif (includeKey === originalKey) continue;\n\t\t\t\t\t\t\t\tif (includeKey in item) {\n\t\t\t\t\t\t\t\t\titem[originalKey] = item[includeKey];\n\t\t\t\t\t\t\t\t\tdelete item[includeKey];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\tasync count({ model, where }) {\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"count\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn await db[model]!.count({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tasync update({ model, where, update }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"update\",\n\t\t\t\t\t});\n\n\t\t\t\t\treturn await db[model]!.update({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\tdata: update,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tasync updateMany({ model, where, update }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"updateMany\",\n\t\t\t\t\t});\n\t\t\t\t\tconst result = await db[model]!.updateMany({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\tdata: update,\n\t\t\t\t\t});\n\t\t\t\t\treturn result ? (result.count as number) : 0;\n\t\t\t\t},\n\t\t\t\tasync delete({ model, where }) {\n\t\t\t\t\tif (!db[model]) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t`Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"delete\",\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait db[model]!.delete({\n\t\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\t// If the record doesn't exist, we don't want to throw an error\n\t\t\t\t\t\tif (e?.meta?.cause === \"Record to delete does not exist.\") return;\n\t\t\t\t\t\tif (e?.code === \"P2025\") return; // Prisma 7+\n\t\t\t\t\t\t// otherwise if it's an unknown error, we want to just log it for debugging.\n\t\t\t\t\t\tconsole.log(e);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tasync deleteMany({ model, where }) {\n\t\t\t\t\tconst whereClause = convertWhereClause({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t\taction: \"deleteMany\",\n\t\t\t\t\t});\n\t\t\t\t\tconst result = await db[model]!.deleteMany({\n\t\t\t\t\t\twhere: whereClause,\n\t\t\t\t\t});\n\t\t\t\t\treturn result ? (result.count as number) : 0;\n\t\t\t\t},\n\t\t\t\toptions: config,\n\t\t\t};\n\t\t};\n\n\tlet adapterOptions: AdapterFactoryOptions | null = null;\n\tadapterOptions = {\n\t\tconfig: {\n\t\t\tadapterId: \"prisma\",\n\t\t\tadapterName: \"Prisma Adapter\",\n\t\t\tusePlural: config.usePlural ?? false,\n\t\t\tdebugLogs: config.debugLogs ?? false,\n\t\t\tsupportsUUIDs: config.provider === \"postgresql\" ? true : false,\n\t\t\tsupportsArrays:\n\t\t\t\tconfig.provider === \"postgresql\" || config.provider === \"mongodb\"\n\t\t\t\t\t? true\n\t\t\t\t\t: false,\n\t\t\ttransaction:\n\t\t\t\t(config.transaction ?? false)\n\t\t\t\t\t? (cb) =>\n\t\t\t\t\t\t\t(prisma as PrismaClientInternal).$transaction((tx) => {\n\t\t\t\t\t\t\t\tconst adapter = createAdapterFactory({\n\t\t\t\t\t\t\t\t\tconfig: adapterOptions!.config,\n\t\t\t\t\t\t\t\t\tadapter: createCustomAdapter(tx),\n\t\t\t\t\t\t\t\t})(lazyOptions!);\n\t\t\t\t\t\t\t\treturn cb(adapter);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t: false,\n\t\t},\n\t\tadapter: createCustomAdapter(prisma),\n\t};\n\n\tconst adapter = createAdapterFactory(adapterOptions);\n\treturn (options: BetterAuthOptions): DBAdapter<BetterAuthOptions> => {\n\t\tlazyOptions = options;\n\t\treturn adapter(options);\n\t};\n};\n"],"mappings":"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"}
|