@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.
Files changed (310) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +32 -0
  3. package/changes.json +14 -0
  4. package/dist/api/index.d.mts +281 -0
  5. package/dist/api/index.mjs +92 -0
  6. package/dist/async_hooks/index.d.mts +6 -0
  7. package/dist/async_hooks/index.mjs +20 -0
  8. package/dist/async_hooks/pure.index.d.mts +6 -0
  9. package/dist/async_hooks/pure.index.mjs +33 -0
  10. package/dist/context/endpoint-context.d.mts +18 -0
  11. package/dist/context/endpoint-context.mjs +29 -0
  12. package/dist/context/global.d.mts +6 -0
  13. package/dist/context/global.mjs +36 -0
  14. package/dist/context/index.d.mts +5 -0
  15. package/dist/context/index.mjs +5 -0
  16. package/dist/context/request-state.d.mts +27 -0
  17. package/dist/context/request-state.mjs +47 -0
  18. package/dist/context/transaction.d.mts +27 -0
  19. package/dist/context/transaction.mjs +96 -0
  20. package/dist/db/adapter/factory.d.mts +17 -0
  21. package/dist/db/adapter/factory.mjs +905 -0
  22. package/dist/db/adapter/get-default-field-name.d.mts +18 -0
  23. package/dist/db/adapter/get-default-field-name.mjs +36 -0
  24. package/dist/db/adapter/get-default-model-name.d.mts +12 -0
  25. package/dist/db/adapter/get-default-model-name.mjs +30 -0
  26. package/dist/db/adapter/get-field-attributes.d.mts +26 -0
  27. package/dist/db/adapter/get-field-attributes.mjs +37 -0
  28. package/dist/db/adapter/get-field-name.d.mts +18 -0
  29. package/dist/db/adapter/get-field-name.mjs +31 -0
  30. package/dist/db/adapter/get-id-field.d.mts +36 -0
  31. package/dist/db/adapter/get-id-field.mjs +64 -0
  32. package/dist/db/adapter/get-model-name.d.mts +12 -0
  33. package/dist/db/adapter/get-model-name.mjs +21 -0
  34. package/dist/db/adapter/index.d.mts +615 -0
  35. package/dist/db/adapter/index.mjs +24 -0
  36. package/dist/db/adapter/types.d.mts +105 -0
  37. package/dist/db/adapter/utils.d.mts +7 -0
  38. package/dist/db/adapter/utils.mjs +37 -0
  39. package/dist/db/get-tables.d.mts +6 -0
  40. package/dist/db/get-tables.mjs +266 -0
  41. package/dist/db/index.d.mts +10 -0
  42. package/dist/db/index.mjs +8 -0
  43. package/dist/db/plugin.d.mts +12 -0
  44. package/dist/db/schema/account.d.mts +28 -0
  45. package/dist/db/schema/account.mjs +17 -0
  46. package/dist/db/schema/rate-limit.d.mts +18 -0
  47. package/dist/db/schema/rate-limit.mjs +9 -0
  48. package/dist/db/schema/session.d.mts +23 -0
  49. package/dist/db/schema/session.mjs +12 -0
  50. package/dist/db/schema/shared.d.mts +10 -0
  51. package/dist/db/schema/shared.mjs +9 -0
  52. package/dist/db/schema/user.d.mts +22 -0
  53. package/dist/db/schema/user.mjs +11 -0
  54. package/dist/db/schema/verification.d.mts +21 -0
  55. package/dist/db/schema/verification.mjs +10 -0
  56. package/dist/db/type.d.mts +194 -0
  57. package/dist/env/color-depth.d.mts +4 -0
  58. package/dist/env/color-depth.mjs +86 -0
  59. package/dist/env/env-impl.d.mts +32 -0
  60. package/dist/env/env-impl.mjs +81 -0
  61. package/dist/env/index.d.mts +4 -0
  62. package/dist/env/index.mjs +4 -0
  63. package/dist/env/logger.d.mts +48 -0
  64. package/dist/env/logger.mjs +79 -0
  65. package/dist/error/codes.d.mts +69 -0
  66. package/dist/error/codes.mjs +55 -0
  67. package/dist/error/index.d.mts +26 -0
  68. package/dist/error/index.mjs +27 -0
  69. package/dist/index.d.mts +9 -0
  70. package/dist/index.mjs +1 -0
  71. package/dist/instrumentation/api.mjs +12 -0
  72. package/dist/instrumentation/attributes.d.mts +11 -0
  73. package/dist/instrumentation/attributes.mjs +10 -0
  74. package/dist/instrumentation/index.d.mts +3 -0
  75. package/dist/instrumentation/index.mjs +3 -0
  76. package/dist/instrumentation/noop.mjs +42 -0
  77. package/dist/instrumentation/pure.index.d.mts +7 -0
  78. package/dist/instrumentation/pure.index.mjs +7 -0
  79. package/dist/instrumentation/tracer.d.mts +13 -0
  80. package/dist/instrumentation/tracer.mjs +53 -0
  81. package/dist/oauth2/client-credentials-token.d.mts +56 -0
  82. package/dist/oauth2/client-credentials-token.mjs +64 -0
  83. package/dist/oauth2/create-authorization-url.d.mts +44 -0
  84. package/dist/oauth2/create-authorization-url.mjs +41 -0
  85. package/dist/oauth2/index.d.mts +8 -0
  86. package/dist/oauth2/index.mjs +7 -0
  87. package/dist/oauth2/oauth-provider.d.mts +192 -0
  88. package/dist/oauth2/refresh-access-token.d.mts +54 -0
  89. package/dist/oauth2/refresh-access-token.mjs +73 -0
  90. package/dist/oauth2/reject-redirects.mjs +60 -0
  91. package/dist/oauth2/utils.d.mts +24 -0
  92. package/dist/oauth2/utils.mjs +48 -0
  93. package/dist/oauth2/validate-authorization-code.d.mts +85 -0
  94. package/dist/oauth2/validate-authorization-code.mjs +86 -0
  95. package/dist/oauth2/verify.d.mts +65 -0
  96. package/dist/oauth2/verify.mjs +202 -0
  97. package/dist/social-providers/apple.d.mts +133 -0
  98. package/dist/social-providers/apple.mjs +117 -0
  99. package/dist/social-providers/atlassian.d.mts +70 -0
  100. package/dist/social-providers/atlassian.mjs +80 -0
  101. package/dist/social-providers/cognito.d.mts +85 -0
  102. package/dist/social-providers/cognito.mjs +162 -0
  103. package/dist/social-providers/discord.d.mts +124 -0
  104. package/dist/social-providers/discord.mjs +62 -0
  105. package/dist/social-providers/dropbox.d.mts +69 -0
  106. package/dist/social-providers/dropbox.mjs +72 -0
  107. package/dist/social-providers/facebook.d.mts +79 -0
  108. package/dist/social-providers/facebook.mjs +157 -0
  109. package/dist/social-providers/figma.d.mts +61 -0
  110. package/dist/social-providers/figma.mjs +83 -0
  111. package/dist/social-providers/github.d.mts +102 -0
  112. package/dist/social-providers/github.mjs +92 -0
  113. package/dist/social-providers/gitlab.d.mts +123 -0
  114. package/dist/social-providers/gitlab.mjs +79 -0
  115. package/dist/social-providers/google.d.mts +123 -0
  116. package/dist/social-providers/google.mjs +137 -0
  117. package/dist/social-providers/huggingface.d.mts +83 -0
  118. package/dist/social-providers/huggingface.mjs +73 -0
  119. package/dist/social-providers/index.d.mts +1834 -0
  120. package/dist/social-providers/index.mjs +78 -0
  121. package/dist/social-providers/kakao.d.mts +161 -0
  122. package/dist/social-providers/kakao.mjs +70 -0
  123. package/dist/social-providers/kick.d.mts +73 -0
  124. package/dist/social-providers/kick.mjs +68 -0
  125. package/dist/social-providers/line.d.mts +105 -0
  126. package/dist/social-providers/line.mjs +110 -0
  127. package/dist/social-providers/linear.d.mts +68 -0
  128. package/dist/social-providers/linear.mjs +85 -0
  129. package/dist/social-providers/linkedin.d.mts +67 -0
  130. package/dist/social-providers/linkedin.mjs +73 -0
  131. package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
  132. package/dist/social-providers/microsoft-entra-id.mjs +152 -0
  133. package/dist/social-providers/naver.d.mts +92 -0
  134. package/dist/social-providers/naver.mjs +65 -0
  135. package/dist/social-providers/notion.d.mts +64 -0
  136. package/dist/social-providers/notion.mjs +72 -0
  137. package/dist/social-providers/paybin.d.mts +71 -0
  138. package/dist/social-providers/paybin.mjs +81 -0
  139. package/dist/social-providers/paypal.d.mts +131 -0
  140. package/dist/social-providers/paypal.mjs +188 -0
  141. package/dist/social-providers/polar.d.mts +74 -0
  142. package/dist/social-providers/polar.mjs +71 -0
  143. package/dist/social-providers/railway.d.mts +65 -0
  144. package/dist/social-providers/railway.mjs +74 -0
  145. package/dist/social-providers/reddit.d.mts +62 -0
  146. package/dist/social-providers/reddit.mjs +81 -0
  147. package/dist/social-providers/roblox.d.mts +70 -0
  148. package/dist/social-providers/roblox.mjs +57 -0
  149. package/dist/social-providers/salesforce.d.mts +79 -0
  150. package/dist/social-providers/salesforce.mjs +87 -0
  151. package/dist/social-providers/slack.d.mts +83 -0
  152. package/dist/social-providers/slack.mjs +66 -0
  153. package/dist/social-providers/spotify.d.mts +63 -0
  154. package/dist/social-providers/spotify.mjs +69 -0
  155. package/dist/social-providers/tiktok.d.mts +168 -0
  156. package/dist/social-providers/tiktok.mjs +60 -0
  157. package/dist/social-providers/twitch.d.mts +79 -0
  158. package/dist/social-providers/twitch.mjs +75 -0
  159. package/dist/social-providers/twitter.d.mts +126 -0
  160. package/dist/social-providers/twitter.mjs +85 -0
  161. package/dist/social-providers/vercel.d.mts +62 -0
  162. package/dist/social-providers/vercel.mjs +58 -0
  163. package/dist/social-providers/vk.d.mts +70 -0
  164. package/dist/social-providers/vk.mjs +81 -0
  165. package/dist/social-providers/wechat.d.mts +113 -0
  166. package/dist/social-providers/wechat.mjs +81 -0
  167. package/dist/social-providers/zoom.d.mts +163 -0
  168. package/dist/social-providers/zoom.mjs +69 -0
  169. package/dist/types/context.d.mts +319 -0
  170. package/dist/types/cookie.d.mts +15 -0
  171. package/dist/types/helper.d.mts +10 -0
  172. package/dist/types/index.d.mts +9 -0
  173. package/dist/types/init-options.d.mts +1430 -0
  174. package/dist/types/plugin-client.d.mts +123 -0
  175. package/dist/types/plugin.d.mts +124 -0
  176. package/dist/types/secret.d.mts +11 -0
  177. package/dist/utils/async.d.mts +22 -0
  178. package/dist/utils/async.mjs +32 -0
  179. package/dist/utils/db.d.mts +9 -0
  180. package/dist/utils/db.mjs +15 -0
  181. package/dist/utils/deprecate.d.mts +9 -0
  182. package/dist/utils/deprecate.mjs +16 -0
  183. package/dist/utils/error-codes.d.mts +13 -0
  184. package/dist/utils/error-codes.mjs +10 -0
  185. package/dist/utils/fetch-metadata.d.mts +4 -0
  186. package/dist/utils/fetch-metadata.mjs +6 -0
  187. package/dist/utils/host.d.mts +147 -0
  188. package/dist/utils/host.mjs +295 -0
  189. package/dist/utils/id.d.mts +4 -0
  190. package/dist/utils/id.mjs +7 -0
  191. package/dist/utils/ip.d.mts +77 -0
  192. package/dist/utils/ip.mjs +230 -0
  193. package/dist/utils/is-api-error.d.mts +6 -0
  194. package/dist/utils/is-api-error.mjs +8 -0
  195. package/dist/utils/json.d.mts +4 -0
  196. package/dist/utils/json.mjs +41 -0
  197. package/dist/utils/redirect-uri.d.mts +20 -0
  198. package/dist/utils/redirect-uri.mjs +48 -0
  199. package/dist/utils/string.d.mts +8 -0
  200. package/dist/utils/string.mjs +25 -0
  201. package/dist/utils/url.d.mts +37 -0
  202. package/dist/utils/url.mjs +61 -0
  203. package/package.json +216 -0
  204. package/src/api/index.ts +185 -0
  205. package/src/async_hooks/index.ts +40 -0
  206. package/src/async_hooks/pure.index.ts +46 -0
  207. package/src/context/endpoint-context.ts +50 -0
  208. package/src/context/global.ts +57 -0
  209. package/src/context/index.ts +23 -0
  210. package/src/context/request-state.ts +91 -0
  211. package/src/context/transaction.ts +169 -0
  212. package/src/db/adapter/factory.ts +1740 -0
  213. package/src/db/adapter/get-default-field-name.ts +59 -0
  214. package/src/db/adapter/get-default-model-name.ts +51 -0
  215. package/src/db/adapter/get-field-attributes.ts +62 -0
  216. package/src/db/adapter/get-field-name.ts +43 -0
  217. package/src/db/adapter/get-id-field.ts +150 -0
  218. package/src/db/adapter/get-model-name.ts +36 -0
  219. package/src/db/adapter/index.ts +656 -0
  220. package/src/db/adapter/types.ts +134 -0
  221. package/src/db/adapter/utils.ts +61 -0
  222. package/src/db/get-tables.ts +304 -0
  223. package/src/db/index.ts +43 -0
  224. package/src/db/plugin.ts +11 -0
  225. package/src/db/schema/account.ts +47 -0
  226. package/src/db/schema/rate-limit.ts +36 -0
  227. package/src/db/schema/session.ts +29 -0
  228. package/src/db/schema/shared.ts +7 -0
  229. package/src/db/schema/user.ts +31 -0
  230. package/src/db/schema/verification.ts +28 -0
  231. package/src/db/type.ts +360 -0
  232. package/src/env/color-depth.ts +172 -0
  233. package/src/env/env-impl.ts +123 -0
  234. package/src/env/index.ts +23 -0
  235. package/src/env/logger.ts +145 -0
  236. package/src/error/codes.ts +72 -0
  237. package/src/error/index.ts +44 -0
  238. package/src/index.ts +1 -0
  239. package/src/instrumentation/api.ts +17 -0
  240. package/src/instrumentation/attributes.ts +22 -0
  241. package/src/instrumentation/index.ts +2 -0
  242. package/src/instrumentation/noop.ts +74 -0
  243. package/src/instrumentation/pure.index.ts +31 -0
  244. package/src/instrumentation/tracer.ts +95 -0
  245. package/src/oauth2/client-credentials-token.ts +126 -0
  246. package/src/oauth2/create-authorization-url.ts +89 -0
  247. package/src/oauth2/index.ts +34 -0
  248. package/src/oauth2/oauth-provider.ts +222 -0
  249. package/src/oauth2/refresh-access-token.ts +157 -0
  250. package/src/oauth2/reject-redirects.ts +70 -0
  251. package/src/oauth2/utils.ts +70 -0
  252. package/src/oauth2/validate-authorization-code.ts +190 -0
  253. package/src/oauth2/verify.ts +408 -0
  254. package/src/social-providers/apple.ts +249 -0
  255. package/src/social-providers/atlassian.ts +133 -0
  256. package/src/social-providers/cognito.ts +281 -0
  257. package/src/social-providers/discord.ts +170 -0
  258. package/src/social-providers/dropbox.ts +112 -0
  259. package/src/social-providers/facebook.ts +288 -0
  260. package/src/social-providers/figma.ts +118 -0
  261. package/src/social-providers/github.ts +184 -0
  262. package/src/social-providers/gitlab.ts +155 -0
  263. package/src/social-providers/google.ts +263 -0
  264. package/src/social-providers/huggingface.ts +119 -0
  265. package/src/social-providers/index.ts +132 -0
  266. package/src/social-providers/kakao.ts +179 -0
  267. package/src/social-providers/kick.ts +109 -0
  268. package/src/social-providers/line.ts +169 -0
  269. package/src/social-providers/linear.ts +121 -0
  270. package/src/social-providers/linkedin.ts +110 -0
  271. package/src/social-providers/microsoft-entra-id.ts +391 -0
  272. package/src/social-providers/naver.ts +113 -0
  273. package/src/social-providers/notion.ts +108 -0
  274. package/src/social-providers/paybin.ts +118 -0
  275. package/src/social-providers/paypal.ts +371 -0
  276. package/src/social-providers/polar.ts +111 -0
  277. package/src/social-providers/railway.ts +100 -0
  278. package/src/social-providers/reddit.ts +126 -0
  279. package/src/social-providers/roblox.ts +112 -0
  280. package/src/social-providers/salesforce.ts +159 -0
  281. package/src/social-providers/slack.ts +112 -0
  282. package/src/social-providers/spotify.ts +94 -0
  283. package/src/social-providers/tiktok.ts +211 -0
  284. package/src/social-providers/twitch.ts +112 -0
  285. package/src/social-providers/twitter.ts +199 -0
  286. package/src/social-providers/vercel.ts +87 -0
  287. package/src/social-providers/vk.ts +125 -0
  288. package/src/social-providers/wechat.ts +220 -0
  289. package/src/social-providers/zoom.ts +230 -0
  290. package/src/types/context.ts +460 -0
  291. package/src/types/cookie.ts +10 -0
  292. package/src/types/helper.ts +27 -0
  293. package/src/types/index.ts +40 -0
  294. package/src/types/init-options.ts +1679 -0
  295. package/src/types/plugin-client.ts +143 -0
  296. package/src/types/plugin.ts +163 -0
  297. package/src/types/secret.ts +8 -0
  298. package/src/utils/async.ts +53 -0
  299. package/src/utils/db.ts +20 -0
  300. package/src/utils/deprecate.ts +21 -0
  301. package/src/utils/error-codes.ts +68 -0
  302. package/src/utils/fetch-metadata.ts +3 -0
  303. package/src/utils/host.ts +416 -0
  304. package/src/utils/id.ts +5 -0
  305. package/src/utils/ip.ts +395 -0
  306. package/src/utils/is-api-error.ts +10 -0
  307. package/src/utils/json.ts +56 -0
  308. package/src/utils/redirect-uri.ts +54 -0
  309. package/src/utils/string.ts +40 -0
  310. package/src/utils/url.ts +77 -0
