@depup/better-auth__core 1.6.23-depup.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +20 -0
- package/README.md +32 -0
- package/changes.json +14 -0
- package/dist/api/index.d.mts +281 -0
- package/dist/api/index.mjs +92 -0
- package/dist/async_hooks/index.d.mts +6 -0
- package/dist/async_hooks/index.mjs +20 -0
- package/dist/async_hooks/pure.index.d.mts +6 -0
- package/dist/async_hooks/pure.index.mjs +33 -0
- package/dist/context/endpoint-context.d.mts +18 -0
- package/dist/context/endpoint-context.mjs +29 -0
- package/dist/context/global.d.mts +6 -0
- package/dist/context/global.mjs +36 -0
- package/dist/context/index.d.mts +5 -0
- package/dist/context/index.mjs +5 -0
- package/dist/context/request-state.d.mts +27 -0
- package/dist/context/request-state.mjs +47 -0
- package/dist/context/transaction.d.mts +27 -0
- package/dist/context/transaction.mjs +96 -0
- package/dist/db/adapter/factory.d.mts +17 -0
- package/dist/db/adapter/factory.mjs +905 -0
- package/dist/db/adapter/get-default-field-name.d.mts +18 -0
- package/dist/db/adapter/get-default-field-name.mjs +36 -0
- package/dist/db/adapter/get-default-model-name.d.mts +12 -0
- package/dist/db/adapter/get-default-model-name.mjs +30 -0
- package/dist/db/adapter/get-field-attributes.d.mts +26 -0
- package/dist/db/adapter/get-field-attributes.mjs +37 -0
- package/dist/db/adapter/get-field-name.d.mts +18 -0
- package/dist/db/adapter/get-field-name.mjs +31 -0
- package/dist/db/adapter/get-id-field.d.mts +36 -0
- package/dist/db/adapter/get-id-field.mjs +64 -0
- package/dist/db/adapter/get-model-name.d.mts +12 -0
- package/dist/db/adapter/get-model-name.mjs +21 -0
- package/dist/db/adapter/index.d.mts +615 -0
- package/dist/db/adapter/index.mjs +24 -0
- package/dist/db/adapter/types.d.mts +105 -0
- package/dist/db/adapter/utils.d.mts +7 -0
- package/dist/db/adapter/utils.mjs +37 -0
- package/dist/db/get-tables.d.mts +6 -0
- package/dist/db/get-tables.mjs +266 -0
- package/dist/db/index.d.mts +10 -0
- package/dist/db/index.mjs +8 -0
- package/dist/db/plugin.d.mts +12 -0
- package/dist/db/schema/account.d.mts +28 -0
- package/dist/db/schema/account.mjs +17 -0
- package/dist/db/schema/rate-limit.d.mts +18 -0
- package/dist/db/schema/rate-limit.mjs +9 -0
- package/dist/db/schema/session.d.mts +23 -0
- package/dist/db/schema/session.mjs +12 -0
- package/dist/db/schema/shared.d.mts +10 -0
- package/dist/db/schema/shared.mjs +9 -0
- package/dist/db/schema/user.d.mts +22 -0
- package/dist/db/schema/user.mjs +11 -0
- package/dist/db/schema/verification.d.mts +21 -0
- package/dist/db/schema/verification.mjs +10 -0
- package/dist/db/type.d.mts +194 -0
- package/dist/env/color-depth.d.mts +4 -0
- package/dist/env/color-depth.mjs +86 -0
- package/dist/env/env-impl.d.mts +32 -0
- package/dist/env/env-impl.mjs +81 -0
- package/dist/env/index.d.mts +4 -0
- package/dist/env/index.mjs +4 -0
- package/dist/env/logger.d.mts +48 -0
- package/dist/env/logger.mjs +79 -0
- package/dist/error/codes.d.mts +69 -0
- package/dist/error/codes.mjs +55 -0
- package/dist/error/index.d.mts +26 -0
- package/dist/error/index.mjs +27 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.mjs +1 -0
- package/dist/instrumentation/api.mjs +12 -0
- package/dist/instrumentation/attributes.d.mts +11 -0
- package/dist/instrumentation/attributes.mjs +10 -0
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.mjs +3 -0
- package/dist/instrumentation/noop.mjs +42 -0
- package/dist/instrumentation/pure.index.d.mts +7 -0
- package/dist/instrumentation/pure.index.mjs +7 -0
- package/dist/instrumentation/tracer.d.mts +13 -0
- package/dist/instrumentation/tracer.mjs +53 -0
- package/dist/oauth2/client-credentials-token.d.mts +56 -0
- package/dist/oauth2/client-credentials-token.mjs +64 -0
- package/dist/oauth2/create-authorization-url.d.mts +44 -0
- package/dist/oauth2/create-authorization-url.mjs +41 -0
- package/dist/oauth2/index.d.mts +8 -0
- package/dist/oauth2/index.mjs +7 -0
- package/dist/oauth2/oauth-provider.d.mts +192 -0
- package/dist/oauth2/refresh-access-token.d.mts +54 -0
- package/dist/oauth2/refresh-access-token.mjs +73 -0
- package/dist/oauth2/reject-redirects.mjs +60 -0
- package/dist/oauth2/utils.d.mts +24 -0
- package/dist/oauth2/utils.mjs +48 -0
- package/dist/oauth2/validate-authorization-code.d.mts +85 -0
- package/dist/oauth2/validate-authorization-code.mjs +86 -0
- package/dist/oauth2/verify.d.mts +65 -0
- package/dist/oauth2/verify.mjs +202 -0
- package/dist/social-providers/apple.d.mts +133 -0
- package/dist/social-providers/apple.mjs +117 -0
- package/dist/social-providers/atlassian.d.mts +70 -0
- package/dist/social-providers/atlassian.mjs +80 -0
- package/dist/social-providers/cognito.d.mts +85 -0
- package/dist/social-providers/cognito.mjs +162 -0
- package/dist/social-providers/discord.d.mts +124 -0
- package/dist/social-providers/discord.mjs +62 -0
- package/dist/social-providers/dropbox.d.mts +69 -0
- package/dist/social-providers/dropbox.mjs +72 -0
- package/dist/social-providers/facebook.d.mts +79 -0
- package/dist/social-providers/facebook.mjs +157 -0
- package/dist/social-providers/figma.d.mts +61 -0
- package/dist/social-providers/figma.mjs +83 -0
- package/dist/social-providers/github.d.mts +102 -0
- package/dist/social-providers/github.mjs +92 -0
- package/dist/social-providers/gitlab.d.mts +123 -0
- package/dist/social-providers/gitlab.mjs +79 -0
- package/dist/social-providers/google.d.mts +123 -0
- package/dist/social-providers/google.mjs +137 -0
- package/dist/social-providers/huggingface.d.mts +83 -0
- package/dist/social-providers/huggingface.mjs +73 -0
- package/dist/social-providers/index.d.mts +1834 -0
- package/dist/social-providers/index.mjs +78 -0
- package/dist/social-providers/kakao.d.mts +161 -0
- package/dist/social-providers/kakao.mjs +70 -0
- package/dist/social-providers/kick.d.mts +73 -0
- package/dist/social-providers/kick.mjs +68 -0
- package/dist/social-providers/line.d.mts +105 -0
- package/dist/social-providers/line.mjs +110 -0
- package/dist/social-providers/linear.d.mts +68 -0
- package/dist/social-providers/linear.mjs +85 -0
- package/dist/social-providers/linkedin.d.mts +67 -0
- package/dist/social-providers/linkedin.mjs +73 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
- package/dist/social-providers/microsoft-entra-id.mjs +152 -0
- package/dist/social-providers/naver.d.mts +92 -0
- package/dist/social-providers/naver.mjs +65 -0
- package/dist/social-providers/notion.d.mts +64 -0
- package/dist/social-providers/notion.mjs +72 -0
- package/dist/social-providers/paybin.d.mts +71 -0
- package/dist/social-providers/paybin.mjs +81 -0
- package/dist/social-providers/paypal.d.mts +131 -0
- package/dist/social-providers/paypal.mjs +188 -0
- package/dist/social-providers/polar.d.mts +74 -0
- package/dist/social-providers/polar.mjs +71 -0
- package/dist/social-providers/railway.d.mts +65 -0
- package/dist/social-providers/railway.mjs +74 -0
- package/dist/social-providers/reddit.d.mts +62 -0
- package/dist/social-providers/reddit.mjs +81 -0
- package/dist/social-providers/roblox.d.mts +70 -0
- package/dist/social-providers/roblox.mjs +57 -0
- package/dist/social-providers/salesforce.d.mts +79 -0
- package/dist/social-providers/salesforce.mjs +87 -0
- package/dist/social-providers/slack.d.mts +83 -0
- package/dist/social-providers/slack.mjs +66 -0
- package/dist/social-providers/spotify.d.mts +63 -0
- package/dist/social-providers/spotify.mjs +69 -0
- package/dist/social-providers/tiktok.d.mts +168 -0
- package/dist/social-providers/tiktok.mjs +60 -0
- package/dist/social-providers/twitch.d.mts +79 -0
- package/dist/social-providers/twitch.mjs +75 -0
- package/dist/social-providers/twitter.d.mts +126 -0
- package/dist/social-providers/twitter.mjs +85 -0
- package/dist/social-providers/vercel.d.mts +62 -0
- package/dist/social-providers/vercel.mjs +58 -0
- package/dist/social-providers/vk.d.mts +70 -0
- package/dist/social-providers/vk.mjs +81 -0
- package/dist/social-providers/wechat.d.mts +113 -0
- package/dist/social-providers/wechat.mjs +81 -0
- package/dist/social-providers/zoom.d.mts +163 -0
- package/dist/social-providers/zoom.mjs +69 -0
- package/dist/types/context.d.mts +319 -0
- package/dist/types/cookie.d.mts +15 -0
- package/dist/types/helper.d.mts +10 -0
- package/dist/types/index.d.mts +9 -0
- package/dist/types/init-options.d.mts +1430 -0
- package/dist/types/plugin-client.d.mts +123 -0
- package/dist/types/plugin.d.mts +124 -0
- package/dist/types/secret.d.mts +11 -0
- package/dist/utils/async.d.mts +22 -0
- package/dist/utils/async.mjs +32 -0
- package/dist/utils/db.d.mts +9 -0
- package/dist/utils/db.mjs +15 -0
- package/dist/utils/deprecate.d.mts +9 -0
- package/dist/utils/deprecate.mjs +16 -0
- package/dist/utils/error-codes.d.mts +13 -0
- package/dist/utils/error-codes.mjs +10 -0
- package/dist/utils/fetch-metadata.d.mts +4 -0
- package/dist/utils/fetch-metadata.mjs +6 -0
- package/dist/utils/host.d.mts +147 -0
- package/dist/utils/host.mjs +295 -0
- package/dist/utils/id.d.mts +4 -0
- package/dist/utils/id.mjs +7 -0
- package/dist/utils/ip.d.mts +77 -0
- package/dist/utils/ip.mjs +230 -0
- package/dist/utils/is-api-error.d.mts +6 -0
- package/dist/utils/is-api-error.mjs +8 -0
- package/dist/utils/json.d.mts +4 -0
- package/dist/utils/json.mjs +41 -0
- package/dist/utils/redirect-uri.d.mts +20 -0
- package/dist/utils/redirect-uri.mjs +48 -0
- package/dist/utils/string.d.mts +8 -0
- package/dist/utils/string.mjs +25 -0
- package/dist/utils/url.d.mts +37 -0
- package/dist/utils/url.mjs +61 -0
- package/package.json +216 -0
- package/src/api/index.ts +185 -0
- package/src/async_hooks/index.ts +40 -0
- package/src/async_hooks/pure.index.ts +46 -0
- package/src/context/endpoint-context.ts +50 -0
- package/src/context/global.ts +57 -0
- package/src/context/index.ts +23 -0
- package/src/context/request-state.ts +91 -0
- package/src/context/transaction.ts +169 -0
- package/src/db/adapter/factory.ts +1740 -0
- package/src/db/adapter/get-default-field-name.ts +59 -0
- package/src/db/adapter/get-default-model-name.ts +51 -0
- package/src/db/adapter/get-field-attributes.ts +62 -0
- package/src/db/adapter/get-field-name.ts +43 -0
- package/src/db/adapter/get-id-field.ts +150 -0
- package/src/db/adapter/get-model-name.ts +36 -0
- package/src/db/adapter/index.ts +656 -0
- package/src/db/adapter/types.ts +134 -0
- package/src/db/adapter/utils.ts +61 -0
- package/src/db/get-tables.ts +304 -0
- package/src/db/index.ts +43 -0
- package/src/db/plugin.ts +11 -0
- package/src/db/schema/account.ts +47 -0
- package/src/db/schema/rate-limit.ts +36 -0
- package/src/db/schema/session.ts +29 -0
- package/src/db/schema/shared.ts +7 -0
- package/src/db/schema/user.ts +31 -0
- package/src/db/schema/verification.ts +28 -0
- package/src/db/type.ts +360 -0
- package/src/env/color-depth.ts +172 -0
- package/src/env/env-impl.ts +123 -0
- package/src/env/index.ts +23 -0
- package/src/env/logger.ts +145 -0
- package/src/error/codes.ts +72 -0
- package/src/error/index.ts +44 -0
- package/src/index.ts +1 -0
- package/src/instrumentation/api.ts +17 -0
- package/src/instrumentation/attributes.ts +22 -0
- package/src/instrumentation/index.ts +2 -0
- package/src/instrumentation/noop.ts +74 -0
- package/src/instrumentation/pure.index.ts +31 -0
- package/src/instrumentation/tracer.ts +95 -0
- package/src/oauth2/client-credentials-token.ts +126 -0
- package/src/oauth2/create-authorization-url.ts +89 -0
- package/src/oauth2/index.ts +34 -0
- package/src/oauth2/oauth-provider.ts +222 -0
- package/src/oauth2/refresh-access-token.ts +157 -0
- package/src/oauth2/reject-redirects.ts +70 -0
- package/src/oauth2/utils.ts +70 -0
- package/src/oauth2/validate-authorization-code.ts +190 -0
- package/src/oauth2/verify.ts +408 -0
- package/src/social-providers/apple.ts +249 -0
- package/src/social-providers/atlassian.ts +133 -0
- package/src/social-providers/cognito.ts +281 -0
- package/src/social-providers/discord.ts +170 -0
- package/src/social-providers/dropbox.ts +112 -0
- package/src/social-providers/facebook.ts +288 -0
- package/src/social-providers/figma.ts +118 -0
- package/src/social-providers/github.ts +184 -0
- package/src/social-providers/gitlab.ts +155 -0
- package/src/social-providers/google.ts +263 -0
- package/src/social-providers/huggingface.ts +119 -0
- package/src/social-providers/index.ts +132 -0
- package/src/social-providers/kakao.ts +179 -0
- package/src/social-providers/kick.ts +109 -0
- package/src/social-providers/line.ts +169 -0
- package/src/social-providers/linear.ts +121 -0
- package/src/social-providers/linkedin.ts +110 -0
- package/src/social-providers/microsoft-entra-id.ts +391 -0
- package/src/social-providers/naver.ts +113 -0
- package/src/social-providers/notion.ts +108 -0
- package/src/social-providers/paybin.ts +118 -0
- package/src/social-providers/paypal.ts +371 -0
- package/src/social-providers/polar.ts +111 -0
- package/src/social-providers/railway.ts +100 -0
- package/src/social-providers/reddit.ts +126 -0
- package/src/social-providers/roblox.ts +112 -0
- package/src/social-providers/salesforce.ts +159 -0
- package/src/social-providers/slack.ts +112 -0
- package/src/social-providers/spotify.ts +94 -0
- package/src/social-providers/tiktok.ts +211 -0
- package/src/social-providers/twitch.ts +112 -0
- package/src/social-providers/twitter.ts +199 -0
- package/src/social-providers/vercel.ts +87 -0
- package/src/social-providers/vk.ts +125 -0
- package/src/social-providers/wechat.ts +220 -0
- package/src/social-providers/zoom.ts +230 -0
- package/src/types/context.ts +460 -0
- package/src/types/cookie.ts +10 -0
- package/src/types/helper.ts +27 -0
- package/src/types/index.ts +40 -0
- package/src/types/init-options.ts +1679 -0
- package/src/types/plugin-client.ts +143 -0
- package/src/types/plugin.ts +163 -0
- package/src/types/secret.ts +8 -0
- package/src/utils/async.ts +53 -0
- package/src/utils/db.ts +20 -0
- package/src/utils/deprecate.ts +21 -0
- package/src/utils/error-codes.ts +68 -0
- package/src/utils/fetch-metadata.ts +3 -0
- package/src/utils/host.ts +416 -0
- package/src/utils/id.ts +5 -0
- package/src/utils/ip.ts +395 -0
- package/src/utils/is-api-error.ts +10 -0
- package/src/utils/json.ts +56 -0
- package/src/utils/redirect-uri.ts +54 -0
- package/src/utils/string.ts +40 -0
- package/src/utils/url.ts +77 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { BetterAuthOptions } from "../../types";
|
|
2
|
+
import type { BetterAuthDBSchema, DBFieldAttribute } from "../type";
|
|
3
|
+
import type {
|
|
4
|
+
CleanedWhere,
|
|
5
|
+
CustomAdapter,
|
|
6
|
+
DBAdapterFactoryConfig,
|
|
7
|
+
JoinConfig,
|
|
8
|
+
DBTransactionAdapter as TransactionAdapter,
|
|
9
|
+
Where,
|
|
10
|
+
} from "./index";
|
|
11
|
+
|
|
12
|
+
export type AdapterFactoryOptions = {
|
|
13
|
+
config: AdapterFactoryConfig;
|
|
14
|
+
adapter: AdapterFactoryCustomizeAdapterCreator;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export interface AdapterFactoryConfig
|
|
18
|
+
extends Omit<DBAdapterFactoryConfig<BetterAuthOptions>, "transaction"> {
|
|
19
|
+
/**
|
|
20
|
+
* Execute multiple operations in a transaction.
|
|
21
|
+
*
|
|
22
|
+
* If the database doesn't support transactions, set this to `false` and operations will be executed sequentially.
|
|
23
|
+
*
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
transaction?:
|
|
27
|
+
| (
|
|
28
|
+
| false
|
|
29
|
+
| (<R>(callback: (trx: TransactionAdapter) => Promise<R>) => Promise<R>)
|
|
30
|
+
)
|
|
31
|
+
| undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type AdapterFactoryCustomizeAdapterCreator = (config: {
|
|
35
|
+
options: BetterAuthOptions;
|
|
36
|
+
/**
|
|
37
|
+
* The schema of the user's Better-Auth instance.
|
|
38
|
+
*/
|
|
39
|
+
schema: BetterAuthDBSchema;
|
|
40
|
+
/**
|
|
41
|
+
* The debug log function.
|
|
42
|
+
*
|
|
43
|
+
* If the config has defined `debugLogs` as `false`, no logs will be shown.
|
|
44
|
+
*/
|
|
45
|
+
debugLog: (...args: unknown[]) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Get the model name which is expected to be saved in the database based on the user's schema.
|
|
48
|
+
*/
|
|
49
|
+
getModelName: (model: string) => string;
|
|
50
|
+
/**
|
|
51
|
+
* Get the field name which is expected to be saved in the database based on the user's schema.
|
|
52
|
+
*/
|
|
53
|
+
getFieldName: ({ model, field }: { model: string; field: string }) => string;
|
|
54
|
+
/**
|
|
55
|
+
* This function helps us get the default model name from the schema defined by devs.
|
|
56
|
+
* Often times, the user will be using the `modelName` which could had been customized by the users.
|
|
57
|
+
* This function helps us get the actual model name useful to match against the schema. (eg: schema[model])
|
|
58
|
+
*
|
|
59
|
+
* If it's still unclear what this does:
|
|
60
|
+
*
|
|
61
|
+
* 1. User can define a custom modelName.
|
|
62
|
+
* 2. When using a custom modelName, doing something like `schema[model]` will not work.
|
|
63
|
+
* 3. Using this function helps us get the actual model name based on the user's defined custom modelName.
|
|
64
|
+
* 4. Thus allowing us to use `schema[model]`.
|
|
65
|
+
*/
|
|
66
|
+
getDefaultModelName: (model: string) => string;
|
|
67
|
+
/**
|
|
68
|
+
* This function helps us get the default field name from the schema defined by devs.
|
|
69
|
+
* Often times, the user will be using the `fieldName` which could had been customized by the users.
|
|
70
|
+
* This function helps us get the actual field name useful to match against the schema. (eg: schema[model].fields[field])
|
|
71
|
+
*
|
|
72
|
+
* If it's still unclear what this does:
|
|
73
|
+
*
|
|
74
|
+
* 1. User can define a custom fieldName.
|
|
75
|
+
* 2. When using a custom fieldName, doing something like `schema[model].fields[field]` will not work.
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
getDefaultFieldName: ({
|
|
79
|
+
model,
|
|
80
|
+
field,
|
|
81
|
+
}: {
|
|
82
|
+
model: string;
|
|
83
|
+
field: string;
|
|
84
|
+
}) => string;
|
|
85
|
+
/**
|
|
86
|
+
* Get the field attributes for a given model and field.
|
|
87
|
+
*
|
|
88
|
+
* Note: any model name or field name is allowed, whether default to schema or not.
|
|
89
|
+
*/
|
|
90
|
+
getFieldAttributes: ({
|
|
91
|
+
model,
|
|
92
|
+
field,
|
|
93
|
+
}: {
|
|
94
|
+
model: string;
|
|
95
|
+
field: string;
|
|
96
|
+
}) => DBFieldAttribute;
|
|
97
|
+
// The following functions are exposed primarily for the purpose of having wrapper adapters.
|
|
98
|
+
transformInput: (
|
|
99
|
+
data: Record<string, unknown>,
|
|
100
|
+
defaultModelName: string,
|
|
101
|
+
action: "create" | "update",
|
|
102
|
+
forceAllowId?: boolean | undefined,
|
|
103
|
+
) => Promise<Record<string, unknown>>;
|
|
104
|
+
transformOutput: (
|
|
105
|
+
data: Record<string, unknown>,
|
|
106
|
+
defaultModelName: string,
|
|
107
|
+
select?: string[] | undefined,
|
|
108
|
+
joinConfig?: JoinConfig | undefined,
|
|
109
|
+
) => Promise<Record<string, unknown>>;
|
|
110
|
+
transformWhereClause: <W extends Where[] | undefined>({
|
|
111
|
+
model,
|
|
112
|
+
where,
|
|
113
|
+
action,
|
|
114
|
+
}: {
|
|
115
|
+
where: W;
|
|
116
|
+
model: string;
|
|
117
|
+
action:
|
|
118
|
+
| "create"
|
|
119
|
+
| "update"
|
|
120
|
+
| "findOne"
|
|
121
|
+
| "findMany"
|
|
122
|
+
| "updateMany"
|
|
123
|
+
| "delete"
|
|
124
|
+
| "deleteMany"
|
|
125
|
+
| "consumeOne"
|
|
126
|
+
| "incrementOne"
|
|
127
|
+
| "count";
|
|
128
|
+
}) => W extends undefined ? undefined : CleanedWhere[];
|
|
129
|
+
}) => CustomAdapter;
|
|
130
|
+
|
|
131
|
+
export type AdapterTestDebugLogs = {
|
|
132
|
+
resetDebugLogs: () => void;
|
|
133
|
+
printDebugLogs: () => void;
|
|
134
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { DBFieldAttribute } from "../type";
|
|
2
|
+
|
|
3
|
+
export function withApplyDefault(
|
|
4
|
+
value: any,
|
|
5
|
+
field: DBFieldAttribute,
|
|
6
|
+
action: "create" | "update" | "findOne" | "findMany",
|
|
7
|
+
) {
|
|
8
|
+
if (action === "update") {
|
|
9
|
+
// Apply onUpdate if value is undefined
|
|
10
|
+
if (value === undefined && field.onUpdate !== undefined) {
|
|
11
|
+
if (typeof field.onUpdate === "function") {
|
|
12
|
+
return field.onUpdate();
|
|
13
|
+
}
|
|
14
|
+
return field.onUpdate;
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
if (action === "create") {
|
|
19
|
+
// we do not want to apply default values if the value is null & not required
|
|
20
|
+
if (value === undefined || (field.required === true && value === null)) {
|
|
21
|
+
if (field.defaultValue !== undefined) {
|
|
22
|
+
if (typeof field.defaultValue === "function") {
|
|
23
|
+
return field.defaultValue();
|
|
24
|
+
}
|
|
25
|
+
return field.defaultValue;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isObject(item: unknown): item is Record<string, unknown> {
|
|
33
|
+
return item !== null && typeof item === "object" && !Array.isArray(item);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function deepmerge<T>(target: T, source: Partial<T>): T {
|
|
37
|
+
if (Array.isArray(target) && Array.isArray(source)) {
|
|
38
|
+
// merge arrays by concatenation
|
|
39
|
+
return [...target, ...source] as T;
|
|
40
|
+
} else if (isObject(target) && isObject(source)) {
|
|
41
|
+
const result: Record<string, unknown> = { ...target };
|
|
42
|
+
|
|
43
|
+
for (const [key, value] of Object.entries(source)) {
|
|
44
|
+
if (value === undefined) continue; // skip undefined
|
|
45
|
+
|
|
46
|
+
if (key in target) {
|
|
47
|
+
result[key] = deepmerge(
|
|
48
|
+
(target as Record<string, unknown>)[key],
|
|
49
|
+
value as unknown as Partial<T>,
|
|
50
|
+
);
|
|
51
|
+
} else {
|
|
52
|
+
result[key] = value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result as T;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// primitives and fallback: source overrides target
|
|
60
|
+
return source as T;
|
|
61
|
+
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import type { BetterAuthOptions } from "../types";
|
|
2
|
+
import type { BetterAuthDBSchema, DBFieldAttribute } from "./type";
|
|
3
|
+
|
|
4
|
+
export const getAuthTables = (
|
|
5
|
+
options: BetterAuthOptions,
|
|
6
|
+
): BetterAuthDBSchema => {
|
|
7
|
+
const pluginSchema = (options.plugins ?? []).reduce(
|
|
8
|
+
(acc, plugin) => {
|
|
9
|
+
const schema = plugin.schema;
|
|
10
|
+
if (!schema) return acc;
|
|
11
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
12
|
+
acc[key] = {
|
|
13
|
+
fields: {
|
|
14
|
+
...acc[key]?.fields,
|
|
15
|
+
...value.fields,
|
|
16
|
+
},
|
|
17
|
+
modelName: value.modelName || key,
|
|
18
|
+
disableMigrations:
|
|
19
|
+
value.disableMigration ?? acc[key]?.disableMigrations,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return acc;
|
|
23
|
+
},
|
|
24
|
+
{} as Record<
|
|
25
|
+
string,
|
|
26
|
+
{
|
|
27
|
+
fields: Record<string, DBFieldAttribute>;
|
|
28
|
+
modelName: string;
|
|
29
|
+
disableMigrations?: boolean | undefined;
|
|
30
|
+
}
|
|
31
|
+
>,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const shouldAddRateLimitTable = options.rateLimit?.storage === "database";
|
|
35
|
+
const rateLimitTable = {
|
|
36
|
+
rateLimit: {
|
|
37
|
+
modelName: options.rateLimit?.modelName || "rateLimit",
|
|
38
|
+
fields: {
|
|
39
|
+
key: {
|
|
40
|
+
type: "string",
|
|
41
|
+
unique: true,
|
|
42
|
+
required: true,
|
|
43
|
+
fieldName: options.rateLimit?.fields?.key || "key",
|
|
44
|
+
},
|
|
45
|
+
count: {
|
|
46
|
+
type: "number",
|
|
47
|
+
required: true,
|
|
48
|
+
fieldName: options.rateLimit?.fields?.count || "count",
|
|
49
|
+
},
|
|
50
|
+
lastRequest: {
|
|
51
|
+
type: "number",
|
|
52
|
+
bigint: true,
|
|
53
|
+
required: true,
|
|
54
|
+
fieldName: options.rateLimit?.fields?.lastRequest || "lastRequest",
|
|
55
|
+
defaultValue: () => Date.now(),
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
} satisfies BetterAuthDBSchema;
|
|
60
|
+
|
|
61
|
+
const { user, session, account, verification, ...pluginTables } =
|
|
62
|
+
pluginSchema;
|
|
63
|
+
|
|
64
|
+
const verificationTable = {
|
|
65
|
+
verification: {
|
|
66
|
+
modelName: options.verification?.modelName || "verification",
|
|
67
|
+
fields: {
|
|
68
|
+
identifier: {
|
|
69
|
+
type: "string",
|
|
70
|
+
required: true,
|
|
71
|
+
fieldName: options.verification?.fields?.identifier || "identifier",
|
|
72
|
+
index: true,
|
|
73
|
+
},
|
|
74
|
+
value: {
|
|
75
|
+
type: "string",
|
|
76
|
+
required: true,
|
|
77
|
+
fieldName: options.verification?.fields?.value || "value",
|
|
78
|
+
},
|
|
79
|
+
expiresAt: {
|
|
80
|
+
type: "date",
|
|
81
|
+
required: true,
|
|
82
|
+
fieldName: options.verification?.fields?.expiresAt || "expiresAt",
|
|
83
|
+
},
|
|
84
|
+
createdAt: {
|
|
85
|
+
type: "date",
|
|
86
|
+
required: true,
|
|
87
|
+
defaultValue: () => new Date(),
|
|
88
|
+
fieldName: options.verification?.fields?.createdAt || "createdAt",
|
|
89
|
+
},
|
|
90
|
+
updatedAt: {
|
|
91
|
+
type: "date",
|
|
92
|
+
required: true,
|
|
93
|
+
defaultValue: () => new Date(),
|
|
94
|
+
onUpdate: () => new Date(),
|
|
95
|
+
fieldName: options.verification?.fields?.updatedAt || "updatedAt",
|
|
96
|
+
},
|
|
97
|
+
...verification?.fields,
|
|
98
|
+
...options.verification?.additionalFields,
|
|
99
|
+
},
|
|
100
|
+
order: 4,
|
|
101
|
+
},
|
|
102
|
+
} satisfies BetterAuthDBSchema;
|
|
103
|
+
|
|
104
|
+
const sessionTable = {
|
|
105
|
+
session: {
|
|
106
|
+
modelName: options.session?.modelName || "session",
|
|
107
|
+
fields: {
|
|
108
|
+
expiresAt: {
|
|
109
|
+
type: "date",
|
|
110
|
+
required: true,
|
|
111
|
+
fieldName: options.session?.fields?.expiresAt || "expiresAt",
|
|
112
|
+
},
|
|
113
|
+
token: {
|
|
114
|
+
type: "string",
|
|
115
|
+
required: true,
|
|
116
|
+
fieldName: options.session?.fields?.token || "token",
|
|
117
|
+
unique: true,
|
|
118
|
+
},
|
|
119
|
+
createdAt: {
|
|
120
|
+
type: "date",
|
|
121
|
+
required: true,
|
|
122
|
+
fieldName: options.session?.fields?.createdAt || "createdAt",
|
|
123
|
+
defaultValue: () => new Date(),
|
|
124
|
+
},
|
|
125
|
+
updatedAt: {
|
|
126
|
+
type: "date",
|
|
127
|
+
required: true,
|
|
128
|
+
fieldName: options.session?.fields?.updatedAt || "updatedAt",
|
|
129
|
+
onUpdate: () => new Date(),
|
|
130
|
+
},
|
|
131
|
+
ipAddress: {
|
|
132
|
+
type: "string",
|
|
133
|
+
required: false,
|
|
134
|
+
fieldName: options.session?.fields?.ipAddress || "ipAddress",
|
|
135
|
+
},
|
|
136
|
+
userAgent: {
|
|
137
|
+
type: "string",
|
|
138
|
+
required: false,
|
|
139
|
+
fieldName: options.session?.fields?.userAgent || "userAgent",
|
|
140
|
+
},
|
|
141
|
+
userId: {
|
|
142
|
+
type: "string",
|
|
143
|
+
fieldName: options.session?.fields?.userId || "userId",
|
|
144
|
+
references: {
|
|
145
|
+
model: options.user?.modelName || "user",
|
|
146
|
+
field: "id",
|
|
147
|
+
onDelete: "cascade",
|
|
148
|
+
},
|
|
149
|
+
required: true,
|
|
150
|
+
index: true,
|
|
151
|
+
},
|
|
152
|
+
...session?.fields,
|
|
153
|
+
...options.session?.additionalFields,
|
|
154
|
+
},
|
|
155
|
+
order: 2,
|
|
156
|
+
},
|
|
157
|
+
} satisfies BetterAuthDBSchema;
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
user: {
|
|
161
|
+
modelName: options.user?.modelName || "user",
|
|
162
|
+
fields: {
|
|
163
|
+
name: {
|
|
164
|
+
type: "string",
|
|
165
|
+
required: true,
|
|
166
|
+
fieldName: options.user?.fields?.name || "name",
|
|
167
|
+
sortable: true,
|
|
168
|
+
},
|
|
169
|
+
email: {
|
|
170
|
+
type: "string",
|
|
171
|
+
// TODO(#9124): drop required+unique in v2; use a partial unique
|
|
172
|
+
// index where email is not null (see schema/user.ts).
|
|
173
|
+
unique: true,
|
|
174
|
+
required: true,
|
|
175
|
+
fieldName: options.user?.fields?.email || "email",
|
|
176
|
+
sortable: true,
|
|
177
|
+
},
|
|
178
|
+
emailVerified: {
|
|
179
|
+
type: "boolean",
|
|
180
|
+
defaultValue: false,
|
|
181
|
+
required: true,
|
|
182
|
+
fieldName: options.user?.fields?.emailVerified || "emailVerified",
|
|
183
|
+
input: false,
|
|
184
|
+
},
|
|
185
|
+
image: {
|
|
186
|
+
type: "string",
|
|
187
|
+
required: false,
|
|
188
|
+
fieldName: options.user?.fields?.image || "image",
|
|
189
|
+
},
|
|
190
|
+
createdAt: {
|
|
191
|
+
type: "date",
|
|
192
|
+
defaultValue: () => new Date(),
|
|
193
|
+
required: true,
|
|
194
|
+
fieldName: options.user?.fields?.createdAt || "createdAt",
|
|
195
|
+
},
|
|
196
|
+
updatedAt: {
|
|
197
|
+
type: "date",
|
|
198
|
+
defaultValue: () => new Date(),
|
|
199
|
+
onUpdate: () => new Date(),
|
|
200
|
+
required: true,
|
|
201
|
+
fieldName: options.user?.fields?.updatedAt || "updatedAt",
|
|
202
|
+
},
|
|
203
|
+
...user?.fields,
|
|
204
|
+
...options.user?.additionalFields,
|
|
205
|
+
},
|
|
206
|
+
order: 1,
|
|
207
|
+
},
|
|
208
|
+
//only add session table if it's not stored in secondary storage
|
|
209
|
+
...(!options.secondaryStorage || options.session?.storeSessionInDatabase
|
|
210
|
+
? sessionTable
|
|
211
|
+
: {}),
|
|
212
|
+
account: {
|
|
213
|
+
modelName: options.account?.modelName || "account",
|
|
214
|
+
fields: {
|
|
215
|
+
accountId: {
|
|
216
|
+
type: "string",
|
|
217
|
+
required: true,
|
|
218
|
+
fieldName: options.account?.fields?.accountId || "accountId",
|
|
219
|
+
},
|
|
220
|
+
providerId: {
|
|
221
|
+
type: "string",
|
|
222
|
+
required: true,
|
|
223
|
+
fieldName: options.account?.fields?.providerId || "providerId",
|
|
224
|
+
},
|
|
225
|
+
userId: {
|
|
226
|
+
type: "string",
|
|
227
|
+
references: {
|
|
228
|
+
model: options.user?.modelName || "user",
|
|
229
|
+
field: "id",
|
|
230
|
+
onDelete: "cascade",
|
|
231
|
+
},
|
|
232
|
+
required: true,
|
|
233
|
+
fieldName: options.account?.fields?.userId || "userId",
|
|
234
|
+
index: true,
|
|
235
|
+
},
|
|
236
|
+
accessToken: {
|
|
237
|
+
type: "string",
|
|
238
|
+
required: false,
|
|
239
|
+
returned: false,
|
|
240
|
+
fieldName: options.account?.fields?.accessToken || "accessToken",
|
|
241
|
+
},
|
|
242
|
+
refreshToken: {
|
|
243
|
+
type: "string",
|
|
244
|
+
required: false,
|
|
245
|
+
returned: false,
|
|
246
|
+
fieldName: options.account?.fields?.refreshToken || "refreshToken",
|
|
247
|
+
},
|
|
248
|
+
idToken: {
|
|
249
|
+
type: "string",
|
|
250
|
+
required: false,
|
|
251
|
+
returned: false,
|
|
252
|
+
fieldName: options.account?.fields?.idToken || "idToken",
|
|
253
|
+
},
|
|
254
|
+
accessTokenExpiresAt: {
|
|
255
|
+
type: "date",
|
|
256
|
+
required: false,
|
|
257
|
+
returned: false,
|
|
258
|
+
fieldName:
|
|
259
|
+
options.account?.fields?.accessTokenExpiresAt ||
|
|
260
|
+
"accessTokenExpiresAt",
|
|
261
|
+
},
|
|
262
|
+
refreshTokenExpiresAt: {
|
|
263
|
+
type: "date",
|
|
264
|
+
required: false,
|
|
265
|
+
returned: false,
|
|
266
|
+
fieldName:
|
|
267
|
+
options.account?.fields?.refreshTokenExpiresAt ||
|
|
268
|
+
"refreshTokenExpiresAt",
|
|
269
|
+
},
|
|
270
|
+
scope: {
|
|
271
|
+
type: "string",
|
|
272
|
+
required: false,
|
|
273
|
+
fieldName: options.account?.fields?.scope || "scope",
|
|
274
|
+
},
|
|
275
|
+
password: {
|
|
276
|
+
type: "string",
|
|
277
|
+
required: false,
|
|
278
|
+
returned: false,
|
|
279
|
+
fieldName: options.account?.fields?.password || "password",
|
|
280
|
+
},
|
|
281
|
+
createdAt: {
|
|
282
|
+
type: "date",
|
|
283
|
+
required: true,
|
|
284
|
+
fieldName: options.account?.fields?.createdAt || "createdAt",
|
|
285
|
+
defaultValue: () => new Date(),
|
|
286
|
+
},
|
|
287
|
+
updatedAt: {
|
|
288
|
+
type: "date",
|
|
289
|
+
required: true,
|
|
290
|
+
fieldName: options.account?.fields?.updatedAt || "updatedAt",
|
|
291
|
+
onUpdate: () => new Date(),
|
|
292
|
+
},
|
|
293
|
+
...account?.fields,
|
|
294
|
+
...options.account?.additionalFields,
|
|
295
|
+
},
|
|
296
|
+
order: 3,
|
|
297
|
+
},
|
|
298
|
+
...(!options.secondaryStorage || options.verification?.storeInDatabase
|
|
299
|
+
? verificationTable
|
|
300
|
+
: {}),
|
|
301
|
+
...pluginTables,
|
|
302
|
+
...(shouldAddRateLimitTable ? rateLimitTable : {}),
|
|
303
|
+
} satisfies BetterAuthDBSchema;
|
|
304
|
+
};
|
package/src/db/index.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export { getAuthTables } from "./get-tables";
|
|
2
|
+
export type { BetterAuthPluginDBSchema } from "./plugin";
|
|
3
|
+
export {
|
|
4
|
+
type Account,
|
|
5
|
+
accountSchema,
|
|
6
|
+
type BaseAccount,
|
|
7
|
+
} from "./schema/account";
|
|
8
|
+
export {
|
|
9
|
+
type BaseRateLimit,
|
|
10
|
+
type RateLimit,
|
|
11
|
+
rateLimitSchema,
|
|
12
|
+
} from "./schema/rate-limit";
|
|
13
|
+
export {
|
|
14
|
+
type BaseSession,
|
|
15
|
+
type Session,
|
|
16
|
+
sessionSchema,
|
|
17
|
+
} from "./schema/session";
|
|
18
|
+
export { coreSchema } from "./schema/shared";
|
|
19
|
+
export { type BaseUser, type User, userSchema } from "./schema/user";
|
|
20
|
+
export {
|
|
21
|
+
type BaseVerification,
|
|
22
|
+
type Verification,
|
|
23
|
+
verificationSchema,
|
|
24
|
+
} from "./schema/verification";
|
|
25
|
+
export type {
|
|
26
|
+
BaseModelNames,
|
|
27
|
+
BetterAuthDBSchema,
|
|
28
|
+
DBFieldAttribute,
|
|
29
|
+
DBFieldAttributeConfig,
|
|
30
|
+
DBFieldType,
|
|
31
|
+
DBPrimitive,
|
|
32
|
+
InferDBFieldInput,
|
|
33
|
+
InferDBFieldOutput,
|
|
34
|
+
InferDBFieldsFromOptions,
|
|
35
|
+
InferDBFieldsFromOptionsInput,
|
|
36
|
+
InferDBFieldsFromPlugins,
|
|
37
|
+
InferDBFieldsFromPluginsInput,
|
|
38
|
+
InferDBFieldsInput,
|
|
39
|
+
InferDBFieldsOutput,
|
|
40
|
+
InferDBValueType,
|
|
41
|
+
ModelNames,
|
|
42
|
+
SecondaryStorage,
|
|
43
|
+
} from "./type";
|
package/src/db/plugin.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { Prettify } from "../../types";
|
|
3
|
+
import type { BetterAuthOptions } from "../../types/init-options";
|
|
4
|
+
import type {
|
|
5
|
+
InferDBFieldsFromOptions,
|
|
6
|
+
InferDBFieldsFromPlugins,
|
|
7
|
+
} from "../type";
|
|
8
|
+
import { coreSchema } from "./shared";
|
|
9
|
+
|
|
10
|
+
export const accountSchema = coreSchema.extend({
|
|
11
|
+
providerId: z.string(),
|
|
12
|
+
accountId: z.string(),
|
|
13
|
+
userId: z.coerce.string(),
|
|
14
|
+
accessToken: z.string().nullish(),
|
|
15
|
+
refreshToken: z.string().nullish(),
|
|
16
|
+
idToken: z.string().nullish(),
|
|
17
|
+
/**
|
|
18
|
+
* Access token expires at
|
|
19
|
+
*/
|
|
20
|
+
accessTokenExpiresAt: z.date().nullish(),
|
|
21
|
+
/**
|
|
22
|
+
* Refresh token expires at
|
|
23
|
+
*/
|
|
24
|
+
refreshTokenExpiresAt: z.date().nullish(),
|
|
25
|
+
/**
|
|
26
|
+
* The scopes that the user has authorized
|
|
27
|
+
*/
|
|
28
|
+
scope: z.string().nullish(),
|
|
29
|
+
/**
|
|
30
|
+
* Password is only stored in the credential provider
|
|
31
|
+
*/
|
|
32
|
+
password: z.string().nullish(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export type BaseAccount = z.infer<typeof accountSchema>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Account schema type used by better-auth, note that it's possible that account could have additional fields
|
|
39
|
+
*/
|
|
40
|
+
export type Account<
|
|
41
|
+
DBOptions extends BetterAuthOptions["account"] = BetterAuthOptions["account"],
|
|
42
|
+
Plugins extends BetterAuthOptions["plugins"] = BetterAuthOptions["plugins"],
|
|
43
|
+
> = Prettify<
|
|
44
|
+
BaseAccount &
|
|
45
|
+
InferDBFieldsFromOptions<DBOptions> &
|
|
46
|
+
InferDBFieldsFromPlugins<"account", Plugins>
|
|
47
|
+
>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { BetterAuthOptions, Prettify } from "../../types";
|
|
3
|
+
import type {
|
|
4
|
+
InferDBFieldsFromOptions,
|
|
5
|
+
InferDBFieldsFromPlugins,
|
|
6
|
+
} from "../type";
|
|
7
|
+
|
|
8
|
+
export const rateLimitSchema = z.object({
|
|
9
|
+
/**
|
|
10
|
+
* The key to use for rate limiting
|
|
11
|
+
*/
|
|
12
|
+
key: z.string(),
|
|
13
|
+
/**
|
|
14
|
+
* The number of requests made
|
|
15
|
+
*/
|
|
16
|
+
count: z.number(),
|
|
17
|
+
/**
|
|
18
|
+
* The last request time in milliseconds
|
|
19
|
+
*/
|
|
20
|
+
lastRequest: z.number(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export type BaseRateLimit = z.infer<typeof rateLimitSchema>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Rate limit schema type used by better-auth for rate limiting
|
|
27
|
+
*/
|
|
28
|
+
export type RateLimit<
|
|
29
|
+
DBOptions extends
|
|
30
|
+
BetterAuthOptions["rateLimit"] = BetterAuthOptions["rateLimit"],
|
|
31
|
+
Plugins extends BetterAuthOptions["plugins"] = BetterAuthOptions["plugins"],
|
|
32
|
+
> = Prettify<
|
|
33
|
+
BaseRateLimit &
|
|
34
|
+
InferDBFieldsFromOptions<DBOptions> &
|
|
35
|
+
InferDBFieldsFromPlugins<"rateLimit", Plugins>
|
|
36
|
+
>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { BetterAuthOptions, Prettify } from "../../types";
|
|
3
|
+
import type {
|
|
4
|
+
InferDBFieldsFromOptions,
|
|
5
|
+
InferDBFieldsFromPlugins,
|
|
6
|
+
} from "../type";
|
|
7
|
+
import { coreSchema } from "./shared";
|
|
8
|
+
|
|
9
|
+
export const sessionSchema = coreSchema.extend({
|
|
10
|
+
userId: z.coerce.string(),
|
|
11
|
+
expiresAt: z.date(),
|
|
12
|
+
token: z.string(),
|
|
13
|
+
ipAddress: z.string().nullish(),
|
|
14
|
+
userAgent: z.string().nullish(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export type BaseSession = z.infer<typeof sessionSchema>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Session schema type used by better-auth, note that it's possible that session could have additional fields
|
|
21
|
+
*/
|
|
22
|
+
export type Session<
|
|
23
|
+
DBOptions extends BetterAuthOptions["session"] = BetterAuthOptions["session"],
|
|
24
|
+
Plugins extends BetterAuthOptions["plugins"] = BetterAuthOptions["plugins"],
|
|
25
|
+
> = Prettify<
|
|
26
|
+
z.infer<typeof sessionSchema> &
|
|
27
|
+
InferDBFieldsFromOptions<DBOptions> &
|
|
28
|
+
InferDBFieldsFromPlugins<"session", Plugins>
|
|
29
|
+
>;
|