@riffdb/better-auth 0.0.0-stage → 0.2.1

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 (226) hide show
  1. package/DESIGN.md +273 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +27 -0
  4. package/README.md +323 -2
  5. package/dist/adapter.d.ts +34 -0
  6. package/dist/adapter.d.ts.map +1 -0
  7. package/dist/adapter.js +1600 -0
  8. package/dist/adapter.js.map +1 -0
  9. package/dist/generated/client.d.ts +2166 -0
  10. package/dist/generated/client.d.ts.map +1 -0
  11. package/dist/generated/client.js +2454 -0
  12. package/dist/generated/client.js.map +1 -0
  13. package/dist/index.d.ts +7 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +7 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/plugin-dispatch.d.ts +37 -0
  18. package/dist/plugin-dispatch.d.ts.map +1 -0
  19. package/dist/plugin-dispatch.js +293 -0
  20. package/dist/plugin-dispatch.js.map +1 -0
  21. package/dist/profile-contract.d.ts +63 -0
  22. package/dist/profile-contract.d.ts.map +1 -0
  23. package/dist/profile-contract.js +543 -0
  24. package/dist/profile-contract.js.map +1 -0
  25. package/dist/profile-plan.d.ts +69 -0
  26. package/dist/profile-plan.d.ts.map +1 -0
  27. package/dist/profile-plan.js +180 -0
  28. package/dist/profile-plan.js.map +1 -0
  29. package/dist/profile.d.ts +48 -0
  30. package/dist/profile.d.ts.map +1 -0
  31. package/dist/profile.js +132 -0
  32. package/dist/profile.js.map +1 -0
  33. package/dist/profiles/custom-fields/profile.d.ts +3 -0
  34. package/dist/profiles/custom-fields/profile.d.ts.map +1 -0
  35. package/dist/profiles/custom-fields/profile.js +475 -0
  36. package/dist/profiles/custom-fields/profile.js.map +1 -0
  37. package/dist/profiles/custom-fields/src/generated/client.d.ts +2710 -0
  38. package/dist/profiles/custom-fields/src/generated/client.d.ts.map +1 -0
  39. package/dist/profiles/custom-fields/src/generated/client.js +2663 -0
  40. package/dist/profiles/custom-fields/src/generated/client.js.map +1 -0
  41. package/dist/profiles/runtime/profile.d.ts +3 -0
  42. package/dist/profiles/runtime/profile.d.ts.map +1 -0
  43. package/dist/profiles/runtime/profile.js +1065 -0
  44. package/dist/profiles/runtime/profile.js.map +1 -0
  45. package/dist/profiles/runtime/src/generated/client.d.ts +4274 -0
  46. package/dist/profiles/runtime/src/generated/client.d.ts.map +1 -0
  47. package/dist/profiles/runtime/src/generated/client.js +4607 -0
  48. package/dist/profiles/runtime/src/generated/client.js.map +1 -0
  49. package/dist/runtime-materialize.d.ts +10 -0
  50. package/dist/runtime-materialize.d.ts.map +1 -0
  51. package/dist/runtime-materialize.js +344 -0
  52. package/dist/runtime-materialize.js.map +1 -0
  53. package/dist/runtime-profile.d.ts +34 -0
  54. package/dist/runtime-profile.d.ts.map +1 -0
  55. package/dist/runtime-profile.js +203 -0
  56. package/dist/runtime-profile.js.map +1 -0
  57. package/dist/testing.d.ts +11 -0
  58. package/dist/testing.d.ts.map +1 -0
  59. package/dist/testing.js +12 -0
  60. package/dist/testing.js.map +1 -0
  61. package/generated/go/client.go +2250 -0
  62. package/generated/mcp/tools.json +13922 -0
  63. package/generated/python/client.py +4454 -0
  64. package/generated/riffdb.application.exact.json +1 -0
  65. package/generated/riffdb.contract.bundle +0 -0
  66. package/generated/rust/client.rs +6524 -0
  67. package/package.json +83 -4
  68. package/profiles/custom-fields/generated/go/client.go +2578 -0
  69. package/profiles/custom-fields/generated/mcp/tools.json +15998 -0
  70. package/profiles/custom-fields/generated/python/client.py +5141 -0
  71. package/profiles/custom-fields/generated/riffdb.application.exact.json +1 -0
  72. package/profiles/custom-fields/generated/riffdb.contract.bundle +0 -0
  73. package/profiles/custom-fields/generated/rust/client.rs +7980 -0
  74. package/profiles/custom-fields/profile.ts +474 -0
  75. package/profiles/custom-fields/riffdb/contract.riff +568 -0
  76. package/profiles/custom-fields/riffdb/queries/admin_users_all_email_asc.riffq +24 -0
  77. package/profiles/custom-fields/riffdb/queries/admin_users_contains_asc.riffq +24 -0
  78. package/profiles/custom-fields/riffdb/queries/admin_users_contains_desc.riffq +24 -0
  79. package/profiles/custom-fields/riffdb/queries/admin_users_email_contains_created_desc.riffq +24 -0
  80. package/profiles/custom-fields/riffdb/queries/admin_users_email_contains_image_asc.riffq +24 -0
  81. package/profiles/custom-fields/riffdb/queries/admin_users_ends_with_asc.riffq +24 -0
  82. package/profiles/custom-fields/riffdb/queries/admin_users_ends_with_desc.riffq +24 -0
  83. package/profiles/custom-fields/riffdb/queries/admin_users_starts_with_asc.riffq +24 -0
  84. package/profiles/custom-fields/riffdb/queries/admin_users_starts_with_desc.riffq +24 -0
  85. package/profiles/custom-fields/riffdb/queries/find_account_by_id.riffq +24 -0
  86. package/profiles/custom-fields/riffdb/queries/find_account_by_provider.riffq +26 -0
  87. package/profiles/custom-fields/riffdb/queries/find_accounts_by_user_id.riffq +25 -0
  88. package/profiles/custom-fields/riffdb/queries/find_accounts_by_user_provider.riffq +27 -0
  89. package/profiles/custom-fields/riffdb/queries/find_active_sessions_by_user_id.riffq +23 -0
  90. package/profiles/custom-fields/riffdb/queries/find_credential_account.riffq +25 -0
  91. package/profiles/custom-fields/riffdb/queries/find_expired_verification_ids.riffq +17 -0
  92. package/profiles/custom-fields/riffdb/queries/find_latest_verification.riffq +20 -0
  93. package/profiles/custom-fields/riffdb/queries/find_session_by_id.riffq +20 -0
  94. package/profiles/custom-fields/riffdb/queries/find_session_by_token.riffq +20 -0
  95. package/profiles/custom-fields/riffdb/queries/find_sessions_by_token_set.riffq +20 -0
  96. package/profiles/custom-fields/riffdb/queries/find_sessions_by_user_id.riffq +21 -0
  97. package/profiles/custom-fields/riffdb/queries/find_user_by_email.riffq +16 -0
  98. package/profiles/custom-fields/riffdb/queries/find_user_by_id.riffq +15 -0
  99. package/profiles/custom-fields/riffdb/queries/find_verification_by_id.riffq +19 -0
  100. package/profiles/custom-fields/riffdb/queries/find_verifications_by_identifier.riffq +21 -0
  101. package/profiles/custom-fields/riffdb/queries/profile_account_with_user_by_provider.riffq +31 -0
  102. package/profiles/custom-fields/riffdb/queries/profile_session_with_user_by_id.riffq +14 -0
  103. package/profiles/custom-fields/riffdb/queries/profile_session_with_user_by_token.riffq +14 -0
  104. package/profiles/custom-fields/riffdb/queries/profile_sessions_with_users_by_token_set.riffq +25 -0
  105. package/profiles/custom-fields/riffdb/queries/profile_user_with_accounts_by_email.riffq +19 -0
  106. package/profiles/custom-fields/riffdb/queries/profile_user_with_accounts_by_id.riffq +19 -0
  107. package/profiles/custom-fields/riffdb.application.json +217 -0
  108. package/profiles/custom-fields/riffdb.application.lock.json +1 -0
  109. package/profiles/custom-fields/riffdb.toml +3 -0
  110. package/profiles/custom-fields/src/generated/client.ts +3096 -0
  111. package/profiles/organization-security/materialization.json +51 -0
  112. package/profiles/organization-security/riffdb/contract.riff +778 -0
  113. package/profiles/organization-security/riffdb/queries/find_account_by_id.riffq +18 -0
  114. package/profiles/organization-security/riffdb/queries/find_invitation_by_email.riffq +17 -0
  115. package/profiles/organization-security/riffdb/queries/find_invitation_by_id.riffq +18 -0
  116. package/profiles/organization-security/riffdb/queries/find_invitation_by_organization_id.riffq +17 -0
  117. package/profiles/organization-security/riffdb/queries/find_member_by_id.riffq +18 -0
  118. package/profiles/organization-security/riffdb/queries/find_member_by_user_id.riffq +17 -0
  119. package/profiles/organization-security/riffdb/queries/find_organization_by_id.riffq +16 -0
  120. package/profiles/organization-security/riffdb/queries/find_organization_by_slug.riffq +16 -0
  121. package/profiles/organization-security/riffdb/queries/find_session_by_id.riffq +18 -0
  122. package/profiles/organization-security/riffdb/queries/find_session_by_token.riffq +16 -0
  123. package/profiles/organization-security/riffdb/queries/find_team_by_id.riffq +18 -0
  124. package/profiles/organization-security/riffdb/queries/find_team_member_by_id.riffq +18 -0
  125. package/profiles/organization-security/riffdb/queries/find_team_member_by_membership_key.riffq +16 -0
  126. package/profiles/organization-security/riffdb/queries/find_team_member_by_team_id.riffq +17 -0
  127. package/profiles/organization-security/riffdb/queries/find_two_factor_by_id.riffq +18 -0
  128. package/profiles/organization-security/riffdb/queries/find_two_factor_by_secret.riffq +17 -0
  129. package/profiles/organization-security/riffdb/queries/find_user_by_email.riffq +16 -0
  130. package/profiles/organization-security/riffdb/queries/find_user_by_id.riffq +16 -0
  131. package/profiles/organization-security/riffdb/queries/find_verification_by_id.riffq +16 -0
  132. package/profiles/organization-security/riffdb/queries/find_verification_by_identifier.riffq +17 -0
  133. package/profiles/organization-security/riffdb.application.json +172 -0
  134. package/profiles/organization-security/riffdb.toml +7 -0
  135. package/profiles/organization-security.profile.json +980 -0
  136. package/profiles/runtime/generated/go/client.go +4511 -0
  137. package/profiles/runtime/generated/mcp/tools.json +30004 -0
  138. package/profiles/runtime/generated/python/client.py +9337 -0
  139. package/profiles/runtime/generated/riffdb.application.exact.json +1 -0
  140. package/profiles/runtime/generated/riffdb.contract.bundle +0 -0
  141. package/profiles/runtime/generated/rust/client.rs +13297 -0
  142. package/profiles/runtime/profile.ts +1064 -0
  143. package/profiles/runtime/riffdb/contract.riff +1053 -0
  144. package/profiles/runtime/riffdb/queries/admin_users_all_email_asc.riffq +24 -0
  145. package/profiles/runtime/riffdb/queries/admin_users_contains_asc.riffq +24 -0
  146. package/profiles/runtime/riffdb/queries/admin_users_contains_desc.riffq +24 -0
  147. package/profiles/runtime/riffdb/queries/admin_users_email_contains_created_desc.riffq +24 -0
  148. package/profiles/runtime/riffdb/queries/admin_users_email_contains_image_asc.riffq +24 -0
  149. package/profiles/runtime/riffdb/queries/admin_users_ends_with_asc.riffq +24 -0
  150. package/profiles/runtime/riffdb/queries/admin_users_ends_with_desc.riffq +24 -0
  151. package/profiles/runtime/riffdb/queries/admin_users_starts_with_asc.riffq +24 -0
  152. package/profiles/runtime/riffdb/queries/admin_users_starts_with_desc.riffq +24 -0
  153. package/profiles/runtime/riffdb/queries/find_account_by_id.riffq +24 -0
  154. package/profiles/runtime/riffdb/queries/find_account_by_provider.riffq +26 -0
  155. package/profiles/runtime/riffdb/queries/find_accounts_by_user_id.riffq +25 -0
  156. package/profiles/runtime/riffdb/queries/find_accounts_by_user_provider.riffq +27 -0
  157. package/profiles/runtime/riffdb/queries/find_active_sessions_by_user_id.riffq +23 -0
  158. package/profiles/runtime/riffdb/queries/find_credential_account.riffq +25 -0
  159. package/profiles/runtime/riffdb/queries/find_expired_verification_ids.riffq +17 -0
  160. package/profiles/runtime/riffdb/queries/find_latest_verification.riffq +20 -0
  161. package/profiles/runtime/riffdb/queries/find_session_by_id.riffq +20 -0
  162. package/profiles/runtime/riffdb/queries/find_session_by_token.riffq +20 -0
  163. package/profiles/runtime/riffdb/queries/find_sessions_by_token_set.riffq +20 -0
  164. package/profiles/runtime/riffdb/queries/find_sessions_by_user_id.riffq +21 -0
  165. package/profiles/runtime/riffdb/queries/find_user_by_email.riffq +16 -0
  166. package/profiles/runtime/riffdb/queries/find_user_by_id.riffq +15 -0
  167. package/profiles/runtime/riffdb/queries/find_verification_by_id.riffq +19 -0
  168. package/profiles/runtime/riffdb/queries/find_verifications_by_identifier.riffq +21 -0
  169. package/profiles/runtime/riffdb/queries/profile_account_with_user_by_provider.riffq +31 -0
  170. package/profiles/runtime/riffdb/queries/profile_invitation_by_email.riffq +17 -0
  171. package/profiles/runtime/riffdb/queries/profile_invitation_by_id.riffq +17 -0
  172. package/profiles/runtime/riffdb/queries/profile_invitation_by_organization_email_status.riffq +19 -0
  173. package/profiles/runtime/riffdb/queries/profile_invitation_by_organization_id.riffq +17 -0
  174. package/profiles/runtime/riffdb/queries/profile_invitation_by_organization_status.riffq +18 -0
  175. package/profiles/runtime/riffdb/queries/profile_member_by_id.riffq +27 -0
  176. package/profiles/runtime/riffdb/queries/profile_member_by_organization.riffq +20 -0
  177. package/profiles/runtime/riffdb/queries/profile_member_by_organization_created_at_asc.riffq +20 -0
  178. package/profiles/runtime/riffdb/queries/profile_member_by_organization_created_at_desc.riffq +20 -0
  179. package/profiles/runtime/riffdb/queries/profile_member_by_organization_role_asc.riffq +20 -0
  180. package/profiles/runtime/riffdb/queries/profile_member_by_organization_role_desc.riffq +20 -0
  181. package/profiles/runtime/riffdb/queries/profile_member_by_organization_user.riffq +28 -0
  182. package/profiles/runtime/riffdb/queries/profile_member_by_user.riffq +27 -0
  183. package/profiles/runtime/riffdb/queries/profile_organization_by_id.riffq +27 -0
  184. package/profiles/runtime/riffdb/queries/profile_organization_by_slug.riffq +27 -0
  185. package/profiles/runtime/riffdb/queries/profile_session_with_user_by_id.riffq +14 -0
  186. package/profiles/runtime/riffdb/queries/profile_session_with_user_by_token.riffq +14 -0
  187. package/profiles/runtime/riffdb/queries/profile_sessions_with_users_by_token_set.riffq +25 -0
  188. package/profiles/runtime/riffdb/queries/profile_two_factor_by_id.riffq +17 -0
  189. package/profiles/runtime/riffdb/queries/profile_two_factor_by_user.riffq +17 -0
  190. package/profiles/runtime/riffdb/queries/profile_user_with_accounts_by_email.riffq +19 -0
  191. package/profiles/runtime/riffdb/queries/profile_user_with_accounts_by_id.riffq +19 -0
  192. package/profiles/runtime/riffdb/queries/profile_users_by_id_set.riffq +8 -0
  193. package/profiles/runtime/riffdb.application.json +324 -0
  194. package/profiles/runtime/riffdb.application.lock.json +1 -0
  195. package/profiles/runtime/riffdb.toml +3 -0
  196. package/profiles/runtime/src/generated/client.ts +5186 -0
  197. package/riffdb/contract.riff +547 -0
  198. package/riffdb/queries/admin_users_all_email_asc.riffq +24 -0
  199. package/riffdb/queries/admin_users_contains_asc.riffq +24 -0
  200. package/riffdb/queries/admin_users_contains_desc.riffq +24 -0
  201. package/riffdb/queries/admin_users_email_contains_created_desc.riffq +24 -0
  202. package/riffdb/queries/admin_users_email_contains_image_asc.riffq +24 -0
  203. package/riffdb/queries/admin_users_ends_with_asc.riffq +24 -0
  204. package/riffdb/queries/admin_users_ends_with_desc.riffq +24 -0
  205. package/riffdb/queries/admin_users_starts_with_asc.riffq +24 -0
  206. package/riffdb/queries/admin_users_starts_with_desc.riffq +24 -0
  207. package/riffdb/queries/find_account_by_id.riffq +24 -0
  208. package/riffdb/queries/find_account_by_provider.riffq +26 -0
  209. package/riffdb/queries/find_accounts_by_user_id.riffq +25 -0
  210. package/riffdb/queries/find_accounts_by_user_provider.riffq +27 -0
  211. package/riffdb/queries/find_active_sessions_by_user_id.riffq +23 -0
  212. package/riffdb/queries/find_credential_account.riffq +25 -0
  213. package/riffdb/queries/find_expired_verification_ids.riffq +17 -0
  214. package/riffdb/queries/find_latest_verification.riffq +20 -0
  215. package/riffdb/queries/find_session_by_id.riffq +20 -0
  216. package/riffdb/queries/find_session_by_token.riffq +20 -0
  217. package/riffdb/queries/find_sessions_by_token_set.riffq +20 -0
  218. package/riffdb/queries/find_sessions_by_user_id.riffq +21 -0
  219. package/riffdb/queries/find_user_by_email.riffq +16 -0
  220. package/riffdb/queries/find_user_by_id.riffq +15 -0
  221. package/riffdb/queries/find_verification_by_id.riffq +19 -0
  222. package/riffdb/queries/find_verifications_by_identifier.riffq +21 -0
  223. package/riffdb.application.json +187 -0
  224. package/riffdb.application.lock.json +1 -0
  225. package/scripts/real-riffdb-runner.mjs +333 -0
  226. package/src/generated/client.ts +2746 -0
