@better-auth/core 1.4.12-beta.2 → 1.4.13

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.
Files changed (185) hide show
  1. package/.turbo/turbo-build.log +172 -35
  2. package/dist/api/index.d.mts +178 -1
  3. package/dist/api/index.mjs +2 -1
  4. package/dist/context/endpoint-context.d.mts +19 -0
  5. package/dist/context/endpoint-context.mjs +31 -0
  6. package/dist/context/global.d.mts +7 -0
  7. package/dist/context/global.mjs +37 -0
  8. package/dist/context/index.d.mts +5 -53
  9. package/dist/context/index.mjs +5 -2
  10. package/dist/context/request-state.d.mts +27 -0
  11. package/dist/context/request-state.mjs +49 -0
  12. package/dist/context/transaction.d.mts +16 -0
  13. package/dist/context/transaction.mjs +52 -0
  14. package/dist/db/adapter/factory.d.mts +27 -0
  15. package/dist/db/adapter/factory.mjs +738 -0
  16. package/dist/db/adapter/get-default-field-name.d.mts +18 -0
  17. package/dist/db/adapter/get-default-field-name.mjs +38 -0
  18. package/dist/db/adapter/get-default-model-name.d.mts +12 -0
  19. package/dist/db/adapter/get-default-model-name.mjs +32 -0
  20. package/dist/db/adapter/get-field-attributes.d.mts +29 -0
  21. package/dist/db/adapter/get-field-attributes.mjs +39 -0
  22. package/dist/db/adapter/get-field-name.d.mts +18 -0
  23. package/dist/db/adapter/get-field-name.mjs +33 -0
  24. package/dist/db/adapter/get-id-field.d.mts +39 -0
  25. package/dist/db/adapter/get-id-field.mjs +68 -0
  26. package/dist/db/adapter/get-model-name.d.mts +12 -0
  27. package/dist/db/adapter/get-model-name.mjs +23 -0
  28. package/dist/db/adapter/index.d.mts +513 -1
  29. package/dist/db/adapter/index.mjs +8 -970
  30. package/dist/db/adapter/types.d.mts +139 -0
  31. package/dist/db/adapter/utils.d.mts +7 -0
  32. package/dist/db/adapter/utils.mjs +38 -0
  33. package/dist/db/get-tables.d.mts +8 -0
  34. package/dist/{get-tables-CMc_Emww.mjs → db/get-tables.mjs} +1 -1
  35. package/dist/db/index.d.mts +10 -2
  36. package/dist/db/index.mjs +7 -60
  37. package/dist/db/plugin.d.mts +12 -0
  38. package/dist/db/schema/account.d.mts +26 -0
  39. package/dist/db/schema/account.mjs +19 -0
  40. package/dist/db/schema/rate-limit.d.mts +14 -0
  41. package/dist/db/schema/rate-limit.mjs +11 -0
  42. package/dist/db/schema/session.d.mts +21 -0
  43. package/dist/db/schema/session.mjs +14 -0
  44. package/dist/db/schema/shared.d.mts +10 -0
  45. package/dist/db/schema/shared.mjs +11 -0
  46. package/dist/db/schema/user.d.mts +20 -0
  47. package/dist/db/schema/user.mjs +13 -0
  48. package/dist/db/schema/verification.d.mts +19 -0
  49. package/dist/db/schema/verification.mjs +12 -0
  50. package/dist/db/type.d.mts +143 -0
  51. package/dist/env/color-depth.d.mts +4 -0
  52. package/dist/env/color-depth.mjs +88 -0
  53. package/dist/env/env-impl.d.mts +32 -0
  54. package/dist/env/env-impl.mjs +82 -0
  55. package/dist/env/index.d.mts +4 -2
  56. package/dist/env/index.mjs +3 -1
  57. package/dist/{index-BRBu0-5h.d.mts → env/logger.d.mts} +1 -35
  58. package/dist/env/logger.mjs +81 -0
  59. package/dist/error/codes.d.mts +48 -0
  60. package/dist/{error-DP1xOn7P.mjs → error/codes.mjs} +3 -14
  61. package/dist/error/index.d.mts +5 -48
  62. package/dist/error/index.mjs +12 -3
  63. package/dist/index.d.mts +8 -2
  64. package/dist/oauth2/client-credentials-token.d.mts +36 -0
  65. package/dist/oauth2/client-credentials-token.mjs +54 -0
  66. package/dist/oauth2/create-authorization-url.d.mts +45 -0
  67. package/dist/oauth2/create-authorization-url.mjs +42 -0
  68. package/dist/oauth2/index.d.mts +8 -2
  69. package/dist/oauth2/index.mjs +6 -2
  70. package/dist/oauth2/oauth-provider.d.mts +194 -0
  71. package/dist/oauth2/refresh-access-token.d.mts +36 -0
  72. package/dist/oauth2/refresh-access-token.mjs +58 -0
  73. package/dist/oauth2/utils.d.mts +7 -0
  74. package/dist/oauth2/utils.mjs +27 -0
  75. package/dist/oauth2/validate-authorization-code.d.mts +55 -0
  76. package/dist/oauth2/validate-authorization-code.mjs +71 -0
  77. package/dist/oauth2/verify.d.mts +49 -0
  78. package/dist/oauth2/verify.mjs +95 -0
  79. package/dist/social-providers/apple.d.mts +119 -0
  80. package/dist/social-providers/apple.mjs +102 -0
  81. package/dist/social-providers/atlassian.d.mts +72 -0
  82. package/dist/social-providers/atlassian.mjs +83 -0
  83. package/dist/social-providers/cognito.d.mts +87 -0
  84. package/dist/social-providers/cognito.mjs +166 -0
  85. package/dist/social-providers/discord.d.mts +126 -0
  86. package/dist/social-providers/discord.mjs +64 -0
  87. package/dist/social-providers/dropbox.d.mts +71 -0
  88. package/dist/social-providers/dropbox.mjs +75 -0
  89. package/dist/social-providers/facebook.d.mts +81 -0
  90. package/dist/social-providers/facebook.mjs +120 -0
  91. package/dist/social-providers/figma.d.mts +63 -0
  92. package/dist/social-providers/figma.mjs +84 -0
  93. package/dist/social-providers/github.d.mts +104 -0
  94. package/dist/social-providers/github.mjs +80 -0
  95. package/dist/social-providers/gitlab.d.mts +125 -0
  96. package/dist/social-providers/gitlab.mjs +82 -0
  97. package/dist/social-providers/google.d.mts +99 -0
  98. package/dist/social-providers/google.mjs +109 -0
  99. package/dist/social-providers/huggingface.d.mts +85 -0
  100. package/dist/social-providers/huggingface.mjs +75 -0
  101. package/dist/social-providers/index.d.mts +1723 -1
  102. package/dist/social-providers/index.mjs +33 -2570
  103. package/dist/social-providers/kakao.d.mts +163 -0
  104. package/dist/social-providers/kakao.mjs +72 -0
  105. package/dist/social-providers/kick.d.mts +75 -0
  106. package/dist/social-providers/kick.mjs +71 -0
  107. package/dist/social-providers/line.d.mts +107 -0
  108. package/dist/social-providers/line.mjs +113 -0
  109. package/dist/social-providers/linear.d.mts +70 -0
  110. package/dist/social-providers/linear.mjs +88 -0
  111. package/dist/social-providers/linkedin.d.mts +69 -0
  112. package/dist/social-providers/linkedin.mjs +76 -0
  113. package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
  114. package/dist/social-providers/microsoft-entra-id.mjs +106 -0
  115. package/dist/social-providers/naver.d.mts +104 -0
  116. package/dist/social-providers/naver.mjs +67 -0
  117. package/dist/social-providers/notion.d.mts +66 -0
  118. package/dist/social-providers/notion.mjs +75 -0
  119. package/dist/social-providers/paybin.d.mts +73 -0
  120. package/dist/social-providers/paybin.mjs +85 -0
  121. package/dist/social-providers/paypal.d.mts +131 -0
  122. package/dist/social-providers/paypal.mjs +144 -0
  123. package/dist/social-providers/polar.d.mts +76 -0
  124. package/dist/social-providers/polar.mjs +73 -0
  125. package/dist/social-providers/reddit.d.mts +64 -0
  126. package/dist/social-providers/reddit.mjs +83 -0
  127. package/dist/social-providers/roblox.d.mts +72 -0
  128. package/dist/social-providers/roblox.mjs +59 -0
  129. package/dist/social-providers/salesforce.d.mts +81 -0
  130. package/dist/social-providers/salesforce.mjs +91 -0
  131. package/dist/social-providers/slack.d.mts +85 -0
  132. package/dist/social-providers/slack.mjs +68 -0
  133. package/dist/social-providers/spotify.d.mts +65 -0
  134. package/dist/social-providers/spotify.mjs +71 -0
  135. package/dist/social-providers/tiktok.d.mts +171 -0
  136. package/dist/social-providers/tiktok.mjs +62 -0
  137. package/dist/social-providers/twitch.d.mts +81 -0
  138. package/dist/social-providers/twitch.mjs +78 -0
  139. package/dist/social-providers/twitter.d.mts +140 -0
  140. package/dist/social-providers/twitter.mjs +87 -0
  141. package/dist/social-providers/vercel.d.mts +64 -0
  142. package/dist/social-providers/vercel.mjs +61 -0
  143. package/dist/social-providers/vk.d.mts +72 -0
  144. package/dist/social-providers/vk.mjs +83 -0
  145. package/dist/social-providers/zoom.d.mts +173 -0
  146. package/dist/social-providers/zoom.mjs +72 -0
  147. package/dist/types/context.d.mts +215 -0
  148. package/dist/types/cookie.d.mts +15 -0
  149. package/dist/types/helper.d.mts +8 -0
  150. package/dist/types/index.d.mts +8 -0
  151. package/dist/types/init-options.d.mts +1266 -0
  152. package/dist/types/plugin-client.d.mts +103 -0
  153. package/dist/types/plugin.d.mts +121 -0
  154. package/dist/utils/deprecate.d.mts +10 -0
  155. package/dist/utils/deprecate.mjs +17 -0
  156. package/dist/utils/error-codes.d.mts +9 -0
  157. package/dist/utils/error-codes.mjs +7 -0
  158. package/dist/utils/id.d.mts +4 -0
  159. package/dist/utils/id.mjs +9 -0
  160. package/dist/utils/index.d.mts +5 -26
  161. package/dist/utils/index.mjs +5 -2
  162. package/dist/utils/json.d.mts +4 -0
  163. package/dist/utils/json.mjs +25 -0
  164. package/dist/utils/string.d.mts +4 -0
  165. package/dist/utils/string.mjs +7 -0
  166. package/package.json +1 -1
  167. package/src/context/endpoint-context.ts +7 -15
  168. package/src/context/global.ts +57 -0
  169. package/src/context/index.ts +1 -0
  170. package/src/context/request-state.ts +7 -12
  171. package/src/context/transaction.ts +7 -16
  172. package/src/db/adapter/factory.ts +13 -13
  173. package/src/db/adapter/get-default-model-name.ts +1 -1
  174. package/src/db/adapter/get-id-field.ts +2 -2
  175. package/src/error/index.ts +2 -3
  176. package/src/social-providers/gitlab.ts +1 -1
  177. package/src/types/context.ts +137 -131
  178. package/src/types/cookie.ts +6 -4
  179. package/src/types/index.ts +2 -1
  180. package/tsdown.config.ts +9 -0
  181. package/dist/context-BGZ8V6DD.mjs +0 -126
  182. package/dist/env-DbssmzoK.mjs +0 -245
  183. package/dist/index-zgYuzZ7O.d.mts +0 -8020
  184. package/dist/oauth2-COJkghlT.mjs +0 -326
  185. package/dist/utils-U2L7n92V.mjs +0 -59