@@ -0,0 +1,905 @@
1
+ import { getCurrentAdapter, runWithTransaction } from "../../context/transaction.mjs";
2
+ import { BetterAuthError } from "../../error/index.mjs";
3
+ import { getAuthTables } from "../get-tables.mjs";
4
+ import { getColorDepth } from "../../env/color-depth.mjs";
5
+ import { TTY_COLORS, createLogger } from "../../env/logger.mjs";
6
+ import { safeJSONParse } from "../../utils/json.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
+ import { ATTR_DB_COLLECTION_NAME, ATTR_DB_OPERATION_NAME, withSpan } from "@better-auth/core/instrumentation";
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?.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 = 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 === "consumeOne" && !config.debugLogs.consumeOne) return;
62
+ else if (method === "incrementOne" && !config.debugLogs.incrementOne) return;
63
+ else if (method === "count" && !config.debugLogs.count) return;
64
+ }
65
+ logger.info(`[${config.adapterName}]`, ...args);
66
+ } else logger.info(`[${config.adapterName}]`, ...args);
67
+ }
68
+ };
69
+ const logger = createLogger(options.logger);
70
+ const getDefaultModelName = initGetDefaultModelName({
71
+ usePlural: config.usePlural,
72
+ schema
73
+ });
74
+ const getDefaultFieldName = initGetDefaultFieldName({
75
+ usePlural: config.usePlural,
76
+ schema
77
+ });
78
+ const getModelName = initGetModelName({
79
+ usePlural: config.usePlural,
80
+ schema
81
+ });
82
+ const getFieldName = initGetFieldName({
83
+ schema,
84
+ usePlural: config.usePlural
85
+ });
86
+ const idField = initGetIdField({
87
+ schema,
88
+ options,
89
+ usePlural: config.usePlural,
90
+ disableIdGeneration: config.disableIdGeneration,
91
+ customIdGenerator: config.customIdGenerator,
92
+ supportsUUIDs: config.supportsUUIDs
93
+ });
94
+ const getFieldAttributes = initGetFieldAttributes({
95
+ schema,
96
+ options,
97
+ usePlural: config.usePlural,
98
+ disableIdGeneration: config.disableIdGeneration,
99
+ customIdGenerator: config.customIdGenerator
100
+ });
101
+ const transformInput = async (data, defaultModelName, action, forceAllowId) => {
102
+ const transformedData = {};
103
+ const fields = schema[defaultModelName].fields;
104
+ const newMappedKeys = config.mapKeysTransformInput ?? {};
105
+ const useNumberId = options.advanced?.database?.generateId === "serial";
106
+ fields.id = idField({
107
+ customModelName: defaultModelName,
108
+ forceAllowId: forceAllowId && "id" in data
109
+ });
110
+ for (const field in fields) {
111
+ let value = data[field];
112
+ const fieldAttributes = fields[field];
113
+ const newFieldName = newMappedKeys[field] || fields[field].fieldName || field;
114
+ if (value === void 0 && (fieldAttributes.defaultValue === void 0 && !fieldAttributes.transform?.input && !(action === "update" && fieldAttributes.onUpdate) || action === "update" && !fieldAttributes.onUpdate)) continue;
115
+ if (fieldAttributes && fieldAttributes.type === "date" && !(value instanceof Date) && typeof value === "string") try {
116
+ value = new Date(value);
117
+ } catch {
118
+ logger.error("[Adapter Factory] Failed to convert string to date", {
119
+ value,
120
+ field
121
+ });
122
+ }
123
+ let newValue = withApplyDefault(value, fieldAttributes, action);
124
+ if (fieldAttributes.transform?.input) newValue = await fieldAttributes.transform.input(newValue);
125
+ if (fieldAttributes.references?.field === "id" && useNumberId) if (Array.isArray(newValue)) newValue = newValue.map((x) => x !== null ? Number(x) : null);
126
+ else newValue = newValue !== null ? Number(newValue) : null;
127
+ else if (config.supportsJSON === false && typeof newValue === "object" && fieldAttributes.type === "json") newValue = JSON.stringify(newValue);
128
+ else if (config.supportsArrays === false && Array.isArray(newValue) && (fieldAttributes.type === "string[]" || fieldAttributes.type === "number[]")) newValue = JSON.stringify(newValue);
129
+ else if (config.supportsDates === false && newValue instanceof Date && fieldAttributes.type === "date") newValue = newValue.toISOString();
130
+ else if (config.supportsBooleans === false && typeof newValue === "boolean") newValue = newValue ? 1 : 0;
131
+ if (config.customTransformInput) newValue = config.customTransformInput({
132
+ data: newValue,
133
+ action,
134
+ field: newFieldName,
135
+ fieldAttributes,
136
+ model: getModelName(defaultModelName),
137
+ schema,
138
+ options
139
+ });
140
+ if (newValue !== void 0) transformedData[newFieldName] = newValue;
141
+ }
142
+ return transformedData;
143
+ };
144
+ const transformOutput = async (data, unsafe_model, select = [], join) => {
145
+ const transformSingleOutput = async (data, unsafe_model, select = []) => {
146
+ if (!data) return null;
147
+ const newMappedKeys = config.mapKeysTransformOutput ?? {};
148
+ const transformedData = {};
149
+ const tableSchema = schema[getDefaultModelName(unsafe_model)].fields;
150
+ const idKey = Object.entries(newMappedKeys).find(([_, v]) => v === "id")?.[0];
151
+ tableSchema[idKey ?? "id"] = { type: options.advanced?.database?.generateId === "serial" ? "number" : "string" };
152
+ for (const key in tableSchema) {
153
+ if (select.length && !select.includes(key)) continue;
154
+ const field = tableSchema[key];
155
+ if (field) {
156
+ const originalKey = field.fieldName || key;
157
+ let newValue = data[Object.entries(newMappedKeys).find(([_, v]) => v === originalKey)?.[0] || originalKey];
158
+ if (field.transform?.output) newValue = await field.transform.output(newValue);
159
+ const newFieldName = newMappedKeys[key] || key;
160
+ if (originalKey === "id" || field.references?.field === "id") {
161
+ if (typeof newValue !== "undefined" && newValue !== null) newValue = String(newValue);
162
+ } else if (config.supportsJSON === false && typeof newValue === "string" && field.type === "json") newValue = safeJSONParse(newValue);
163
+ else if (config.supportsArrays === false && typeof newValue === "string" && (field.type === "string[]" || field.type === "number[]")) newValue = safeJSONParse(newValue);
164
+ else if (config.supportsDates === false && typeof newValue === "string" && field.type === "date") newValue = new Date(newValue);
165
+ else if (config.supportsBooleans === false && typeof newValue === "number" && field.type === "boolean") newValue = newValue === 1;
166
+ if (config.customTransformOutput) newValue = config.customTransformOutput({
167
+ data: newValue,
168
+ field: newFieldName,
169
+ fieldAttributes: field,
170
+ select,
171
+ model: getModelName(unsafe_model),
172
+ schema,
173
+ options
174
+ });
175
+ transformedData[newFieldName] = newValue;
176
+ }
177
+ }
178
+ return transformedData;
179
+ };
180
+ if (!join || Object.keys(join).length === 0) return await transformSingleOutput(data, unsafe_model, select);
181
+ unsafe_model = getDefaultModelName(unsafe_model);
182
+ const transformedData = await transformSingleOutput(data, unsafe_model, select);
183
+ const requiredModels = Object.entries(join).map(([model, joinConfig]) => ({
184
+ modelName: getModelName(model),
185
+ defaultModelName: getDefaultModelName(model),
186
+ joinConfig
187
+ }));
188
+ if (!data) return null;
189
+ for (const { modelName, defaultModelName, joinConfig } of requiredModels) {
190
+ let joinedData = await (async () => {
191
+ if (options.experimental?.joins) return data[modelName];
192
+ else return await handleFallbackJoin({
193
+ baseModel: unsafe_model,
194
+ baseData: transformedData,
195
+ joinModel: modelName,
196
+ specificJoinConfig: joinConfig
197
+ });
198
+ })();
199
+ if (joinedData === void 0 || joinedData === null) joinedData = joinConfig.relation === "one-to-one" ? null : [];
200
+ if (joinConfig.relation === "one-to-many" && !Array.isArray(joinedData)) joinedData = [joinedData];
201
+ const transformed = [];
202
+ if (Array.isArray(joinedData)) for (const item of joinedData) {
203
+ const transformedItem = await transformSingleOutput(item, modelName, []);
204
+ transformed.push(transformedItem);
205
+ }
206
+ else {
207
+ const transformedItem = await transformSingleOutput(joinedData, modelName, []);
208
+ transformed.push(transformedItem);
209
+ }
210
+ transformedData[defaultModelName] = (joinConfig.relation === "one-to-one" ? transformed[0] : transformed) ?? null;
211
+ }
212
+ return transformedData;
213
+ };
214
+ const transformWhereClause = ({ model, where, action }) => {
215
+ if (!where) return void 0;
216
+ const newMappedKeys = config.mapKeysTransformInput ?? {};
217
+ return where.map((w) => {
218
+ const { field: unsafe_field, value, operator = "eq", connector = "AND", mode = "sensitive" } = w;
219
+ if (operator === "in") {
220
+ if (!Array.isArray(value)) throw new BetterAuthError("Value must be an array");
221
+ }
222
+ let newValue = value;
223
+ const defaultModelName = getDefaultModelName(model);
224
+ const defaultFieldName = getDefaultFieldName({
225
+ field: unsafe_field,
226
+ model
227
+ });
228
+ const fieldName = newMappedKeys[defaultFieldName] || getFieldName({
229
+ field: defaultFieldName,
230
+ model: defaultModelName
231
+ });
232
+ const fieldAttr = getFieldAttributes({
233
+ field: defaultFieldName,
234
+ model: defaultModelName
235
+ });
236
+ const useNumberId = options.advanced?.database?.generateId === "serial";
237
+ if (defaultFieldName === "id" || fieldAttr.references?.field === "id") {
238
+ if (useNumberId) if (Array.isArray(value)) newValue = value.map(Number);
239
+ else newValue = Number(value);
240
+ }
241
+ if (fieldAttr.type === "date" && value instanceof Date && !config.supportsDates) newValue = value.toISOString();
242
+ if (fieldAttr.type === "boolean" && typeof newValue === "string") newValue = newValue === "true";
243
+ if (fieldAttr.type === "number") {
244
+ if (typeof newValue === "string" && newValue.trim() !== "") {
245
+ const parsed = Number(newValue);
246
+ if (!Number.isNaN(parsed)) newValue = parsed;
247
+ } else if (Array.isArray(newValue)) {
248
+ const parsed = newValue.map((v) => typeof v === "string" && v.trim() !== "" ? Number(v) : NaN);
249
+ if (parsed.every((n) => !Number.isNaN(n))) newValue = parsed;
250
+ }
251
+ }
252
+ if (fieldAttr.type === "boolean" && typeof newValue === "boolean" && !config.supportsBooleans) newValue = newValue ? 1 : 0;
253
+ if (fieldAttr.type === "json" && typeof value === "object" && !config.supportsJSON) try {
254
+ newValue = JSON.stringify(value);
255
+ } catch (error) {
256
+ throw new Error(`Failed to stringify JSON value for field ${fieldName}`, { cause: error });
257
+ }
258
+ if (config.customTransformInput) newValue = config.customTransformInput({
259
+ data: newValue,
260
+ fieldAttributes: fieldAttr,
261
+ field: fieldName,
262
+ model: getModelName(model),
263
+ schema,
264
+ options,
265
+ action
266
+ });
267
+ return {
268
+ operator,
269
+ connector,
270
+ field: fieldName,
271
+ value: newValue,
272
+ mode
273
+ };
274
+ });
275
+ };
276
+ const transformJoinClause = (baseModel, unsanitizedJoin, select) => {
277
+ if (!unsanitizedJoin) return void 0;
278
+ if (Object.keys(unsanitizedJoin).length === 0) return void 0;
279
+ const transformedJoin = {};
280
+ for (const [model, join] of Object.entries(unsanitizedJoin)) {
281
+ if (!join) continue;
282
+ const defaultModelName = getDefaultModelName(model);
283
+ const defaultBaseModelName = getDefaultModelName(baseModel);
284
+ let foreignKeys = Object.entries(schema[defaultModelName].fields).filter(([field, fieldAttributes]) => fieldAttributes.references && getDefaultModelName(fieldAttributes.references.model) === defaultBaseModelName);
285
+ let isForwardJoin = true;
286
+ if (!foreignKeys.length) {
287
+ foreignKeys = Object.entries(schema[defaultBaseModelName].fields).filter(([field, fieldAttributes]) => fieldAttributes.references && getDefaultModelName(fieldAttributes.references.model) === defaultModelName);
288
+ isForwardJoin = false;
289
+ }
290
+ if (!foreignKeys.length) throw new BetterAuthError(`No foreign key found for model ${model} and base model ${baseModel} while performing join operation.`);
291
+ 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.`);
292
+ const [foreignKey, foreignKeyAttributes] = foreignKeys[0];
293
+ if (!foreignKeyAttributes.references) throw new BetterAuthError(`No references found for foreign key ${foreignKey} on model ${model} while performing join operation.`);
294
+ let from;
295
+ let to;
296
+ let requiredSelectField;
297
+ if (isForwardJoin) {
298
+ requiredSelectField = foreignKeyAttributes.references.field;
299
+ from = getFieldName({
300
+ model: baseModel,
301
+ field: requiredSelectField
302
+ });
303
+ to = getFieldName({
304
+ model,
305
+ field: foreignKey
306
+ });
307
+ } else {
308
+ requiredSelectField = foreignKey;
309
+ from = getFieldName({
310
+ model: baseModel,
311
+ field: requiredSelectField
312
+ });
313
+ to = getFieldName({
314
+ model,
315
+ field: foreignKeyAttributes.references.field
316
+ });
317
+ }
318
+ if (select && !select.includes(requiredSelectField)) select.push(requiredSelectField);
319
+ const isUnique = to === "id" ? true : foreignKeyAttributes.unique ?? false;
320
+ let limit = options.advanced?.database?.defaultFindManyLimit ?? 100;
321
+ if (isUnique) limit = 1;
322
+ else if (typeof join === "object" && typeof join.limit === "number") limit = join.limit;
323
+ transformedJoin[getModelName(model)] = {
324
+ on: {
325
+ from,
326
+ to
327
+ },
328
+ limit,
329
+ relation: isUnique ? "one-to-one" : "one-to-many"
330
+ };
331
+ }
332
+ return {
333
+ join: transformedJoin,
334
+ select
335
+ };
336
+ };
337
+ /**
338
+ * Handle joins by making separate queries and combining results (fallback for adapters that don't support native joins).
339
+ */
340
+ const handleFallbackJoin = async ({ baseModel, baseData, joinModel, specificJoinConfig: joinConfig }) => {
341
+ if (!baseData) return baseData;
342
+ const modelName = getModelName(joinModel);
343
+ const field = joinConfig.on.to;
344
+ const value = baseData[getDefaultFieldName({
345
+ field: joinConfig.on.from,
346
+ model: baseModel
347
+ })];
348
+ if (value === null || value === void 0) return joinConfig.relation === "one-to-one" ? null : [];
349
+ let result;
350
+ const where = transformWhereClause({
351
+ model: modelName,
352
+ where: [{
353
+ field,
354
+ value,
355
+ operator: "eq",
356
+ connector: "AND"
357
+ }],
358
+ action: "findOne"
359
+ });
360
+ try {
361
+ if (joinConfig.relation === "one-to-one") result = await withSpan(`db findOne ${modelName}`, {
362
+ [ATTR_DB_OPERATION_NAME]: "findOne",
363
+ [ATTR_DB_COLLECTION_NAME]: modelName
364
+ }, () => adapterInstance.findOne({
365
+ model: modelName,
366
+ where
367
+ }));
368
+ else {
369
+ const limit = joinConfig.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
370
+ result = await withSpan(`db findMany ${modelName}`, {
371
+ [ATTR_DB_OPERATION_NAME]: "findMany",
372
+ [ATTR_DB_COLLECTION_NAME]: modelName
373
+ }, () => adapterInstance.findMany({
374
+ model: modelName,
375
+ where,
376
+ limit
377
+ }));
378
+ }
379
+ } catch (error) {
380
+ logger.error(`Failed to query fallback join for model ${modelName}:`, {
381
+ where,
382
+ limit: joinConfig.limit
383
+ });
384
+ console.error(error);
385
+ throw error;
386
+ }
387
+ return result;
388
+ };
389
+ const adapterInstance = customAdapter({
390
+ options,
391
+ schema,
392
+ debugLog,
393
+ getFieldName,
394
+ getModelName,
395
+ getDefaultModelName,
396
+ getDefaultFieldName,
397
+ getFieldAttributes,
398
+ transformInput,
399
+ transformOutput,
400
+ transformWhereClause
401
+ });
402
+ let lazyLoadTransaction = null;
403
+ const adapter = {
404
+ transaction: async (cb) => {
405
+ if (!lazyLoadTransaction) if (!config.transaction) lazyLoadTransaction = createAsIsTransaction(adapter);
406
+ else {
407
+ logger.debug(`[${config.adapterName}] - Using provided transaction implementation.`);
408
+ lazyLoadTransaction = config.transaction;
409
+ }
410
+ return lazyLoadTransaction(cb);
411
+ },
412
+ create: async ({ data: unsafeData, model: unsafeModel, select, forceAllowId = false }) => {
413
+ transactionId++;
414
+ const thisTransactionId = transactionId;
415
+ const model = getModelName(unsafeModel);
416
+ unsafeModel = getDefaultModelName(unsafeModel);
417
+ if ("id" in unsafeData && typeof unsafeData.id !== "undefined" && !forceAllowId) {
418
+ 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.`);
419
+ const stack = (/* @__PURE__ */ new Error()).stack?.split("\n").filter((_, i) => i !== 1).join("\n").replace("Error:", "Create method with `id` being called at:");
420
+ console.log(stack);
421
+ unsafeData.id = void 0;
422
+ }
423
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("create")} ${formatAction("Unsafe Input")}:`, {
424
+ model,
425
+ data: unsafeData
426
+ });
427
+ let data = unsafeData;
428
+ if (!config.disableTransformInput) data = await transformInput(unsafeData, unsafeModel, "create", forceAllowId);
429
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`, `${formatMethod("create")} ${formatAction("Parsed Input")}:`, {
430
+ model,
431
+ data
432
+ });
433
+ const res = await withSpan(`db create ${model}`, {
434
+ [ATTR_DB_OPERATION_NAME]: "create",
435
+ [ATTR_DB_COLLECTION_NAME]: model
436
+ }, () => adapterInstance.create({
437
+ data,
438
+ model
439
+ }));
440
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`, `${formatMethod("create")} ${formatAction("DB Result")}:`, {
441
+ model,
442
+ res
443
+ });
444
+ let transformed = res;
445
+ if (!config.disableTransformOutput) transformed = await transformOutput(res, unsafeModel, select, void 0);
446
+ debugLog({ method: "create" }, `${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`, `${formatMethod("create")} ${formatAction("Parsed Result")}:`, {
447
+ model,
448
+ data: transformed
449
+ });
450
+ return transformed;
451
+ },
452
+ update: async ({ model: unsafeModel, where: unsafeWhere, update: unsafeData }) => {
453
+ transactionId++;
454
+ const thisTransactionId = transactionId;
455
+ unsafeModel = getDefaultModelName(unsafeModel);
456
+ const model = getModelName(unsafeModel);
457
+ const where = transformWhereClause({
458
+ model: unsafeModel,
459
+ where: unsafeWhere,
460
+ action: "update"
461
+ });
462
+ if (where.length === 0) return null;
463
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("update")} ${formatAction("Unsafe Input")}:`, {
464
+ model,
465
+ data: unsafeData
466
+ });
467
+ let data = unsafeData;
468
+ if (!config.disableTransformInput) data = await transformInput(unsafeData, unsafeModel, "update");
469
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`, `${formatMethod("update")} ${formatAction("Parsed Input")}:`, {
470
+ model,
471
+ data
472
+ });
473
+ const res = await withSpan(`db update ${model}`, {
474
+ [ATTR_DB_OPERATION_NAME]: "update",
475
+ [ATTR_DB_COLLECTION_NAME]: model
476
+ }, () => adapterInstance.update({
477
+ model,
478
+ where,
479
+ update: data
480
+ }));
481
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`, `${formatMethod("update")} ${formatAction("DB Result")}:`, {
482
+ model,
483
+ data: res
484
+ });
485
+ let transformed = res;
486
+ if (!config.disableTransformOutput) transformed = await transformOutput(res, unsafeModel, void 0, void 0);
487
+ debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`, `${formatMethod("update")} ${formatAction("Parsed Result")}:`, {
488
+ model,
489
+ data: transformed
490
+ });
491
+ return transformed;
492
+ },
493
+ updateMany: async ({ model: unsafeModel, where: unsafeWhere, update: unsafeData }) => {
494
+ transactionId++;
495
+ const thisTransactionId = transactionId;
496
+ const model = getModelName(unsafeModel);
497
+ const where = transformWhereClause({
498
+ model: unsafeModel,
499
+ where: unsafeWhere,
500
+ action: "updateMany"
501
+ });
502
+ unsafeModel = getDefaultModelName(unsafeModel);
503
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("updateMany")} ${formatAction("Unsafe Input")}:`, {
504
+ model,
505
+ data: unsafeData
506
+ });
507
+ let data = unsafeData;
508
+ if (!config.disableTransformInput) data = await transformInput(unsafeData, unsafeModel, "update");
509
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`, `${formatMethod("updateMany")} ${formatAction("Parsed Input")}:`, {
510
+ model,
511
+ data
512
+ });
513
+ const updatedCount = await withSpan(`db updateMany ${model}`, {
514
+ [ATTR_DB_OPERATION_NAME]: "updateMany",
515
+ [ATTR_DB_COLLECTION_NAME]: model
516
+ }, () => adapterInstance.updateMany({
517
+ model,
518
+ where,
519
+ update: data
520
+ }));
521
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`, `${formatMethod("updateMany")} ${formatAction("DB Result")}:`, {
522
+ model,
523
+ data: updatedCount
524
+ });
525
+ debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`, `${formatMethod("updateMany")} ${formatAction("Parsed Result")}:`, {
526
+ model,
527
+ data: updatedCount
528
+ });
529
+ return updatedCount;
530
+ },
531
+ findOne: async ({ model: unsafeModel, where: unsafeWhere, select, join: unsafeJoin }) => {
532
+ transactionId++;
533
+ const thisTransactionId = transactionId;
534
+ const model = getModelName(unsafeModel);
535
+ const where = transformWhereClause({
536
+ model: unsafeModel,
537
+ where: unsafeWhere,
538
+ action: "findOne"
539
+ });
540
+ unsafeModel = getDefaultModelName(unsafeModel);
541
+ let join;
542
+ let passJoinToAdapter = true;
543
+ if (!config.disableTransformJoin) {
544
+ const result = transformJoinClause(unsafeModel, unsafeJoin, select);
545
+ if (result) {
546
+ join = result.join;
547
+ select = result.select;
548
+ }
549
+ if (!options.experimental?.joins && join && Object.keys(join).length > 0) passJoinToAdapter = false;
550
+ } else join = unsafeJoin;
551
+ debugLog({ method: "findOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`, `${formatMethod("findOne")}:`, {
552
+ model,
553
+ where,
554
+ select,
555
+ join
556
+ });
557
+ const res = await withSpan(`db findOne ${model}`, {
558
+ [ATTR_DB_OPERATION_NAME]: "findOne",
559
+ [ATTR_DB_COLLECTION_NAME]: model
560
+ }, () => adapterInstance.findOne({
561
+ model,
562
+ where,
563
+ select,
564
+ join: passJoinToAdapter ? join : void 0
565
+ }));
566
+ debugLog({ method: "findOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`, `${formatMethod("findOne")} ${formatAction("DB Result")}:`, {
567
+ model,
568
+ data: res
569
+ });
570
+ let transformed = res;
571
+ if (!config.disableTransformOutput) transformed = await transformOutput(res, unsafeModel, select, join);
572
+ debugLog({ method: "findOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`, `${formatMethod("findOne")} ${formatAction("Parsed Result")}:`, {
573
+ model,
574
+ data: transformed
575
+ });
576
+ return transformed;
577
+ },
578
+ findMany: async ({ model: unsafeModel, where: unsafeWhere, limit: unsafeLimit, select, sortBy, offset, join: unsafeJoin }) => {
579
+ transactionId++;
580
+ const thisTransactionId = transactionId;
581
+ const limit = unsafeLimit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
582
+ const model = getModelName(unsafeModel);
583
+ const where = transformWhereClause({
584
+ model: unsafeModel,
585
+ where: unsafeWhere,
586
+ action: "findMany"
587
+ });
588
+ unsafeModel = getDefaultModelName(unsafeModel);
589
+ let join;
590
+ let passJoinToAdapter = true;
591
+ if (!config.disableTransformJoin) {
592
+ const result = transformJoinClause(unsafeModel, unsafeJoin, select);
593
+ if (result) {
594
+ join = result.join;
595
+ select = result.select;
596
+ }
597
+ if (!options.experimental?.joins && join && Object.keys(join).length > 0) passJoinToAdapter = false;
598
+ } else join = unsafeJoin;
599
+ debugLog({ method: "findMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`, `${formatMethod("findMany")}:`, {
600
+ model,
601
+ where,
602
+ limit,
603
+ sortBy,
604
+ offset,
605
+ join
606
+ });
607
+ const res = await withSpan(`db findMany ${model}`, {
608
+ [ATTR_DB_OPERATION_NAME]: "findMany",
609
+ [ATTR_DB_COLLECTION_NAME]: model
610
+ }, () => adapterInstance.findMany({
611
+ model,
612
+ where,
613
+ limit,
614
+ select,
615
+ sortBy,
616
+ offset,
617
+ join: passJoinToAdapter ? join : void 0
618
+ }));
619
+ debugLog({ method: "findMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`, `${formatMethod("findMany")} ${formatAction("DB Result")}:`, {
620
+ model,
621
+ data: res
622
+ });
623
+ let transformed = res;
624
+ if (!config.disableTransformOutput) transformed = await Promise.all(res.map(async (r) => {
625
+ return await transformOutput(r, unsafeModel, void 0, join);
626
+ }));
627
+ debugLog({ method: "findMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`, `${formatMethod("findMany")} ${formatAction("Parsed Result")}:`, {
628
+ model,
629
+ data: transformed
630
+ });
631
+ return transformed;
632
+ },
633
+ delete: async ({ model: unsafeModel, where: unsafeWhere }) => {
634
+ transactionId++;
635
+ const thisTransactionId = transactionId;
636
+ const model = getModelName(unsafeModel);
637
+ const where = transformWhereClause({
638
+ model: unsafeModel,
639
+ where: unsafeWhere,
640
+ action: "delete"
641
+ });
642
+ unsafeModel = getDefaultModelName(unsafeModel);
643
+ debugLog({ method: "delete" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("delete")}:`, {
644
+ model,
645
+ where
646
+ });
647
+ await withSpan(`db delete ${model}`, {
648
+ [ATTR_DB_OPERATION_NAME]: "delete",
649
+ [ATTR_DB_COLLECTION_NAME]: model
650
+ }, () => adapterInstance.delete({
651
+ model,
652
+ where
653
+ }));
654
+ debugLog({ method: "delete" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`, `${formatMethod("delete")} ${formatAction("DB Result")}:`, { model });
655
+ },
656
+ deleteMany: async ({ model: unsafeModel, where: unsafeWhere }) => {
657
+ transactionId++;
658
+ const thisTransactionId = transactionId;
659
+ const model = getModelName(unsafeModel);
660
+ const where = transformWhereClause({
661
+ model: unsafeModel,
662
+ where: unsafeWhere,
663
+ action: "deleteMany"
664
+ });
665
+ unsafeModel = getDefaultModelName(unsafeModel);
666
+ debugLog({ method: "deleteMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("deleteMany")} ${formatAction("DeleteMany")}:`, {
667
+ model,
668
+ where
669
+ });
670
+ const res = await withSpan(`db deleteMany ${model}`, {
671
+ [ATTR_DB_OPERATION_NAME]: "deleteMany",
672
+ [ATTR_DB_COLLECTION_NAME]: model
673
+ }, () => adapterInstance.deleteMany({
674
+ model,
675
+ where
676
+ }));
677
+ debugLog({ method: "deleteMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`, `${formatMethod("deleteMany")} ${formatAction("DB Result")}:`, {
678
+ model,
679
+ data: res
680
+ });
681
+ return res;
682
+ },
683
+ consumeOne: async ({ model: unsafeModel, where: unsafeWhere }) => {
684
+ transactionId++;
685
+ const thisTransactionId = transactionId;
686
+ const model = getModelName(unsafeModel);
687
+ const where = transformWhereClause({
688
+ model: unsafeModel,
689
+ where: unsafeWhere,
690
+ action: "consumeOne"
691
+ });
692
+ unsafeModel = getDefaultModelName(unsafeModel);
693
+ debugLog({ method: "consumeOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`, `${formatMethod("consumeOne")} ${formatAction("ConsumeOne")}:`, {
694
+ model,
695
+ where
696
+ });
697
+ let res;
698
+ let resultNeedsOutputTransform = true;
699
+ if (adapterInstance.consumeOne) res = await withSpan(`db consumeOne ${model}`, {
700
+ [ATTR_DB_OPERATION_NAME]: "consumeOne",
701
+ [ATTR_DB_COLLECTION_NAME]: model
702
+ }, () => adapterInstance.consumeOne({
703
+ model,
704
+ where
705
+ }));
706
+ else {
707
+ res = await withSpan(`db consumeOne ${model}`, {
708
+ [ATTR_DB_OPERATION_NAME]: "consumeOne",
709
+ [ATTR_DB_COLLECTION_NAME]: model
710
+ }, () => runWithTransaction(adapter, async () => {
711
+ const trx = await getCurrentAdapter(adapter);
712
+ const target = (await trx.findMany({
713
+ model: unsafeModel,
714
+ where: unsafeWhere,
715
+ limit: 1
716
+ }))[0];
717
+ if (!target) return null;
718
+ const deleted = await trx.deleteMany({
719
+ model: unsafeModel,
720
+ where: [...unsafeWhere, {
721
+ field: "id",
722
+ value: target.id,
723
+ operator: "eq",
724
+ connector: "AND",
725
+ mode: "sensitive"
726
+ }]
727
+ });
728
+ if (typeof deleted !== "number") throw new BetterAuthError(`Adapter "${config.adapterId}" returned a non-numeric value from deleteMany during the consumeOne fallback. Return the number of deleted rows, or implement a native consumeOne for atomic single-use consumption.`);
729
+ return deleted > 0 ? target : null;
730
+ }));
731
+ resultNeedsOutputTransform = false;
732
+ }
733
+ debugLog({ method: "consumeOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`, `${formatMethod("consumeOne")} ${formatAction("DB Result")}:`, {
734
+ model,
735
+ data: res
736
+ });
737
+ let transformed = res;
738
+ if (!config.disableTransformOutput && resultNeedsOutputTransform && res) transformed = await transformOutput(res, unsafeModel, void 0, void 0);
739
+ debugLog({ method: "consumeOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`, `${formatMethod("consumeOne")} ${formatAction("Parsed Result")}:`, {
740
+ model,
741
+ data: transformed
742
+ });
743
+ return transformed;
744
+ },
745
+ incrementOne: async ({ model: unsafeModel, where: unsafeWhere, increment: unsafeIncrement, set: unsafeSet }) => {
746
+ const hasIncrement = Object.keys(unsafeIncrement).length > 0;
747
+ const hasSet = !!unsafeSet && Object.keys(unsafeSet).length > 0;
748
+ if (!hasIncrement && !hasSet) throw new BetterAuthError("incrementOne requires a non-empty `increment` or `set`; both were empty.");
749
+ transactionId++;
750
+ const thisTransactionId = transactionId;
751
+ const model = getModelName(unsafeModel);
752
+ const where = transformWhereClause({
753
+ model: unsafeModel,
754
+ where: unsafeWhere,
755
+ action: "incrementOne"
756
+ });
757
+ unsafeModel = getDefaultModelName(unsafeModel);
758
+ debugLog({ method: "incrementOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`, `${formatMethod("incrementOne")} ${formatAction("IncrementOne")}:`, {
759
+ model,
760
+ where,
761
+ increment: unsafeIncrement,
762
+ set: unsafeSet
763
+ });
764
+ let res;
765
+ let resultNeedsOutputTransform = true;
766
+ if (adapterInstance.incrementOne) {
767
+ const mappedKeys = config.mapKeysTransformInput ?? {};
768
+ const increment = {};
769
+ for (const [field, delta] of Object.entries(unsafeIncrement)) increment[mappedKeys[field] || getFieldName({
770
+ model: unsafeModel,
771
+ field
772
+ })] = delta;
773
+ let set;
774
+ if (unsafeSet && !config.disableTransformInput) set = await transformInput(unsafeSet, unsafeModel, "update");
775
+ else set = unsafeSet;
776
+ if (Object.keys(increment).length === 0 && (!set || Object.keys(set).length === 0)) throw new BetterAuthError("incrementOne resolved to an empty update: every increment/set field was unknown to the schema or transformed away.");
777
+ res = await withSpan(`db incrementOne ${model}`, {
778
+ [ATTR_DB_OPERATION_NAME]: "incrementOne",
779
+ [ATTR_DB_COLLECTION_NAME]: model
780
+ }, () => adapterInstance.incrementOne({
781
+ model,
782
+ where,
783
+ increment,
784
+ set
785
+ }));
786
+ } else {
787
+ res = await withSpan(`db incrementOne ${model}`, {
788
+ [ATTR_DB_OPERATION_NAME]: "incrementOne",
789
+ [ATTR_DB_COLLECTION_NAME]: model
790
+ }, () => runWithTransaction(adapter, async () => {
791
+ const trx = await getCurrentAdapter(adapter);
792
+ const target = (await trx.findMany({
793
+ model: unsafeModel,
794
+ where: unsafeWhere,
795
+ limit: 1
796
+ }))[0];
797
+ if (!target) return null;
798
+ const nextValues = { ...unsafeSet ?? {} };
799
+ for (const [field, delta] of Object.entries(unsafeIncrement)) nextValues[field] = (typeof target[field] === "number" ? target[field] : 0) + delta;
800
+ const updated = await trx.updateMany({
801
+ model: unsafeModel,
802
+ where: [...unsafeWhere, {
803
+ field: "id",
804
+ value: target.id,
805
+ operator: "eq",
806
+ connector: "AND",
807
+ mode: "sensitive"
808
+ }],
809
+ update: nextValues
810
+ });
811
+ if (typeof updated !== "number") throw new BetterAuthError(`Adapter "${config.adapterId}" returned a non-numeric value from updateMany during the incrementOne fallback. Return the number of updated rows, or implement a native incrementOne for atomic guarded counter updates.`);
812
+ return updated > 0 ? {
813
+ ...target,
814
+ ...nextValues
815
+ } : null;
816
+ }));
817
+ resultNeedsOutputTransform = false;
818
+ }
819
+ debugLog({ method: "incrementOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`, `${formatMethod("incrementOne")} ${formatAction("DB Result")}:`, {
820
+ model,
821
+ data: res
822
+ });
823
+ let transformed = res;
824
+ if (!config.disableTransformOutput && resultNeedsOutputTransform && res) transformed = await transformOutput(res, unsafeModel, void 0, void 0);
825
+ debugLog({ method: "incrementOne" }, `${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`, `${formatMethod("incrementOne")} ${formatAction("Parsed Result")}:`, {
826
+ model,
827
+ data: transformed
828
+ });
829
+ return transformed;
830
+ },
831
+ count: async ({ model: unsafeModel, where: unsafeWhere }) => {
832
+ transactionId++;
833
+ const thisTransactionId = transactionId;
834
+ const model = getModelName(unsafeModel);
835
+ const where = transformWhereClause({
836
+ model: unsafeModel,
837
+ where: unsafeWhere,
838
+ action: "count"
839
+ });
840
+ unsafeModel = getDefaultModelName(unsafeModel);
841
+ debugLog({ method: "count" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("count")}:`, {
842
+ model,
843
+ where
844
+ });
845
+ const res = await withSpan(`db count ${model}`, {
846
+ [ATTR_DB_OPERATION_NAME]: "count",
847
+ [ATTR_DB_COLLECTION_NAME]: model
848
+ }, () => adapterInstance.count({
849
+ model,
850
+ where
851
+ }));
852
+ debugLog({ method: "count" }, `${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`, `${formatMethod("count")}:`, {
853
+ model,
854
+ data: res
855
+ });
856
+ return res;
857
+ },
858
+ createSchema: adapterInstance.createSchema ? async (_, file) => {
859
+ const tables = getAuthTables(options);
860
+ if (options.secondaryStorage && !options.session?.storeSessionInDatabase) delete tables.session;
861
+ return adapterInstance.createSchema({
862
+ file,
863
+ tables
864
+ });
865
+ } : void 0,
866
+ options: {
867
+ adapterConfig: config,
868
+ ...adapterInstance.options ?? {}
869
+ },
870
+ id: config.adapterId,
871
+ ...config.debugLogs?.isRunningAdapterTests ? { adapterTestDebugLogs: {
872
+ resetDebugLogs() {
873
+ debugLogs = debugLogs.filter((log) => log.instance !== uniqueAdapterFactoryInstanceId);
874
+ },
875
+ printDebugLogs() {
876
+ const separator = `─`.repeat(80);
877
+ const logs = debugLogs.filter((log) => log.instance === uniqueAdapterFactoryInstanceId);
878
+ if (logs.length === 0) return;
879
+ const log = logs.reverse().map((log) => {
880
+ log.args[0] = `\n${log.args[0]}`;
881
+ return [...log.args, "\n"];
882
+ }).reduce((prev, curr) => {
883
+ return [...curr, ...prev];
884
+ }, [`\n${separator}`]);
885
+ console.log(...log);
886
+ }
887
+ } } : {}
888
+ };
889
+ return adapter;
890
+ };
891
+ function formatTransactionId(transactionId) {
892
+ if (getColorDepth() < 8) return `#${transactionId}`;
893
+ return `${TTY_COLORS.fg.magenta}#${transactionId}${TTY_COLORS.reset}`;
894
+ }
895
+ function formatStep(step, total) {
896
+ return `${TTY_COLORS.bg.black}${TTY_COLORS.fg.yellow}[${step}/${total}]${TTY_COLORS.reset}`;
897
+ }
898
+ function formatMethod(method) {
899
+ return `${TTY_COLORS.bright}${method}${TTY_COLORS.reset}`;
900
+ }
901
+ function formatAction(action) {
902
+ return `${TTY_COLORS.dim}(${action})${TTY_COLORS.reset}`;
903
+ }
904
+ //#endregion
905
+ export { createAdapterFactory };