@@ -0,0 +1,1600 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join, parse } from "node:path";
3
+ import { createRequire } from "node:module";
4
+ import { DriverGeneratedApplicationTransport, } from "@riffdb/client";
5
+ import { createAdapterFactory, } from "better-auth/adapters";
6
+ import { RiffDBBetterAuthCoreClient, } from "./generated/client.js";
7
+ import { BETTER_AUTH_PINNED_VERSION, SUPPORTED_BETTER_AUTH_VERSIONS } from "./profile.js";
8
+ import { validateRuntimeProfile, instantiateProfileClient, encodeProfileField, decodeProfileField, storageField } from "./runtime-profile.js";
9
+ import { ProfilePluginDispatcher } from "./plugin-dispatch.js";
10
+ const CORE_SCHEMA_FIELDS = {
11
+ user: ["name", "email", "emailVerified", "image", "createdAt", "updatedAt"],
12
+ session: [
13
+ "expiresAt",
14
+ "token",
15
+ "createdAt",
16
+ "updatedAt",
17
+ "ipAddress",
18
+ "userAgent",
19
+ "userId",
20
+ ],
21
+ account: [
22
+ "accountId",
23
+ "providerId",
24
+ "userId",
25
+ "accessToken",
26
+ "refreshToken",
27
+ "idToken",
28
+ "accessTokenExpiresAt",
29
+ "refreshTokenExpiresAt",
30
+ "scope",
31
+ "password",
32
+ "createdAt",
33
+ "updatedAt",
34
+ ],
35
+ verification: ["identifier", "value", "expiresAt", "createdAt", "updatedAt"],
36
+ };
37
+ export class RiffDBBetterAuthCallError extends Error {
38
+ code;
39
+ operation;
40
+ outcome;
41
+ constructor(code, operation, outcome) {
42
+ super(outcome === undefined
43
+ ? `RiffDB Better Auth ${operation} failed: ${code}`
44
+ : `RiffDB Better Auth ${operation} failed: ${code} (${outcome})`);
45
+ this.code = code;
46
+ this.operation = operation;
47
+ this.outcome = outcome;
48
+ this.name = "RiffDBBetterAuthCallError";
49
+ }
50
+ }
51
+ function fail(code, operation, outcome) {
52
+ throw new RiffDBBetterAuthCallError(code, operation, outcome);
53
+ }
54
+ function isUuid(value) {
55
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(value);
56
+ }
57
+ function validateConfiguration(config) {
58
+ if (!isUuid(config.organizationId))
59
+ fail("invalid_configuration", "configuration");
60
+ if (config.debugLogs !== undefined && config.debugLogs !== false) {
61
+ fail("invalid_configuration", "debugLogs");
62
+ }
63
+ }
64
+ export function assertSupportedBetterAuthInstallation(installedVersion = resolveInstalledBetterAuthVersion()) {
65
+ if (!SUPPORTED_BETTER_AUTH_VERSIONS.some((version) => version === installedVersion)) {
66
+ fail("invalid_configuration", "betterAuthVersion");
67
+ }
68
+ }
69
+ function resolveInstalledBetterAuthVersion() {
70
+ const require = createRequire(import.meta.url);
71
+ let directory = dirname(require.resolve("better-auth"));
72
+ const root = parse(directory).root;
73
+ for (let depth = 0; depth < 8 && directory !== root; depth += 1) {
74
+ try {
75
+ const manifest = JSON.parse(readFileSync(join(directory, "package.json"), "utf8"));
76
+ if (manifest.name === "better-auth" && typeof manifest.version === "string") {
77
+ return manifest.version;
78
+ }
79
+ }
80
+ catch (error) {
81
+ const code = error.code;
82
+ if (code !== "ENOENT" && code !== "ENOTDIR")
83
+ throw error;
84
+ }
85
+ directory = dirname(directory);
86
+ }
87
+ fail("invalid_configuration", "betterAuthVersion");
88
+ }
89
+ function validateResolvedSchema(options, schema, profile) {
90
+ if (options.advanced?.database?.generateId !== "uuid") {
91
+ fail("invalid_configuration", "generateId");
92
+ }
93
+ if (options.databaseHooks !== undefined || options.emailAndPassword?.revokeSessionsOnPasswordReset) {
94
+ fail("invalid_configuration", "transactionConfiguration");
95
+ }
96
+ if (profile !== undefined) {
97
+ try {
98
+ validateRuntimeProfile(profile, options, schema);
99
+ }
100
+ catch {
101
+ fail("invalid_configuration", "compiledProfile");
102
+ }
103
+ return;
104
+ }
105
+ for (const plugin of options.plugins ?? []) {
106
+ if (plugin.id !== "next-cookies" || plugin.version !== BETTER_AUTH_PINNED_VERSION || plugin.schema !== undefined) {
107
+ fail("invalid_configuration", "plugins");
108
+ }
109
+ }
110
+ const modelNames = Object.keys(schema).sort();
111
+ const expectedModels = Object.keys(CORE_SCHEMA_FIELDS).sort();
112
+ if (JSON.stringify(modelNames) !== JSON.stringify(expectedModels)) {
113
+ fail("invalid_configuration", "models");
114
+ }
115
+ for (const model of expectedModels) {
116
+ const resolved = schema[model];
117
+ if (resolved === undefined || resolved.modelName !== model) {
118
+ fail("invalid_configuration", `${model}.modelName`);
119
+ }
120
+ const fields = Object.keys(resolved.fields).sort();
121
+ const expected = [...CORE_SCHEMA_FIELDS[model]].sort();
122
+ if (JSON.stringify(fields) !== JSON.stringify(expected)) {
123
+ fail("invalid_configuration", `${model}.fields`);
124
+ }
125
+ for (const field of expected) {
126
+ const attributes = resolved.fields[field];
127
+ if (attributes?.fieldName !== undefined && attributes.fieldName !== field) {
128
+ fail("invalid_configuration", `${model}.${field}.fieldName`);
129
+ }
130
+ }
131
+ }
132
+ }
133
+ function asRecord(value, operation) {
134
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
135
+ fail("invalid_record_shape", operation);
136
+ }
137
+ return value;
138
+ }
139
+ function requiredString(record, field, operation) {
140
+ const value = record[field];
141
+ if (typeof value !== "string" || value.length === 0)
142
+ fail("invalid_record_shape", operation);
143
+ return value;
144
+ }
145
+ function nullableString(record, field, operation) {
146
+ const value = record[field];
147
+ if (value === undefined || value === null)
148
+ return null;
149
+ if (typeof value !== "string")
150
+ fail("invalid_record_shape", operation);
151
+ return value;
152
+ }
153
+ function requiredBoolean(record, field, operation) {
154
+ const value = record[field];
155
+ if (typeof value !== "boolean")
156
+ fail("invalid_record_shape", operation);
157
+ return value;
158
+ }
159
+ function requiredDate(record, field, operation) {
160
+ const value = record[field];
161
+ if (!(value instanceof Date) || !Number.isFinite(value.getTime())) {
162
+ fail("invalid_record_shape", operation);
163
+ }
164
+ return value;
165
+ }
166
+ function nullableDate(record, field, operation) {
167
+ const value = record[field];
168
+ if (value === undefined || value === null)
169
+ return null;
170
+ if (!(value instanceof Date) || !Number.isFinite(value.getTime())) {
171
+ fail("invalid_record_shape", operation);
172
+ }
173
+ return value;
174
+ }
175
+ function toTimestamp(value) {
176
+ const milliseconds = value.getTime();
177
+ const seconds = Math.floor(milliseconds / 1_000);
178
+ return {
179
+ seconds: BigInt(seconds),
180
+ nanos: (milliseconds - seconds * 1_000) * 1_000_000,
181
+ };
182
+ }
183
+ function fromTimestamp(value) {
184
+ const milliseconds = Number(value.seconds) * 1_000 + value.nanos / 1_000_000;
185
+ if (!Number.isSafeInteger(milliseconds))
186
+ fail("invalid_record_shape", "timestamp result");
187
+ return new Date(milliseconds);
188
+ }
189
+ function timestampOrNull(value) {
190
+ return value === null ? null : toTimestamp(value);
191
+ }
192
+ function exactWhere(where, fields) {
193
+ if (where === undefined || where.length !== fields.length)
194
+ return false;
195
+ const actualFields = new Set(where.map((clause) => clause.field));
196
+ return (actualFields.size === fields.length &&
197
+ fields.every((field) => actualFields.has(field)) &&
198
+ where.every((clause) => clause.operator === "eq" &&
199
+ clause.connector === "AND" &&
200
+ clause.mode === "sensitive"));
201
+ }
202
+ function exactWhereShape(where, shape) {
203
+ if (where === undefined || where.length !== shape.length)
204
+ return false;
205
+ return (new Set(where.map((clause) => clause.field)).size === shape.length &&
206
+ shape.every(({ field, operator }) => where.some((clause) => clause.field === field && clause.operator === operator)) &&
207
+ where.every((clause) => clause.connector === "AND" && clause.mode === "sensitive"));
208
+ }
209
+ function whereValue(where, field, operation) {
210
+ const value = where.find((clause) => clause.field === field)?.value;
211
+ if (typeof value !== "string")
212
+ fail("unsupported_call_shape", operation);
213
+ return value;
214
+ }
215
+ function whereDate(where, field, operation) {
216
+ const value = where.find((clause) => clause.field === field)?.value;
217
+ if (!(value instanceof Date) || !Number.isFinite(value.getTime())) {
218
+ fail("unsupported_call_shape", operation);
219
+ }
220
+ return value;
221
+ }
222
+ function whereStringSet(where, field, operation) {
223
+ const value = where.find((clause) => clause.field === field)?.value;
224
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item.length === 0)) {
225
+ fail("unsupported_call_shape", operation);
226
+ }
227
+ const values = [...new Set(value)];
228
+ if (values.length === 0 || values.length > 32)
229
+ fail("result_bound_exceeded", operation);
230
+ return values;
231
+ }
232
+ function adminUserWhere(where, operation) {
233
+ const clauses = where ?? [];
234
+ if (clauses.length > 2)
235
+ fail("unsupported_call_shape", operation);
236
+ const id = clauses.find((clause) => clause.field === "id");
237
+ const search = clauses.find((clause) => clause.field !== "id");
238
+ if ((id !== undefined &&
239
+ (id.operator !== "eq" || id.connector !== "AND" || id.mode !== "sensitive")) ||
240
+ (search !== undefined &&
241
+ (search.field !== "email" ||
242
+ !new Set(["contains", "starts_with", "ends_with"]).has(search.operator ?? "") ||
243
+ search.connector !== "AND" ||
244
+ search.mode !== "sensitive")) ||
245
+ (id === undefined && search === undefined && clauses.length !== 0) ||
246
+ Number(id !== undefined) + Number(search !== undefined) !== clauses.length) {
247
+ fail("unsupported_call_shape", operation);
248
+ }
249
+ const userId = id === undefined ? null : id.value;
250
+ if (userId !== null && (typeof userId !== "string" || !isUuid(userId))) {
251
+ fail("unsupported_call_shape", operation);
252
+ }
253
+ if (search === undefined)
254
+ return Object.freeze({ userId });
255
+ if (typeof search.value !== "string" || search.value.length === 0) {
256
+ fail("unsupported_call_shape", operation);
257
+ }
258
+ return Object.freeze({
259
+ operator: search.operator,
260
+ needle: search.value,
261
+ userId,
262
+ });
263
+ }
264
+ function assertNoJoin(join, operation) {
265
+ if (join !== undefined && Object.keys(join).length !== 0) {
266
+ fail("unsupported_call_shape", operation);
267
+ }
268
+ }
269
+ function requireOutcome(result, operation, expected) {
270
+ const outcome = result.outcome.outcome;
271
+ if (outcome !== expected)
272
+ fail("declared_outcome", operation, outcome);
273
+ }
274
+ function mapUser(row) {
275
+ return {
276
+ id: row.user_id,
277
+ name: row.name,
278
+ email: row.email,
279
+ emailVerified: row.email_verified,
280
+ image: row.image,
281
+ createdAt: fromTimestamp(row.created_at),
282
+ updatedAt: fromTimestamp(row.updated_at),
283
+ };
284
+ }
285
+ function mapSession(row) {
286
+ return {
287
+ id: row.id,
288
+ userId: row.user_id,
289
+ token: row.token,
290
+ expiresAt: fromTimestamp(row.expires_at),
291
+ ipAddress: row.ip_address,
292
+ userAgent: row.user_agent,
293
+ createdAt: fromTimestamp(row.created_at),
294
+ updatedAt: fromTimestamp(row.updated_at),
295
+ };
296
+ }
297
+ function mapAccount(row) {
298
+ return {
299
+ id: row.id,
300
+ userId: row.user_id,
301
+ accountId: row.account_id,
302
+ providerId: row.provider_id,
303
+ accessToken: row.access_token,
304
+ refreshToken: row.refresh_token,
305
+ accessTokenExpiresAt: row.access_token_expires_at === null ? null : fromTimestamp(row.access_token_expires_at),
306
+ refreshTokenExpiresAt: row.refresh_token_expires_at === null ? null : fromTimestamp(row.refresh_token_expires_at),
307
+ scope: row.scope,
308
+ idToken: row.id_token,
309
+ password: row.password,
310
+ createdAt: fromTimestamp(row.created_at),
311
+ updatedAt: fromTimestamp(row.updated_at),
312
+ };
313
+ }
314
+ function mapVerification(row) {
315
+ return {
316
+ id: row.verification_id,
317
+ identifier: row.identifier,
318
+ value: row.value,
319
+ expiresAt: fromTimestamp(row.expires_at),
320
+ createdAt: fromTimestamp(row.created_at),
321
+ updatedAt: fromTimestamp(row.updated_at),
322
+ };
323
+ }
324
+ class CoreDispatcher {
325
+ client;
326
+ organizationId;
327
+ resetModelForTesting;
328
+ profile;
329
+ plugins;
330
+ constructor(client, organizationId, resetModelForTesting, profile) {
331
+ this.client = client;
332
+ this.organizationId = organizationId;
333
+ this.resetModelForTesting = resetModelForTesting;
334
+ this.profile = profile;
335
+ this.plugins = profile === undefined ? undefined : new ProfilePluginDispatcher(profile, client, organizationId);
336
+ }
337
+ fields(model) {
338
+ return this.profile?.plan.models.find((entry) => entry.name === model)?.fields
339
+ .filter((field) => !CORE_SCHEMA_FIELDS[model].includes(field.name)) ?? [];
340
+ }
341
+ encodeExtra(model, data, prefix = "") {
342
+ return Object.fromEntries(this.fields(model).map((field) => [prefix + storageField(field.name), encodeProfileField(field, data[field.name])]));
343
+ }
344
+ decodeExtra(model, row) {
345
+ return Object.fromEntries(this.fields(model).map((field) => [field.name, decodeProfileField(field, row[storageField(field.name)])]));
346
+ }
347
+ mapUser = (row) => ({ ...mapUser(row), ...this.decodeExtra("user", row) });
348
+ mapSession = (row) => ({ ...mapSession(row), ...this.decodeExtra("session", row) });
349
+ mapAccount = (row) => ({ ...mapAccount(row), ...this.decodeExtra("account", row) });
350
+ mapVerification = (row) => ({ ...mapVerification(row), ...this.decodeExtra("verification", row) });
351
+ normalizeCreate(model, data) {
352
+ if (!(model in CORE_SCHEMA_FIELDS))
353
+ return { ...data };
354
+ return { ...data, ...this.decodeExtra(model, this.encodeExtra(model, data)) };
355
+ }
356
+ async create(model, dataValue) {
357
+ const data = asRecord(dataValue, `create ${model}`);
358
+ if (this.plugins?.supports(model))
359
+ return this.plugins.create(model, data);
360
+ if (model === "user") {
361
+ const result = await this.client.createUser({
362
+ ...this.encodeExtra("user", data),
363
+ request_id: "",
364
+ organization_id: this.organizationId,
365
+ id: requiredString(data, "id", "create user"),
366
+ name: requiredString(data, "name", "create user"),
367
+ email: requiredString(data, "email", "create user"),
368
+ email_verified: requiredBoolean(data, "emailVerified", "create user"),
369
+ image: nullableString(data, "image", "create user"),
370
+ created_at: toTimestamp(requiredDate(data, "createdAt", "create user")),
371
+ updated_at: toTimestamp(requiredDate(data, "updatedAt", "create user")),
372
+ });
373
+ requireOutcome(result, "create user", "UserCreated");
374
+ return { ...this.normalizeCreate(model, data), image: data.image ?? null };
375
+ }
376
+ if (model === "account") {
377
+ const result = await this.client.createAccount({
378
+ ...this.encodeExtra("account", data),
379
+ request_id: "",
380
+ organization_id: this.organizationId,
381
+ id: requiredString(data, "id", "create account"),
382
+ user_id: requiredString(data, "userId", "create account"),
383
+ account_id: requiredString(data, "accountId", "create account"),
384
+ provider_id: requiredString(data, "providerId", "create account"),
385
+ access_token: nullableString(data, "accessToken", "create account"),
386
+ refresh_token: nullableString(data, "refreshToken", "create account"),
387
+ access_token_expires_at: timestampOrNull(nullableDate(data, "accessTokenExpiresAt", "create account")),
388
+ refresh_token_expires_at: timestampOrNull(nullableDate(data, "refreshTokenExpiresAt", "create account")),
389
+ scope: nullableString(data, "scope", "create account"),
390
+ id_token: nullableString(data, "idToken", "create account"),
391
+ password: nullableString(data, "password", "create account"),
392
+ created_at: toTimestamp(requiredDate(data, "createdAt", "create account")),
393
+ updated_at: toTimestamp(requiredDate(data, "updatedAt", "create account")),
394
+ });
395
+ requireOutcome(result, "create account", "AccountCreated");
396
+ return this.normalizeCreate(model, data);
397
+ }
398
+ if (model === "session") {
399
+ const token = requiredString(data, "token", "create session");
400
+ const result = await this.client.createSession({
401
+ ...this.encodeExtra("session", data),
402
+ request_id: "",
403
+ organization_id: this.organizationId,
404
+ id: requiredString(data, "id", "create session"),
405
+ user_id: requiredString(data, "userId", "create session"),
406
+ token,
407
+ expires_at: toTimestamp(requiredDate(data, "expiresAt", "create session")),
408
+ ip_address: nullableString(data, "ipAddress", "create session"),
409
+ user_agent: nullableString(data, "userAgent", "create session"),
410
+ created_at: toTimestamp(requiredDate(data, "createdAt", "create session")),
411
+ updated_at: toTimestamp(requiredDate(data, "updatedAt", "create session")),
412
+ });
413
+ requireOutcome(result, "create session", "SessionCreated");
414
+ return this.normalizeCreate(model, data);
415
+ }
416
+ if (model === "verification") {
417
+ const result = await this.client.createVerification({
418
+ ...this.encodeExtra("verification", data),
419
+ request_id: "",
420
+ organization_id: this.organizationId,
421
+ id: requiredString(data, "id", "create verification"),
422
+ identifier: requiredString(data, "identifier", "create verification"),
423
+ value: requiredString(data, "value", "create verification"),
424
+ expires_at: toTimestamp(requiredDate(data, "expiresAt", "create verification")),
425
+ created_at: toTimestamp(requiredDate(data, "createdAt", "create verification")),
426
+ updated_at: toTimestamp(requiredDate(data, "updatedAt", "create verification")),
427
+ });
428
+ requireOutcome(result, "create verification", "VerificationCreated");
429
+ return this.normalizeCreate(model, data);
430
+ }
431
+ return fail("unsupported_model", `create ${model}`);
432
+ }
433
+ async findOne(model, where, join) {
434
+ if (this.plugins?.supports(model))
435
+ return (await this.plugins.read(model, where, 1, undefined, 0, join)).rows[0] ?? null;
436
+ if (this.plugins !== undefined && join !== undefined && Object.keys(join).length > 0) {
437
+ const value = await this.plugins.joinedCore(model, where, join, false);
438
+ if (value.outcome === "Missing")
439
+ return null;
440
+ if (model === "user" && value.accounts.length > 32)
441
+ fail("result_bound_exceeded", "user accounts");
442
+ if (model === "user")
443
+ return { ...this.mapUser(value.user),
444
+ account: value.accounts.slice(0, join.account?.limit ?? 100).map(this.mapAccount) };
445
+ return { ...this.mapSession(value.session),
446
+ user: this.mapUser(value.user) };
447
+ }
448
+ assertNoJoin(join, `findOne ${model}`);
449
+ if (model === "user" && exactWhere(where, ["email"])) {
450
+ const result = await this.client.findUserByEmail({
451
+ organization_id: this.organizationId,
452
+ email: whereValue(where, "email", "findOne user"),
453
+ });
454
+ const row = result.value.users[0];
455
+ return row === undefined ? null : this.mapUser(row);
456
+ }
457
+ if (model === "user" && exactWhere(where, ["id"])) {
458
+ const result = await this.client.findUserById({
459
+ organization_id: this.organizationId,
460
+ id: whereValue(where, "id", "findOne user"),
461
+ });
462
+ return result.value.outcome === "Missing" ? null : this.mapUser(result.value.user);
463
+ }
464
+ if (model === "session" && exactWhere(where, ["token"])) {
465
+ const token = whereValue(where, "token", "findOne session");
466
+ const result = await this.client.findSessionByToken({
467
+ organization_id: this.organizationId,
468
+ token,
469
+ });
470
+ const row = result.value.sessions[0];
471
+ return row === undefined ? null : this.mapSession(row);
472
+ }
473
+ if (model === "session" && exactWhere(where, ["id"])) {
474
+ const result = await this.client.findSessionById({
475
+ organization_id: this.organizationId,
476
+ id: whereValue(where, "id", "findOne session"),
477
+ });
478
+ const row = result.value.sessions[0];
479
+ return row === undefined ? null : this.mapSession(row);
480
+ }
481
+ if (model === "account" && exactWhere(where, ["id"])) {
482
+ const result = await this.client.findAccountById({
483
+ organization_id: this.organizationId,
484
+ id: whereValue(where, "id", "findOne account"),
485
+ });
486
+ const row = result.value.accounts[0];
487
+ return row === undefined ? null : this.mapAccount(row);
488
+ }
489
+ if (model === "account" && exactWhere(where, ["accountId", "providerId"])) {
490
+ const result = await this.client.findAccountByProvider({
491
+ organization_id: this.organizationId,
492
+ account_id: whereValue(where, "accountId", "findOne account"),
493
+ provider_id: whereValue(where, "providerId", "findOne account"),
494
+ });
495
+ const row = result.value.accounts[0];
496
+ return row === undefined ? null : this.mapAccount(row);
497
+ }
498
+ if (model === "account" && exactWhere(where, ["userId", "accountId", "providerId"])) {
499
+ const result = await this.client.findCredentialAccount({
500
+ organization_id: this.organizationId,
501
+ user_id: whereValue(where, "userId", "findCredentialAccount"),
502
+ account_id: whereValue(where, "accountId", "findCredentialAccount"),
503
+ provider_id: whereValue(where, "providerId", "findCredentialAccount"),
504
+ });
505
+ const row = result.value.accounts[0];
506
+ return row === undefined ? null : this.mapAccount(row);
507
+ }
508
+ if (model === "verification" && exactWhere(where, ["id"])) {
509
+ const result = await this.client.findVerificationById({
510
+ organization_id: this.organizationId,
511
+ id: whereValue(where, "id", "findOne verification"),
512
+ });
513
+ const value = result.value;
514
+ return value.outcome === "Missing"
515
+ ? null
516
+ : this.mapVerification(value.verification);
517
+ }
518
+ return fail("unsupported_call_shape", `findOne ${model}`);
519
+ }
520
+ async update(model, where, updateValue) {
521
+ if (this.plugins?.supports(model))
522
+ return this.plugins.update(model, where, asRecord(updateValue, "update"));
523
+ if (model === "account" && exactWhere(where, ["id"])) {
524
+ const update = asRecord(updateValue, "update account");
525
+ const allowed = new Set([
526
+ ...this.fields("account").map((field) => field.name),
527
+ "accountId",
528
+ "providerId",
529
+ "accessToken",
530
+ "refreshToken",
531
+ "accessTokenExpiresAt",
532
+ "refreshTokenExpiresAt",
533
+ "scope",
534
+ "idToken",
535
+ "password",
536
+ "updatedAt",
537
+ ]);
538
+ const fields = Object.keys(update);
539
+ if (fields.length === 0 || fields.some((field) => !allowed.has(field))) {
540
+ fail("unsupported_call_shape", "update account");
541
+ }
542
+ const id = whereValue(where, "id", "update account");
543
+ for (let attempt = 0; attempt < 3; attempt += 1) {
544
+ const found = await this.client.findAccountById({
545
+ organization_id: this.organizationId,
546
+ id,
547
+ });
548
+ const row = found.value.accounts[0];
549
+ if (row === undefined)
550
+ return null;
551
+ const successor = { ...mapAccount(row), ...update };
552
+ const updated = await this.client.updateAccount({
553
+ ...this.encodeExtra("account", successor),
554
+ request_id: "",
555
+ organization_id: this.organizationId,
556
+ user_id: row.user_id,
557
+ account_id: row.id,
558
+ expected_revision: row.revision,
559
+ external_account_id: requiredString(successor, "accountId", "update account"),
560
+ provider_id: requiredString(successor, "providerId", "update account"),
561
+ access_token: nullableString(successor, "accessToken", "update account"),
562
+ refresh_token: nullableString(successor, "refreshToken", "update account"),
563
+ access_token_expires_at: timestampOrNull(nullableDate(successor, "accessTokenExpiresAt", "update account")),
564
+ refresh_token_expires_at: timestampOrNull(nullableDate(successor, "refreshTokenExpiresAt", "update account")),
565
+ scope: nullableString(successor, "scope", "update account"),
566
+ id_token: nullableString(successor, "idToken", "update account"),
567
+ password: nullableString(successor, "password", "update account"),
568
+ updated_at: toTimestamp(requiredDate(successor, "updatedAt", "update account")),
569
+ });
570
+ if (updated.outcome.outcome === "AccountUpdateStale")
571
+ continue;
572
+ if (updated.outcome.outcome === "AccountUpdateMissing")
573
+ return null;
574
+ requireOutcome(updated, "update account", "AccountUpdated");
575
+ return successor;
576
+ }
577
+ return fail("declared_outcome", "update account", "AccountUpdateStale");
578
+ }
579
+ if (model === "session" &&
580
+ (exactWhere(where, ["id"]) || exactWhere(where, ["token"]))) {
581
+ const update = asRecord(updateValue, "update session");
582
+ const allowed = new Set(["expiresAt", "ipAddress", "userAgent", "updatedAt", ...this.fields("session").map((field) => field.name)]);
583
+ const fields = Object.keys(update);
584
+ if (fields.length === 0 || fields.some((field) => !allowed.has(field))) {
585
+ fail("unsupported_call_shape", "update session");
586
+ }
587
+ for (let attempt = 0; attempt < 3; attempt += 1) {
588
+ const result = exactWhere(where, ["id"])
589
+ ? await this.client.findSessionById({
590
+ organization_id: this.organizationId,
591
+ id: whereValue(where, "id", "update session"),
592
+ })
593
+ : await this.client.findSessionByToken({
594
+ organization_id: this.organizationId,
595
+ token: whereValue(where, "token", "update session"),
596
+ });
597
+ const row = result.value.sessions[0];
598
+ if (row === undefined)
599
+ return null;
600
+ const current = this.mapSession(row);
601
+ const successor = { ...current, ...update };
602
+ const updated = await this.client.updateSession({
603
+ ...this.encodeExtra("session", successor),
604
+ request_id: "",
605
+ organization_id: this.organizationId,
606
+ user_id: row.user_id,
607
+ session_id: row.id,
608
+ expected_revision: row.revision,
609
+ expires_at: toTimestamp(requiredDate(successor, "expiresAt", "update session")),
610
+ ip_address: nullableString(successor, "ipAddress", "update session"),
611
+ user_agent: nullableString(successor, "userAgent", "update session"),
612
+ updated_at: toTimestamp(requiredDate(successor, "updatedAt", "update session")),
613
+ });
614
+ if (updated.outcome.outcome === "SessionUpdateStale")
615
+ continue;
616
+ if (updated.outcome.outcome === "SessionUpdateMissing")
617
+ return null;
618
+ requireOutcome(updated, "update session", "SessionUpdated");
619
+ return successor;
620
+ }
621
+ return fail("declared_outcome", "update session", "SessionUpdateStale");
622
+ }
623
+ if (model !== "user" ||
624
+ (!exactWhere(where, ["id"]) && !exactWhere(where, ["email"]))) {
625
+ if (model !== "verification" || !exactWhere(where, ["identifier"])) {
626
+ return fail("unsupported_call_shape", `update ${model}`);
627
+ }
628
+ const update = asRecord(updateValue, "update verification");
629
+ const allowed = new Set(["value", "expiresAt", "updatedAt", ...this.fields("verification").map((field) => field.name)]);
630
+ const fields = Object.keys(update);
631
+ if (fields.length === 0 || fields.some((field) => !allowed.has(field))) {
632
+ fail("unsupported_call_shape", "update verification");
633
+ }
634
+ const identifier = whereValue(where, "identifier", "update verification");
635
+ for (let attempt = 0; attempt < 3; attempt += 1) {
636
+ const found = await this.client.findLatestVerification({
637
+ organization_id: this.organizationId,
638
+ identifier,
639
+ });
640
+ const row = found.value.verifications[0];
641
+ if (row === undefined)
642
+ return null;
643
+ const successor = { ...mapVerification(row), ...update };
644
+ const result = await this.client.updateVerification({
645
+ ...this.encodeExtra("verification", successor),
646
+ request_id: "",
647
+ organization_id: this.organizationId,
648
+ verification_id: row.verification_id,
649
+ expected_revision: row.revision,
650
+ value: requiredString(successor, "value", "update verification"),
651
+ expires_at: toTimestamp(requiredDate(successor, "expiresAt", "update verification")),
652
+ updated_at: toTimestamp(requiredDate(successor, "updatedAt", "update verification")),
653
+ });
654
+ if (result.outcome.outcome === "VerificationUpdateStale")
655
+ continue;
656
+ if (result.outcome.outcome === "VerificationUpdateMissing")
657
+ return null;
658
+ requireOutcome(result, "update verification", "VerificationUpdated");
659
+ return successor;
660
+ }
661
+ return fail("declared_outcome", "update verification", "VerificationUpdateStale");
662
+ }
663
+ const update = asRecord(updateValue, "update user");
664
+ const allowed = new Set(["name", "email", "emailVerified", "image", "updatedAt", ...this.fields("user").map((field) => field.name)]);
665
+ const fields = Object.keys(update);
666
+ if (fields.length === 0 || fields.some((field) => !allowed.has(field))) {
667
+ fail("unsupported_call_shape", "update user");
668
+ }
669
+ let userId = exactWhere(where, ["id"])
670
+ ? whereValue(where, "id", "update user")
671
+ : undefined;
672
+ const initialEmail = exactWhere(where, ["email"])
673
+ ? whereValue(where, "email", "update user")
674
+ : undefined;
675
+ for (let attempt = 0; attempt < 3; attempt += 1) {
676
+ const row = userId === undefined
677
+ ? (await this.client.findUserByEmail({
678
+ organization_id: this.organizationId,
679
+ email: initialEmail,
680
+ })).value.users[0]
681
+ : (await this.client.findUserById({
682
+ organization_id: this.organizationId,
683
+ id: userId,
684
+ })).value;
685
+ if (row === undefined || ("outcome" in row && row.outcome === "Missing"))
686
+ return null;
687
+ const resolved = "outcome" in row ? row.user : row;
688
+ userId = resolved.user_id;
689
+ const current = this.mapUser(resolved);
690
+ const successor = { ...current, ...update };
691
+ const result = await this.client.updateUser({
692
+ ...this.encodeExtra("user", successor),
693
+ request_id: "",
694
+ organization_id: this.organizationId,
695
+ user_id: userId,
696
+ expected_revision: resolved.revision,
697
+ name: requiredString(successor, "name", "update user"),
698
+ email: requiredString(successor, "email", "update user"),
699
+ email_verified: requiredBoolean(successor, "emailVerified", "update user"),
700
+ image: nullableString(successor, "image", "update user"),
701
+ updated_at: toTimestamp(requiredDate(successor, "updatedAt", "update user")),
702
+ });
703
+ if (result.outcome.outcome === "UserUpdateStale")
704
+ continue;
705
+ if (result.outcome.outcome === "UserUpdateMissing")
706
+ return null;
707
+ requireOutcome(result, "update user", "UserUpdated");
708
+ return successor;
709
+ }
710
+ return fail("declared_outcome", "update user", "UserUpdateStale");
711
+ }
712
+ async findMany(model, where, limit, sortBy, offset, join) {
713
+ if (this.plugins?.supports(model))
714
+ return (await this.plugins.read(model, where, limit, sortBy, offset, join)).rows;
715
+ if (this.plugins !== undefined && join !== undefined && Object.keys(join).length > 0) {
716
+ if (sortBy !== undefined || (offset !== undefined && offset !== 0))
717
+ fail("unsupported_call_shape", "core join window");
718
+ const value = await this.plugins.joinedCore(model, where ?? [], join, true, limit);
719
+ const rows = value[model === "account" ? "accounts" : "sessions"];
720
+ const users = value.users;
721
+ if (rows.length > 32 || users.length > 32)
722
+ fail("result_bound_exceeded", "core join");
723
+ return rows.slice(0, limit).map((row) => ({
724
+ ...(model === "account" ? this.mapAccount(row) : this.mapSession(row)),
725
+ user: this.mapUser(users.find((user) => user.user_id === row.user_id) ?? fail("invalid_record_shape", "core join user")),
726
+ }));
727
+ }
728
+ if (model === "user" && this.profile?.plan.plugins.includes("organization") && exactWhereShape(where, [{ field: "id", operator: "in" }])) {
729
+ assertNoJoin(join, "user ID set");
730
+ if (sortBy !== undefined || (offset !== undefined && offset !== 0))
731
+ fail("unsupported_call_shape", "user ID set");
732
+ return this.plugins.usersById(where, limit);
733
+ }
734
+ assertNoJoin(join, `findMany ${model}`);
735
+ if (!Number.isInteger(limit) || limit < 1)
736
+ fail("unsupported_call_shape", `findMany ${model}`);
737
+ if (model === "user") {
738
+ const window = await this.adminUserWindow(where, limit, sortBy, offset);
739
+ return window.users.map(this.mapUser);
740
+ }
741
+ if (offset !== undefined && offset !== 0)
742
+ fail("unsupported_call_shape", `findMany ${model}`);
743
+ if (model === "account" && exactWhere(where, ["userId"]) && sortBy === undefined) {
744
+ if (limit > 100)
745
+ fail("result_bound_exceeded", "findMany account");
746
+ const result = await this.client.findAccountsByUserId({
747
+ organization_id: this.organizationId,
748
+ user_id: whereValue(where, "userId", "findMany account"),
749
+ after: null,
750
+ });
751
+ if (result.nextCursor !== undefined)
752
+ fail("result_bound_exceeded", "findMany account");
753
+ return result.value.accounts.slice(0, limit).map(this.mapAccount);
754
+ }
755
+ if (model === "account" && exactWhere(where, ["providerId", "accountId"]) && sortBy === undefined) {
756
+ if (limit > 100)
757
+ fail("result_bound_exceeded", "findMany provider account");
758
+ const result = await this.client.findAccountByProvider({ organization_id: this.organizationId,
759
+ account_id: whereValue(where, "accountId", "findMany provider account"),
760
+ provider_id: whereValue(where, "providerId", "findMany provider account") });
761
+ return result.value.accounts.map(this.mapAccount);
762
+ }
763
+ if (model === "session" && exactWhere(where, ["userId"]) && sortBy === undefined) {
764
+ const result = await this.client.findSessionsByUserId({
765
+ organization_id: this.organizationId,
766
+ user_id: whereValue(where, "userId", "findMany session"),
767
+ after: null,
768
+ });
769
+ if (result.nextCursor !== undefined)
770
+ fail("result_bound_exceeded", "findMany session");
771
+ return result.value.sessions.slice(0, limit).map(this.mapSession);
772
+ }
773
+ if (model === "session" &&
774
+ exactWhereShape(where, [
775
+ { field: "userId", operator: "eq" },
776
+ { field: "expiresAt", operator: "gt" },
777
+ ]) &&
778
+ sortBy === undefined) {
779
+ const result = await this.client.findActiveSessionsByUserId({
780
+ organization_id: this.organizationId,
781
+ user_id: whereValue(where, "userId", "findMany active session"),
782
+ expires_after: toTimestamp(whereDate(where, "expiresAt", "findMany active session")),
783
+ after: null,
784
+ });
785
+ if (result.nextCursor !== undefined) {
786
+ fail("result_bound_exceeded", "findMany active session");
787
+ }
788
+ return result.value.sessions.slice(0, limit).map(this.mapSession);
789
+ }
790
+ const tokenSetShape = exactWhereShape(where, [{ field: "token", operator: "in" }]);
791
+ const activeTokenSetShape = exactWhereShape(where, [
792
+ { field: "token", operator: "in" },
793
+ { field: "expiresAt", operator: "gt" },
794
+ ]);
795
+ if (model === "session" &&
796
+ tokenSetShape &&
797
+ sortBy === undefined) {
798
+ const tokens = whereStringSet(where, "token", "findMany session token set");
799
+ const result = await this.client.findSessionsByTokenSet({
800
+ organization_id: this.organizationId,
801
+ tokens,
802
+ });
803
+ return result.value.sessions.slice(0, limit).map(this.mapSession);
804
+ }
805
+ if (model === "session" && activeTokenSetShape) {
806
+ return fail("unsupported_call_shape", "findMany session token set with expiry");
807
+ }
808
+ if (model === "verification" &&
809
+ exactWhere(where, ["identifier"]) &&
810
+ sortBy?.field === "createdAt" &&
811
+ sortBy.direction === "desc" &&
812
+ limit === 1) {
813
+ const result = await this.client.findLatestVerification({
814
+ organization_id: this.organizationId,
815
+ identifier: whereValue(where, "identifier", "findMany verification"),
816
+ });
817
+ return result.value.verifications.map(this.mapVerification);
818
+ }
819
+ if (model === "verification" && exactWhere(where, ["identifier"]) && sortBy !== undefined) {
820
+ return fail("unsupported_call_shape", "findMany verification sort");
821
+ }
822
+ if (model === "verification" && exactWhere(where, ["identifier"]) && limit <= 32) {
823
+ const result = await this.client.findVerificationsByIdentifier({
824
+ organization_id: this.organizationId,
825
+ identifier: whereValue(where, "identifier", "findMany verification"),
826
+ after: null,
827
+ });
828
+ if (result.nextCursor !== undefined)
829
+ fail("result_bound_exceeded", "findMany verification");
830
+ return result.value.verifications.slice(0, limit).map(this.mapVerification);
831
+ }
832
+ return fail("unsupported_call_shape", `findMany ${model}`);
833
+ }
834
+ async adminUserWindow(where, limit, sortBy, offset = 0) {
835
+ if (limit > 100 || !Number.isSafeInteger(offset) || offset < 0 || offset > 4_096) {
836
+ fail("result_bound_exceeded", "findMany user");
837
+ }
838
+ const selected = adminUserWhere(where, "findMany user");
839
+ const parameters = {
840
+ organization_id: this.organizationId,
841
+ user_id: selected.userId,
842
+ limit,
843
+ offset: BigInt(offset),
844
+ };
845
+ if (selected.operator === undefined) {
846
+ if (sortBy !== undefined && (sortBy.field !== "email" || sortBy.direction !== "asc")) {
847
+ fail("unsupported_call_shape", "findMany user sort");
848
+ }
849
+ const result = await this.client.adminUsersAllEmailAsc({
850
+ ...parameters,
851
+ minimum_email: "",
852
+ });
853
+ return result.value;
854
+ }
855
+ const direction = sortBy?.direction ?? "asc";
856
+ const field = sortBy?.field ?? "email";
857
+ const searchParameters = { ...parameters, needle: selected.needle };
858
+ if (field === "createdAt" && direction === "desc" && selected.operator === "contains") {
859
+ return (await this.client.adminUsersEmailContainsCreatedDesc(searchParameters)).value;
860
+ }
861
+ if (field === "image" && direction === "asc" && selected.operator === "contains") {
862
+ return (await this.client.adminUsersEmailContainsImageAsc(searchParameters)).value;
863
+ }
864
+ if (field !== "email")
865
+ fail("unsupported_call_shape", "findMany user sort");
866
+ if (selected.operator === "contains") {
867
+ return direction === "asc"
868
+ ? (await this.client.adminUsersContainsAsc(searchParameters)).value
869
+ : (await this.client.adminUsersContainsDesc(searchParameters)).value;
870
+ }
871
+ if (selected.operator === "starts_with") {
872
+ return direction === "asc"
873
+ ? (await this.client.adminUsersStartsWithAsc(searchParameters)).value
874
+ : (await this.client.adminUsersStartsWithDesc(searchParameters)).value;
875
+ }
876
+ return direction === "asc"
877
+ ? (await this.client.adminUsersEndsWithAsc(searchParameters)).value
878
+ : (await this.client.adminUsersEndsWithDesc(searchParameters)).value;
879
+ }
880
+ async count(model, where) {
881
+ if (this.plugins?.supports(model)) {
882
+ if (model !== "member" || !exactWhere(where, ["organizationId"]))
883
+ fail("unsupported_call_shape", "plugin count");
884
+ return (await this.plugins.read(model, where, 1)).total;
885
+ }
886
+ if (model !== "user")
887
+ fail("unsupported_call_shape", `count ${model}`);
888
+ const window = await this.adminUserWindow(where, 1, undefined, 0);
889
+ const total = window.total.value;
890
+ if (total > BigInt(Number.MAX_SAFE_INTEGER))
891
+ fail("result_bound_exceeded", "count user");
892
+ return Number(total);
893
+ }
894
+ async delete(model, where) {
895
+ if (this.plugins?.supports(model)) {
896
+ if (!exactWhere(where, ["id"]))
897
+ fail("unsupported_call_shape", "plugin delete");
898
+ return this.plugins.deleteIds(model, [whereValue(where, "id", "plugin delete")]);
899
+ }
900
+ if (model === "user" && this.profile?.plan.plugins.includes("organization"))
901
+ fail("unsupported_call_shape", "delete user in organization profile");
902
+ if (model === "user" && exactWhere(where, ["id"])) {
903
+ const result = await this.client.deleteUser({
904
+ request_id: "",
905
+ organization_id: this.organizationId,
906
+ user_ids: [whereValue(where, "id", "delete user")],
907
+ });
908
+ if (result.outcome.outcome === "DeleteUserCascadeLimitExceeded") {
909
+ fail("result_bound_exceeded", "delete user", result.outcome.outcome);
910
+ }
911
+ if (!new Set(["UserDeleted", "DeleteUserMissing"]).has(result.outcome.outcome)) {
912
+ fail("declared_outcome", "delete user", result.outcome.outcome);
913
+ }
914
+ return;
915
+ }
916
+ if (model === "account" && exactWhere(where, ["id"])) {
917
+ const account = await this.findOne(model, where);
918
+ if (account === null)
919
+ return;
920
+ const result = await this.client.deleteAccount({
921
+ request_id: "",
922
+ organization_id: this.organizationId,
923
+ user_id: requiredString(account, "userId", "delete account"),
924
+ account_ids: [requiredString(account, "id", "delete account")],
925
+ });
926
+ if (!new Set(["AccountDeleted", "AccountMissing"]).has(result.outcome.outcome)) {
927
+ fail("declared_outcome", "delete account", result.outcome.outcome);
928
+ }
929
+ return;
930
+ }
931
+ if (model === "verification" && exactWhere(where, ["id"])) {
932
+ const result = await this.client.deleteVerification({
933
+ request_id: "",
934
+ organization_id: this.organizationId,
935
+ verification_ids: [whereValue(where, "id", "delete verification")],
936
+ });
937
+ if (!new Set(["VerificationDeleted", "VerificationMissing"]).has(result.outcome.outcome)) {
938
+ fail("declared_outcome", "delete verification", result.outcome.outcome);
939
+ }
940
+ return;
941
+ }
942
+ if (model === "verification" && exactWhere(where, ["identifier"])) {
943
+ const rows = await this.findMany("verification", where, 32);
944
+ if (rows.length === 0)
945
+ return;
946
+ const result = await this.client.deleteVerification({
947
+ request_id: "",
948
+ organization_id: this.organizationId,
949
+ verification_ids: rows.map((row) => requiredString(row, "id", "delete verification by identifier")),
950
+ });
951
+ requireOutcome(result, "delete verification by identifier", "VerificationDeleted");
952
+ return;
953
+ }
954
+ if (model === "session" &&
955
+ (exactWhere(where, ["id"]) || exactWhere(where, ["token"]))) {
956
+ const session = await this.findOne("session", where);
957
+ if (session === null)
958
+ return;
959
+ const result = await this.client.deleteSession({
960
+ request_id: "",
961
+ organization_id: this.organizationId,
962
+ user_id: requiredString(session, "userId", "delete session"),
963
+ session_ids: [requiredString(session, "id", "delete session")],
964
+ });
965
+ if (!new Set(["SessionDeleted", "SessionMissing"]).has(result.outcome.outcome)) {
966
+ fail("declared_outcome", "delete session", result.outcome.outcome);
967
+ }
968
+ return;
969
+ }
970
+ fail("unsupported_call_shape", `delete ${model}`);
971
+ }
972
+ async deleteMany(model, where) {
973
+ if (this.plugins?.supports(model) && where.length > 0) {
974
+ if (!(model === "twoFactor" && (exactWhere(where, ["userId"]) || exactWhere(where, ["id"]))) &&
975
+ !(model === "member" && exactWhere(where, ["id"])))
976
+ fail("unsupported_call_shape", "plugin deleteMany");
977
+ const result = await this.plugins.read(model, where, 100);
978
+ if (result.total > 100)
979
+ fail("result_bound_exceeded", "plugin deleteMany");
980
+ await this.plugins.deleteIds(model, result.rows.map((row) => requiredString(row, "id", "plugin deleteMany")));
981
+ return result.rows.length;
982
+ }
983
+ if (where.length === 0 && this.resetModelForTesting !== undefined) {
984
+ return this.resetModelForTesting(model);
985
+ }
986
+ if (model === "session" && exactWhere(where, ["userId"])) {
987
+ const rows = await this.findMany(model, where, 32);
988
+ if (rows.length === 0)
989
+ return 0;
990
+ const result = await this.client.deleteSession({
991
+ request_id: "",
992
+ organization_id: this.organizationId,
993
+ user_id: whereValue(where, "userId", "deleteMany session"),
994
+ session_ids: rows.map((row) => requiredString(row, "id", "deleteMany session")),
995
+ });
996
+ requireOutcome(result, "deleteMany session", "SessionDeleted");
997
+ return rows.length;
998
+ }
999
+ if (model === "session" &&
1000
+ exactWhereShape(where, [{ field: "token", operator: "in" }])) {
1001
+ const rows = await this.findMany(model, where, 32);
1002
+ const byUser = new Map();
1003
+ for (const row of rows) {
1004
+ const userId = requiredString(row, "userId", "deleteMany session token set");
1005
+ const ids = byUser.get(userId) ?? [];
1006
+ ids.push(requiredString(row, "id", "deleteMany session token set"));
1007
+ byUser.set(userId, ids);
1008
+ }
1009
+ for (const [userId, sessionIds] of byUser) {
1010
+ const result = await this.client.deleteSession({
1011
+ request_id: "",
1012
+ organization_id: this.organizationId,
1013
+ user_id: userId,
1014
+ session_ids: sessionIds,
1015
+ });
1016
+ requireOutcome(result, "deleteMany session token set", "SessionDeleted");
1017
+ }
1018
+ return rows.length;
1019
+ }
1020
+ if (model === "account" && exactWhere(where, ["userId"])) {
1021
+ const rows = await this.findMany(model, where, 100);
1022
+ if (rows.length === 0)
1023
+ return 0;
1024
+ if (rows.length > 32)
1025
+ fail("result_bound_exceeded", "deleteMany account");
1026
+ const result = await this.client.deleteAccount({
1027
+ request_id: "",
1028
+ organization_id: this.organizationId,
1029
+ user_id: whereValue(where, "userId", "deleteMany account"),
1030
+ account_ids: rows.map((row) => requiredString(row, "id", "deleteMany account")),
1031
+ });
1032
+ requireOutcome(result, "deleteMany account", "AccountDeleted");
1033
+ return rows.length;
1034
+ }
1035
+ if (model === "verification" &&
1036
+ exactWhereShape(where, [{ field: "expiresAt", operator: "lt" }])) {
1037
+ const result = await this.client.findExpiredVerificationIds({
1038
+ organization_id: this.organizationId,
1039
+ expires_before: toTimestamp(whereDate(where, "expiresAt", "deleteMany expired verification")),
1040
+ after: null,
1041
+ });
1042
+ if (result.nextCursor !== undefined) {
1043
+ fail("result_bound_exceeded", "deleteMany expired verification");
1044
+ }
1045
+ const ids = result.value.verifications.map((row) => row.verification_id);
1046
+ if (ids.length === 0)
1047
+ return 0;
1048
+ const deleted = await this.client.deleteVerification({
1049
+ request_id: "",
1050
+ organization_id: this.organizationId,
1051
+ verification_ids: ids,
1052
+ });
1053
+ requireOutcome(deleted, "deleteMany expired verification", "VerificationDeleted");
1054
+ return ids.length;
1055
+ }
1056
+ if (model !== "verification" || !exactWhere(where, ["identifier"])) {
1057
+ return fail("unsupported_call_shape", `deleteMany ${model}`);
1058
+ }
1059
+ const rows = await this.findMany("verification", where, 32);
1060
+ if (rows.length === 0)
1061
+ return 0;
1062
+ const result = await this.client.consumeVerificationSet({
1063
+ request_id: "",
1064
+ organization_id: this.organizationId,
1065
+ verification_ids: rows.map((row) => requiredString(row, "id", "deleteMany verification")),
1066
+ });
1067
+ requireOutcome(result, "deleteMany verification", "VerificationSetConsumed");
1068
+ return rows.length;
1069
+ }
1070
+ async consumeOne(model, where) {
1071
+ if (model !== "verification" || !exactWhere(where, ["id"])) {
1072
+ return fail("unsupported_call_shape", `consumeOne ${model}`);
1073
+ }
1074
+ const result = await this.client.consumeVerification({
1075
+ request_id: "",
1076
+ organization_id: this.organizationId,
1077
+ verification_id: whereValue(where, "id", "consumeOne verification"),
1078
+ });
1079
+ if (result.outcome.outcome === "VerificationConsumeMissing")
1080
+ return null;
1081
+ requireOutcome(result, "consumeOne verification", "VerificationConsumed");
1082
+ return this.mapVerification(result.outcome);
1083
+ }
1084
+ async prepareConsume(id) {
1085
+ const { value } = await this.client.findVerificationById({
1086
+ organization_id: this.organizationId, id,
1087
+ });
1088
+ return value.outcome === "Missing" ? null : {
1089
+ row: this.mapVerification(value.verification), revision: value.verification.revision,
1090
+ };
1091
+ }
1092
+ async commitConsume(snapshot) {
1093
+ const result = await this.client.consumeVerificationSnapshot({
1094
+ request_id: "", organization_id: this.organizationId,
1095
+ verification_id: requiredString(snapshot.row, "id", "consumeOne"),
1096
+ expected_revision: snapshot.revision,
1097
+ });
1098
+ if (result.outcome.outcome === "VerificationConsumeMissing")
1099
+ return false;
1100
+ requireOutcome(result, "consumeOne", "VerificationConsumed");
1101
+ return true;
1102
+ }
1103
+ async commitPasswordReset(snapshot, where, update, cleanup) {
1104
+ const userId = whereValue(where, "userId", "resetPassword");
1105
+ if (!exactWhere(where, ["userId", "providerId", "accountId"]) ||
1106
+ whereValue(where, "providerId", "resetPassword") !== "credential" ||
1107
+ whereValue(where, "accountId", "resetPassword") !== userId ||
1108
+ snapshot.row.value !== userId || cleanup.length !== 0 ||
1109
+ Object.keys(update).some((field) => field !== "password" && field !== "updatedAt")) {
1110
+ fail("unsupported_transaction_shape", "resetPassword");
1111
+ }
1112
+ const password = requiredString(update, "password", "resetPassword");
1113
+ const updatedAt = toTimestamp(requiredDate(update, "updatedAt", "resetPassword"));
1114
+ for (let attempt = 0; attempt < 3; attempt += 1) {
1115
+ const { value } = await this.client.findCredentialAccount({
1116
+ organization_id: this.organizationId, user_id: userId, account_id: userId, provider_id: "credential",
1117
+ });
1118
+ const account = value.accounts[0];
1119
+ if (account === undefined)
1120
+ fail("unsupported_transaction_shape", "resetPassword create account");
1121
+ const result = await this.client.resetCredentialPassword({
1122
+ request_id: "", organization_id: this.organizationId,
1123
+ verification_ids: [requiredString(snapshot.row, "id", "resetPassword")],
1124
+ verification_revision: snapshot.revision,
1125
+ user_id: userId, external_account_id: userId, account_id: account.id,
1126
+ account_revision: account.revision, password, updated_at: updatedAt,
1127
+ });
1128
+ if (result.outcome.outcome === "PasswordAccountStale")
1129
+ continue;
1130
+ requireOutcome(result, "resetPassword", "CredentialPasswordReset");
1131
+ return;
1132
+ }
1133
+ fail("declared_outcome", "resetPassword", "PasswordAccountStale");
1134
+ }
1135
+ async updateMany(model, where, updateValue) {
1136
+ if (model === "account" && exactWhere(where, ["userId", "providerId", "accountId"])) {
1137
+ const userId = whereValue(where, "userId", "update credential password");
1138
+ if (whereValue(where, "providerId", "update credential password") !== "credential" ||
1139
+ whereValue(where, "accountId", "update credential password") !== userId ||
1140
+ Object.keys(updateValue).some((field) => field !== "password" && field !== "updatedAt"))
1141
+ fail("unsupported_call_shape", "update credential password");
1142
+ const password = requiredString(updateValue, "password", "update credential password");
1143
+ const updatedAt = toTimestamp(requiredDate(updateValue, "updatedAt", "update credential password"));
1144
+ for (let attempt = 0; attempt < 3; attempt += 1) {
1145
+ const { value } = await this.client.findCredentialAccount({ organization_id: this.organizationId,
1146
+ user_id: userId, account_id: userId, provider_id: "credential" });
1147
+ const account = value.accounts[0];
1148
+ if (account === undefined)
1149
+ return 0;
1150
+ const result = await this.client.updateCredentialPassword({ request_id: "", organization_id: this.organizationId,
1151
+ user_id: userId, account_id: account.id, external_account_id: userId, expected_revision: account.revision,
1152
+ password, updated_at: updatedAt });
1153
+ if (result.outcome.outcome === "PasswordAccountStale")
1154
+ continue;
1155
+ if (result.outcome.outcome === "PasswordAccountMissing")
1156
+ return 0;
1157
+ requireOutcome(result, "update credential password", "CredentialPasswordUpdated");
1158
+ return 1;
1159
+ }
1160
+ fail("declared_outcome", "update credential password", "PasswordAccountStale");
1161
+ }
1162
+ if (model !== "account" || !exactWhere(where, ["userId", "providerId"])) {
1163
+ return fail("unsupported_call_shape", `updateMany ${model}`);
1164
+ }
1165
+ const update = asRecord(updateValue, "updateMany account");
1166
+ const updateFields = Object.keys(update).sort();
1167
+ if (JSON.stringify(updateFields) !== JSON.stringify(["password", "updatedAt"])) {
1168
+ fail("unsupported_call_shape", "updateMany account");
1169
+ }
1170
+ const userId = whereValue(where, "userId", "updateMany account");
1171
+ const providerId = whereValue(where, "providerId", "updateMany account");
1172
+ const updatedAt = requiredDate(update, "updatedAt", "updateMany account");
1173
+ for (let attempt = 0; attempt < 3; attempt += 1) {
1174
+ const found = await this.client.findAccountsByUserProvider({
1175
+ organization_id: this.organizationId,
1176
+ user_id: userId,
1177
+ provider_id: providerId,
1178
+ after: null,
1179
+ });
1180
+ if (found.nextCursor !== undefined)
1181
+ fail("result_bound_exceeded", "updateMany account");
1182
+ const accounts = found.value.accounts;
1183
+ if (accounts.length === 0)
1184
+ return 0;
1185
+ const result = await this.client.updateAccountPasswords({
1186
+ request_id: "",
1187
+ organization_id: this.organizationId,
1188
+ user_id: userId,
1189
+ updates: accounts.map((account) => ({
1190
+ organization_id: this.organizationId,
1191
+ user_id: userId,
1192
+ account_id: account.id,
1193
+ provider_id: providerId,
1194
+ password: nullableString(update, "password", "updateMany account"),
1195
+ updated_at: toTimestamp(updatedAt),
1196
+ expected_revision: account.revision,
1197
+ })),
1198
+ });
1199
+ if (result.outcome.outcome === "PasswordAccountStale" ||
1200
+ result.outcome.outcome === "PasswordAccountMissing" ||
1201
+ result.outcome.outcome === "PasswordProviderMismatch") {
1202
+ continue;
1203
+ }
1204
+ requireOutcome(result, "updateMany account", "AccountPasswordsUpdated");
1205
+ return accounts.length;
1206
+ }
1207
+ return fail("declared_outcome", "updateMany account", "PasswordAccountStale");
1208
+ }
1209
+ async commitSignup(records) {
1210
+ if (records.length !== 3)
1211
+ fail("unsupported_transaction_shape", "transaction signup");
1212
+ const byModel = new Map(records.map((record) => [record.model, record.data]));
1213
+ if (byModel.size !== 3 || !["user", "account", "session"].every((name) => byModel.has(name))) {
1214
+ fail("unsupported_transaction_shape", "transaction signup");
1215
+ }
1216
+ const user = byModel.get("user");
1217
+ const account = byModel.get("account");
1218
+ const session = byModel.get("session");
1219
+ const userId = requiredString(user, "id", "transaction signup");
1220
+ const sessionToken = requiredString(session, "token", "transaction signup");
1221
+ if (requiredString(account, "userId", "transaction signup") !== userId ||
1222
+ requiredString(session, "userId", "transaction signup") !== userId) {
1223
+ fail("unsupported_transaction_shape", "transaction signup");
1224
+ }
1225
+ const result = await this.client.createSignupGraph({
1226
+ ...this.encodeExtra("user", user, "user_"),
1227
+ ...this.encodeExtra("session", session, "session_"),
1228
+ ...this.encodeExtra("account", account, "account_"),
1229
+ request_id: "",
1230
+ organization_id: this.organizationId,
1231
+ user_id: userId,
1232
+ user_name: requiredString(user, "name", "transaction signup"),
1233
+ user_email: requiredString(user, "email", "transaction signup"),
1234
+ user_email_verified: requiredBoolean(user, "emailVerified", "transaction signup"),
1235
+ user_image: nullableString(user, "image", "transaction signup"),
1236
+ user_created_at: toTimestamp(requiredDate(user, "createdAt", "transaction signup")),
1237
+ user_updated_at: toTimestamp(requiredDate(user, "updatedAt", "transaction signup")),
1238
+ account_id: requiredString(account, "id", "transaction signup"),
1239
+ external_account_id: requiredString(account, "accountId", "transaction signup"),
1240
+ provider_id: requiredString(account, "providerId", "transaction signup"),
1241
+ account_password: nullableString(account, "password", "transaction signup"),
1242
+ account_created_at: toTimestamp(requiredDate(account, "createdAt", "transaction signup")),
1243
+ account_updated_at: toTimestamp(requiredDate(account, "updatedAt", "transaction signup")),
1244
+ session_id: requiredString(session, "id", "transaction signup"),
1245
+ session_token: sessionToken,
1246
+ session_expires_at: toTimestamp(requiredDate(session, "expiresAt", "transaction signup")),
1247
+ session_ip_address: nullableString(session, "ipAddress", "transaction signup"),
1248
+ session_user_agent: nullableString(session, "userAgent", "transaction signup"),
1249
+ session_created_at: toTimestamp(requiredDate(session, "createdAt", "transaction signup")),
1250
+ session_updated_at: toTimestamp(requiredDate(session, "updatedAt", "transaction signup")),
1251
+ });
1252
+ requireOutcome(result, "transaction signup", "SignupGraphCreated");
1253
+ }
1254
+ async commitOAuthUser(records) {
1255
+ if (records.length !== 2)
1256
+ fail("unsupported_transaction_shape", "transaction OAuth user");
1257
+ const byModel = new Map(records.map((record) => [record.model, record.data]));
1258
+ if (byModel.size !== 2 || !["user", "account"].every((name) => byModel.has(name))) {
1259
+ fail("unsupported_transaction_shape", "transaction OAuth user");
1260
+ }
1261
+ const user = byModel.get("user");
1262
+ const account = byModel.get("account");
1263
+ const userId = requiredString(user, "id", "transaction OAuth user");
1264
+ if (requiredString(account, "userId", "transaction OAuth user") !== userId) {
1265
+ fail("unsupported_transaction_shape", "transaction OAuth user");
1266
+ }
1267
+ const result = await this.client.createOAuthUserGraph({
1268
+ ...this.encodeExtra("user", user, "user_"),
1269
+ ...this.encodeExtra("account", account, "account_"),
1270
+ request_id: "",
1271
+ organization_id: this.organizationId,
1272
+ user_id: userId,
1273
+ user_name: requiredString(user, "name", "transaction OAuth user"),
1274
+ user_email: requiredString(user, "email", "transaction OAuth user"),
1275
+ user_email_verified: requiredBoolean(user, "emailVerified", "transaction OAuth user"),
1276
+ user_image: nullableString(user, "image", "transaction OAuth user"),
1277
+ user_created_at: toTimestamp(requiredDate(user, "createdAt", "transaction OAuth user")),
1278
+ user_updated_at: toTimestamp(requiredDate(user, "updatedAt", "transaction OAuth user")),
1279
+ account_id: requiredString(account, "id", "transaction OAuth user"),
1280
+ external_account_id: requiredString(account, "accountId", "transaction OAuth user"),
1281
+ provider_id: requiredString(account, "providerId", "transaction OAuth user"),
1282
+ access_token: nullableString(account, "accessToken", "transaction OAuth user"),
1283
+ refresh_token: nullableString(account, "refreshToken", "transaction OAuth user"),
1284
+ access_token_expires_at: timestampOrNull(nullableDate(account, "accessTokenExpiresAt", "transaction OAuth user")),
1285
+ refresh_token_expires_at: timestampOrNull(nullableDate(account, "refreshTokenExpiresAt", "transaction OAuth user")),
1286
+ scope: nullableString(account, "scope", "transaction OAuth user"),
1287
+ id_token: nullableString(account, "idToken", "transaction OAuth user"),
1288
+ password: nullableString(account, "password", "transaction OAuth user"),
1289
+ account_created_at: toTimestamp(requiredDate(account, "createdAt", "transaction OAuth user")),
1290
+ account_updated_at: toTimestamp(requiredDate(account, "updatedAt", "transaction OAuth user")),
1291
+ });
1292
+ requireOutcome(result, "transaction OAuth user", "OAuthUserGraphCreated");
1293
+ }
1294
+ async commitVerificationConsume(rows) {
1295
+ if (rows.length < 1 || rows.length > 32) {
1296
+ fail("unsupported_transaction_shape", "transaction verification consume");
1297
+ }
1298
+ const result = await this.client.consumeVerificationSet({
1299
+ request_id: "",
1300
+ organization_id: this.organizationId,
1301
+ verification_ids: rows.map((row) => requiredString(row, "id", "transaction verification consume")),
1302
+ });
1303
+ requireOutcome(result, "transaction verification consume", "VerificationSetConsumed");
1304
+ }
1305
+ async increment(model, where, increment, set) {
1306
+ if (!this.plugins?.supports(model))
1307
+ fail("unsupported_call_shape", `incrementOne ${model}`);
1308
+ return this.plugins.increment(model, where, { ...increment }, set === undefined ? {} : { ...set });
1309
+ }
1310
+ async commitMemberActivation(data, where, update) {
1311
+ if (this.plugins === undefined || !exactWhere(where, ["token"]))
1312
+ fail("unsupported_transaction_shape", "member activation");
1313
+ for (let attempt = 0; attempt < 3; attempt += 1) {
1314
+ const { value } = await this.client.findSessionByToken({ organization_id: this.organizationId,
1315
+ token: whereValue(where, "token", "member activation") });
1316
+ const raw = value.sessions[0];
1317
+ if (raw === undefined)
1318
+ fail("declared_outcome", "member activation", "SessionMissing");
1319
+ await this.plugins.createMemberAndActivate(data, this.mapSession(raw), raw, update);
1320
+ return;
1321
+ }
1322
+ }
1323
+ async commitPasswordChange(where, update) {
1324
+ const account = await this.findOne("account", where);
1325
+ if (account === null || account.providerId !== "credential" || account.accountId !== account.userId) {
1326
+ fail("declared_outcome", "changePassword", "PasswordAccountMissing");
1327
+ }
1328
+ const userId = requiredString(account, "userId", "changePassword");
1329
+ const affected = await this.updateMany("account", [
1330
+ { field: "userId", value: userId, operator: "eq", connector: "AND", mode: "sensitive" },
1331
+ { field: "accountId", value: userId, operator: "eq", connector: "AND", mode: "sensitive" },
1332
+ { field: "providerId", value: "credential", operator: "eq", connector: "AND", mode: "sensitive" },
1333
+ ], update);
1334
+ if (affected !== 1)
1335
+ fail("declared_outcome", "changePassword", "PasswordAccountMissing");
1336
+ }
1337
+ }
1338
+ function genericCreate(implementation) {
1339
+ return implementation;
1340
+ }
1341
+ function genericFindOne(implementation) {
1342
+ return implementation;
1343
+ }
1344
+ function genericFindMany(implementation) {
1345
+ return implementation;
1346
+ }
1347
+ function genericConsumeOne(implementation) {
1348
+ return implementation;
1349
+ }
1350
+ function genericUpdate(implementation) {
1351
+ return implementation;
1352
+ }
1353
+ class TransactionRecorder {
1354
+ dispatcher;
1355
+ creates = [];
1356
+ consumeAttempted = false;
1357
+ consumedVerification;
1358
+ verificationDeleteRows;
1359
+ verificationDeleteIdentifier;
1360
+ verificationSnapshot;
1361
+ passwordReset;
1362
+ lostConsume = false;
1363
+ organizationDeletion;
1364
+ memberDeletion;
1365
+ sessionActivation;
1366
+ passwordChange;
1367
+ constructor(dispatcher) {
1368
+ this.dispatcher = dispatcher;
1369
+ }
1370
+ customAdapter() {
1371
+ return {
1372
+ create: genericCreate(async ({ model, data }) => {
1373
+ const copied = this.dispatcher.normalizeCreate(model, data);
1374
+ this.creates.push({ model, data: copied });
1375
+ return copied;
1376
+ }),
1377
+ findOne: genericFindOne(async ({ model, where, join }) => this.dispatcher.findOne(model, where, join)),
1378
+ findMany: genericFindMany(async ({ model, where, limit, sortBy, offset, join }) => this.dispatcher.findMany(model, where, limit, sortBy, offset, join)),
1379
+ count: async () => fail("unsupported_transaction_shape", "transaction count"),
1380
+ update: genericUpdate(async ({ model, where, update }) => {
1381
+ if (model === "account" && exactWhere(where, ["id"]) && this.passwordChange === undefined &&
1382
+ typeof update.password === "string" && Object.keys(update).every((field) => field === "password" || field === "updatedAt")) {
1383
+ requiredString(update, "password", "changePassword");
1384
+ requiredDate(update, "updatedAt", "changePassword");
1385
+ const current = await this.dispatcher.findOne("account", where);
1386
+ if (current === null)
1387
+ fail("declared_outcome", "changePassword", "PasswordAccountMissing");
1388
+ this.passwordChange = { where, update };
1389
+ return { ...current, ...update };
1390
+ }
1391
+ if (this.dispatcher.plugins === undefined || model !== "session" || !exactWhere(where, ["token"]) ||
1392
+ this.sessionActivation !== undefined || this.creates.length !== 1 || this.creates[0].model !== "member" ||
1393
+ Object.keys(update).some((field) => field !== "activeOrganizationId" && field !== "updatedAt"))
1394
+ fail("unsupported_transaction_shape", "member activation");
1395
+ const current = await this.dispatcher.findOne("session", where);
1396
+ if (current === null)
1397
+ return null;
1398
+ this.sessionActivation = { where, update };
1399
+ return { ...current, ...update };
1400
+ }),
1401
+ updateMany: async ({ model, where, update }) => {
1402
+ if (model !== "account" || !exactWhere(where, ["userId", "providerId", "accountId"]) ||
1403
+ !this.consumeAttempted || this.passwordReset !== undefined ||
1404
+ Object.keys(update).some((field) => field !== "password" && field !== "updatedAt")) {
1405
+ fail("unsupported_transaction_shape", "transaction updateMany");
1406
+ }
1407
+ this.passwordReset = { where, update };
1408
+ return 1;
1409
+ },
1410
+ delete: async ({ model, where }) => {
1411
+ if (this.dispatcher.plugins === undefined || !exactWhere(where, ["id"]))
1412
+ fail("unsupported_transaction_shape", "transaction delete");
1413
+ const id = whereValue(where, "id", "transaction delete");
1414
+ if (model === "organization" && this.organizationDeletion?.id === id && this.organizationDeletion.models.join(",") === "member,invitation") {
1415
+ this.organizationDeletion.deleted = true;
1416
+ return;
1417
+ }
1418
+ if (model === "member" && this.memberDeletion === undefined && this.organizationDeletion === undefined) {
1419
+ this.memberDeletion = id;
1420
+ return;
1421
+ }
1422
+ fail("unsupported_transaction_shape", "transaction delete");
1423
+ },
1424
+ deleteMany: async ({ model, where }) => {
1425
+ if (this.dispatcher.plugins !== undefined && ["member", "invitation"].includes(model) && exactWhere(where, ["organizationId"])) {
1426
+ const id = whereValue(where, "organizationId", "organization delete");
1427
+ this.organizationDeletion ??= { id, models: [], deleted: false };
1428
+ if (this.organizationDeletion.id !== id || this.organizationDeletion.deleted ||
1429
+ model !== (this.organizationDeletion.models.length === 0 ? "member" : "invitation") || this.organizationDeletion.models.length >= 2)
1430
+ fail("unsupported_transaction_shape", "organization delete");
1431
+ this.organizationDeletion.models.push(model);
1432
+ return 0; // The upstream graph ignores these counts; one cascade commits them together.
1433
+ }
1434
+ if (model !== "verification" ||
1435
+ !exactWhere(where, ["identifier"]) ||
1436
+ !this.consumeAttempted ||
1437
+ this.verificationDeleteRows !== undefined) {
1438
+ return fail("unsupported_transaction_shape", "transaction deleteMany");
1439
+ }
1440
+ this.verificationDeleteIdentifier = whereValue(where, "identifier", "transaction deleteMany verification");
1441
+ this.verificationDeleteRows = (await this.dispatcher.findMany("verification", where, 32))
1442
+ .filter((row) => row.id !== this.consumedVerification?.id);
1443
+ return this.verificationDeleteRows.length;
1444
+ },
1445
+ consumeOne: genericConsumeOne(async ({ model, where }) => {
1446
+ if (model !== "verification" ||
1447
+ !exactWhere(where, ["id"]) ||
1448
+ this.consumeAttempted) {
1449
+ return fail("unsupported_transaction_shape", "transaction consumeOne");
1450
+ }
1451
+ this.consumeAttempted = true;
1452
+ this.verificationSnapshot = await this.dispatcher.prepareConsume(whereValue(where, "id", "consumeOne"));
1453
+ this.consumedVerification = this.verificationSnapshot?.row ?? null;
1454
+ return this.consumedVerification;
1455
+ }),
1456
+ incrementOne: async () => fail("unsupported_transaction_shape", "transaction incrementOne"),
1457
+ };
1458
+ }
1459
+ async commit() {
1460
+ const hasVerificationMutation = this.consumeAttempted || this.verificationDeleteRows !== undefined;
1461
+ const hasOrganizationMutation = this.organizationDeletion !== undefined || this.memberDeletion !== undefined;
1462
+ if (this.passwordChange !== undefined) {
1463
+ if (hasVerificationMutation || hasOrganizationMutation || this.creates.length > 0 || this.sessionActivation !== undefined)
1464
+ fail("unsupported_transaction_shape", "mixed password change");
1465
+ await this.dispatcher.commitPasswordChange(this.passwordChange.where, this.passwordChange.update);
1466
+ return;
1467
+ }
1468
+ if (hasOrganizationMutation) {
1469
+ if (this.creates.length > 0 || hasVerificationMutation || this.sessionActivation !== undefined ||
1470
+ (this.organizationDeletion !== undefined && this.memberDeletion !== undefined))
1471
+ fail("unsupported_transaction_shape", "mixed organization transaction");
1472
+ if (this.organizationDeletion !== undefined) {
1473
+ if (!this.organizationDeletion.deleted)
1474
+ fail("unsupported_transaction_shape", "incomplete organization deletion");
1475
+ await this.dispatcher.plugins.deleteIds("organization", [this.organizationDeletion.id]);
1476
+ }
1477
+ else
1478
+ await this.dispatcher.plugins.deleteIds("member", [this.memberDeletion]);
1479
+ return;
1480
+ }
1481
+ if (this.creates.length > 0 && hasVerificationMutation) {
1482
+ fail("unsupported_transaction_shape", "mixed transaction");
1483
+ }
1484
+ if (this.creates.length > 0) {
1485
+ if (this.creates.length === 1 && this.creates[0].model === "member" && this.sessionActivation !== undefined) {
1486
+ await this.dispatcher.commitMemberActivation(this.creates[0].data, this.sessionActivation.where, this.sessionActivation.update);
1487
+ return;
1488
+ }
1489
+ if (this.creates.length === 2) {
1490
+ await this.dispatcher.commitOAuthUser(this.creates);
1491
+ }
1492
+ else {
1493
+ await this.dispatcher.commitSignup(this.creates);
1494
+ }
1495
+ return;
1496
+ }
1497
+ if (hasVerificationMutation) {
1498
+ if (!this.consumeAttempted || this.consumedVerification === undefined) {
1499
+ fail("unsupported_transaction_shape", "transaction verification consume");
1500
+ }
1501
+ if (this.verificationSnapshot == null)
1502
+ return;
1503
+ if (this.verificationDeleteRows !== undefined && this.consumedVerification !== null &&
1504
+ this.consumedVerification.identifier !== this.verificationDeleteIdentifier) {
1505
+ fail("unsupported_transaction_shape", "transaction verification consume");
1506
+ }
1507
+ if (this.passwordReset !== undefined) {
1508
+ await this.dispatcher.commitPasswordReset(this.verificationSnapshot, this.passwordReset.where, this.passwordReset.update, this.verificationDeleteRows ?? []);
1509
+ return;
1510
+ }
1511
+ if (!await this.dispatcher.commitConsume(this.verificationSnapshot)) {
1512
+ this.lostConsume = true;
1513
+ return;
1514
+ }
1515
+ if (this.verificationDeleteRows !== undefined && this.verificationDeleteRows.length > 0) {
1516
+ await this.dispatcher.commitVerificationConsume(this.verificationDeleteRows);
1517
+ }
1518
+ }
1519
+ }
1520
+ }
1521
+ function customAdapter(dispatcher) {
1522
+ return {
1523
+ create: genericCreate(async ({ model, data }) => dispatcher.create(model, data)),
1524
+ findOne: genericFindOne(async ({ model, where, join }) => dispatcher.findOne(model, where, join)),
1525
+ findMany: genericFindMany(async ({ model, where, limit, sortBy, offset, join }) => dispatcher.findMany(model, where, limit, sortBy, offset, join)),
1526
+ count: async ({ model, where }) => dispatcher.count(model, where),
1527
+ update: genericUpdate(async ({ model, where, update }) => dispatcher.update(model, where, update)),
1528
+ updateMany: async ({ model, where, update }) => dispatcher.updateMany(model, where, update),
1529
+ delete: async ({ model, where }) => dispatcher.delete(model, where),
1530
+ deleteMany: async ({ model, where }) => dispatcher.deleteMany(model, where),
1531
+ consumeOne: genericConsumeOne(async ({ model, where }) => dispatcher.consumeOne(model, where)),
1532
+ incrementOne: (async ({ model, where, increment, set }) => dispatcher.increment(model, where, increment, set)),
1533
+ };
1534
+ }
1535
+ const BASE_FACTORY_CONFIG = {
1536
+ adapterId: "riffdb",
1537
+ adapterName: "RiffDB Better Auth Core",
1538
+ usePlural: false,
1539
+ supportsNumericIds: false,
1540
+ supportsUUIDs: false,
1541
+ supportsJSON: false,
1542
+ supportsDates: true,
1543
+ supportsBooleans: true,
1544
+ supportsArrays: false,
1545
+ };
1546
+ export function buildRiffDBBetterAuthAdapter(config) {
1547
+ assertSupportedBetterAuthInstallation();
1548
+ validateConfiguration(config);
1549
+ return (options) => {
1550
+ if (config.profile !== undefined)
1551
+ options = { ...options, advanced: { ...options.advanced,
1552
+ database: { ...options.advanced?.database, joins: true } } };
1553
+ const dispatcher = new CoreDispatcher(config.client.causalSession(), config.organizationId, config.resetModelForTesting, config.profile);
1554
+ const factory = createAdapterFactory({
1555
+ config: {
1556
+ ...BASE_FACTORY_CONFIG,
1557
+ adapterName: config.profile?.plan.name ?? BASE_FACTORY_CONFIG.adapterName,
1558
+ debugLogs: false,
1559
+ transaction: async (callback) => {
1560
+ const recorder = new TransactionRecorder(dispatcher);
1561
+ const transactionFactory = createAdapterFactory({
1562
+ config: {
1563
+ ...BASE_FACTORY_CONFIG,
1564
+ debugLogs: false,
1565
+ transaction: false,
1566
+ },
1567
+ adapter: ({ options: transactionOptions, schema }) => {
1568
+ validateResolvedSchema(transactionOptions, schema, config.profile);
1569
+ return recorder.customAdapter();
1570
+ },
1571
+ });
1572
+ const transactionAdapter = transactionFactory(options);
1573
+ const result = await callback(transactionAdapter);
1574
+ await recorder.commit();
1575
+ return recorder.lostConsume ? null : result;
1576
+ },
1577
+ },
1578
+ adapter: ({ options: resolvedOptions, schema }) => {
1579
+ validateResolvedSchema(resolvedOptions, schema, config.profile);
1580
+ return customAdapter(dispatcher);
1581
+ },
1582
+ });
1583
+ return factory(options);
1584
+ };
1585
+ }
1586
+ export function riffdbAdapter(config) {
1587
+ const commandAttemptBudget = config.commandAttemptBudget ?? 3;
1588
+ if (!Number.isInteger(commandAttemptBudget) || commandAttemptBudget < 1 || commandAttemptBudget > 10) {
1589
+ fail("invalid_configuration", "commandAttemptBudget");
1590
+ }
1591
+ const transport = new DriverGeneratedApplicationTransport(config.driver);
1592
+ return buildRiffDBBetterAuthAdapter({
1593
+ client: config.profile === undefined ? new RiffDBBetterAuthCoreClient(transport, commandAttemptBudget) :
1594
+ instantiateProfileClient(config.profile, transport, commandAttemptBudget),
1595
+ organizationId: config.organizationId,
1596
+ ...(config.debugLogs === undefined ? {} : { debugLogs: config.debugLogs }),
1597
+ ...(config.profile === undefined ? {} : { profile: config.profile }),
1598
+ });
1599
+ }
1600
+ //# sourceMappingURL=adapter.js.map