@@ -0,0 +1,738 @@
1
+ import { getAuthTables } from "../get-tables.mjs";
2
+ import { getColorDepth } from "../../env/color-depth.mjs";
3
+ import { TTY_COLORS, createLogger } from "../../env/logger.mjs";
4
+ import "../../env/index.mjs";
5
+ import { safeJSONParse } from "../../utils/json.mjs";
6
+ import { BetterAuthError } from "../../error/index.mjs";
7
+ import { initGetDefaultModelName } from "./get-default-model-name.mjs";
8
+ import { initGetDefaultFieldName } from "./get-default-field-name.mjs";
9
+ import { initGetIdField } from "./get-id-field.mjs";
10
+ import { initGetFieldAttributes } from "./get-field-attributes.mjs";
11
+ import { initGetFieldName } from "./get-field-name.mjs";
12
+ import { initGetModelName } from "./get-model-name.mjs";
13
+ import { withApplyDefault } from "./utils.mjs";
14
+
15
+ //#region src/db/adapter/factory.ts
16
+ let debugLogs = [];
17
+ let transactionId = -1;
18
+ const createAsIsTransaction = (adapter) => (fn) => fn(adapter);
19
+ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (options) => {
20
+ const uniqueAdapterFactoryInstanceId = Math.random().toString(36).substring(2, 15);
21
+ const config = {
22
+ ...cfg,
23
+ supportsBooleans: cfg.supportsBooleans ?? true,
24
+ supportsDates: cfg.supportsDates ?? true,
25
+ supportsJSON: cfg.supportsJSON ?? false,
26
+ adapterName: cfg.adapterName ?? cfg.adapterId,
27
+ supportsNumericIds: cfg.supportsNumericIds ?? true,
28
+ supportsUUIDs: cfg.supportsUUIDs ?? false,
29
+ supportsArrays: cfg.supportsArrays ?? false,
30
+ transaction: cfg.transaction ?? false,
31
+ disableTransformInput: cfg.disableTransformInput ?? false,
32
+ disableTransformOutput: cfg.disableTransformOutput ?? false,
33
+ disableTransformJoin: cfg.disableTransformJoin ?? false
34
+ };
35
+ if ((options.advanced?.database?.useNumberId === true || options.advanced?.database?.generateId === "serial") && config.supportsNumericIds === false) throw new BetterAuthError(`[${config.adapterName}] Your database or database adapter does not support numeric ids. Please disable "useNumberId" in your config.`);
36
+ const schema = getAuthTables(options);
37
+ const debugLog = (...args) => {
38
+ if (config.debugLogs === true || typeof config.debugLogs === "object") {
39
+ const logger$1 = createLogger({ level: "info" });
40
+ if (typeof config.debugLogs === "object" && "isRunningAdapterTests" in config.debugLogs) {
41
+ if (config.debugLogs.isRunningAdapterTests) {
42
+ args.shift();
43
+ debugLogs.push({
44
+ instance: uniqueAdapterFactoryInstanceId,
45
+ args
46
+ });
47
+ }
48
+ return;
49
+ }
50
+ if (typeof config.debugLogs === "object" && config.debugLogs.logCondition && !config.debugLogs.logCondition?.()) return;
51
+ if (typeof args[0] === "object" && "method" in args[0]) {
52
+ const method = args.shift().method;
53
+ if (typeof config.debugLogs === "object") {
54
+ if (method === "create" && !config.debugLogs.create) return;
55
+ else if (method === "update" && !config.debugLogs.update) return;
56
+ else if (method === "updateMany" && !config.debugLogs.updateMany) return;
57
+ else if (method === "findOne" && !config.debugLogs.findOne) return;
58
+ else if (method === "findMany" && !config.debugLogs.findMany) return;
59
+ else if (method === "delete" && !config.debugLogs.delete) return;
60
+ else if (method === "deleteMany" && !config.debugLogs.deleteMany) return;
61
+ else if (method === "count" && !config.debugLogs.count) return;
62
+ }
63
+ logger$1.info(`[${config.adapterName}]`, ...args);
64
+ } else logger$1.info(`[${config.adapterName}]`, ...args);
65
+ }
66
+ };
67
+ const logger = createLogger(options.logger);
68
+ const getDefaultModelName = initGetDefaultModelName({
69
+ usePlural: config.usePlural,
70
+ schema
71
+ });
72
+ const getDefaultFieldName = initGetDefaultFieldName({
73
+ usePlural: config.usePlural,
74
+ schema
75
+ });
76
+ const getModelName = initGetModelName({
77
+ usePlural: config.usePlural,
78
+ schema
79
+ });
80
+ const getFieldName = initGetFieldName({
81
+ schema,
82
+ usePlural: config.usePlural
83
+ });
84
+ const idField = initGetIdField({
85
+ schema,
86
+ options,
87
+ usePlural: config.usePlural,
88
+ disableIdGeneration: config.disableIdGeneration,
89
+ customIdGenerator: config.customIdGenerator,
90
+ supportsUUIDs: config.supportsUUIDs
91
+ });
92
+ const getFieldAttributes = initGetFieldAttributes({
93
+ schema,
94
+ options,
95
+ usePlural: config.usePlural,
96
+ disableIdGeneration: config.disableIdGeneration,
97
+ customIdGenerator: config.customIdGenerator
98
+ });
99
+ const transformInput = async (data, defaultModelName, action, forceAllowId) => {
100
+ const transformedData = {};
101
+ const fields = schema[defaultModelName].fields;
102
+ const newMappedKeys = config.mapKeysTransformInput ?? {};
103
+ const useNumberId = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
104
+ fields.id = idField({
105
+ customModelName: defaultModelName,
106
+ forceAllowId: forceAllowId && "id" in data
107
+ });
108
+ for (const field in fields) {
109
+ let value = data[field];
110
+ const fieldAttributes = fields[field];
111
+ const newFieldName = newMappedKeys[field] || fields[field].fieldName || field;
112
+ if (value === void 0 && (fieldAttributes.defaultValue === void 0 && !fieldAttributes.transform?.input && !(action === "update" && fieldAttributes.onUpdate) || action === "update" && !fieldAttributes.onUpdate)) continue;
113
+ if (fieldAttributes && fieldAttributes.type === "date" && !(value instanceof Date) && typeof value === "string") try {
114
+ value = new Date(value);
115
+ } catch {
116
+ logger.error("[Adapter Factory] Failed to convert string to date", {
117
+ value,
118
+ field
119
+ });
120
+ }
121
+ let newValue = withApplyDefault(value, fieldAttributes, action);
122
+ if (fieldAttributes.transform?.input) newValue = await fieldAttributes.transform.input(newValue);
123
+ if (fieldAttributes.references?.field === "id" && useNumberId) if (Array.isArray(newValue)) newValue = newValue.map((x) => x !== null ? Number(x) : null);
124
+ else newValue = newValue !== null ? Number(newValue) : null;
125
+ else if (config.supportsJSON === false && typeof newValue === "object" && fieldAttributes.type === "json") newValue = JSON.stringify(newValue);
126
+ else if (config.supportsArrays === false && Array.isArray(newValue) && (fieldAttributes.type === "string[]" || fieldAttributes.type === "number[]")) newValue = JSON.stringify(newValue);
127
+ else if (config.supportsDates === false && newValue instanceof Date && fieldAttributes.type === "date") newValue = newValue.toISOString();
128
+ else if (config.supportsBooleans === false && typeof newValue === "boolean") newValue = newValue ? 1 : 0;
129
+ if (config.customTransformInput) newValue = config.customTransformInput({
130
+ data: newValue,
131
+ action,
132
+ field: newFieldName,
133
+ fieldAttributes,
134
+ model: getModelName(defaultModelName),
135
+ schema,
136
+ options
137
+ });
138
+ if (newValue !== void 0) transformedData[newFieldName] = newValue;
139
+ }
140
+ return transformedData;
141
+ };
142
+ const transformOutput = async (data, unsafe_model, select = [], join) => {
143
+ const transformSingleOutput = async (data$1, unsafe_model$1, select$1 = []) => {
144
+ if (!data$1) return null;
145
+ const newMappedKeys = config.mapKeysTransformOutput ?? {};
146
+ const transformedData$1 = {};
147
+ const tableSchema = schema[getDefaultModelName(unsafe_model$1)].fields;
148
+ const idKey = Object.entries(newMappedKeys).find(([_, v]) => v === "id")?.[0];
149
+ tableSchema[idKey ?? "id"] = { type: options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial" ? "number" : "string" };
150
+ for (const key in tableSchema) {
151
+ if (select$1.length && !select$1.includes(key)) continue;
152
+ const field = tableSchema[key];
153
+ if (field) {
154
+ const originalKey = field.fieldName || key;
155
+ let newValue = data$1[Object.entries(newMappedKeys).find(([_, v]) => v === originalKey)?.[0] || originalKey];
156
+ if (field.transform?.output) newValue = await field.transform.output(newValue);
157
+ const newFieldName = newMappedKeys[key] || key;
158
+ if (originalKey === "id" || field.references?.field === "id") {
159
+ if (typeof newValue !== "undefined" && newValue !== null) newValue = String(newValue);
160
+ } else if (config.supportsJSON === false && typeof newValue === "string" && field.type === "json") newValue = safeJSONParse(newValue);
161
+ else if (config.supportsArrays === false && typeof newValue === "string" && (field.type === "string[]" || field.type === "number[]")) newValue = safeJSONParse(newValue);
162
+ else if (config.supportsDates === false && typeof newValue === "string" && field.type === "date") newValue = new Date(newValue);
163
+ else if (config.supportsBooleans === false && typeof newValue === "number" && field.type === "boolean") newValue = newValue === 1;
164
+ if (config.customTransformOutput) newValue = config.customTransformOutput({
165
+ data: newValue,
166
+ field: newFieldName,
167
+ fieldAttributes: field,
168
+ select: select$1,
169
+ model: getModelName(unsafe_model$1),
170
+ schema,
171
+ options
172
+ });
173
+ transformedData$1[newFieldName] = newValue;
174
+ }
175
+ }
176
+ return transformedData$1;
177
+ };
178
+ if (!join || Object.keys(join).length === 0) return await transformSingleOutput(data, unsafe_model, select);
179
+ unsafe_model = getDefaultModelName(unsafe_model);
180
+ const transformedData = await transformSingleOutput(data, unsafe_model, select);
181
+ const requiredModels = Object.entries(join).map(([model, joinConfig]) => ({
182
+ modelName: getModelName(model),
183
+ defaultModelName: getDefaultModelName(model),
184
+ joinConfig
185
+ }));
186
+ if (!data) return null;
187
+ for (const { modelName, defaultModelName, joinConfig } of requiredModels) {
188
+ let joinedData = await (async () => {
189
+ if (options.experimental?.joins) return data[modelName];
190
+ else return await handleFallbackJoin({
191
+ baseModel: unsafe_model,
192
+ baseData: transformedData,
193
+ joinModel: modelName,
194
+ specificJoinConfig: joinConfig
195
+ });
196
+ })();
197
+ if (joinedData === void 0 || joinedData === null) joinedData = joinConfig.relation === "one-to-one" ? null : [];
198
+ if (joinConfig.relation === "one-to-many" && !Array.isArray(joinedData)) joinedData = [joinedData];
199
+ const transformed = [];
200
+ if (Array.isArray(joinedData)) for (const item of joinedData) {
201
+ const transformedItem = await transformSingleOutput(item, modelName, []);
202
+ transformed.push(transformedItem);
203
+ }
204
+ else {
205
+ const transformedItem = await transformSingleOutput(joinedData, modelName, []);
206
+ transformed.push(transformedItem);
207
+ }
208
+ transformedData[defaultModelName] = (joinConfig.relation === "one-to-one" ? transformed[0] : transformed) ?? null;
209
+ }
210
+ return transformedData;
211
+ };
212
+ const transformWhereClause = ({ model, where, action }) => {
213
+ if (!where) return void 0;
214
+ const newMappedKeys = config.mapKeysTransformInput ?? {};
215
+ return where.map((w) => {
216
+ const { field: unsafe_field, value, operator = "eq", connector = "AND" } = w;
217
+ if (operator === "in") {
218
+ if (!Array.isArray(value)) throw new BetterAuthError("Value must be an array");
219
+ }
220
+ let newValue = value;
221
+ const defaultModelName = getDefaultModelName(model);
222
+ const defaultFieldName = getDefaultFieldName({
223
+ field: unsafe_field,
224
+ model
225
+ });
226
+ const fieldName = newMappedKeys[defaultFieldName] || getFieldName({
227
+ field: defaultFieldName,
228
+ model: defaultModelName
229
+ });
230
+ const fieldAttr = getFieldAttributes({
231
+ field: defaultFieldName,
232
+ model: defaultModelName
233
+ });
234
+ const useNumberId = options.advanced?.database?.useNumberId || options.advanced?.database?.generateId === "serial";
235
+ if (defaultFieldName === "id" || fieldAttr.references?.field === "id") {
236
+ if (useNumberId) if (Array.isArray(value)) newValue = value.map(Number);
237
+ else newValue = Number(value);
238
+ }
239
+ if (fieldAttr.type === "date" && value instanceof Date && !config.supportsDates) newValue = value.toISOString();
240
+ if (fieldAttr.type === "boolean" && typeof value === "boolean" && !config.supportsBooleans) newValue = value ? 1 : 0;
241
+ if (fieldAttr.type === "json" && typeof value === "object" && !config.supportsJSON) try {
242
+ newValue = JSON.stringify(value);
243
+ } catch (error) {
244
+ throw new Error(`Failed to stringify JSON value for field ${fieldName}`, { cause: error });
245
+ }
246
+ if (config.customTransformInput) newValue = config.customTransformInput({
247
+ data: newValue,
248
+ fieldAttributes: fieldAttr,
249
+ field: fieldName,
250
+ model: getModelName(model),
251
+ schema,
252
+ options,
253
+ action
254
+ });
255
+ return {
256
+ operator,
257
+ connector,
258
+ field: fieldName,
259
+ value: newValue
260
+ };
261
+ });
262
+ };
263
+ const transformJoinClause = (baseModel, unsanitizedJoin, select) => {
264
+ if (!unsanitizedJoin) return void 0;
265
+ if (Object.keys(unsanitizedJoin).length === 0) return void 0;
266
+ const transformedJoin = {};
267
+ for (const [model, join] of Object.entries(unsanitizedJoin)) {
268
+ if (!join) continue;
269
+ const defaultModelName = getDefaultModelName(model);
270
+ const defaultBaseModelName = getDefaultModelName(baseModel);
271
+ let foreignKeys = Object.entries(schema[defaultModelName].fields).filter(([field, fieldAttributes]) => fieldAttributes.references && getDefaultModelName(fieldAttributes.references.model) === defaultBaseModelName);
272
+ let isForwardJoin = true;
273
+ if (!foreignKeys.length) {
274
+ foreignKeys = Object.entries(schema[defaultBaseModelName].fields).filter(([field, fieldAttributes]) => fieldAttributes.references && getDefaultModelName(fieldAttributes.references.model) === defaultModelName);
275
+ isForwardJoin = false;
276
+ }
277
+ if (!foreignKeys.length) throw new BetterAuthError(`No foreign key found for model ${model} and base model ${baseModel} while performing join operation.`);
278
+ else if (foreignKeys.length > 1) throw new BetterAuthError(`Multiple foreign keys found for model ${model} and base model ${baseModel} while performing join operation. Only one foreign key is supported.`);
279
+ const [foreignKey, foreignKeyAttributes] = foreignKeys[0];
280
+ if (!foreignKeyAttributes.references) throw new BetterAuthError(`No references found for foreign key ${foreignKey} on model ${model} while performing join operation.`);
281
+ let from;
282
+ let to;
283
+ let requiredSelectField;
284
+ if (isForwardJoin) {
285
+ requiredSelectField = foreignKeyAttributes.references.field;
286
+ from = getFieldName({
287
+ model: baseModel,
288
+ field: requiredSelectField
289
+ });
290
+ to = getFieldName({
291
+ model,
292
+ field: foreignKey
293
+ });
294
+ } else {
295
+ requiredSelectField = foreignKey;
296
+ from = getFieldName({
297
+ model: baseModel,
298
+ field: requiredSelectField
299
+ });
300
+ to = getFieldName({
301
+ model,
302
+ field: foreignKeyAttributes.references.field
303
+ });
304
+ }
305
+ if (select && !select.includes(requiredSelectField)) select.push(requiredSelectField);
306
+ const isUnique = to === "id" ? true : foreignKeyAttributes.unique ?? false;
307
+ let limit = options.advanced?.database?.defaultFindManyLimit ?? 100;
308
+ if (isUnique) limit = 1;
309
+ else if (typeof join === "object" && typeof join.limit === "number") limit = join.limit;
310
+ transformedJoin[getModelName(model)] = {
311
+ on: {
312
+ from,
313
+ to
314
+ },
315
+ limit,
316
+ relation: isUnique ? "one-to-one" : "one-to-many"
317
+ };
318
+ }
319
+ return {
320
+ join: transformedJoin,
321
+ select
322
+ };
323
+ };
324
+ /**
325
+ * Handle joins by making separate queries and combining results (fallback for adapters that don't support native joins).
326
+ */
327
+ const handleFallbackJoin = async ({ baseModel, baseData, joinModel, specificJoinConfig: joinConfig }) => {
328
+ if (!baseData) return baseData;
329
+ const modelName = getModelName(joinModel);
330
+ const field = joinConfig.on.to;
331
+ const value = baseData[getDefaultFieldName({
332
+ field: joinConfig.on.from,
333
+ model: baseModel
334
+ })];
335
+ if (value === null || value === void 0) return joinConfig.relation === "one-to-one" ? null : [];
336
+ let result;
337
+ const where = transformWhereClause({
338
+ model: modelName,
339
+ where: [{
340
+ field,
341
+ value,
342
+ operator: "eq",
343
+ connector: "AND"
344
+ }],
345
+ action: "findOne"
346
+ });
347
+ try {
348
+ if (joinConfig.relation === "one-to-one") result = await adapterInstance.findOne({
349
+ model: modelName,
350
+ where
351
+ });
352
+ else {
353
+ const limit = joinConfig.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
354
+ result = await adapterInstance.findMany({
355
+ model: modelName,
356
+ where,
357
+ limit
358
+ });
359
+ }
360
+ } catch (error) {
361
+ logger.error(`Failed to query fallback join for model ${modelName}:`, {
362
+ where,
363
+ limit: joinConfig.limit
364
+ });
365
+ console.error(error);
366
+ throw error;
367
+ }
368
+ return result;
369
+ };
370
+ const adapterInstance = customAdapter({
371
+ options,
372
+ schema,
373
+ debugLog,
374
+ getFieldName,
375
+ getModelName,
376
+ getDefaultModelName,
377
+ getDefaultFieldName,
378
+ getFieldAttributes,
379
+ transformInput,
380
+ transformOutput,
381
+ transformWhereClause
382
+ });
383
+ let lazyLoadTransaction = null;
384
+ const adapter = {
385
+ transaction: async (cb) => {
386
+ if (!lazyLoadTransaction) if (!config.transaction) lazyLoadTransaction = createAsIsTransaction(adapter);
387
+ else {
388
+ logger.debug(`[${config.adapterName}] - Using provided transaction implementation.`);
389
+ lazyLoadTransaction = config.transaction;
390
+ }
391
+ return lazyLoadTransaction(cb);
392
+ },
393
+ create: async ({ data: unsafeData, model: unsafeModel, select, forceAllowId = false }) => {
394
+ transactionId++;
395
+ const thisTransactionId = transactionId;
396
+ const model = getModelName(unsafeModel);
397
+ unsafeModel = getDefaultModelName(unsafeModel);
398
+ if ("id" in unsafeData && typeof unsafeData.id !== "undefined" && !forceAllowId) {
399
+ logger.warn(`[${config.adapterName}] - You are trying to create a record with an id. This is not allowed as we handle id generation for you, unless you pass in the \`forceAllowId\` parameter. The id will be ignored.`);
400
+ const stack = (/* @__PURE__ */ new Error()).stack?.split("\n").filter((_, i) => i !== 1).join("\n").replace("Error:", "Create method with `id` being called at:");
401
+ console.log(stack);
402
+ unsafeData.id = void 0;
403
+ }
404
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("create")} ${formatAction("Unsafe Input")}:`, {
405
+ model,
406
+ data: unsafeData
407
+ });
408
+ let data = unsafeData;
409
+ if (!config.disableTransformInput) data = await transformInput(unsafeData, unsafeModel, "create", forceAllowId);
410
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`, `${formatMethod("create")} ${formatAction("Parsed Input")}:`, {
411
+ model,
412
+ data
413
+ });
414
+ const res = await adapterInstance.create({
415
+ data,
416
+ model
417
+ });
418
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`, `${formatMethod("create")} ${formatAction("DB Result")}:`, {
419
+ model,
420
+ res
421
+ });
422
+ let transformed = res;
423
+ if (!config.disableTransformOutput) transformed = await transformOutput(res, unsafeModel, select, void 0);
424
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`, `${formatMethod("create")} ${formatAction("Parsed Result")}:`, {
425
+ model,
426
+ data: transformed
427
+ });
428
+ return transformed;
429
+ },
430
+ update: async ({ model: unsafeModel, where: unsafeWhere, update: unsafeData }) => {
431
+ transactionId++;
432
+ const thisTransactionId = transactionId;
433
+ unsafeModel = getDefaultModelName(unsafeModel);
434
+ const model = getModelName(unsafeModel);
435
+ const where = transformWhereClause({
436
+ model: unsafeModel,
437
+ where: unsafeWhere,
438
+ action: "update"
439
+ });
440
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("update")} ${formatAction("Unsafe Input")}:`, {
441
+ model,
442
+ data: unsafeData
443
+ });
444
+ let data = unsafeData;
445
+ if (!config.disableTransformInput) data = await transformInput(unsafeData, unsafeModel, "update");
446
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`, `${formatMethod("update")} ${formatAction("Parsed Input")}:`, {
447
+ model,
448
+ data
449
+ });
450
+ const res = await adapterInstance.update({
451
+ model,
452
+ where,
453
+ update: data
454
+ });
455
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`, `${formatMethod("update")} ${formatAction("DB Result")}:`, {
456
+ model,
457
+ data: res
458
+ });
459
+ let transformed = res;
460
+ if (!config.disableTransformOutput) transformed = await transformOutput(res, unsafeModel, void 0, void 0);
461
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`, `${formatMethod("update")} ${formatAction("Parsed Result")}:`, {
462
+ model,
463
+ data: transformed
464
+ });
465
+ return transformed;
466
+ },
467
+ updateMany: async ({ model: unsafeModel, where: unsafeWhere, update: unsafeData }) => {
468
+ transactionId++;
469
+ const thisTransactionId = transactionId;
470
+ const model = getModelName(unsafeModel);
471
+ const where = transformWhereClause({
472
+ model: unsafeModel,
473
+ where: unsafeWhere,
474
+ action: "updateMany"
475
+ });
476
+ unsafeModel = getDefaultModelName(unsafeModel);
477
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("updateMany")} ${formatAction("Unsafe Input")}:`, {
478
+ model,
479
+ data: unsafeData
480
+ });
481
+ let data = unsafeData;
482
+ if (!config.disableTransformInput) data = await transformInput(unsafeData, unsafeModel, "update");
483
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`, `${formatMethod("updateMany")} ${formatAction("Parsed Input")}:`, {
484
+ model,
485
+ data
486
+ });
487
+ const updatedCount = await adapterInstance.updateMany({
488
+ model,
489
+ where,
490
+ update: data
491
+ });
492
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`, `${formatMethod("updateMany")} ${formatAction("DB Result")}:`, {
493
+ model,
494
+ data: updatedCount
495
+ });
496
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`, `${formatMethod("updateMany")} ${formatAction("Parsed Result")}:`, {
497
+ model,
498
+ data: updatedCount
499
+ });
500
+ return updatedCount;
501
+ },
502
+ findOne: async ({ model: unsafeModel, where: unsafeWhere, select, join: unsafeJoin }) => {
503
+ transactionId++;
504
+ const thisTransactionId = transactionId;
505
+ const model = getModelName(unsafeModel);
506
+ const where = transformWhereClause({
507
+ model: unsafeModel,
508
+ where: unsafeWhere,
509
+ action: "findOne"
510
+ });
511
+ unsafeModel = getDefaultModelName(unsafeModel);
512
+ let join;
513
+ let passJoinToAdapter = true;
514
+ if (!config.disableTransformJoin) {
515
+ const result = transformJoinClause(unsafeModel, unsafeJoin, select);
516
+ if (result) {
517
+ join = result.join;
518
+ select = result.select;
519
+ }
520
+ if (!options.experimental?.joins && join && Object.keys(join).length > 0) passJoinToAdapter = false;
521
+ } else join = unsafeJoin;
522
+ debugLog({ method: "findOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`, `${formatMethod("findOne")}:`, {
523
+ model,
524
+ where,
525
+ select,
526
+ join
527
+ });
528
+ const res = await adapterInstance.findOne({
529
+ model,
530
+ where,
531
+ select,
532
+ join: passJoinToAdapter ? join : void 0
533
+ });
534
+ debugLog({ method: "findOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`, `${formatMethod("findOne")} ${formatAction("DB Result")}:`, {
535
+ model,
536
+ data: res
537
+ });
538
+ let transformed = res;
539
+ if (!config.disableTransformOutput) transformed = await transformOutput(res, unsafeModel, select, join);
540
+ debugLog({ method: "findOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`, `${formatMethod("findOne")} ${formatAction("Parsed Result")}:`, {
541
+ model,
542
+ data: transformed
543
+ });
544
+ return transformed;
545
+ },
546
+ findMany: async ({ model: unsafeModel, where: unsafeWhere, limit: unsafeLimit, sortBy, offset, join: unsafeJoin }) => {
547
+ transactionId++;
548
+ const thisTransactionId = transactionId;
549
+ const limit = unsafeLimit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
550
+ const model = getModelName(unsafeModel);
551
+ const where = transformWhereClause({
552
+ model: unsafeModel,
553
+ where: unsafeWhere,
554
+ action: "findMany"
555
+ });
556
+ unsafeModel = getDefaultModelName(unsafeModel);
557
+ let join;
558
+ let passJoinToAdapter = true;
559
+ if (!config.disableTransformJoin) {
560
+ const result = transformJoinClause(unsafeModel, unsafeJoin, void 0);
561
+ if (result) join = result.join;
562
+ if (!options.experimental?.joins && join && Object.keys(join).length > 0) passJoinToAdapter = false;
563
+ } else join = unsafeJoin;
564
+ debugLog({ method: "findMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`, `${formatMethod("findMany")}:`, {
565
+ model,
566
+ where,
567
+ limit,
568
+ sortBy,
569
+ offset,
570
+ join
571
+ });
572
+ const res = await adapterInstance.findMany({
573
+ model,
574
+ where,
575
+ limit,
576
+ sortBy,
577
+ offset,
578
+ join: passJoinToAdapter ? join : void 0
579
+ });
580
+ debugLog({ method: "findMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`, `${formatMethod("findMany")} ${formatAction("DB Result")}:`, {
581
+ model,
582
+ data: res
583
+ });
584
+ let transformed = res;
585
+ if (!config.disableTransformOutput) transformed = await Promise.all(res.map(async (r) => {
586
+ return await transformOutput(r, unsafeModel, void 0, join);
587
+ }));
588
+ debugLog({ method: "findMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`, `${formatMethod("findMany")} ${formatAction("Parsed Result")}:`, {
589
+ model,
590
+ data: transformed
591
+ });
592
+ return transformed;
593
+ },
594
+ delete: async ({ model: unsafeModel, where: unsafeWhere }) => {
595
+ transactionId++;
596
+ const thisTransactionId = transactionId;
597
+ const model = getModelName(unsafeModel);
598
+ const where = transformWhereClause({
599
+ model: unsafeModel,
600
+ where: unsafeWhere,
601
+ action: "delete"
602
+ });
603
+ unsafeModel = getDefaultModelName(unsafeModel);
604
+ debugLog({ method: "delete" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("delete")}:`, {
605
+ model,
606
+ where
607
+ });
608
+ await adapterInstance.delete({
609
+ model,
610
+ where
611
+ });
612
+ debugLog({ method: "delete" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`, `${formatMethod("delete")} ${formatAction("DB Result")}:`, { model });
613
+ },
614
+ deleteMany: async ({ model: unsafeModel, where: unsafeWhere }) => {
615
+ transactionId++;
616
+ const thisTransactionId = transactionId;
617
+ const model = getModelName(unsafeModel);
618
+ const where = transformWhereClause({
619
+ model: unsafeModel,
620
+ where: unsafeWhere,
621
+ action: "deleteMany"
622
+ });
623
+ unsafeModel = getDefaultModelName(unsafeModel);
624
+ debugLog({ method: "deleteMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("deleteMany")} ${formatAction("DeleteMany")}:`, {
625
+ model,
626
+ where
627
+ });
628
+ const res = await adapterInstance.deleteMany({
629
+ model,
630
+ where
631
+ });
632
+ debugLog({ method: "deleteMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`, `${formatMethod("deleteMany")} ${formatAction("DB Result")}:`, {
633
+ model,
634
+ data: res
635
+ });
636
+ return res;
637
+ },
638
+ count: async ({ model: unsafeModel, where: unsafeWhere }) => {
639
+ transactionId++;
640
+ const thisTransactionId = transactionId;
641
+ const model = getModelName(unsafeModel);
642
+ const where = transformWhereClause({
643
+ model: unsafeModel,
644
+ where: unsafeWhere,
645
+ action: "count"
646
+ });
647
+ unsafeModel = getDefaultModelName(unsafeModel);
648
+ debugLog({ method: "count" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("count")}:`, {
649
+ model,
650
+ where
651
+ });
652
+ const res = await adapterInstance.count({
653
+ model,
654
+ where
655
+ });
656
+ debugLog({ method: "count" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`, `${formatMethod("count")}:`, {
657
+ model,
658
+ data: res
659
+ });
660
+ return res;
661
+ },
662
+ createSchema: adapterInstance.createSchema ? async (_, file) => {
663
+ const tables = getAuthTables(options);
664
+ if (options.secondaryStorage && !options.session?.storeSessionInDatabase) delete tables.session;
665
+ if (options.rateLimit && options.rateLimit.storage === "database" && (typeof options.rateLimit.enabled === "undefined" || options.rateLimit.enabled === true)) tables.ratelimit = {
666
+ modelName: options.rateLimit.modelName ?? "ratelimit",
667
+ fields: {
668
+ key: {
669
+ type: "string",
670
+ unique: true,
671
+ required: true,
672
+ fieldName: options.rateLimit.fields?.key ?? "key"
673
+ },
674
+ count: {
675
+ type: "number",
676
+ required: true,
677
+ fieldName: options.rateLimit.fields?.count ?? "count"
678
+ },
679
+ lastRequest: {
680
+ type: "number",
681
+ required: true,
682
+ bigint: true,
683
+ defaultValue: () => Date.now(),
684
+ fieldName: options.rateLimit.fields?.lastRequest ?? "lastRequest"
685
+ }
686
+ }
687
+ };
688
+ return adapterInstance.createSchema({
689
+ file,
690
+ tables
691
+ });
692
+ } : void 0,
693
+ options: {
694
+ adapterConfig: config,
695
+ ...adapterInstance.options ?? {}
696
+ },
697
+ id: config.adapterId,
698
+ ...config.debugLogs?.isRunningAdapterTests ? { adapterTestDebugLogs: {
699
+ resetDebugLogs() {
700
+ debugLogs = debugLogs.filter((log) => log.instance !== uniqueAdapterFactoryInstanceId);
701
+ },
702
+ printDebugLogs() {
703
+ const separator = `─`.repeat(80);
704
+ const logs = debugLogs.filter((log$1) => log$1.instance === uniqueAdapterFactoryInstanceId);
705
+ if (logs.length === 0) return;
706
+ const log = logs.reverse().map((log$1) => {
707
+ log$1.args[0] = `\n${log$1.args[0]}`;
708
+ return [...log$1.args, "\n"];
709
+ }).reduce((prev, curr) => {
710
+ return [...curr, ...prev];
711
+ }, [`\n${separator}`]);
712
+ console.log(...log);
713
+ }
714
+ } } : {}
715
+ };
716
+ return adapter;
717
+ };
718
+ function formatTransactionId(transactionId$1) {
719
+ if (getColorDepth() < 8) return `#${transactionId$1}`;
720
+ return `${TTY_COLORS.fg.magenta}#${transactionId$1}${TTY_COLORS.reset}`;
721
+ }
722
+ function formatStep(step, total) {
723
+ return `${TTY_COLORS.bg.black}${TTY_COLORS.fg.yellow}[${step}/${total}]${TTY_COLORS.reset}`;
724
+ }
725
+ function formatMethod(method) {
726
+ return `${TTY_COLORS.bright}${method}${TTY_COLORS.reset}`;
727
+ }
728
+ function formatAction(action) {
729
+ return `${TTY_COLORS.dim}(${action})${TTY_COLORS.reset}`;
730
+ }
731
+ /**
732
+ * @deprecated Use `createAdapterFactory` instead. This export will be removed in a future version.
733
+ * @alias
734
+ */
735
+ const createAdapter = createAdapterFactory;
736
+
737
+ //#endregion
738
+ export { createAdapter, createAdapterFactory };