@effect-auth/core 0.1.0-alpha.1 → 0.1.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/README.md +790 -73
  2. package/dist/ApiKey.d.ts +207 -0
  3. package/dist/ApiKey.d.ts.map +1 -0
  4. package/dist/ApiKey.js +275 -0
  5. package/dist/ApiKey.js.map +1 -0
  6. package/dist/AuditLog.d.ts +335 -1
  7. package/dist/AuditLog.d.ts.map +1 -1
  8. package/dist/AuditLog.js +318 -1
  9. package/dist/AuditLog.js.map +1 -1
  10. package/dist/AuthConfig.d.ts +42 -0
  11. package/dist/AuthConfig.d.ts.map +1 -0
  12. package/dist/AuthConfig.js +43 -0
  13. package/dist/AuthConfig.js.map +1 -0
  14. package/dist/AuthFlow.d.ts +462 -36
  15. package/dist/AuthFlow.d.ts.map +1 -1
  16. package/dist/AuthFlow.js +657 -5
  17. package/dist/AuthFlow.js.map +1 -1
  18. package/dist/AuthKernel.d.ts +3 -0
  19. package/dist/AuthKernel.d.ts.map +1 -0
  20. package/dist/AuthKernel.js +9 -0
  21. package/dist/AuthKernel.js.map +1 -0
  22. package/dist/Challenge.d.ts +24 -4
  23. package/dist/Challenge.d.ts.map +1 -1
  24. package/dist/Challenge.js +167 -1
  25. package/dist/Challenge.js.map +1 -1
  26. package/dist/Client.d.ts +449 -0
  27. package/dist/Client.d.ts.map +1 -0
  28. package/dist/Client.js +985 -0
  29. package/dist/Client.js.map +1 -0
  30. package/dist/Crypto.d.ts +6 -1
  31. package/dist/Crypto.d.ts.map +1 -1
  32. package/dist/Crypto.js +62 -1
  33. package/dist/Crypto.js.map +1 -1
  34. package/dist/DomainVerification.d.ts +200 -0
  35. package/dist/DomainVerification.d.ts.map +1 -0
  36. package/dist/DomainVerification.js +304 -0
  37. package/dist/DomainVerification.js.map +1 -0
  38. package/dist/EffectQbSqliteStorage.d.ts +985 -0
  39. package/dist/EffectQbSqliteStorage.d.ts.map +1 -0
  40. package/dist/EffectQbSqliteStorage.js +2824 -0
  41. package/dist/EffectQbSqliteStorage.js.map +1 -0
  42. package/dist/EmailOtp.d.ts +120 -0
  43. package/dist/EmailOtp.d.ts.map +1 -0
  44. package/dist/EmailOtp.js +286 -0
  45. package/dist/EmailOtp.js.map +1 -0
  46. package/dist/EmailVerification.d.ts +121 -0
  47. package/dist/EmailVerification.d.ts.map +1 -0
  48. package/dist/EmailVerification.js +200 -0
  49. package/dist/EmailVerification.js.map +1 -0
  50. package/dist/HttpApi/Api.d.ts +2410 -0
  51. package/dist/HttpApi/Api.d.ts.map +1 -0
  52. package/dist/HttpApi/Api.js +3026 -0
  53. package/dist/HttpApi/Api.js.map +1 -0
  54. package/dist/HttpApi/Endpoints.d.ts +1073 -0
  55. package/dist/HttpApi/Endpoints.d.ts.map +1 -0
  56. package/dist/HttpApi/Endpoints.js +428 -0
  57. package/dist/HttpApi/Endpoints.js.map +1 -0
  58. package/dist/HttpApi/Errors.d.ts +114 -0
  59. package/dist/HttpApi/Errors.d.ts.map +1 -0
  60. package/dist/HttpApi/Errors.js +230 -0
  61. package/dist/HttpApi/Errors.js.map +1 -0
  62. package/dist/HttpApi/Schemas.d.ts +1254 -0
  63. package/dist/HttpApi/Schemas.d.ts.map +1 -0
  64. package/dist/HttpApi/Schemas.js +862 -0
  65. package/dist/HttpApi/Schemas.js.map +1 -0
  66. package/dist/HttpApi/Security.d.ts +159 -0
  67. package/dist/HttpApi/Security.d.ts.map +1 -0
  68. package/dist/HttpApi/Security.js +530 -0
  69. package/dist/HttpApi/Security.js.map +1 -0
  70. package/dist/HttpApi/Transport.d.ts +65 -0
  71. package/dist/HttpApi/Transport.d.ts.map +1 -0
  72. package/dist/HttpApi/Transport.js +311 -0
  73. package/dist/HttpApi/Transport.js.map +1 -0
  74. package/dist/HttpApi/index.d.ts +8 -0
  75. package/dist/HttpApi/index.d.ts.map +1 -0
  76. package/dist/HttpApi/index.js +7 -0
  77. package/dist/HttpApi/index.js.map +1 -0
  78. package/dist/HttpApi.d.ts +2 -0
  79. package/dist/HttpApi.d.ts.map +1 -0
  80. package/dist/HttpApi.js +2 -0
  81. package/dist/HttpApi.js.map +1 -0
  82. package/dist/Identifiers.d.ts +3 -0
  83. package/dist/Identifiers.d.ts.map +1 -1
  84. package/dist/Identifiers.js +2 -0
  85. package/dist/Identifiers.js.map +1 -1
  86. package/dist/IncidentAction.d.ts +80 -0
  87. package/dist/IncidentAction.d.ts.map +1 -0
  88. package/dist/IncidentAction.js +158 -0
  89. package/dist/IncidentAction.js.map +1 -0
  90. package/dist/Internal.d.ts +7 -0
  91. package/dist/Internal.d.ts.map +1 -0
  92. package/dist/Internal.js +12 -0
  93. package/dist/Internal.js.map +1 -0
  94. package/dist/Jwt.d.ts +281 -0
  95. package/dist/Jwt.d.ts.map +1 -0
  96. package/dist/Jwt.js +721 -0
  97. package/dist/Jwt.js.map +1 -0
  98. package/dist/LoginApproval.d.ts +314 -0
  99. package/dist/LoginApproval.d.ts.map +1 -0
  100. package/dist/LoginApproval.js +551 -0
  101. package/dist/LoginApproval.js.map +1 -0
  102. package/dist/LoginNotification.d.ts +183 -0
  103. package/dist/LoginNotification.d.ts.map +1 -0
  104. package/dist/LoginNotification.js +329 -0
  105. package/dist/LoginNotification.js.map +1 -0
  106. package/dist/LoginRisk.d.ts +344 -0
  107. package/dist/LoginRisk.d.ts.map +1 -0
  108. package/dist/LoginRisk.js +484 -0
  109. package/dist/LoginRisk.js.map +1 -0
  110. package/dist/MachineAuth.d.ts +73 -0
  111. package/dist/MachineAuth.d.ts.map +1 -0
  112. package/dist/MachineAuth.js +147 -0
  113. package/dist/MachineAuth.js.map +1 -0
  114. package/dist/MagicLink.d.ts +85 -0
  115. package/dist/MagicLink.d.ts.map +1 -0
  116. package/dist/MagicLink.js +206 -0
  117. package/dist/MagicLink.js.map +1 -0
  118. package/dist/Mailer.d.ts +147 -0
  119. package/dist/Mailer.d.ts.map +1 -0
  120. package/dist/Mailer.js +208 -0
  121. package/dist/Mailer.js.map +1 -0
  122. package/dist/OAuth.d.ts +1890 -0
  123. package/dist/OAuth.d.ts.map +1 -0
  124. package/dist/OAuth.js +3063 -0
  125. package/dist/OAuth.js.map +1 -0
  126. package/dist/Passkey.d.ts +334 -0
  127. package/dist/Passkey.d.ts.map +1 -0
  128. package/dist/Passkey.js +422 -0
  129. package/dist/Passkey.js.map +1 -0
  130. package/dist/PasskeySimpleWebAuthn.d.ts +11 -0
  131. package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -0
  132. package/dist/PasskeySimpleWebAuthn.js +181 -0
  133. package/dist/PasskeySimpleWebAuthn.js.map +1 -0
  134. package/dist/Password.d.ts +237 -0
  135. package/dist/Password.d.ts.map +1 -0
  136. package/dist/Password.js +641 -0
  137. package/dist/Password.js.map +1 -0
  138. package/dist/Policy.d.ts +7 -4
  139. package/dist/Policy.d.ts.map +1 -1
  140. package/dist/Policy.js +28 -5
  141. package/dist/Policy.js.map +1 -1
  142. package/dist/Privacy.d.ts +15 -0
  143. package/dist/Privacy.d.ts.map +1 -1
  144. package/dist/Privacy.js +58 -1
  145. package/dist/Privacy.js.map +1 -1
  146. package/dist/RateLimiter.d.ts +104 -0
  147. package/dist/RateLimiter.d.ts.map +1 -0
  148. package/dist/RateLimiter.js +118 -0
  149. package/dist/RateLimiter.js.map +1 -0
  150. package/dist/RecoveryCode.d.ts +169 -0
  151. package/dist/RecoveryCode.d.ts.map +1 -0
  152. package/dist/RecoveryCode.js +299 -0
  153. package/dist/RecoveryCode.js.map +1 -0
  154. package/dist/RefreshToken.d.ts +222 -0
  155. package/dist/RefreshToken.d.ts.map +1 -0
  156. package/dist/RefreshToken.js +342 -0
  157. package/dist/RefreshToken.js.map +1 -0
  158. package/dist/Retention.d.ts +98 -0
  159. package/dist/Retention.d.ts.map +1 -0
  160. package/dist/Retention.js +204 -0
  161. package/dist/Retention.js.map +1 -0
  162. package/dist/SecurityTimeline.d.ts +78 -0
  163. package/dist/SecurityTimeline.d.ts.map +1 -0
  164. package/dist/SecurityTimeline.js +461 -0
  165. package/dist/SecurityTimeline.js.map +1 -0
  166. package/dist/Sessions.d.ts +123 -11
  167. package/dist/Sessions.d.ts.map +1 -1
  168. package/dist/Sessions.js +534 -1
  169. package/dist/Sessions.js.map +1 -1
  170. package/dist/StepUp.d.ts +44 -0
  171. package/dist/StepUp.d.ts.map +1 -0
  172. package/dist/StepUp.js +82 -0
  173. package/dist/StepUp.js.map +1 -0
  174. package/dist/Storage.d.ts +73 -5
  175. package/dist/Storage.d.ts.map +1 -1
  176. package/dist/Storage.js +11 -1
  177. package/dist/Storage.js.map +1 -1
  178. package/dist/StorageMigrations.d.ts +23 -1
  179. package/dist/StorageMigrations.d.ts.map +1 -1
  180. package/dist/StorageMigrations.js +462 -2
  181. package/dist/StorageMigrations.js.map +1 -1
  182. package/dist/Testing.d.ts +9 -1
  183. package/dist/Testing.d.ts.map +1 -1
  184. package/dist/Testing.js +30 -2
  185. package/dist/Testing.js.map +1 -1
  186. package/dist/Totp.d.ts +220 -0
  187. package/dist/Totp.d.ts.map +1 -0
  188. package/dist/Totp.js +477 -0
  189. package/dist/Totp.js.map +1 -0
  190. package/dist/TrustedDevice.d.ts +127 -0
  191. package/dist/TrustedDevice.d.ts.map +1 -0
  192. package/dist/TrustedDevice.js +252 -0
  193. package/dist/TrustedDevice.js.map +1 -0
  194. package/dist/WaitUntil.d.ts.map +1 -1
  195. package/dist/WaitUntil.js +1 -1
  196. package/dist/WaitUntil.js.map +1 -1
  197. package/dist/Webhook.d.ts +380 -0
  198. package/dist/Webhook.d.ts.map +1 -0
  199. package/dist/Webhook.js +592 -0
  200. package/dist/Webhook.js.map +1 -0
  201. package/dist/alchemy/cloudflare/Email.d.ts +25 -0
  202. package/dist/alchemy/cloudflare/Email.d.ts.map +1 -0
  203. package/dist/alchemy/cloudflare/Email.js +117 -0
  204. package/dist/alchemy/cloudflare/Email.js.map +1 -0
  205. package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts +34 -0
  206. package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
  207. package/dist/alchemy/cloudflare/RateLimitDurableObject.js +30 -0
  208. package/dist/alchemy/cloudflare/RateLimitDurableObject.js.map +1 -0
  209. package/dist/cloudflare/Email.d.ts +25 -0
  210. package/dist/cloudflare/Email.d.ts.map +1 -0
  211. package/dist/cloudflare/Email.js +153 -0
  212. package/dist/cloudflare/Email.js.map +1 -0
  213. package/dist/cloudflare/RateLimitDurableObject.d.ts +50 -0
  214. package/dist/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
  215. package/dist/cloudflare/RateLimitDurableObject.js +51 -0
  216. package/dist/cloudflare/RateLimitDurableObject.js.map +1 -0
  217. package/dist/index.d.ts +25 -0
  218. package/dist/index.d.ts.map +1 -1
  219. package/dist/index.js +25 -0
  220. package/dist/index.js.map +1 -1
  221. package/dist/internal/RateLimitDurableObject.d.ts +32 -0
  222. package/dist/internal/RateLimitDurableObject.d.ts.map +1 -0
  223. package/dist/internal/RateLimitDurableObject.js +80 -0
  224. package/dist/internal/RateLimitDurableObject.js.map +1 -0
  225. package/migrations/0002_auth_password.sql +25 -0
  226. package/migrations/0003_auth_login_approval_review.sql +22 -0
  227. package/migrations/0004_auth_trusted_device.sql +12 -0
  228. package/migrations/0005_auth_passkey.sql +17 -0
  229. package/migrations/0006_auth_totp_factor.sql +17 -0
  230. package/migrations/0007_auth_recovery_code.sql +13 -0
  231. package/migrations/0008_auth_api_key.sql +17 -0
  232. package/migrations/0009_auth_refresh_token.sql +21 -0
  233. package/migrations/0010_auth_jwt_revocation.sql +8 -0
  234. package/migrations/0011_auth_oauth_account.sql +16 -0
  235. package/migrations/0012_auth_oauth_provider_token_vault.sql +20 -0
  236. package/migrations/0013_auth_security_timeline.sql +16 -0
  237. package/migrations/0014_auth_webhook_outbox.sql +16 -0
  238. package/migrations/0015_auth_webhook_replay.sql +7 -0
  239. package/migrations/0016_auth_login_risk_history.sql +23 -0
  240. package/migrations/0017_auth_audit_log.sql +17 -0
  241. package/migrations/0018_auth_domain_verification.sql +18 -0
  242. package/migrations/0019_auth_oauth_authorization_code.sql +17 -0
  243. package/migrations/0020_auth_oauth_provider_mode_token.sql +24 -0
  244. package/migrations/0021_auth_oauth_client_secret.sql +14 -0
  245. package/migrations/0022_auth_oauth_client.sql +15 -0
  246. package/migrations/0023_auth_oauth_consent.sql +15 -0
  247. package/package.json +162 -26
  248. package/dist/D1Kysely.d.ts +0 -40
  249. package/dist/D1Kysely.d.ts.map +0 -1
  250. package/dist/D1Kysely.js +0 -75
  251. package/dist/D1Kysely.js.map +0 -1
  252. package/dist/KyselyStorage.d.ts +0 -41
  253. package/dist/KyselyStorage.d.ts.map +0 -1
  254. package/dist/KyselyStorage.js +0 -176
  255. package/dist/KyselyStorage.js.map +0 -1
@@ -0,0 +1,2824 @@
1
+ import { Data, Effect, Layer, Option, Redacted } from "effect";
2
+ import { Column, Executor, Query, Scalar, Table } from "effect-qb/sqlite";
3
+ import { AuditLogStore, AuditLogStoreError, auditEventActorUserId, auditEventUserId, filterAuditLogEvents, } from "./AuditLog.js";
4
+ import { ApiKeyId, ApiKeyPrefix, ApiKeySecretHash, ApiKeyStore, ApiKeyStoreError, } from "./ApiKey.js";
5
+ import { DomainName, DomainVerificationId, DomainVerificationProofToken, DomainVerificationStore, DomainVerificationStoreError, } from "./DomainVerification.js";
6
+ import { AuthFlowId, ChallengeId, CredentialId, Email, OAuthAccountId, OAuthClientId, OAuthProviderId, SessionId, UnixMillis, UserId, } from "./Identifiers.js";
7
+ import { currentUnixMillis } from "./Internal.js";
8
+ import { JwtError, JwtRevocationStore } from "./Jwt.js";
9
+ import { LoginApprovalReviewError, LoginApprovalReviewStore, } from "./LoginApproval.js";
10
+ import { LoginRiskContext, LoginRiskHistory, LoginRiskHistoryError, LoginRiskSignal, maxLoginRiskLevel, } from "./LoginRisk.js";
11
+ import { OAuthAccountStore, OAuthAccountStoreError, OAuthAuthorizationCodeStore, OAuthAuthorizationCodeStoreError, OAuthClientStore, OAuthClientStoreError, OAuthConsentStore, OAuthConsentStoreError, OAuthClientSecretHash, OAuthClientSecretPrefix, OAuthClientSecretStore, OAuthClientSecretStoreError, OAuthCodeChallenge, OAuthProviderModeTokenStore, OAuthProviderModeTokenStoreError, OAuthProviderTokenVault, OAuthProviderTokenVaultError, } from "./OAuth.js";
12
+ import { PasskeyCredentialId, PasskeyCredentialStore, PasskeyCredentialStoreError, } from "./Passkey.js";
13
+ import { RecoveryCodeHash, RecoveryCodeStore, RecoveryCodeStoreError, } from "./RecoveryCode.js";
14
+ import { RefreshTokenFamilyId, RefreshTokenId, RefreshTokenSecretHash, RefreshTokenStore, RefreshTokenStoreError, } from "./RefreshToken.js";
15
+ import { filterSecurityTimelineEvents, SecurityTimelineEventId, SecurityTimelineStore, SecurityTimelineStoreError, } from "./SecurityTimeline.js";
16
+ import { CredentialStore, SessionStore, StorageError, UserStore, VerificationStore, } from "./Storage.js";
17
+ import { TotpFactorStore, TotpFactorStoreError, TotpSecret, } from "./Totp.js";
18
+ import { filterTrustedDevicesForUser, TrustedDeviceError, TrustedDeviceStore, } from "./TrustedDevice.js";
19
+ import { filterDueWebhookOutboxRecords, WebhookOutboxItemId, WebhookOutboxStore, WebhookOutboxStoreError, WebhookReplayStore, WebhookReplayStoreError, } from "./Webhook.js";
20
+ export class D1EffectQbError extends Data.TaggedError("D1EffectQbError") {
21
+ }
22
+ const makeAuthUserTable = (name) => Table.make(name, {
23
+ id: Column.text().pipe(Column.primaryKey),
24
+ email: Column.text(),
25
+ email_verified: Column.int(),
26
+ created_at: Column.int(),
27
+ updated_at: Column.int(),
28
+ disabled_at: Column.int().pipe(Column.nullable),
29
+ metadata: Column.text().pipe(Column.nullable),
30
+ });
31
+ const makeAuthCredentialTable = (name) => Table.make(name, {
32
+ id: Column.text().pipe(Column.primaryKey),
33
+ user_id: Column.text(),
34
+ type: Column.text(),
35
+ password_hash: Column.text().pipe(Column.nullable),
36
+ created_at: Column.int(),
37
+ updated_at: Column.int(),
38
+ revoked_at: Column.int().pipe(Column.nullable),
39
+ metadata: Column.text().pipe(Column.nullable),
40
+ });
41
+ const makeAuthSessionTable = (name) => Table.make(name, {
42
+ id: Column.text().pipe(Column.primaryKey),
43
+ user_id: Column.text(),
44
+ secret_hash: Column.text(),
45
+ created_at: Column.int(),
46
+ expires_at: Column.int(),
47
+ auth_time: Column.int(),
48
+ aal: Column.text(),
49
+ amr: Column.text(),
50
+ mfa_verified_at: Column.int().pipe(Column.nullable),
51
+ metadata: Column.text().pipe(Column.nullable),
52
+ revoked_at: Column.int().pipe(Column.nullable),
53
+ last_seen_at: Column.int().pipe(Column.nullable),
54
+ rotated_at: Column.int().pipe(Column.nullable),
55
+ });
56
+ const makeAuthVerificationTable = (name) => Table.make(name, {
57
+ id: Column.text().pipe(Column.primaryKey),
58
+ type: Column.text(),
59
+ subject: Column.text(),
60
+ secret_hash: Column.text().pipe(Column.nullable),
61
+ created_at: Column.int(),
62
+ expires_at: Column.int(),
63
+ metadata: Column.text().pipe(Column.nullable),
64
+ consumed_at: Column.int().pipe(Column.nullable),
65
+ });
66
+ const makeAuthAuditLogTable = (name) => Table.make(name, {
67
+ id: Column.text().pipe(Column.nullable),
68
+ type: Column.text(),
69
+ user_id: Column.text().pipe(Column.nullable),
70
+ actor_user_id: Column.text().pipe(Column.nullable),
71
+ occurred_at: Column.int(),
72
+ request_ip_hash: Column.text().pipe(Column.nullable),
73
+ request_user_agent_hash: Column.text().pipe(Column.nullable),
74
+ event: Column.text(),
75
+ created_at: Column.int(),
76
+ });
77
+ const makeAuthLoginApprovalReviewTable = (name) => Table.make(name, {
78
+ approval_challenge_id: Column.text().pipe(Column.primaryKey),
79
+ flow_id: Column.text(),
80
+ user_id: Column.text(),
81
+ channel: Column.text(),
82
+ reason: Column.text(),
83
+ session_binding: Column.text(),
84
+ same_device_required: Column.int(),
85
+ status: Column.text(),
86
+ created_at: Column.int(),
87
+ expires_at: Column.int(),
88
+ reviewed_at: Column.int().pipe(Column.nullable),
89
+ reviewed_by: Column.text().pipe(Column.nullable),
90
+ denied_reason: Column.text().pipe(Column.nullable),
91
+ risk: Column.text().pipe(Column.nullable),
92
+ metadata: Column.text().pipe(Column.nullable),
93
+ review_metadata: Column.text().pipe(Column.nullable),
94
+ });
95
+ const makeAuthLoginRiskHistoryTable = (name) => Table.make(name, {
96
+ id: Column.text().pipe(Column.primaryKey),
97
+ user_id: Column.text(),
98
+ occurred_at: Column.int(),
99
+ outcome: Column.text(),
100
+ method: Column.text(),
101
+ amr: Column.text(),
102
+ aal: Column.text(),
103
+ device_status: Column.text(),
104
+ device_key: Column.text().pipe(Column.nullable),
105
+ location_key: Column.text().pipe(Column.nullable),
106
+ country: Column.text().pipe(Column.nullable),
107
+ region: Column.text().pipe(Column.nullable),
108
+ latitude_micro: Column.int().pipe(Column.nullable),
109
+ longitude_micro: Column.int().pipe(Column.nullable),
110
+ risk_level: Column.text().pipe(Column.nullable),
111
+ created_at: Column.int(),
112
+ });
113
+ const makeAuthTrustedDeviceTable = (name) => Table.make(name, {
114
+ user_id: Column.text(),
115
+ token_hash: Column.text(),
116
+ created_at: Column.int(),
117
+ last_seen_at: Column.int(),
118
+ expires_at: Column.int(),
119
+ metadata: Column.text().pipe(Column.nullable),
120
+ });
121
+ const makeAuthPasskeyCredentialTable = (name) => Table.make(name, {
122
+ id: Column.text().pipe(Column.primaryKey),
123
+ user_id: Column.text(),
124
+ credential_id: Column.text(),
125
+ public_key: Column.text(),
126
+ sign_count: Column.int(),
127
+ transports: Column.text().pipe(Column.nullable),
128
+ backed_up: Column.int().pipe(Column.nullable),
129
+ created_at: Column.int(),
130
+ last_used_at: Column.int().pipe(Column.nullable),
131
+ revoked_at: Column.int().pipe(Column.nullable),
132
+ metadata: Column.text().pipe(Column.nullable),
133
+ });
134
+ const makeAuthTotpFactorTable = (name) => Table.make(name, {
135
+ id: Column.text().pipe(Column.primaryKey),
136
+ user_id: Column.text(),
137
+ secret: Column.text(),
138
+ algorithm: Column.text(),
139
+ digits: Column.int(),
140
+ period: Column.int(),
141
+ created_at: Column.int(),
142
+ confirmed_at: Column.int().pipe(Column.nullable),
143
+ last_used_at: Column.int().pipe(Column.nullable),
144
+ revoked_at: Column.int().pipe(Column.nullable),
145
+ metadata: Column.text().pipe(Column.nullable),
146
+ });
147
+ const makeAuthRecoveryCodeTable = (name) => Table.make(name, {
148
+ id: Column.text().pipe(Column.primaryKey),
149
+ user_id: Column.text(),
150
+ code_hash: Column.text(),
151
+ created_at: Column.int(),
152
+ used_at: Column.int().pipe(Column.nullable),
153
+ revoked_at: Column.int().pipe(Column.nullable),
154
+ metadata: Column.text().pipe(Column.nullable),
155
+ });
156
+ const makeAuthApiKeyTable = (name) => Table.make(name, {
157
+ id: Column.text().pipe(Column.primaryKey),
158
+ user_id: Column.text(),
159
+ prefix: Column.text(),
160
+ secret_hash: Column.text(),
161
+ scopes: Column.text(),
162
+ created_at: Column.int(),
163
+ expires_at: Column.int().pipe(Column.nullable),
164
+ last_used_at: Column.int().pipe(Column.nullable),
165
+ revoked_at: Column.int().pipe(Column.nullable),
166
+ metadata: Column.text().pipe(Column.nullable),
167
+ });
168
+ const makeAuthRefreshTokenTable = (name) => Table.make(name, {
169
+ id: Column.text().pipe(Column.primaryKey),
170
+ family_id: Column.text(),
171
+ user_id: Column.text(),
172
+ secret_hash: Column.text(),
173
+ created_at: Column.int(),
174
+ expires_at: Column.int(),
175
+ last_used_at: Column.int().pipe(Column.nullable),
176
+ rotated_at: Column.int().pipe(Column.nullable),
177
+ replaced_by_id: Column.text().pipe(Column.nullable),
178
+ revoked_at: Column.int().pipe(Column.nullable),
179
+ reuse_detected_at: Column.int().pipe(Column.nullable),
180
+ metadata: Column.text().pipe(Column.nullable),
181
+ });
182
+ const makeAuthJwtRevocationTable = (name) => Table.make(name, {
183
+ jwt_id: Column.text().pipe(Column.primaryKey),
184
+ revoked_at: Column.int(),
185
+ expires_at: Column.int().pipe(Column.nullable),
186
+ reason: Column.text().pipe(Column.nullable),
187
+ });
188
+ const makeAuthOAuthAccountTable = (name) => Table.make(name, {
189
+ id: Column.text().pipe(Column.primaryKey),
190
+ provider_id: Column.text(),
191
+ provider_account_id: Column.text(),
192
+ user_id: Column.text(),
193
+ email: Column.text().pipe(Column.nullable),
194
+ email_verified: Column.int().pipe(Column.nullable),
195
+ created_at: Column.int(),
196
+ updated_at: Column.int(),
197
+ unlinked_at: Column.int().pipe(Column.nullable),
198
+ metadata: Column.text().pipe(Column.nullable),
199
+ });
200
+ const makeAuthOAuthProviderTokenVaultTable = (name) => Table.make(name, {
201
+ account_id: Column.text().pipe(Column.primaryKey),
202
+ user_id: Column.text(),
203
+ provider_id: Column.text(),
204
+ provider_account_id: Column.text(),
205
+ access_token_ciphertext: Column.text(),
206
+ refresh_token_ciphertext: Column.text().pipe(Column.nullable),
207
+ id_token_ciphertext: Column.text().pipe(Column.nullable),
208
+ token_type: Column.text(),
209
+ scopes: Column.text().pipe(Column.nullable),
210
+ expires_at: Column.int().pipe(Column.nullable),
211
+ updated_at: Column.int(),
212
+ revoked_at: Column.int().pipe(Column.nullable),
213
+ revocation_reason: Column.text().pipe(Column.nullable),
214
+ });
215
+ const makeAuthOAuthClientTable = (name) => Table.make(name, {
216
+ id: Column.text().pipe(Column.primaryKey),
217
+ type: Column.text(),
218
+ status: Column.text(),
219
+ name: Column.text().pipe(Column.nullable),
220
+ redirect_uris: Column.text(),
221
+ allowed_grant_types: Column.text(),
222
+ allowed_response_types: Column.text(),
223
+ allowed_scopes: Column.text().pipe(Column.nullable),
224
+ created_at: Column.int().pipe(Column.nullable),
225
+ updated_at: Column.int().pipe(Column.nullable),
226
+ metadata: Column.text().pipe(Column.nullable),
227
+ });
228
+ const makeAuthOAuthConsentTable = (name) => Table.make(name, {
229
+ id: Column.text().pipe(Column.primaryKey),
230
+ user_id: Column.text(),
231
+ client_id: Column.text(),
232
+ scopes: Column.text(),
233
+ granted_at: Column.int(),
234
+ expires_at: Column.int().pipe(Column.nullable),
235
+ revoked_at: Column.int().pipe(Column.nullable),
236
+ metadata: Column.text().pipe(Column.nullable),
237
+ });
238
+ const makeAuthOAuthAuthorizationCodeTable = (name) => Table.make(name, {
239
+ code_hash: Column.text().pipe(Column.primaryKey),
240
+ client_id: Column.text(),
241
+ subject: Column.text(),
242
+ redirect_uri: Column.text(),
243
+ scopes: Column.text(),
244
+ code_challenge: Column.text().pipe(Column.nullable),
245
+ code_challenge_method: Column.text().pipe(Column.nullable),
246
+ issued_at: Column.int(),
247
+ expires_at: Column.int(),
248
+ consumed_at: Column.int().pipe(Column.nullable),
249
+ metadata: Column.text().pipe(Column.nullable),
250
+ });
251
+ const makeAuthOAuthClientSecretTable = (name) => Table.make(name, {
252
+ prefix: Column.text().pipe(Column.primaryKey),
253
+ client_id: Column.text(),
254
+ secret_hash: Column.text(),
255
+ authentication_methods: Column.text(),
256
+ created_at: Column.int(),
257
+ expires_at: Column.int().pipe(Column.nullable),
258
+ last_used_at: Column.int().pipe(Column.nullable),
259
+ revoked_at: Column.int().pipe(Column.nullable),
260
+ metadata: Column.text().pipe(Column.nullable),
261
+ });
262
+ const makeAuthOAuthProviderModeTokenTable = (name) => Table.make(name, {
263
+ token_hash: Column.text().pipe(Column.primaryKey),
264
+ token_type: Column.text(),
265
+ client_id: Column.text(),
266
+ subject: Column.text(),
267
+ scopes: Column.text(),
268
+ issued_at: Column.int(),
269
+ expires_at: Column.int(),
270
+ issuer: Column.text().pipe(Column.nullable),
271
+ audience: Column.text().pipe(Column.nullable),
272
+ jwt_id: Column.text().pipe(Column.nullable),
273
+ revoked_at: Column.int().pipe(Column.nullable),
274
+ revocation_reason: Column.text().pipe(Column.nullable),
275
+ rotated_at: Column.int().pipe(Column.nullable),
276
+ replaced_by_token_hash: Column.text().pipe(Column.nullable),
277
+ metadata: Column.text().pipe(Column.nullable),
278
+ });
279
+ const makeAuthDomainVerificationTable = (name) => Table.make(name, {
280
+ id: Column.text().pipe(Column.primaryKey),
281
+ owner_id: Column.text(),
282
+ domain: Column.text(),
283
+ proof_method: Column.text(),
284
+ proof_token: Column.text(),
285
+ status: Column.text(),
286
+ created_at: Column.int(),
287
+ expires_at: Column.int(),
288
+ verified_at: Column.int().pipe(Column.nullable),
289
+ revoked_at: Column.int().pipe(Column.nullable),
290
+ last_checked_at: Column.int().pipe(Column.nullable),
291
+ metadata: Column.text().pipe(Column.nullable),
292
+ });
293
+ const makeAuthSecurityTimelineTable = (name) => Table.make(name, {
294
+ id: Column.text().pipe(Column.primaryKey),
295
+ user_id: Column.text(),
296
+ type: Column.text(),
297
+ category: Column.text(),
298
+ severity: Column.text(),
299
+ occurred_at: Column.int(),
300
+ summary: Column.text(),
301
+ actor: Column.text().pipe(Column.nullable),
302
+ request: Column.text().pipe(Column.nullable),
303
+ metadata: Column.text().pipe(Column.nullable),
304
+ });
305
+ const makeAuthWebhookOutboxTable = (name) => Table.make(name, {
306
+ id: Column.text().pipe(Column.primaryKey),
307
+ endpoint_key: Column.text(),
308
+ event: Column.text(),
309
+ status: Column.text(),
310
+ attempts: Column.int(),
311
+ next_attempt_at: Column.int(),
312
+ created_at: Column.int(),
313
+ updated_at: Column.int(),
314
+ delivered_at: Column.int().pipe(Column.nullable),
315
+ last_error: Column.text().pipe(Column.nullable),
316
+ });
317
+ const makeAuthWebhookReplayTable = (name) => Table.make(name, {
318
+ id: Column.text().pipe(Column.primaryKey),
319
+ expires_at: Column.int(),
320
+ created_at: Column.int(),
321
+ });
322
+ const authSqliteTablesTypeId = Symbol.for("@effect-auth/core/EffectQbSqliteStorage/AuthSqliteTables");
323
+ const jsonEncode = (value) => value === undefined ? null : JSON.stringify(value);
324
+ const jsonDecode = (value) => {
325
+ if (value === null || value === undefined) {
326
+ return undefined;
327
+ }
328
+ return typeof value === "string" ? JSON.parse(value) : value;
329
+ };
330
+ const optionalUnixMillis = (value) => value === null || value === undefined ? undefined : UnixMillis(Number(value));
331
+ const decodeAmr = (value) => typeof value === "string"
332
+ ? JSON.parse(value)
333
+ : value;
334
+ const decodeBoolean = (value) => {
335
+ if (typeof value === "boolean") {
336
+ return value;
337
+ }
338
+ if (typeof value === "number") {
339
+ return value !== 0;
340
+ }
341
+ if (typeof value === "string") {
342
+ return value !== "" && value !== "0" && value !== "false";
343
+ }
344
+ return value !== null && value !== undefined;
345
+ };
346
+ const mutationValues = (value) => value;
347
+ const queryInsert = (table, values) => Query.insert(table, values);
348
+ const queryUpdate = (table, values) => Query.update(table, values);
349
+ const queryEq = (left, right) => Query.eq(left, right);
350
+ const queryGt = (left, right) => Query.gt(left, right);
351
+ const queryLt = (left, right) => Query.lt(left, right);
352
+ const queryLte = (left, right) => Query.lte(left, right);
353
+ const queryIsNull = (value) => Query.isNull(value);
354
+ const queryIn = (value, first, ...rest) => Query.in(value, first, ...rest);
355
+ const executePlan = (executor, plan) => executor.execute(plan);
356
+ const omitUndefined = (record) => Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
357
+ const sessionMetadataEnvelopeKey = "__effectAuthSession";
358
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
359
+ const metadataWithReason = (metadata, key, reason) => reason === undefined ? metadata : { ...metadata, [key]: reason };
360
+ const isLoginRiskLevel = (value) => value === "unknown" ||
361
+ value === "low" ||
362
+ value === "medium" ||
363
+ value === "high" ||
364
+ value === "critical";
365
+ const decodeLoginRiskSignal = (value) => {
366
+ const record = isRecord(value) ? value : {};
367
+ const level = isLoginRiskLevel(record.level) ? record.level : undefined;
368
+ return LoginRiskSignal.make({
369
+ type: typeof record.type === "string" ? record.type : "unknown",
370
+ ...(level === undefined ? {} : { level }),
371
+ ...(isRecord(record.metadata) ? { metadata: record.metadata } : {}),
372
+ });
373
+ };
374
+ const decodeLoginRiskContext = (value) => {
375
+ const decoded = jsonDecode(value);
376
+ if (!isRecord(decoded)) {
377
+ return undefined;
378
+ }
379
+ return LoginRiskContext.make({
380
+ level: isLoginRiskLevel(decoded.level) ? decoded.level : "unknown",
381
+ signals: Array.isArray(decoded.signals)
382
+ ? decoded.signals.map(decodeLoginRiskSignal)
383
+ : [],
384
+ ...(isRecord(decoded.metadata) ? { metadata: decoded.metadata } : {}),
385
+ });
386
+ };
387
+ const encodeLoginRiskSignal = (signal) => omitUndefined({
388
+ type: signal.type,
389
+ level: signal.level,
390
+ metadata: signal.metadata,
391
+ });
392
+ const encodeLoginRiskContext = (risk) => risk === undefined
393
+ ? null
394
+ : jsonEncode(omitUndefined({
395
+ level: risk.level,
396
+ signals: risk.signals.map(encodeLoginRiskSignal),
397
+ metadata: risk.metadata,
398
+ }));
399
+ const decodeSessionMetadata = (value) => {
400
+ const decoded = jsonDecode(value);
401
+ const envelope = isRecord(decoded)
402
+ ? decoded[sessionMetadataEnvelopeKey]
403
+ : undefined;
404
+ if (!isRecord(envelope) || envelope.version !== 1) {
405
+ return omitUndefined({
406
+ metadata: decoded,
407
+ });
408
+ }
409
+ return omitUndefined({
410
+ metadata: envelope.metadata,
411
+ claims: envelope.claims,
412
+ });
413
+ };
414
+ const encodeSessionMetadata = (row) => {
415
+ if (row.claims === undefined) {
416
+ return jsonEncode(row.metadata);
417
+ }
418
+ return jsonEncode({
419
+ [sessionMetadataEnvelopeKey]: omitUndefined({
420
+ version: 1,
421
+ metadata: row.metadata,
422
+ claims: row.claims,
423
+ }),
424
+ });
425
+ };
426
+ const decodeDefaultUserRow = (row) => omitUndefined({
427
+ id: UserId(row.id),
428
+ email: Email(row.email),
429
+ emailVerified: decodeBoolean(row.emailVerified),
430
+ createdAt: UnixMillis(Number(row.createdAt)),
431
+ updatedAt: UnixMillis(Number(row.updatedAt)),
432
+ disabledAt: optionalUnixMillis(row.disabledAt),
433
+ metadata: jsonDecode(row.metadata),
434
+ });
435
+ const decodeUserRow = (tables, row) => tables.user.decode === undefined
436
+ ? decodeDefaultUserRow(row)
437
+ : tables.user.decode(row);
438
+ const decodeDefaultPasswordCredentialRow = (row) => omitUndefined({
439
+ id: CredentialId(row.id),
440
+ userId: UserId(row.userId),
441
+ passwordHash: row.passwordHash ?? "",
442
+ createdAt: UnixMillis(Number(row.createdAt)),
443
+ updatedAt: UnixMillis(Number(row.updatedAt)),
444
+ revokedAt: optionalUnixMillis(row.revokedAt),
445
+ metadata: jsonDecode(row.metadata),
446
+ });
447
+ const decodePasswordCredentialRow = (tables, row) => tables.credential.decodePassword === undefined
448
+ ? decodeDefaultPasswordCredentialRow(row)
449
+ : tables.credential.decodePassword(row);
450
+ const decodeDefaultSessionRow = (row) => {
451
+ const sessionMetadata = decodeSessionMetadata(row.metadata);
452
+ return omitUndefined({
453
+ id: SessionId(row.id),
454
+ userId: UserId(row.userId),
455
+ secretHash: row.secretHash,
456
+ createdAt: UnixMillis(Number(row.createdAt)),
457
+ expiresAt: UnixMillis(Number(row.expiresAt)),
458
+ authTime: UnixMillis(Number(row.authTime)),
459
+ aal: row.aal,
460
+ amr: decodeAmr(row.amr),
461
+ mfaVerifiedAt: optionalUnixMillis(row.mfaVerifiedAt),
462
+ metadata: sessionMetadata.metadata,
463
+ claims: sessionMetadata.claims,
464
+ revokedAt: optionalUnixMillis(row.revokedAt),
465
+ lastSeenAt: optionalUnixMillis(row.lastSeenAt),
466
+ rotatedAt: optionalUnixMillis(row.rotatedAt),
467
+ });
468
+ };
469
+ const decodeSessionRow = (tables, row) => tables.session.decode === undefined
470
+ ? decodeDefaultSessionRow(row)
471
+ : tables.session.decode(row);
472
+ const decodeDefaultVerificationRow = (row) => omitUndefined({
473
+ id: ChallengeId(row.id),
474
+ type: row.type,
475
+ subject: row.subject,
476
+ secretHash: row.secretHash ?? undefined,
477
+ createdAt: UnixMillis(Number(row.createdAt)),
478
+ expiresAt: UnixMillis(Number(row.expiresAt)),
479
+ metadata: jsonDecode(row.metadata),
480
+ consumedAt: optionalUnixMillis(row.consumedAt),
481
+ });
482
+ const decodeVerificationRow = (tables, row) => tables.verification.decode === undefined
483
+ ? decodeDefaultVerificationRow(row)
484
+ : tables.verification.decode(row);
485
+ const decodeDefaultAuditLogEvent = (row) => jsonDecode(row.event);
486
+ const decodeAuditLogEvent = (tables, row) => tables.auditLog.decode === undefined
487
+ ? decodeDefaultAuditLogEvent(row)
488
+ : tables.auditLog.decode(row);
489
+ const decodeDefaultLoginApprovalReviewRow = (row) => omitUndefined({
490
+ approvalChallengeId: ChallengeId(row.approvalChallengeId),
491
+ flowId: AuthFlowId(row.flowId),
492
+ userId: UserId(row.userId),
493
+ channel: row.channel,
494
+ reason: row.reason,
495
+ sessionBinding: row.sessionBinding,
496
+ sameDeviceRequired: decodeBoolean(row.sameDeviceRequired),
497
+ status: row.status,
498
+ createdAt: UnixMillis(Number(row.createdAt)),
499
+ expiresAt: UnixMillis(Number(row.expiresAt)),
500
+ reviewedAt: optionalUnixMillis(row.reviewedAt),
501
+ reviewedBy: row.reviewedBy === null
502
+ ? undefined
503
+ : row.reviewedBy,
504
+ deniedReason: row.deniedReason === null ? undefined : row.deniedReason,
505
+ risk: decodeLoginRiskContext(row.risk),
506
+ metadata: jsonDecode(row.metadata),
507
+ reviewMetadata: jsonDecode(row.reviewMetadata),
508
+ });
509
+ const decodeLoginApprovalReviewRow = (tables, row) => tables.loginApprovalReview.decode === undefined
510
+ ? decodeDefaultLoginApprovalReviewRow(row)
511
+ : tables.loginApprovalReview.decode(row);
512
+ const decodeDefaultLoginRiskHistoryRecord = (row) => omitUndefined({
513
+ id: row.id,
514
+ userId: UserId(row.userId),
515
+ occurredAt: UnixMillis(Number(row.occurredAt)),
516
+ outcome: row.outcome,
517
+ method: row.method,
518
+ amr: decodeAmr(row.amr),
519
+ aal: row.aal,
520
+ device: { status: row.deviceStatus },
521
+ deviceKey: row.deviceKey ?? undefined,
522
+ locationKey: row.locationKey ?? undefined,
523
+ country: row.country ?? undefined,
524
+ region: row.region ?? undefined,
525
+ latitude: row.latitudeMicro === null ? undefined : Number(row.latitudeMicro) / 1_000_000,
526
+ longitude: row.longitudeMicro === null
527
+ ? undefined
528
+ : Number(row.longitudeMicro) / 1_000_000,
529
+ riskLevel: row.riskLevel === null ? undefined : row.riskLevel,
530
+ createdAt: UnixMillis(Number(row.createdAt)),
531
+ });
532
+ const decodeLoginRiskHistoryRecord = (tables, row) => tables.loginRiskHistory.decode === undefined
533
+ ? decodeDefaultLoginRiskHistoryRecord(row)
534
+ : tables.loginRiskHistory.decode(row);
535
+ const decodeDefaultTrustedDeviceRow = (row) => omitUndefined({
536
+ userId: UserId(row.userId),
537
+ tokenHash: row.tokenHash,
538
+ createdAt: UnixMillis(Number(row.createdAt)),
539
+ lastSeenAt: UnixMillis(Number(row.lastSeenAt)),
540
+ expiresAt: UnixMillis(Number(row.expiresAt)),
541
+ metadata: jsonDecode(row.metadata),
542
+ });
543
+ const decodeTrustedDeviceRow = (tables, row) => tables.trustedDevice.decode === undefined
544
+ ? decodeDefaultTrustedDeviceRow(row)
545
+ : tables.trustedDevice.decode(row);
546
+ const decodePasskeyTransports = (value) => {
547
+ const decoded = jsonDecode(value);
548
+ return Array.isArray(decoded) ? decoded : undefined;
549
+ };
550
+ const decodeDefaultPasskeyCredentialRow = (row) => omitUndefined({
551
+ id: CredentialId(row.id),
552
+ userId: UserId(row.userId),
553
+ credentialId: PasskeyCredentialId(row.credentialId),
554
+ publicKey: row.publicKey,
555
+ signCount: Number(row.signCount),
556
+ transports: decodePasskeyTransports(row.transports),
557
+ backedUp: row.backedUp === null || row.backedUp === undefined
558
+ ? undefined
559
+ : decodeBoolean(row.backedUp),
560
+ createdAt: UnixMillis(Number(row.createdAt)),
561
+ lastUsedAt: optionalUnixMillis(row.lastUsedAt),
562
+ revokedAt: optionalUnixMillis(row.revokedAt),
563
+ metadata: jsonDecode(row.metadata),
564
+ });
565
+ const decodePasskeyCredentialRow = (tables, row) => tables.passkeyCredential.decode === undefined
566
+ ? decodeDefaultPasskeyCredentialRow(row)
567
+ : tables.passkeyCredential.decode(row);
568
+ const decodeDefaultTotpFactorRow = (row) => omitUndefined({
569
+ id: CredentialId(row.id),
570
+ userId: UserId(row.userId),
571
+ secret: Redacted.make(TotpSecret(row.secret)),
572
+ algorithm: row.algorithm,
573
+ digits: Number(row.digits),
574
+ period: Number(row.period),
575
+ createdAt: UnixMillis(Number(row.createdAt)),
576
+ confirmedAt: optionalUnixMillis(row.confirmedAt),
577
+ lastUsedAt: optionalUnixMillis(row.lastUsedAt),
578
+ revokedAt: optionalUnixMillis(row.revokedAt),
579
+ metadata: jsonDecode(row.metadata),
580
+ });
581
+ const decodeTotpFactorRow = (tables, row) => tables.totpFactor.decode === undefined
582
+ ? decodeDefaultTotpFactorRow(row)
583
+ : tables.totpFactor.decode(row);
584
+ const decodeDefaultRecoveryCodeRow = (row) => omitUndefined({
585
+ id: CredentialId(row.id),
586
+ userId: UserId(row.userId),
587
+ codeHash: RecoveryCodeHash(row.codeHash),
588
+ createdAt: UnixMillis(Number(row.createdAt)),
589
+ usedAt: optionalUnixMillis(row.usedAt),
590
+ revokedAt: optionalUnixMillis(row.revokedAt),
591
+ metadata: jsonDecode(row.metadata),
592
+ });
593
+ const decodeRecoveryCodeRow = (tables, row) => tables.recoveryCode.decode === undefined
594
+ ? decodeDefaultRecoveryCodeRow(row)
595
+ : tables.recoveryCode.decode(row);
596
+ const decodeStringArray = (value) => {
597
+ const decoded = jsonDecode(value);
598
+ return Array.isArray(decoded) ? decoded.map(String) : [];
599
+ };
600
+ const decodeOptionalStringArray = (value) => {
601
+ const decoded = jsonDecode(value);
602
+ return Array.isArray(decoded) ? decoded.map(String) : undefined;
603
+ };
604
+ const decodeDefaultApiKeyRow = (row) => omitUndefined({
605
+ id: ApiKeyId(row.id),
606
+ userId: UserId(row.userId),
607
+ prefix: ApiKeyPrefix(row.prefix),
608
+ secretHash: ApiKeySecretHash(row.secretHash),
609
+ scopes: decodeStringArray(row.scopes),
610
+ createdAt: UnixMillis(Number(row.createdAt)),
611
+ expiresAt: optionalUnixMillis(row.expiresAt),
612
+ lastUsedAt: optionalUnixMillis(row.lastUsedAt),
613
+ revokedAt: optionalUnixMillis(row.revokedAt),
614
+ metadata: jsonDecode(row.metadata),
615
+ });
616
+ const decodeApiKeyRow = (tables, row) => tables.apiKey.decode === undefined
617
+ ? decodeDefaultApiKeyRow(row)
618
+ : tables.apiKey.decode(row);
619
+ const decodeDefaultRefreshTokenRow = (row) => omitUndefined({
620
+ id: RefreshTokenId(row.id),
621
+ familyId: RefreshTokenFamilyId(row.familyId),
622
+ userId: UserId(row.userId),
623
+ secretHash: RefreshTokenSecretHash(row.secretHash),
624
+ createdAt: UnixMillis(Number(row.createdAt)),
625
+ expiresAt: UnixMillis(Number(row.expiresAt)),
626
+ lastUsedAt: optionalUnixMillis(row.lastUsedAt),
627
+ rotatedAt: optionalUnixMillis(row.rotatedAt),
628
+ replacedById: row.replacedById === null ? undefined : RefreshTokenId(row.replacedById),
629
+ revokedAt: optionalUnixMillis(row.revokedAt),
630
+ reuseDetectedAt: optionalUnixMillis(row.reuseDetectedAt),
631
+ metadata: jsonDecode(row.metadata),
632
+ });
633
+ const decodeRefreshTokenRow = (tables, row) => tables.refreshToken.decode === undefined
634
+ ? decodeDefaultRefreshTokenRow(row)
635
+ : tables.refreshToken.decode(row);
636
+ const decodeDefaultJwtRevocationRow = (row) => omitUndefined({
637
+ jwtId: row.jwtId,
638
+ revokedAt: UnixMillis(Number(row.revokedAt)),
639
+ expiresAt: optionalUnixMillis(row.expiresAt),
640
+ reason: row.reason ?? undefined,
641
+ });
642
+ const decodeJwtRevocationRow = (tables, row) => tables.jwtRevocation.decode === undefined
643
+ ? decodeDefaultJwtRevocationRow(row)
644
+ : tables.jwtRevocation.decode(row);
645
+ const decodeDefaultOAuthAccountRow = (row) => omitUndefined({
646
+ id: OAuthAccountId(row.id),
647
+ providerId: OAuthProviderId(row.providerId),
648
+ providerAccountId: row.providerAccountId,
649
+ userId: UserId(row.userId),
650
+ email: row.email === null ? undefined : Email(row.email),
651
+ emailVerified: row.emailVerified === null || row.emailVerified === undefined
652
+ ? undefined
653
+ : decodeBoolean(row.emailVerified),
654
+ createdAt: UnixMillis(Number(row.createdAt)),
655
+ updatedAt: UnixMillis(Number(row.updatedAt)),
656
+ unlinkedAt: optionalUnixMillis(row.unlinkedAt),
657
+ metadata: jsonDecode(row.metadata),
658
+ });
659
+ const decodeOAuthAccountRow = (tables, row) => tables.oauthAccount.decode === undefined
660
+ ? decodeDefaultOAuthAccountRow(row)
661
+ : tables.oauthAccount.decode(row);
662
+ const decodeDefaultOAuthProviderTokenVaultRow = (row) => omitUndefined({
663
+ accountId: OAuthAccountId(row.accountId),
664
+ userId: UserId(row.userId),
665
+ providerId: OAuthProviderId(row.providerId),
666
+ providerAccountId: row.providerAccountId,
667
+ accessTokenCiphertext: Redacted.make(row.accessTokenCiphertext),
668
+ refreshTokenCiphertext: row.refreshTokenCiphertext === null
669
+ ? undefined
670
+ : Redacted.make(row.refreshTokenCiphertext),
671
+ idTokenCiphertext: row.idTokenCiphertext === null
672
+ ? undefined
673
+ : Redacted.make(row.idTokenCiphertext),
674
+ tokenType: row.tokenType,
675
+ scopes: decodeOptionalStringArray(row.scopes),
676
+ expiresAt: optionalUnixMillis(row.expiresAt),
677
+ updatedAt: UnixMillis(Number(row.updatedAt)),
678
+ revokedAt: optionalUnixMillis(row.revokedAt),
679
+ revocationReason: row.revocationReason ?? undefined,
680
+ });
681
+ const decodeOAuthProviderTokenVaultRow = (tables, row) => tables.oauthProviderTokenVault.decode === undefined
682
+ ? decodeDefaultOAuthProviderTokenVaultRow(row)
683
+ : tables.oauthProviderTokenVault.decode(row);
684
+ const decodeDefaultOAuthClientRow = (row) => omitUndefined({
685
+ id: OAuthClientId(row.id),
686
+ type: row.type,
687
+ status: row.status,
688
+ name: row.name ?? undefined,
689
+ redirectUris: decodeStringArray(row.redirectUris),
690
+ allowedGrantTypes: decodeStringArray(row.allowedGrantTypes),
691
+ allowedResponseTypes: decodeStringArray(row.allowedResponseTypes),
692
+ allowedScopes: decodeOptionalStringArray(row.allowedScopes),
693
+ createdAt: optionalUnixMillis(row.createdAt),
694
+ updatedAt: optionalUnixMillis(row.updatedAt),
695
+ metadata: jsonDecode(row.metadata),
696
+ });
697
+ const decodeOAuthClientRow = (tables, row) => tables.oauthClient.decode === undefined
698
+ ? decodeDefaultOAuthClientRow(row)
699
+ : tables.oauthClient.decode(row);
700
+ const decodeDefaultOAuthConsentRow = (row) => omitUndefined({
701
+ userId: UserId(row.userId),
702
+ clientId: OAuthClientId(row.clientId),
703
+ scopes: decodeStringArray(row.scopes),
704
+ grantedAt: UnixMillis(Number(row.grantedAt)),
705
+ expiresAt: optionalUnixMillis(row.expiresAt),
706
+ revokedAt: optionalUnixMillis(row.revokedAt),
707
+ metadata: jsonDecode(row.metadata),
708
+ });
709
+ const decodeOAuthConsentRow = (tables, row) => tables.oauthConsent.decode === undefined
710
+ ? decodeDefaultOAuthConsentRow(row)
711
+ : tables.oauthConsent.decode(row);
712
+ const oauthConsentCoversScopes = (record, scopes = []) => scopes.every((scope) => record.scopes.includes(scope));
713
+ const isOAuthConsentActive = (record, input) => record.revokedAt === undefined &&
714
+ (record.expiresAt === undefined || Number(record.expiresAt) > Number(input.now)) &&
715
+ oauthConsentCoversScopes(record, input.scopes);
716
+ const oauthClientRedirectUriValidationResult = (client, input) => {
717
+ if (client === undefined) {
718
+ return { valid: false, reason: "unknown_client" };
719
+ }
720
+ if (client.status !== "active") {
721
+ return { valid: false, reason: "disabled_client" };
722
+ }
723
+ const responseType = input.responseType ?? "code";
724
+ if (!client.allowedResponseTypes.includes(responseType)) {
725
+ return { valid: false, reason: "unsupported_response_type" };
726
+ }
727
+ if (input.grantType !== undefined &&
728
+ !client.allowedGrantTypes.includes(input.grantType)) {
729
+ return { valid: false, reason: "unsupported_grant_type" };
730
+ }
731
+ if (!client.redirectUris.includes(input.redirectUri)) {
732
+ return { valid: false, reason: "redirect_uri_mismatch" };
733
+ }
734
+ return { valid: true, client };
735
+ };
736
+ const decodeDefaultOAuthAuthorizationCodeRow = (row) => omitUndefined({
737
+ codeHash: row.codeHash,
738
+ clientId: OAuthClientId(row.clientId),
739
+ subject: row.subject,
740
+ redirectUri: row.redirectUri,
741
+ scopes: decodeStringArray(row.scopes),
742
+ codeChallenge: row.codeChallenge === null ? undefined : OAuthCodeChallenge(row.codeChallenge),
743
+ codeChallengeMethod: row.codeChallengeMethod === null
744
+ ? undefined
745
+ : row.codeChallengeMethod,
746
+ issuedAt: UnixMillis(Number(row.issuedAt)),
747
+ expiresAt: UnixMillis(Number(row.expiresAt)),
748
+ consumedAt: optionalUnixMillis(row.consumedAt),
749
+ metadata: jsonDecode(row.metadata),
750
+ });
751
+ const decodeOAuthAuthorizationCodeRow = (tables, row) => tables.oauthAuthorizationCode.decode === undefined
752
+ ? decodeDefaultOAuthAuthorizationCodeRow(row)
753
+ : tables.oauthAuthorizationCode.decode(row);
754
+ const decodeDefaultOAuthClientSecretRow = (row) => omitUndefined({
755
+ prefix: OAuthClientSecretPrefix(row.prefix),
756
+ clientId: OAuthClientId(row.clientId),
757
+ secretHash: OAuthClientSecretHash(row.secretHash),
758
+ authenticationMethods: decodeStringArray(row.authenticationMethods),
759
+ createdAt: UnixMillis(Number(row.createdAt)),
760
+ expiresAt: optionalUnixMillis(row.expiresAt),
761
+ lastUsedAt: optionalUnixMillis(row.lastUsedAt),
762
+ revokedAt: optionalUnixMillis(row.revokedAt),
763
+ metadata: jsonDecode(row.metadata),
764
+ });
765
+ const decodeOAuthClientSecretRow = (tables, row) => tables.oauthClientSecret.decode === undefined
766
+ ? decodeDefaultOAuthClientSecretRow(row)
767
+ : tables.oauthClientSecret.decode(row);
768
+ const decodeOAuthProviderModeTokenAudience = (value) => {
769
+ const decoded = jsonDecode(value);
770
+ if (typeof decoded === "string") {
771
+ return decoded;
772
+ }
773
+ return Array.isArray(decoded) ? decoded.map(String) : undefined;
774
+ };
775
+ const decodeDefaultOAuthProviderModeTokenRow = (row) => omitUndefined({
776
+ tokenHash: row.tokenHash,
777
+ tokenType: row.tokenType,
778
+ clientId: OAuthClientId(row.clientId),
779
+ subject: row.subject,
780
+ scopes: decodeStringArray(row.scopes),
781
+ issuedAt: UnixMillis(Number(row.issuedAt)),
782
+ expiresAt: UnixMillis(Number(row.expiresAt)),
783
+ issuer: row.issuer ?? undefined,
784
+ audience: decodeOAuthProviderModeTokenAudience(row.audience),
785
+ jwtId: row.jwtId ?? undefined,
786
+ revokedAt: optionalUnixMillis(row.revokedAt),
787
+ revocationReason: row.revocationReason ?? undefined,
788
+ rotatedAt: optionalUnixMillis(row.rotatedAt),
789
+ replacedByTokenHash: row.replacedByTokenHash ?? undefined,
790
+ metadata: jsonDecode(row.metadata),
791
+ });
792
+ const decodeOAuthProviderModeTokenRow = (tables, row) => tables.oauthProviderModeToken.decode === undefined
793
+ ? decodeDefaultOAuthProviderModeTokenRow(row)
794
+ : tables.oauthProviderModeToken.decode(row);
795
+ const decodeDefaultDomainVerificationRecord = (row) => omitUndefined({
796
+ id: DomainVerificationId(row.id),
797
+ ownerId: row.ownerId,
798
+ domain: DomainName(row.domain),
799
+ proofMethod: row.proofMethod,
800
+ proofToken: DomainVerificationProofToken(row.proofToken),
801
+ status: row.status,
802
+ createdAt: UnixMillis(Number(row.createdAt)),
803
+ expiresAt: UnixMillis(Number(row.expiresAt)),
804
+ verifiedAt: optionalUnixMillis(row.verifiedAt),
805
+ revokedAt: optionalUnixMillis(row.revokedAt),
806
+ lastCheckedAt: optionalUnixMillis(row.lastCheckedAt),
807
+ metadata: jsonDecode(row.metadata),
808
+ });
809
+ const decodeDomainVerificationRecord = (tables, row) => tables.domainVerification.decode === undefined
810
+ ? decodeDefaultDomainVerificationRecord(row)
811
+ : tables.domainVerification.decode(row);
812
+ const decodeDefaultSecurityTimelineEvent = (row) => omitUndefined({
813
+ id: SecurityTimelineEventId(row.id),
814
+ userId: UserId(row.userId),
815
+ type: row.type,
816
+ category: row.category,
817
+ severity: row.severity,
818
+ occurredAt: UnixMillis(Number(row.occurredAt)),
819
+ summary: row.summary,
820
+ actor: jsonDecode(row.actor),
821
+ request: jsonDecode(row.request),
822
+ metadata: jsonDecode(row.metadata),
823
+ });
824
+ const decodeSecurityTimelineEvent = (tables, row) => tables.securityTimeline.decode === undefined
825
+ ? decodeDefaultSecurityTimelineEvent(row)
826
+ : tables.securityTimeline.decode(row);
827
+ const decodeDefaultWebhookOutboxRecord = (row) => omitUndefined({
828
+ id: WebhookOutboxItemId(row.id),
829
+ endpointKey: row.endpointKey,
830
+ event: jsonDecode(row.event),
831
+ status: row.status,
832
+ attempts: Number(row.attempts),
833
+ nextAttemptAt: UnixMillis(Number(row.nextAttemptAt)),
834
+ createdAt: UnixMillis(Number(row.createdAt)),
835
+ updatedAt: UnixMillis(Number(row.updatedAt)),
836
+ deliveredAt: optionalUnixMillis(row.deliveredAt),
837
+ lastError: row.lastError ?? undefined,
838
+ });
839
+ const decodeWebhookOutboxRecord = (tables, row) => tables.webhookOutbox.decode === undefined
840
+ ? decodeDefaultWebhookOutboxRecord(row)
841
+ : tables.webhookOutbox.decode(row);
842
+ const providerTokenVaultTokens = (record) => omitUndefined({
843
+ accessTokenCiphertext: record.accessTokenCiphertext,
844
+ refreshTokenCiphertext: record.refreshTokenCiphertext,
845
+ idTokenCiphertext: record.idTokenCiphertext,
846
+ tokenType: record.tokenType,
847
+ scopes: record.scopes === undefined ? undefined : [...record.scopes],
848
+ expiresAt: record.expiresAt,
849
+ });
850
+ const userInsert = (row) => ({
851
+ id: row.id,
852
+ email: row.email,
853
+ email_verified: row.emailVerified ? 1 : 0,
854
+ created_at: Number(row.createdAt),
855
+ updated_at: Number(row.updatedAt),
856
+ disabled_at: row.disabledAt === undefined ? null : Number(row.disabledAt),
857
+ metadata: jsonEncode(row.metadata),
858
+ });
859
+ const passwordCredentialInsert = (row) => ({
860
+ id: row.id,
861
+ user_id: row.userId,
862
+ type: "password",
863
+ password_hash: row.passwordHash,
864
+ created_at: Number(row.createdAt),
865
+ updated_at: Number(row.updatedAt),
866
+ revoked_at: row.revokedAt === undefined ? null : Number(row.revokedAt),
867
+ metadata: jsonEncode(row.metadata),
868
+ });
869
+ const passwordCredentialUpdatePassword = (input) => ({
870
+ password_hash: input.passwordHash,
871
+ updated_at: Number(input.updatedAt),
872
+ });
873
+ const sessionInsert = (row) => ({
874
+ id: row.id,
875
+ user_id: row.userId,
876
+ secret_hash: row.secretHash,
877
+ created_at: Number(row.createdAt),
878
+ expires_at: Number(row.expiresAt),
879
+ auth_time: Number(row.authTime),
880
+ aal: row.aal,
881
+ amr: JSON.stringify(row.amr),
882
+ mfa_verified_at: row.mfaVerifiedAt === undefined ? null : Number(row.mfaVerifiedAt),
883
+ metadata: encodeSessionMetadata(row),
884
+ revoked_at: null,
885
+ last_seen_at: null,
886
+ rotated_at: null,
887
+ });
888
+ const verificationInsert = (row) => ({
889
+ id: row.id,
890
+ type: row.type,
891
+ subject: row.subject,
892
+ secret_hash: row.secretHash ?? null,
893
+ created_at: Number(row.createdAt),
894
+ expires_at: Number(row.expiresAt),
895
+ metadata: jsonEncode(row.metadata),
896
+ consumed_at: null,
897
+ });
898
+ const auditLogInsert = (event, createdAt) => ({
899
+ id: event.id ?? null,
900
+ type: event.type,
901
+ user_id: auditEventUserId(event) ?? null,
902
+ actor_user_id: auditEventActorUserId(event) ?? null,
903
+ occurred_at: Number(event.occurredAt),
904
+ request_ip_hash: event.request?.ipHash ?? null,
905
+ request_user_agent_hash: event.request?.userAgentHash ?? null,
906
+ event: JSON.stringify(event),
907
+ created_at: Number(createdAt),
908
+ });
909
+ const loginApprovalReviewInsert = (row) => ({
910
+ approval_challenge_id: row.approvalChallengeId,
911
+ flow_id: row.flowId,
912
+ user_id: row.userId,
913
+ channel: row.channel,
914
+ reason: row.reason,
915
+ session_binding: row.sessionBinding,
916
+ same_device_required: row.sameDeviceRequired ? 1 : 0,
917
+ status: row.status,
918
+ created_at: Number(row.createdAt),
919
+ expires_at: Number(row.expiresAt),
920
+ reviewed_at: row.reviewedAt === undefined ? null : Number(row.reviewedAt),
921
+ reviewed_by: row.reviewedBy ?? null,
922
+ denied_reason: row.deniedReason ?? null,
923
+ risk: encodeLoginRiskContext(row.risk),
924
+ metadata: jsonEncode(row.metadata),
925
+ review_metadata: jsonEncode(row.reviewMetadata),
926
+ });
927
+ const coordinateMicro = (value) => value === undefined || !Number.isFinite(value)
928
+ ? null
929
+ : Math.round(value * 1_000_000);
930
+ const loginRiskHistoryInsert = (row) => ({
931
+ id: row.id,
932
+ user_id: row.userId,
933
+ occurred_at: Number(row.occurredAt),
934
+ outcome: row.outcome,
935
+ method: row.method,
936
+ amr: JSON.stringify(row.amr),
937
+ aal: row.aal,
938
+ device_status: row.device.status,
939
+ device_key: row.deviceKey ?? null,
940
+ location_key: row.locationKey ?? null,
941
+ country: row.country ?? null,
942
+ region: row.region ?? null,
943
+ latitude_micro: coordinateMicro(row.latitude),
944
+ longitude_micro: coordinateMicro(row.longitude),
945
+ risk_level: row.riskLevel ?? null,
946
+ created_at: Number(row.createdAt),
947
+ });
948
+ const userMarkEmailVerifiedUpdate = (input) => ({
949
+ email_verified: 1,
950
+ updated_at: Number(input.updatedAt),
951
+ });
952
+ const sessionRefreshUpdate = (input) => omitUndefined({
953
+ expires_at: Number(input.expiresAt),
954
+ last_seen_at: input.lastSeenAt === undefined ? undefined : Number(input.lastSeenAt),
955
+ });
956
+ const sessionRotateUpdate = (input) => omitUndefined({
957
+ secret_hash: input.secretHash,
958
+ rotated_at: Number(input.rotatedAt),
959
+ expires_at: input.expiresAt === undefined ? undefined : Number(input.expiresAt),
960
+ });
961
+ const sessionUpdateClaimsUpdate = (row, input) => omitUndefined({
962
+ aal: input.aal,
963
+ amr: input.amr === undefined ? undefined : JSON.stringify(input.amr),
964
+ mfa_verified_at: input.mfaVerifiedAt === undefined ? undefined : Number(input.mfaVerifiedAt),
965
+ metadata: encodeSessionMetadata({
966
+ ...row,
967
+ claims: input.claims ?? row.claims,
968
+ }),
969
+ });
970
+ const sessionRevokeUpdate = (input) => ({
971
+ revoked_at: Number(input.revokedAt),
972
+ });
973
+ const verificationConsumeUpdate = (input) => ({
974
+ consumed_at: Number(input.consumedAt),
975
+ });
976
+ const loginApprovalReviewApproveUpdate = (input) => ({
977
+ status: "approved",
978
+ reviewed_at: Number(input.reviewedAt),
979
+ reviewed_by: input.reviewedBy ?? null,
980
+ review_metadata: jsonEncode(input.metadata),
981
+ });
982
+ const loginApprovalReviewDenyUpdate = (input) => ({
983
+ status: "denied",
984
+ reviewed_at: Number(input.reviewedAt),
985
+ reviewed_by: input.reviewedBy ?? null,
986
+ denied_reason: input.reason ?? null,
987
+ review_metadata: jsonEncode(input.metadata),
988
+ });
989
+ const trustedDeviceInsert = (input, createdAt) => ({
990
+ user_id: input.userId,
991
+ token_hash: input.tokenHash,
992
+ created_at: Number(createdAt),
993
+ last_seen_at: Number(input.now),
994
+ expires_at: Number(input.expiresAt),
995
+ metadata: jsonEncode(input.metadata),
996
+ });
997
+ const trustedDeviceUpdate = (input, existing) => ({
998
+ last_seen_at: Number(input.now),
999
+ expires_at: Number(input.expiresAt),
1000
+ metadata: jsonEncode(input.metadata ?? existing.metadata),
1001
+ });
1002
+ const passkeyCredentialInsert = (row) => ({
1003
+ id: row.id,
1004
+ user_id: row.userId,
1005
+ credential_id: row.credentialId,
1006
+ public_key: row.publicKey,
1007
+ sign_count: row.signCount,
1008
+ transports: jsonEncode(row.transports),
1009
+ backed_up: row.backedUp === undefined ? null : row.backedUp ? 1 : 0,
1010
+ created_at: Number(row.createdAt),
1011
+ last_used_at: row.lastUsedAt === undefined ? null : Number(row.lastUsedAt),
1012
+ revoked_at: row.revokedAt === undefined ? null : Number(row.revokedAt),
1013
+ metadata: jsonEncode(row.metadata),
1014
+ });
1015
+ const passkeyCredentialUpdateSignCount = (input) => omitUndefined({
1016
+ sign_count: input.signCount,
1017
+ last_used_at: Number(input.lastUsedAt),
1018
+ metadata: input.metadata === undefined ? undefined : jsonEncode(input.metadata),
1019
+ });
1020
+ const passkeyCredentialRevoke = (input, row) => ({
1021
+ revoked_at: Number(input.revokedAt),
1022
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1023
+ });
1024
+ const totpFactorInsert = (row) => ({
1025
+ id: row.id,
1026
+ user_id: row.userId,
1027
+ secret: Redacted.value(row.secret),
1028
+ algorithm: row.algorithm,
1029
+ digits: row.digits,
1030
+ period: row.period,
1031
+ created_at: Number(row.createdAt),
1032
+ confirmed_at: row.confirmedAt === undefined ? null : Number(row.confirmedAt),
1033
+ last_used_at: row.lastUsedAt === undefined ? null : Number(row.lastUsedAt),
1034
+ revoked_at: row.revokedAt === undefined ? null : Number(row.revokedAt),
1035
+ metadata: jsonEncode(row.metadata),
1036
+ });
1037
+ const totpFactorConfirm = (input) => omitUndefined({
1038
+ confirmed_at: Number(input.confirmedAt),
1039
+ metadata: input.metadata === undefined ? undefined : jsonEncode(input.metadata),
1040
+ });
1041
+ const totpFactorMarkUsed = (input) => omitUndefined({
1042
+ last_used_at: Number(input.lastUsedAt),
1043
+ metadata: input.metadata === undefined ? undefined : jsonEncode(input.metadata),
1044
+ });
1045
+ const totpFactorRevoke = (input, row) => ({
1046
+ revoked_at: Number(input.revokedAt),
1047
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1048
+ });
1049
+ const recoveryCodeInsert = (row) => ({
1050
+ id: row.id,
1051
+ user_id: row.userId,
1052
+ code_hash: row.codeHash,
1053
+ created_at: Number(row.createdAt),
1054
+ used_at: row.usedAt === undefined ? null : Number(row.usedAt),
1055
+ revoked_at: row.revokedAt === undefined ? null : Number(row.revokedAt),
1056
+ metadata: jsonEncode(row.metadata),
1057
+ });
1058
+ const recoveryCodeMarkUsed = (input) => omitUndefined({
1059
+ used_at: Number(input.usedAt),
1060
+ metadata: input.metadata === undefined ? undefined : jsonEncode(input.metadata),
1061
+ });
1062
+ const recoveryCodeRevoke = (input, row) => ({
1063
+ revoked_at: Number(input.revokedAt),
1064
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1065
+ });
1066
+ const apiKeyInsert = (row) => ({
1067
+ id: row.id,
1068
+ user_id: row.userId,
1069
+ prefix: row.prefix,
1070
+ secret_hash: row.secretHash,
1071
+ scopes: JSON.stringify(row.scopes),
1072
+ created_at: Number(row.createdAt),
1073
+ expires_at: row.expiresAt === undefined ? null : Number(row.expiresAt),
1074
+ last_used_at: row.lastUsedAt === undefined ? null : Number(row.lastUsedAt),
1075
+ revoked_at: row.revokedAt === undefined ? null : Number(row.revokedAt),
1076
+ metadata: jsonEncode(row.metadata),
1077
+ });
1078
+ const apiKeyMarkUsed = (input) => omitUndefined({
1079
+ last_used_at: Number(input.lastUsedAt),
1080
+ metadata: input.metadata === undefined ? undefined : jsonEncode(input.metadata),
1081
+ });
1082
+ const apiKeyRevoke = (input, row) => ({
1083
+ revoked_at: Number(input.revokedAt),
1084
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1085
+ });
1086
+ const refreshTokenInsert = (row) => ({
1087
+ id: row.id,
1088
+ family_id: row.familyId,
1089
+ user_id: row.userId,
1090
+ secret_hash: row.secretHash,
1091
+ created_at: Number(row.createdAt),
1092
+ expires_at: Number(row.expiresAt),
1093
+ last_used_at: row.lastUsedAt === undefined ? null : Number(row.lastUsedAt),
1094
+ rotated_at: row.rotatedAt === undefined ? null : Number(row.rotatedAt),
1095
+ replaced_by_id: row.replacedById ?? null,
1096
+ revoked_at: row.revokedAt === undefined ? null : Number(row.revokedAt),
1097
+ reuse_detected_at: row.reuseDetectedAt === undefined ? null : Number(row.reuseDetectedAt),
1098
+ metadata: jsonEncode(row.metadata),
1099
+ });
1100
+ const refreshTokenRotate = (input) => ({
1101
+ last_used_at: Number(input.rotatedAt),
1102
+ rotated_at: Number(input.rotatedAt),
1103
+ replaced_by_id: input.replacement.id,
1104
+ });
1105
+ const refreshTokenMarkReuseDetected = (input) => ({
1106
+ reuse_detected_at: Number(input.reuseDetectedAt),
1107
+ });
1108
+ const refreshTokenRevoke = (input, row) => ({
1109
+ revoked_at: Number(input.revokedAt),
1110
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1111
+ });
1112
+ const refreshTokenRevokeFamily = (input, row) => ({
1113
+ revoked_at: Number(input.revokedAt),
1114
+ metadata: jsonEncode(metadataWithReason(row.metadata, "familyRevokeReason", input.reason)),
1115
+ });
1116
+ const jwtRevocationInsert = (record) => ({
1117
+ jwt_id: record.jwtId,
1118
+ revoked_at: Number(record.revokedAt),
1119
+ expires_at: record.expiresAt === undefined ? null : Number(record.expiresAt),
1120
+ reason: record.reason ?? null,
1121
+ });
1122
+ const oauthAccountInsert = (row) => ({
1123
+ id: row.id,
1124
+ provider_id: row.providerId,
1125
+ provider_account_id: row.providerAccountId,
1126
+ user_id: row.userId,
1127
+ email: row.email ?? null,
1128
+ email_verified: row.emailVerified === undefined ? null : row.emailVerified ? 1 : 0,
1129
+ created_at: Number(row.createdAt),
1130
+ updated_at: Number(row.updatedAt),
1131
+ unlinked_at: row.unlinkedAt === undefined ? null : Number(row.unlinkedAt),
1132
+ metadata: jsonEncode(row.metadata),
1133
+ });
1134
+ const oauthAccountUnlink = (input, row) => ({
1135
+ unlinked_at: Number(input.unlinkedAt),
1136
+ metadata: jsonEncode(metadataWithReason(row.metadata, "unlinkReason", input.reason)),
1137
+ });
1138
+ const oauthProviderTokenVaultValues = (row) => ({
1139
+ account_id: row.accountId,
1140
+ user_id: row.userId,
1141
+ provider_id: row.providerId,
1142
+ provider_account_id: row.providerAccountId,
1143
+ access_token_ciphertext: Redacted.value(row.accessTokenCiphertext),
1144
+ refresh_token_ciphertext: row.refreshTokenCiphertext === undefined
1145
+ ? null
1146
+ : Redacted.value(row.refreshTokenCiphertext),
1147
+ id_token_ciphertext: row.idTokenCiphertext === undefined ? null : Redacted.value(row.idTokenCiphertext),
1148
+ token_type: row.tokenType,
1149
+ scopes: jsonEncode(row.scopes),
1150
+ expires_at: row.expiresAt === undefined ? null : Number(row.expiresAt),
1151
+ updated_at: Number(row.updatedAt),
1152
+ revoked_at: row.revokedAt === undefined ? null : Number(row.revokedAt),
1153
+ revocation_reason: row.revocationReason ?? null,
1154
+ });
1155
+ const oauthProviderTokenVaultMarkRevoked = (input) => ({
1156
+ revoked_at: Number(input.revokedAt),
1157
+ revocation_reason: input.reason,
1158
+ });
1159
+ const oauthClientValues = (record) => ({
1160
+ id: record.id,
1161
+ type: record.type,
1162
+ status: record.status,
1163
+ name: record.name ?? null,
1164
+ redirect_uris: JSON.stringify(record.redirectUris),
1165
+ allowed_grant_types: JSON.stringify(record.allowedGrantTypes),
1166
+ allowed_response_types: JSON.stringify(record.allowedResponseTypes),
1167
+ allowed_scopes: jsonEncode(record.allowedScopes),
1168
+ created_at: record.createdAt === undefined ? null : Number(record.createdAt),
1169
+ updated_at: record.updatedAt === undefined ? null : Number(record.updatedAt),
1170
+ metadata: jsonEncode(record.metadata),
1171
+ });
1172
+ const oauthConsentId = (input) => JSON.stringify([input.userId, input.clientId]);
1173
+ const oauthConsentValues = (record) => ({
1174
+ id: oauthConsentId(record),
1175
+ user_id: record.userId,
1176
+ client_id: record.clientId,
1177
+ scopes: JSON.stringify(record.scopes),
1178
+ granted_at: Number(record.grantedAt),
1179
+ expires_at: record.expiresAt === undefined ? null : Number(record.expiresAt),
1180
+ revoked_at: record.revokedAt === undefined ? null : Number(record.revokedAt),
1181
+ metadata: jsonEncode(record.metadata),
1182
+ });
1183
+ const oauthConsentRevoke = (input, row) => ({
1184
+ revoked_at: Number(row.revokedAt ?? input.revokedAt),
1185
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1186
+ });
1187
+ const oauthAuthorizationCodeValues = (record) => ({
1188
+ code_hash: record.codeHash,
1189
+ client_id: record.clientId,
1190
+ subject: record.subject,
1191
+ redirect_uri: record.redirectUri,
1192
+ scopes: JSON.stringify(record.scopes),
1193
+ code_challenge: record.codeChallenge ?? null,
1194
+ code_challenge_method: record.codeChallengeMethod ?? null,
1195
+ issued_at: Number(record.issuedAt),
1196
+ expires_at: Number(record.expiresAt),
1197
+ consumed_at: record.consumedAt === undefined ? null : Number(record.consumedAt),
1198
+ metadata: jsonEncode(record.metadata),
1199
+ });
1200
+ const oauthAuthorizationCodeMarkConsumed = (input) => ({
1201
+ consumed_at: Number(input.consumedAt),
1202
+ });
1203
+ const oauthClientSecretValues = (record) => ({
1204
+ prefix: record.prefix,
1205
+ client_id: record.clientId,
1206
+ secret_hash: record.secretHash,
1207
+ authentication_methods: JSON.stringify(record.authenticationMethods),
1208
+ created_at: Number(record.createdAt),
1209
+ expires_at: record.expiresAt === undefined ? null : Number(record.expiresAt),
1210
+ last_used_at: record.lastUsedAt === undefined ? null : Number(record.lastUsedAt),
1211
+ revoked_at: record.revokedAt === undefined ? null : Number(record.revokedAt),
1212
+ metadata: jsonEncode(record.metadata),
1213
+ });
1214
+ const oauthClientSecretMarkUsed = (input) => omitUndefined({
1215
+ last_used_at: Number(input.lastUsedAt),
1216
+ metadata: input.metadata === undefined ? undefined : jsonEncode(input.metadata),
1217
+ });
1218
+ const oauthClientSecretRevoke = (input, row) => ({
1219
+ revoked_at: Number(input.revokedAt),
1220
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1221
+ });
1222
+ const oauthProviderModeTokenValues = (record) => ({
1223
+ token_hash: record.tokenHash,
1224
+ token_type: record.tokenType,
1225
+ client_id: record.clientId,
1226
+ subject: record.subject,
1227
+ scopes: JSON.stringify(record.scopes),
1228
+ issued_at: Number(record.issuedAt),
1229
+ expires_at: Number(record.expiresAt),
1230
+ issuer: record.issuer ?? null,
1231
+ audience: jsonEncode(record.audience),
1232
+ jwt_id: record.jwtId ?? null,
1233
+ revoked_at: record.revokedAt === undefined ? null : Number(record.revokedAt),
1234
+ revocation_reason: record.revocationReason ?? null,
1235
+ rotated_at: record.rotatedAt === undefined ? null : Number(record.rotatedAt),
1236
+ replaced_by_token_hash: record.replacedByTokenHash ?? null,
1237
+ metadata: jsonEncode(record.metadata),
1238
+ });
1239
+ const oauthProviderModeTokenRevoke = (input, row) => ({
1240
+ revoked_at: Number(row.revokedAt ?? input.revokedAt),
1241
+ revocation_reason: row.revocationReason ?? input.reason ?? null,
1242
+ });
1243
+ const oauthProviderModeTokenRotate = (input) => ({
1244
+ rotated_at: Number(input.rotatedAt),
1245
+ replaced_by_token_hash: input.replacedByTokenHash,
1246
+ });
1247
+ const domainVerificationValues = (record) => ({
1248
+ id: record.id,
1249
+ owner_id: record.ownerId,
1250
+ domain: record.domain,
1251
+ proof_method: record.proofMethod,
1252
+ proof_token: record.proofToken,
1253
+ status: record.status,
1254
+ created_at: Number(record.createdAt),
1255
+ expires_at: Number(record.expiresAt),
1256
+ verified_at: record.verifiedAt === undefined ? null : Number(record.verifiedAt),
1257
+ revoked_at: record.revokedAt === undefined ? null : Number(record.revokedAt),
1258
+ last_checked_at: record.lastCheckedAt === undefined ? null : Number(record.lastCheckedAt),
1259
+ metadata: jsonEncode(record.metadata),
1260
+ });
1261
+ const domainVerificationMarkVerified = (input) => omitUndefined({
1262
+ status: "verified",
1263
+ verified_at: Number(input.verifiedAt),
1264
+ last_checked_at: Number(input.verifiedAt),
1265
+ metadata: input.metadata === undefined ? undefined : jsonEncode(input.metadata),
1266
+ });
1267
+ const domainVerificationRevoke = (input, row) => ({
1268
+ status: "revoked",
1269
+ revoked_at: Number(input.revokedAt),
1270
+ metadata: jsonEncode(metadataWithReason(row.metadata, "revokeReason", input.reason)),
1271
+ });
1272
+ const securityTimelineInsert = (event) => ({
1273
+ id: event.id,
1274
+ user_id: event.userId,
1275
+ type: event.type,
1276
+ category: event.category,
1277
+ severity: event.severity,
1278
+ occurred_at: Number(event.occurredAt),
1279
+ summary: event.summary,
1280
+ actor: jsonEncode(event.actor),
1281
+ request: jsonEncode(event.request),
1282
+ metadata: jsonEncode(event.metadata),
1283
+ });
1284
+ const webhookOutboxInsert = (record) => ({
1285
+ id: record.id,
1286
+ endpoint_key: record.endpointKey,
1287
+ event: jsonEncode(record.event),
1288
+ status: record.status,
1289
+ attempts: record.attempts,
1290
+ next_attempt_at: Number(record.nextAttemptAt),
1291
+ created_at: Number(record.createdAt),
1292
+ updated_at: Number(record.updatedAt),
1293
+ delivered_at: record.deliveredAt === undefined ? null : Number(record.deliveredAt),
1294
+ last_error: record.lastError ?? null,
1295
+ });
1296
+ const webhookOutboxMarkDelivered = (input) => ({
1297
+ status: "delivered",
1298
+ delivered_at: Number(input.deliveredAt),
1299
+ updated_at: Number(input.deliveredAt),
1300
+ last_error: null,
1301
+ });
1302
+ const webhookOutboxMarkFailed = (input) => ({
1303
+ status: "failed",
1304
+ attempts: input.attempts,
1305
+ next_attempt_at: Number(input.nextAttemptAt),
1306
+ updated_at: Number(input.failedAt),
1307
+ last_error: input.error ?? null,
1308
+ });
1309
+ const webhookOutboxMarkDeadLettered = (input) => ({
1310
+ status: "dead_lettered",
1311
+ updated_at: Number(input.deadLetteredAt),
1312
+ last_error: input.error ?? null,
1313
+ });
1314
+ const webhookReplayInsert = (input) => ({
1315
+ id: input.id,
1316
+ expires_at: Number(input.expiresAt),
1317
+ created_at: Number(input.now),
1318
+ });
1319
+ const webhookReplayUpdate = (input) => ({
1320
+ expires_at: Number(input.expiresAt),
1321
+ created_at: Number(input.now),
1322
+ });
1323
+ const jwtRevocationUpdate = (record) => ({
1324
+ revoked_at: Number(record.revokedAt),
1325
+ expires_at: record.expiresAt === undefined ? null : Number(record.expiresAt),
1326
+ reason: record.reason ?? null,
1327
+ });
1328
+ const authSqliteTableName = (name, defaultName) => name ?? defaultName;
1329
+ const makeInternalAuthSqliteTables = (names = {}) => {
1330
+ const user = makeAuthUserTable(names.user ?? "auth_user");
1331
+ const credential = makeAuthCredentialTable(names.credential ?? "auth_credential");
1332
+ const session = makeAuthSessionTable(names.session ?? "auth_session");
1333
+ const verification = makeAuthVerificationTable(names.verification ?? "auth_verification");
1334
+ const auditLog = makeAuthAuditLogTable(authSqliteTableName(names.auditLog, "auth_audit_log"));
1335
+ const loginApprovalReview = makeAuthLoginApprovalReviewTable(names.loginApprovalReview ?? "auth_login_approval_review");
1336
+ const loginRiskHistory = makeAuthLoginRiskHistoryTable(names.loginRiskHistory ?? "auth_login_risk_history");
1337
+ const trustedDevice = makeAuthTrustedDeviceTable(names.trustedDevice ?? "auth_trusted_device");
1338
+ const passkeyCredential = makeAuthPasskeyCredentialTable(names.passkeyCredential ?? "auth_passkey_credential");
1339
+ const totpFactor = makeAuthTotpFactorTable(names.totpFactor ?? "auth_totp_factor");
1340
+ const recoveryCode = makeAuthRecoveryCodeTable(names.recoveryCode ?? "auth_recovery_code");
1341
+ const apiKey = makeAuthApiKeyTable(names.apiKey ?? "auth_api_key");
1342
+ const refreshToken = makeAuthRefreshTokenTable(names.refreshToken ?? "auth_refresh_token");
1343
+ const jwtRevocation = makeAuthJwtRevocationTable(names.jwtRevocation ?? "auth_jwt_revocation");
1344
+ const oauthAccount = makeAuthOAuthAccountTable(names.oauthAccount ?? "auth_oauth_account");
1345
+ const oauthClient = makeAuthOAuthClientTable(authSqliteTableName(names.oauthClient, "auth_oauth_client"));
1346
+ const oauthConsent = makeAuthOAuthConsentTable(authSqliteTableName(names.oauthConsent, "auth_oauth_consent"));
1347
+ const oauthAuthorizationCode = makeAuthOAuthAuthorizationCodeTable(authSqliteTableName(names.oauthAuthorizationCode, "auth_oauth_authorization_code"));
1348
+ const oauthClientSecret = makeAuthOAuthClientSecretTable(authSqliteTableName(names.oauthClientSecret, "auth_oauth_client_secret"));
1349
+ const oauthProviderModeToken = makeAuthOAuthProviderModeTokenTable(authSqliteTableName(names.oauthProviderModeToken, "auth_oauth_provider_mode_token"));
1350
+ const oauthProviderTokenVault = makeAuthOAuthProviderTokenVaultTable(names.oauthProviderTokenVault ?? "auth_oauth_provider_token_vault");
1351
+ const domainVerification = makeAuthDomainVerificationTable(authSqliteTableName(names.domainVerification, "auth_domain_verification"));
1352
+ const securityTimeline = makeAuthSecurityTimelineTable(names.securityTimeline ?? "auth_security_timeline");
1353
+ const webhookOutbox = makeAuthWebhookOutboxTable(names.webhookOutbox ?? "auth_webhook_outbox");
1354
+ const webhookReplay = makeAuthWebhookReplayTable(names.webhookReplay ?? "auth_webhook_replay");
1355
+ return {
1356
+ user: {
1357
+ table: user,
1358
+ select: {
1359
+ id: user.id,
1360
+ email: user.email,
1361
+ emailVerified: user.email_verified,
1362
+ createdAt: user.created_at,
1363
+ updatedAt: user.updated_at,
1364
+ disabledAt: user.disabled_at,
1365
+ metadata: user.metadata,
1366
+ },
1367
+ insert: userInsert,
1368
+ markEmailVerified: userMarkEmailVerifiedUpdate,
1369
+ },
1370
+ credential: {
1371
+ table: credential,
1372
+ select: {
1373
+ id: credential.id,
1374
+ userId: credential.user_id,
1375
+ type: credential.type,
1376
+ passwordHash: credential.password_hash,
1377
+ createdAt: credential.created_at,
1378
+ updatedAt: credential.updated_at,
1379
+ revokedAt: credential.revoked_at,
1380
+ metadata: credential.metadata,
1381
+ },
1382
+ insertPassword: passwordCredentialInsert,
1383
+ updatePassword: passwordCredentialUpdatePassword,
1384
+ },
1385
+ session: {
1386
+ table: session,
1387
+ select: {
1388
+ id: session.id,
1389
+ userId: session.user_id,
1390
+ secretHash: session.secret_hash,
1391
+ createdAt: session.created_at,
1392
+ expiresAt: session.expires_at,
1393
+ authTime: session.auth_time,
1394
+ aal: session.aal,
1395
+ amr: session.amr,
1396
+ mfaVerifiedAt: session.mfa_verified_at,
1397
+ metadata: session.metadata,
1398
+ revokedAt: session.revoked_at,
1399
+ lastSeenAt: session.last_seen_at,
1400
+ rotatedAt: session.rotated_at,
1401
+ },
1402
+ insert: sessionInsert,
1403
+ refresh: sessionRefreshUpdate,
1404
+ rotate: sessionRotateUpdate,
1405
+ updateClaims: sessionUpdateClaimsUpdate,
1406
+ revoke: sessionRevokeUpdate,
1407
+ },
1408
+ verification: {
1409
+ table: verification,
1410
+ select: {
1411
+ id: verification.id,
1412
+ type: verification.type,
1413
+ subject: verification.subject,
1414
+ secretHash: verification.secret_hash,
1415
+ createdAt: verification.created_at,
1416
+ expiresAt: verification.expires_at,
1417
+ metadata: verification.metadata,
1418
+ consumedAt: verification.consumed_at,
1419
+ },
1420
+ insert: verificationInsert,
1421
+ consume: verificationConsumeUpdate,
1422
+ },
1423
+ auditLog: {
1424
+ table: auditLog,
1425
+ select: {
1426
+ id: auditLog.id,
1427
+ type: auditLog.type,
1428
+ userId: auditLog.user_id,
1429
+ actorUserId: auditLog.actor_user_id,
1430
+ occurredAt: auditLog.occurred_at,
1431
+ requestIpHash: auditLog.request_ip_hash,
1432
+ requestUserAgentHash: auditLog.request_user_agent_hash,
1433
+ event: auditLog.event,
1434
+ createdAt: auditLog.created_at,
1435
+ },
1436
+ insert: auditLogInsert,
1437
+ },
1438
+ loginApprovalReview: {
1439
+ table: loginApprovalReview,
1440
+ select: {
1441
+ approvalChallengeId: loginApprovalReview.approval_challenge_id,
1442
+ flowId: loginApprovalReview.flow_id,
1443
+ userId: loginApprovalReview.user_id,
1444
+ channel: loginApprovalReview.channel,
1445
+ reason: loginApprovalReview.reason,
1446
+ sessionBinding: loginApprovalReview.session_binding,
1447
+ sameDeviceRequired: loginApprovalReview.same_device_required,
1448
+ status: loginApprovalReview.status,
1449
+ createdAt: loginApprovalReview.created_at,
1450
+ expiresAt: loginApprovalReview.expires_at,
1451
+ reviewedAt: loginApprovalReview.reviewed_at,
1452
+ reviewedBy: loginApprovalReview.reviewed_by,
1453
+ deniedReason: loginApprovalReview.denied_reason,
1454
+ risk: loginApprovalReview.risk,
1455
+ metadata: loginApprovalReview.metadata,
1456
+ reviewMetadata: loginApprovalReview.review_metadata,
1457
+ },
1458
+ insertPending: loginApprovalReviewInsert,
1459
+ approve: loginApprovalReviewApproveUpdate,
1460
+ deny: loginApprovalReviewDenyUpdate,
1461
+ },
1462
+ loginRiskHistory: {
1463
+ table: loginRiskHistory,
1464
+ select: {
1465
+ id: loginRiskHistory.id,
1466
+ userId: loginRiskHistory.user_id,
1467
+ occurredAt: loginRiskHistory.occurred_at,
1468
+ outcome: loginRiskHistory.outcome,
1469
+ method: loginRiskHistory.method,
1470
+ amr: loginRiskHistory.amr,
1471
+ aal: loginRiskHistory.aal,
1472
+ deviceStatus: loginRiskHistory.device_status,
1473
+ deviceKey: loginRiskHistory.device_key,
1474
+ locationKey: loginRiskHistory.location_key,
1475
+ country: loginRiskHistory.country,
1476
+ region: loginRiskHistory.region,
1477
+ latitudeMicro: loginRiskHistory.latitude_micro,
1478
+ longitudeMicro: loginRiskHistory.longitude_micro,
1479
+ riskLevel: loginRiskHistory.risk_level,
1480
+ createdAt: loginRiskHistory.created_at,
1481
+ },
1482
+ insert: loginRiskHistoryInsert,
1483
+ },
1484
+ trustedDevice: {
1485
+ table: trustedDevice,
1486
+ select: {
1487
+ userId: trustedDevice.user_id,
1488
+ tokenHash: trustedDevice.token_hash,
1489
+ createdAt: trustedDevice.created_at,
1490
+ lastSeenAt: trustedDevice.last_seen_at,
1491
+ expiresAt: trustedDevice.expires_at,
1492
+ metadata: trustedDevice.metadata,
1493
+ },
1494
+ insert: trustedDeviceInsert,
1495
+ update: trustedDeviceUpdate,
1496
+ },
1497
+ passkeyCredential: {
1498
+ table: passkeyCredential,
1499
+ select: {
1500
+ id: passkeyCredential.id,
1501
+ userId: passkeyCredential.user_id,
1502
+ credentialId: passkeyCredential.credential_id,
1503
+ publicKey: passkeyCredential.public_key,
1504
+ signCount: passkeyCredential.sign_count,
1505
+ transports: passkeyCredential.transports,
1506
+ backedUp: passkeyCredential.backed_up,
1507
+ createdAt: passkeyCredential.created_at,
1508
+ lastUsedAt: passkeyCredential.last_used_at,
1509
+ revokedAt: passkeyCredential.revoked_at,
1510
+ metadata: passkeyCredential.metadata,
1511
+ },
1512
+ insert: passkeyCredentialInsert,
1513
+ updateSignCount: passkeyCredentialUpdateSignCount,
1514
+ revoke: passkeyCredentialRevoke,
1515
+ },
1516
+ totpFactor: {
1517
+ table: totpFactor,
1518
+ select: {
1519
+ id: totpFactor.id,
1520
+ userId: totpFactor.user_id,
1521
+ secret: totpFactor.secret,
1522
+ algorithm: totpFactor.algorithm,
1523
+ digits: totpFactor.digits,
1524
+ period: totpFactor.period,
1525
+ createdAt: totpFactor.created_at,
1526
+ confirmedAt: totpFactor.confirmed_at,
1527
+ lastUsedAt: totpFactor.last_used_at,
1528
+ revokedAt: totpFactor.revoked_at,
1529
+ metadata: totpFactor.metadata,
1530
+ },
1531
+ insert: totpFactorInsert,
1532
+ confirm: totpFactorConfirm,
1533
+ markUsed: totpFactorMarkUsed,
1534
+ revoke: totpFactorRevoke,
1535
+ },
1536
+ recoveryCode: {
1537
+ table: recoveryCode,
1538
+ select: {
1539
+ id: recoveryCode.id,
1540
+ userId: recoveryCode.user_id,
1541
+ codeHash: recoveryCode.code_hash,
1542
+ createdAt: recoveryCode.created_at,
1543
+ usedAt: recoveryCode.used_at,
1544
+ revokedAt: recoveryCode.revoked_at,
1545
+ metadata: recoveryCode.metadata,
1546
+ },
1547
+ insert: recoveryCodeInsert,
1548
+ markUsed: recoveryCodeMarkUsed,
1549
+ revoke: recoveryCodeRevoke,
1550
+ },
1551
+ apiKey: {
1552
+ table: apiKey,
1553
+ select: {
1554
+ id: apiKey.id,
1555
+ userId: apiKey.user_id,
1556
+ prefix: apiKey.prefix,
1557
+ secretHash: apiKey.secret_hash,
1558
+ scopes: apiKey.scopes,
1559
+ createdAt: apiKey.created_at,
1560
+ expiresAt: apiKey.expires_at,
1561
+ lastUsedAt: apiKey.last_used_at,
1562
+ revokedAt: apiKey.revoked_at,
1563
+ metadata: apiKey.metadata,
1564
+ },
1565
+ insert: apiKeyInsert,
1566
+ markUsed: apiKeyMarkUsed,
1567
+ revoke: apiKeyRevoke,
1568
+ },
1569
+ refreshToken: {
1570
+ table: refreshToken,
1571
+ select: {
1572
+ id: refreshToken.id,
1573
+ familyId: refreshToken.family_id,
1574
+ userId: refreshToken.user_id,
1575
+ secretHash: refreshToken.secret_hash,
1576
+ createdAt: refreshToken.created_at,
1577
+ expiresAt: refreshToken.expires_at,
1578
+ lastUsedAt: refreshToken.last_used_at,
1579
+ rotatedAt: refreshToken.rotated_at,
1580
+ replacedById: refreshToken.replaced_by_id,
1581
+ revokedAt: refreshToken.revoked_at,
1582
+ reuseDetectedAt: refreshToken.reuse_detected_at,
1583
+ metadata: refreshToken.metadata,
1584
+ },
1585
+ insert: refreshTokenInsert,
1586
+ rotate: refreshTokenRotate,
1587
+ markReuseDetected: refreshTokenMarkReuseDetected,
1588
+ revoke: refreshTokenRevoke,
1589
+ revokeFamily: refreshTokenRevokeFamily,
1590
+ },
1591
+ jwtRevocation: {
1592
+ table: jwtRevocation,
1593
+ select: {
1594
+ jwtId: jwtRevocation.jwt_id,
1595
+ revokedAt: jwtRevocation.revoked_at,
1596
+ expiresAt: jwtRevocation.expires_at,
1597
+ reason: jwtRevocation.reason,
1598
+ },
1599
+ insert: jwtRevocationInsert,
1600
+ update: jwtRevocationUpdate,
1601
+ },
1602
+ oauthAccount: {
1603
+ table: oauthAccount,
1604
+ select: {
1605
+ id: oauthAccount.id,
1606
+ providerId: oauthAccount.provider_id,
1607
+ providerAccountId: oauthAccount.provider_account_id,
1608
+ userId: oauthAccount.user_id,
1609
+ email: oauthAccount.email,
1610
+ emailVerified: oauthAccount.email_verified,
1611
+ createdAt: oauthAccount.created_at,
1612
+ updatedAt: oauthAccount.updated_at,
1613
+ unlinkedAt: oauthAccount.unlinked_at,
1614
+ metadata: oauthAccount.metadata,
1615
+ },
1616
+ insert: oauthAccountInsert,
1617
+ unlink: oauthAccountUnlink,
1618
+ },
1619
+ oauthClient: {
1620
+ table: oauthClient,
1621
+ select: {
1622
+ id: oauthClient.id,
1623
+ type: oauthClient.type,
1624
+ status: oauthClient.status,
1625
+ name: oauthClient.name,
1626
+ redirectUris: oauthClient.redirect_uris,
1627
+ allowedGrantTypes: oauthClient.allowed_grant_types,
1628
+ allowedResponseTypes: oauthClient.allowed_response_types,
1629
+ allowedScopes: oauthClient.allowed_scopes,
1630
+ createdAt: oauthClient.created_at,
1631
+ updatedAt: oauthClient.updated_at,
1632
+ metadata: oauthClient.metadata,
1633
+ },
1634
+ insert: oauthClientValues,
1635
+ update: oauthClientValues,
1636
+ },
1637
+ oauthConsent: {
1638
+ table: oauthConsent,
1639
+ select: {
1640
+ id: oauthConsent.id,
1641
+ userId: oauthConsent.user_id,
1642
+ clientId: oauthConsent.client_id,
1643
+ scopes: oauthConsent.scopes,
1644
+ grantedAt: oauthConsent.granted_at,
1645
+ expiresAt: oauthConsent.expires_at,
1646
+ revokedAt: oauthConsent.revoked_at,
1647
+ metadata: oauthConsent.metadata,
1648
+ },
1649
+ insert: oauthConsentValues,
1650
+ update: oauthConsentValues,
1651
+ revoke: oauthConsentRevoke,
1652
+ },
1653
+ oauthAuthorizationCode: {
1654
+ table: oauthAuthorizationCode,
1655
+ select: {
1656
+ codeHash: oauthAuthorizationCode.code_hash,
1657
+ clientId: oauthAuthorizationCode.client_id,
1658
+ subject: oauthAuthorizationCode.subject,
1659
+ redirectUri: oauthAuthorizationCode.redirect_uri,
1660
+ scopes: oauthAuthorizationCode.scopes,
1661
+ codeChallenge: oauthAuthorizationCode.code_challenge,
1662
+ codeChallengeMethod: oauthAuthorizationCode.code_challenge_method,
1663
+ issuedAt: oauthAuthorizationCode.issued_at,
1664
+ expiresAt: oauthAuthorizationCode.expires_at,
1665
+ consumedAt: oauthAuthorizationCode.consumed_at,
1666
+ metadata: oauthAuthorizationCode.metadata,
1667
+ },
1668
+ insert: oauthAuthorizationCodeValues,
1669
+ update: oauthAuthorizationCodeValues,
1670
+ markConsumed: oauthAuthorizationCodeMarkConsumed,
1671
+ },
1672
+ oauthClientSecret: {
1673
+ table: oauthClientSecret,
1674
+ select: {
1675
+ prefix: oauthClientSecret.prefix,
1676
+ clientId: oauthClientSecret.client_id,
1677
+ secretHash: oauthClientSecret.secret_hash,
1678
+ authenticationMethods: oauthClientSecret.authentication_methods,
1679
+ createdAt: oauthClientSecret.created_at,
1680
+ expiresAt: oauthClientSecret.expires_at,
1681
+ lastUsedAt: oauthClientSecret.last_used_at,
1682
+ revokedAt: oauthClientSecret.revoked_at,
1683
+ metadata: oauthClientSecret.metadata,
1684
+ },
1685
+ insert: oauthClientSecretValues,
1686
+ update: oauthClientSecretValues,
1687
+ markUsed: oauthClientSecretMarkUsed,
1688
+ revoke: oauthClientSecretRevoke,
1689
+ },
1690
+ oauthProviderModeToken: {
1691
+ table: oauthProviderModeToken,
1692
+ select: {
1693
+ tokenHash: oauthProviderModeToken.token_hash,
1694
+ tokenType: oauthProviderModeToken.token_type,
1695
+ clientId: oauthProviderModeToken.client_id,
1696
+ subject: oauthProviderModeToken.subject,
1697
+ scopes: oauthProviderModeToken.scopes,
1698
+ issuedAt: oauthProviderModeToken.issued_at,
1699
+ expiresAt: oauthProviderModeToken.expires_at,
1700
+ issuer: oauthProviderModeToken.issuer,
1701
+ audience: oauthProviderModeToken.audience,
1702
+ jwtId: oauthProviderModeToken.jwt_id,
1703
+ revokedAt: oauthProviderModeToken.revoked_at,
1704
+ revocationReason: oauthProviderModeToken.revocation_reason,
1705
+ rotatedAt: oauthProviderModeToken.rotated_at,
1706
+ replacedByTokenHash: oauthProviderModeToken.replaced_by_token_hash,
1707
+ metadata: oauthProviderModeToken.metadata,
1708
+ },
1709
+ insert: oauthProviderModeTokenValues,
1710
+ update: oauthProviderModeTokenValues,
1711
+ revoke: oauthProviderModeTokenRevoke,
1712
+ rotate: oauthProviderModeTokenRotate,
1713
+ },
1714
+ oauthProviderTokenVault: {
1715
+ table: oauthProviderTokenVault,
1716
+ select: {
1717
+ accountId: oauthProviderTokenVault.account_id,
1718
+ userId: oauthProviderTokenVault.user_id,
1719
+ providerId: oauthProviderTokenVault.provider_id,
1720
+ providerAccountId: oauthProviderTokenVault.provider_account_id,
1721
+ accessTokenCiphertext: oauthProviderTokenVault.access_token_ciphertext,
1722
+ refreshTokenCiphertext: oauthProviderTokenVault.refresh_token_ciphertext,
1723
+ idTokenCiphertext: oauthProviderTokenVault.id_token_ciphertext,
1724
+ tokenType: oauthProviderTokenVault.token_type,
1725
+ scopes: oauthProviderTokenVault.scopes,
1726
+ expiresAt: oauthProviderTokenVault.expires_at,
1727
+ updatedAt: oauthProviderTokenVault.updated_at,
1728
+ revokedAt: oauthProviderTokenVault.revoked_at,
1729
+ revocationReason: oauthProviderTokenVault.revocation_reason,
1730
+ },
1731
+ insert: oauthProviderTokenVaultValues,
1732
+ update: oauthProviderTokenVaultValues,
1733
+ markRevoked: oauthProviderTokenVaultMarkRevoked,
1734
+ },
1735
+ domainVerification: {
1736
+ table: domainVerification,
1737
+ select: {
1738
+ id: domainVerification.id,
1739
+ ownerId: domainVerification.owner_id,
1740
+ domain: domainVerification.domain,
1741
+ proofMethod: domainVerification.proof_method,
1742
+ proofToken: domainVerification.proof_token,
1743
+ status: domainVerification.status,
1744
+ createdAt: domainVerification.created_at,
1745
+ expiresAt: domainVerification.expires_at,
1746
+ verifiedAt: domainVerification.verified_at,
1747
+ revokedAt: domainVerification.revoked_at,
1748
+ lastCheckedAt: domainVerification.last_checked_at,
1749
+ metadata: domainVerification.metadata,
1750
+ },
1751
+ insert: domainVerificationValues,
1752
+ update: domainVerificationValues,
1753
+ markVerified: domainVerificationMarkVerified,
1754
+ revoke: domainVerificationRevoke,
1755
+ },
1756
+ securityTimeline: {
1757
+ table: securityTimeline,
1758
+ select: {
1759
+ id: securityTimeline.id,
1760
+ userId: securityTimeline.user_id,
1761
+ type: securityTimeline.type,
1762
+ category: securityTimeline.category,
1763
+ severity: securityTimeline.severity,
1764
+ occurredAt: securityTimeline.occurred_at,
1765
+ summary: securityTimeline.summary,
1766
+ actor: securityTimeline.actor,
1767
+ request: securityTimeline.request,
1768
+ metadata: securityTimeline.metadata,
1769
+ },
1770
+ insert: securityTimelineInsert,
1771
+ },
1772
+ webhookOutbox: {
1773
+ table: webhookOutbox,
1774
+ select: {
1775
+ id: webhookOutbox.id,
1776
+ endpointKey: webhookOutbox.endpoint_key,
1777
+ event: webhookOutbox.event,
1778
+ status: webhookOutbox.status,
1779
+ attempts: webhookOutbox.attempts,
1780
+ nextAttemptAt: webhookOutbox.next_attempt_at,
1781
+ createdAt: webhookOutbox.created_at,
1782
+ updatedAt: webhookOutbox.updated_at,
1783
+ deliveredAt: webhookOutbox.delivered_at,
1784
+ lastError: webhookOutbox.last_error,
1785
+ },
1786
+ insert: webhookOutboxInsert,
1787
+ markDelivered: webhookOutboxMarkDelivered,
1788
+ markFailed: webhookOutboxMarkFailed,
1789
+ markDeadLettered: webhookOutboxMarkDeadLettered,
1790
+ },
1791
+ webhookReplay: {
1792
+ table: webhookReplay,
1793
+ select: {
1794
+ id: webhookReplay.id,
1795
+ expiresAt: webhookReplay.expires_at,
1796
+ createdAt: webhookReplay.created_at,
1797
+ },
1798
+ insert: webhookReplayInsert,
1799
+ update: webhookReplayUpdate,
1800
+ },
1801
+ };
1802
+ };
1803
+ const asAuthSqliteTables = (tables) => tables;
1804
+ export const defineEffectQbAuthTables = (tables) => asAuthSqliteTables(tables);
1805
+ export const makeAuthSqliteTables = (names = {}) => asAuthSqliteTables(makeInternalAuthSqliteTables(names));
1806
+ export const authSqliteTables = makeAuthSqliteTables();
1807
+ const selectUserColumns = (tables) => tables.user.select;
1808
+ const selectCredentialColumns = (tables) => tables.credential.select;
1809
+ const selectSessionColumns = (tables) => tables.session.select;
1810
+ const selectVerificationColumns = (tables) => tables.verification.select;
1811
+ const selectAuditLogColumns = (tables) => tables.auditLog.select;
1812
+ const selectLoginApprovalReviewColumns = (tables) => tables.loginApprovalReview.select;
1813
+ const selectLoginRiskHistoryColumns = (tables) => tables.loginRiskHistory.select;
1814
+ const selectTrustedDeviceColumns = (tables) => tables.trustedDevice.select;
1815
+ const selectPasskeyCredentialColumns = (tables) => tables.passkeyCredential.select;
1816
+ const selectTotpFactorColumns = (tables) => tables.totpFactor.select;
1817
+ const selectRecoveryCodeColumns = (tables) => tables.recoveryCode.select;
1818
+ const selectApiKeyColumns = (tables) => tables.apiKey.select;
1819
+ const selectRefreshTokenColumns = (tables) => tables.refreshToken.select;
1820
+ const selectJwtRevocationColumns = (tables) => tables.jwtRevocation.select;
1821
+ const selectOAuthAccountColumns = (tables) => tables.oauthAccount.select;
1822
+ const selectOAuthClientColumns = (tables) => tables.oauthClient.select;
1823
+ const selectOAuthConsentColumns = (tables) => tables.oauthConsent.select;
1824
+ const selectOAuthAuthorizationCodeColumns = (tables) => tables.oauthAuthorizationCode.select;
1825
+ const selectOAuthClientSecretColumns = (tables) => tables.oauthClientSecret.select;
1826
+ const selectOAuthProviderModeTokenColumns = (tables) => tables.oauthProviderModeToken.select;
1827
+ const selectOAuthProviderTokenVaultColumns = (tables) => tables.oauthProviderTokenVault.select;
1828
+ const selectDomainVerificationColumns = (tables) => tables.domainVerification.select;
1829
+ const selectSecurityTimelineColumns = (tables) => tables.securityTimeline.select;
1830
+ const selectWebhookOutboxColumns = (tables) => tables.webhookOutbox.select;
1831
+ const selectWebhookReplayColumns = (tables) => tables.webhookReplay.select;
1832
+ const storageError = (entity, operation, cause) => StorageError.fromUnknown(entity, operation, cause);
1833
+ const auditLogStoreError = (operation, cause) => new AuditLogStoreError({
1834
+ operation,
1835
+ message: `Audit log ${operation} failed`,
1836
+ cause,
1837
+ });
1838
+ const loginApprovalReviewStoreError = (operation, cause) => new LoginApprovalReviewError({
1839
+ message: `Login approval review ${operation} failed`,
1840
+ cause,
1841
+ });
1842
+ const loginRiskHistoryStoreError = (operation, cause) => new LoginRiskHistoryError({
1843
+ operation,
1844
+ message: `Login risk history ${operation} failed`,
1845
+ cause,
1846
+ });
1847
+ const trustedDeviceStoreError = (operation, cause) => new TrustedDeviceError({
1848
+ operation,
1849
+ message: `Trusted device ${operation} failed`,
1850
+ cause,
1851
+ });
1852
+ const passkeyCredentialStoreError = (operation, cause) => new PasskeyCredentialStoreError({
1853
+ operation,
1854
+ message: `Passkey credential ${operation} failed`,
1855
+ cause,
1856
+ });
1857
+ const totpFactorStoreError = (operation, cause) => new TotpFactorStoreError({
1858
+ operation,
1859
+ message: `TOTP factor ${operation} failed`,
1860
+ cause,
1861
+ });
1862
+ const recoveryCodeStoreError = (operation, cause) => new RecoveryCodeStoreError({
1863
+ operation,
1864
+ message: `Recovery code ${operation} failed`,
1865
+ cause,
1866
+ });
1867
+ const apiKeyStoreError = (operation, cause) => new ApiKeyStoreError({
1868
+ operation,
1869
+ message: `API key ${operation} failed`,
1870
+ cause,
1871
+ });
1872
+ const refreshTokenStoreError = (operation, cause) => new RefreshTokenStoreError({
1873
+ operation,
1874
+ message: `Refresh token ${operation} failed`,
1875
+ cause,
1876
+ });
1877
+ const jwtRevocationStoreError = (operation, cause) => new JwtError({
1878
+ operation: "revocation",
1879
+ message: `JWT revocation ${operation} failed`,
1880
+ cause,
1881
+ });
1882
+ const oauthAccountStoreError = (operation, cause) => new OAuthAccountStoreError({
1883
+ operation,
1884
+ message: `OAuth account ${operation} failed`,
1885
+ cause,
1886
+ });
1887
+ const oauthClientStoreError = (operation, cause) => new OAuthClientStoreError({
1888
+ operation,
1889
+ message: `OAuth client ${operation} failed`,
1890
+ cause,
1891
+ });
1892
+ const oauthConsentStoreError = (operation, cause) => new OAuthConsentStoreError({
1893
+ operation,
1894
+ message: `OAuth consent ${operation} failed`,
1895
+ cause,
1896
+ });
1897
+ const oauthAuthorizationCodeStoreError = (operation, cause) => new OAuthAuthorizationCodeStoreError({
1898
+ operation,
1899
+ message: `OAuth authorization code ${operation} failed`,
1900
+ cause,
1901
+ });
1902
+ const oauthClientSecretStoreError = (operation, cause) => new OAuthClientSecretStoreError({
1903
+ operation,
1904
+ message: `OAuth client secret ${operation} failed`,
1905
+ cause,
1906
+ });
1907
+ const oauthProviderModeTokenStoreError = (operation, cause) => new OAuthProviderModeTokenStoreError({
1908
+ operation,
1909
+ message: `OAuth provider-mode token ${operation} failed`,
1910
+ cause,
1911
+ });
1912
+ const oauthProviderTokenVaultError = (operation, cause) => new OAuthProviderTokenVaultError({
1913
+ operation,
1914
+ message: `OAuth provider token vault ${operation} failed`,
1915
+ cause,
1916
+ });
1917
+ const domainVerificationStoreError = (operation, cause) => new DomainVerificationStoreError({
1918
+ operation,
1919
+ message: `Domain verification ${operation} failed`,
1920
+ cause,
1921
+ });
1922
+ const securityTimelineStoreError = (operation, cause) => new SecurityTimelineStoreError({
1923
+ operation,
1924
+ message: `Security timeline ${operation} failed`,
1925
+ cause,
1926
+ });
1927
+ const webhookOutboxStoreError = (operation, cause) => new WebhookOutboxStoreError({
1928
+ operation,
1929
+ message: `Webhook outbox ${operation} failed`,
1930
+ cause,
1931
+ });
1932
+ const webhookReplayStoreError = (operation, cause) => new WebhookReplayStoreError({
1933
+ operation,
1934
+ message: `Webhook replay ${operation} failed`,
1935
+ cause,
1936
+ });
1937
+ const findUserById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectUserColumns(tables)).pipe(Query.from(tables.user.table), Query.where(queryEq(tables.user.select.id, id)))).pipe(Effect.mapError((cause) => storageError("user", operation, cause)), Effect.map((rows) => rows[0] === undefined
1938
+ ? Option.none()
1939
+ : Option.some(decodeUserRow(tables, rows[0]))));
1940
+ const findUserByEmail = (executor, tables, email, operation = "find") => executePlan(executor, Query.select(selectUserColumns(tables)).pipe(Query.from(tables.user.table), Query.where(queryEq(tables.user.select.email, email)))).pipe(Effect.mapError((cause) => storageError("user", operation, cause)), Effect.map((rows) => rows[0] === undefined
1941
+ ? Option.none()
1942
+ : Option.some(decodeUserRow(tables, rows[0]))));
1943
+ const findPasswordCredentialByUserId = (executor, tables, userId, operation = "find") => executePlan(executor, Query.select(selectCredentialColumns(tables)).pipe(Query.from(tables.credential.table), Query.where(queryEq(tables.credential.select.userId, userId)), Query.where(queryEq(tables.credential.select.type, "password")))).pipe(Effect.mapError((cause) => storageError("credential", operation, cause)), Effect.map((rows) => rows[0] === undefined
1944
+ ? Option.none()
1945
+ : Option.some(decodePasswordCredentialRow(tables, rows[0]))));
1946
+ const findJwtRevocation = (executor, tables, jwtId, operation = "find") => executePlan(executor, Query.select(selectJwtRevocationColumns(tables)).pipe(Query.from(tables.jwtRevocation.table), Query.where(queryEq(tables.jwtRevocation.select.jwtId, jwtId)))).pipe(Effect.mapError((cause) => jwtRevocationStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1947
+ ? Option.none()
1948
+ : Option.some(decodeJwtRevocationRow(tables, rows[0]))));
1949
+ const findSessionById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectSessionColumns(tables)).pipe(Query.from(tables.session.table), Query.where(queryEq(tables.session.select.id, id)))).pipe(Effect.mapError((cause) => storageError("session", operation, cause)), Effect.map((rows) => rows[0] === undefined
1950
+ ? Option.none()
1951
+ : Option.some(decodeSessionRow(tables, rows[0]))));
1952
+ const listSessionsByUser = (executor, tables, input, operation = "listByUser") => executePlan(executor, Query.select(selectSessionColumns(tables)).pipe(Query.from(tables.session.table), Query.where(queryEq(tables.session.select.userId, input.userId)))).pipe(Effect.mapError((cause) => storageError("session", operation, cause)), Effect.map((rows) => rows.map((row) => decodeSessionRow(tables, row))));
1953
+ const findVerificationById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectVerificationColumns(tables)).pipe(Query.from(tables.verification.table), Query.where(queryEq(tables.verification.select.id, id)))).pipe(Effect.mapError((cause) => storageError("verification", operation, cause)), Effect.map((rows) => rows[0] === undefined
1954
+ ? Option.none()
1955
+ : Option.some(decodeVerificationRow(tables, rows[0]))));
1956
+ const findLoginApprovalReviewByApprovalChallengeId = (executor, tables, input, operation = "find") => executePlan(executor, Query.select(selectLoginApprovalReviewColumns(tables)).pipe(Query.from(tables.loginApprovalReview.table), Query.where(queryEq(tables.loginApprovalReview.select.approvalChallengeId, input.approvalChallengeId)))).pipe(Effect.mapError((cause) => loginApprovalReviewStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1957
+ ? Option.none()
1958
+ : Option.some(decodeLoginApprovalReviewRow(tables, rows[0]))));
1959
+ const findTrustedDevice = (executor, tables, input, operation = "status") => executePlan(executor, Query.select(selectTrustedDeviceColumns(tables)).pipe(Query.from(tables.trustedDevice.table), Query.where(queryEq(tables.trustedDevice.select.userId, input.userId)), Query.where(queryEq(tables.trustedDevice.select.tokenHash, input.tokenHash)), Query.where(queryGt(tables.trustedDevice.select.expiresAt, Number(input.now))))).pipe(Effect.mapError((cause) => trustedDeviceStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1960
+ ? Option.none()
1961
+ : Option.some(decodeTrustedDeviceRow(tables, rows[0]))));
1962
+ const findTrustedDeviceIncludingExpired = (executor, tables, input) => executePlan(executor, Query.select(selectTrustedDeviceColumns(tables)).pipe(Query.from(tables.trustedDevice.table), Query.where(queryEq(tables.trustedDevice.select.userId, input.userId)), Query.where(queryEq(tables.trustedDevice.select.tokenHash, input.tokenHash)))).pipe(Effect.mapError((cause) => trustedDeviceStoreError("trust", cause)), Effect.map((rows) => rows[0] === undefined
1963
+ ? Option.none()
1964
+ : Option.some(decodeTrustedDeviceRow(tables, rows[0]))));
1965
+ const listTrustedDevicesForUser = (executor, tables, input, operation = "list") => executePlan(executor, Query.select(selectTrustedDeviceColumns(tables)).pipe(Query.from(tables.trustedDevice.table), Query.where(queryEq(tables.trustedDevice.select.userId, input.userId)), Query.where(queryGt(tables.trustedDevice.select.expiresAt, Number(input.now))))).pipe(Effect.mapError((cause) => trustedDeviceStoreError(operation, cause)), Effect.map((rows) => filterTrustedDevicesForUser(rows.map((row) => decodeTrustedDeviceRow(tables, row)), input)));
1966
+ const findPasskeyCredentialByCredentialId = (executor, tables, credentialId, operation = "find") => executePlan(executor, Query.select(selectPasskeyCredentialColumns(tables)).pipe(Query.from(tables.passkeyCredential.table), Query.where(queryEq(tables.passkeyCredential.select.credentialId, credentialId)))).pipe(Effect.mapError((cause) => passkeyCredentialStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1967
+ ? Option.none()
1968
+ : Option.some(decodePasskeyCredentialRow(tables, rows[0]))));
1969
+ const findTotpFactorById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectTotpFactorColumns(tables)).pipe(Query.from(tables.totpFactor.table), Query.where(queryEq(tables.totpFactor.select.id, id)))).pipe(Effect.mapError((cause) => totpFactorStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1970
+ ? Option.none()
1971
+ : Option.some(decodeTotpFactorRow(tables, rows[0]))));
1972
+ const findRecoveryCodeById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectRecoveryCodeColumns(tables)).pipe(Query.from(tables.recoveryCode.table), Query.where(queryEq(tables.recoveryCode.select.id, id)))).pipe(Effect.mapError((cause) => recoveryCodeStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1973
+ ? Option.none()
1974
+ : Option.some(decodeRecoveryCodeRow(tables, rows[0]))));
1975
+ const findApiKeyById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectApiKeyColumns(tables)).pipe(Query.from(tables.apiKey.table), Query.where(queryEq(tables.apiKey.select.id, id)))).pipe(Effect.mapError((cause) => apiKeyStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1976
+ ? Option.none()
1977
+ : Option.some(decodeApiKeyRow(tables, rows[0]))));
1978
+ const findApiKeyByPrefix = (executor, tables, prefix, operation = "find") => executePlan(executor, Query.select(selectApiKeyColumns(tables)).pipe(Query.from(tables.apiKey.table), Query.where(queryEq(tables.apiKey.select.prefix, prefix)))).pipe(Effect.mapError((cause) => apiKeyStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1979
+ ? Option.none()
1980
+ : Option.some(decodeApiKeyRow(tables, rows[0]))));
1981
+ const findRefreshTokenById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectRefreshTokenColumns(tables)).pipe(Query.from(tables.refreshToken.table), Query.where(queryEq(tables.refreshToken.select.id, id)))).pipe(Effect.mapError((cause) => refreshTokenStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1982
+ ? Option.none()
1983
+ : Option.some(decodeRefreshTokenRow(tables, rows[0]))));
1984
+ const findRefreshTokenBySecretHash = (executor, tables, hash, operation = "find") => executePlan(executor, Query.select(selectRefreshTokenColumns(tables)).pipe(Query.from(tables.refreshToken.table), Query.where(queryEq(tables.refreshToken.select.secretHash, hash)))).pipe(Effect.mapError((cause) => refreshTokenStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1985
+ ? Option.none()
1986
+ : Option.some(decodeRefreshTokenRow(tables, rows[0]))));
1987
+ const findOAuthAccountById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectOAuthAccountColumns(tables)).pipe(Query.from(tables.oauthAccount.table), Query.where(queryEq(tables.oauthAccount.select.id, id)))).pipe(Effect.mapError((cause) => oauthAccountStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1988
+ ? Option.none()
1989
+ : Option.some(decodeOAuthAccountRow(tables, rows[0]))));
1990
+ const findOAuthAccountByProviderAccount = (executor, tables, input, operation = "find") => {
1991
+ const base = Query.select(selectOAuthAccountColumns(tables)).pipe(Query.from(tables.oauthAccount.table), Query.where(queryEq(tables.oauthAccount.select.providerId, input.providerId)), Query.where(queryEq(tables.oauthAccount.select.providerAccountId, input.providerAccountId)));
1992
+ const query = input.includeUnlinked === true
1993
+ ? base
1994
+ : base.pipe(Query.where(queryIsNull(tables.oauthAccount.select.unlinkedAt)));
1995
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => oauthAccountStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
1996
+ ? Option.none()
1997
+ : Option.some(decodeOAuthAccountRow(tables, rows[0]))));
1998
+ };
1999
+ const findOAuthClientById = (executor, tables, input, operation = "find") => executePlan(executor, Query.select(selectOAuthClientColumns(tables)).pipe(Query.from(tables.oauthClient.table), Query.where(queryEq(tables.oauthClient.select.id, input.clientId)))).pipe(Effect.mapError((cause) => oauthClientStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2000
+ ? Option.none()
2001
+ : Option.some(decodeOAuthClientRow(tables, rows[0]))));
2002
+ const findOAuthConsentByUserAndClient = (executor, tables, input, operation = "find-active") => executePlan(executor, Query.select(selectOAuthConsentColumns(tables)).pipe(Query.from(tables.oauthConsent.table), Query.where(queryEq(tables.oauthConsent.select.userId, input.userId)), Query.where(queryEq(tables.oauthConsent.select.clientId, input.clientId)))).pipe(Effect.mapError((cause) => oauthConsentStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2003
+ ? Option.none()
2004
+ : Option.some(decodeOAuthConsentRow(tables, rows[0]))));
2005
+ const deleteOAuthConsentRowsBefore = (executor, tables, column, before) => executePlan(executor, Query.delete(tables.oauthConsent.table).pipe(Query.where(queryLt(column, Number(before))), Query.returning({ id: tables.oauthConsent.select.id }))).pipe(Effect.map((rows) => rows.length));
2006
+ const deleteOAuthInactiveConsents = (executor, tables, input) => Effect.gen(function* () {
2007
+ const expiredDeleted = input.beforeExpiresAt === undefined
2008
+ ? 0
2009
+ : yield* deleteOAuthConsentRowsBefore(executor, tables, tables.oauthConsent.select.expiresAt, input.beforeExpiresAt);
2010
+ const revokedDeleted = input.beforeRevokedAt === undefined
2011
+ ? 0
2012
+ : yield* deleteOAuthConsentRowsBefore(executor, tables, tables.oauthConsent.select.revokedAt, input.beforeRevokedAt);
2013
+ return expiredDeleted + revokedDeleted;
2014
+ }).pipe(Effect.mapError((cause) => oauthConsentStoreError("deleteInactive", cause)));
2015
+ const findOAuthAuthorizationCodeByHash = (executor, tables, input, operation = "find") => executePlan(executor, Query.select(selectOAuthAuthorizationCodeColumns(tables)).pipe(Query.from(tables.oauthAuthorizationCode.table), Query.where(queryEq(tables.oauthAuthorizationCode.select.codeHash, input.codeHash)))).pipe(Effect.mapError((cause) => oauthAuthorizationCodeStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2016
+ ? Option.none()
2017
+ : Option.some(decodeOAuthAuthorizationCodeRow(tables, rows[0]))));
2018
+ const findOAuthClientSecretByClientIdAndPrefix = (executor, tables, input, operation = "find") => executePlan(executor, Query.select(selectOAuthClientSecretColumns(tables)).pipe(Query.from(tables.oauthClientSecret.table), Query.where(queryEq(tables.oauthClientSecret.select.clientId, input.clientId)), Query.where(queryEq(tables.oauthClientSecret.select.prefix, input.prefix)))).pipe(Effect.mapError((cause) => oauthClientSecretStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2019
+ ? Option.none()
2020
+ : Option.some(decodeOAuthClientSecretRow(tables, rows[0]))));
2021
+ const findOAuthProviderModeTokenByHash = (executor, tables, input, operation = "find") => executePlan(executor, Query.select(selectOAuthProviderModeTokenColumns(tables)).pipe(Query.from(tables.oauthProviderModeToken.table), Query.where(queryEq(tables.oauthProviderModeToken.select.tokenHash, input.tokenHash)))).pipe(Effect.mapError((cause) => oauthProviderModeTokenStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2022
+ ? Option.none()
2023
+ : Option.some(decodeOAuthProviderModeTokenRow(tables, rows[0]))));
2024
+ const deleteOAuthProviderModeTokenRowsBefore = (executor, tables, column, before) => executePlan(executor, Query.delete(tables.oauthProviderModeToken.table).pipe(Query.where(queryLt(column, Number(before))), Query.returning({ tokenHash: tables.oauthProviderModeToken.select.tokenHash }))).pipe(Effect.map((rows) => rows.length));
2025
+ const deleteOAuthProviderModeRetiredTokens = (executor, tables, input) => Effect.gen(function* () {
2026
+ const expiredDeleted = input.beforeExpiresAt === undefined
2027
+ ? 0
2028
+ : yield* deleteOAuthProviderModeTokenRowsBefore(executor, tables, tables.oauthProviderModeToken.select.expiresAt, input.beforeExpiresAt);
2029
+ const revokedDeleted = input.beforeRevokedAt === undefined
2030
+ ? 0
2031
+ : yield* deleteOAuthProviderModeTokenRowsBefore(executor, tables, tables.oauthProviderModeToken.select.revokedAt, input.beforeRevokedAt);
2032
+ const rotatedDeleted = input.beforeRotatedAt === undefined
2033
+ ? 0
2034
+ : yield* deleteOAuthProviderModeTokenRowsBefore(executor, tables, tables.oauthProviderModeToken.select.rotatedAt, input.beforeRotatedAt);
2035
+ return expiredDeleted + revokedDeleted + rotatedDeleted;
2036
+ }).pipe(Effect.mapError((cause) => oauthProviderModeTokenStoreError("deleteRetired", cause)));
2037
+ const findOAuthProviderTokenVaultRecordByAccountId = (executor, tables, input, operation, includeRevoked = false) => {
2038
+ const base = Query.select(selectOAuthProviderTokenVaultColumns(tables)).pipe(Query.from(tables.oauthProviderTokenVault.table), Query.where(queryEq(tables.oauthProviderTokenVault.select.accountId, input.accountId)));
2039
+ const query = includeRevoked
2040
+ ? base
2041
+ : base.pipe(Query.where(queryIsNull(tables.oauthProviderTokenVault.select.revokedAt)));
2042
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => oauthProviderTokenVaultError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2043
+ ? Option.none()
2044
+ : Option.some(decodeOAuthProviderTokenVaultRow(tables, rows[0]))));
2045
+ };
2046
+ const findDomainVerificationById = (executor, tables, id, operation = "find") => executePlan(executor, Query.select(selectDomainVerificationColumns(tables)).pipe(Query.from(tables.domainVerification.table), Query.where(queryEq(tables.domainVerification.select.id, id)))).pipe(Effect.mapError((cause) => domainVerificationStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2047
+ ? Option.none()
2048
+ : Option.some(decodeDomainVerificationRecord(tables, rows[0]))));
2049
+ const findDomainVerificationByOwnerAndDomain = (executor, tables, input, operation = "find") => executePlan(executor, Query.select(selectDomainVerificationColumns(tables)).pipe(Query.from(tables.domainVerification.table), Query.where(queryEq(tables.domainVerification.select.ownerId, input.ownerId)), Query.where(queryEq(tables.domainVerification.select.domain, input.domain)))).pipe(Effect.mapError((cause) => domainVerificationStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2050
+ ? Option.none()
2051
+ : Option.some(decodeDomainVerificationRecord(tables, rows[0]))));
2052
+ const listSecurityTimelineByUser = (executor, tables, input, operation = "list") => executePlan(executor, Query.select(selectSecurityTimelineColumns(tables)).pipe(Query.from(tables.securityTimeline.table), Query.where(queryEq(tables.securityTimeline.select.userId, input.userId)))).pipe(Effect.mapError((cause) => securityTimelineStoreError(operation, cause)), Effect.map((rows) => filterSecurityTimelineEvents(rows.map((row) => decodeSecurityTimelineEvent(tables, row)), input)));
2053
+ const deleteSecurityTimelineBefore = (executor, tables, input) => {
2054
+ const base = Query.delete(tables.securityTimeline.table).pipe(Query.where(queryLt(tables.securityTimeline.select.occurredAt, Number(input.beforeOccurredAt))));
2055
+ const query = input.userId === undefined
2056
+ ? base
2057
+ : base.pipe(Query.where(queryEq(tables.securityTimeline.select.userId, input.userId)));
2058
+ return executePlan(executor, query.pipe(Query.returning({ id: tables.securityTimeline.select.id }))).pipe(Effect.mapError((cause) => securityTimelineStoreError("deleteBefore", cause)), Effect.map((rows) => rows.length));
2059
+ };
2060
+ const findWebhookOutboxRecordById = (executor, tables, id, operation) => executePlan(executor, Query.select(selectWebhookOutboxColumns(tables)).pipe(Query.from(tables.webhookOutbox.table), Query.where(queryEq(tables.webhookOutbox.select.id, id)))).pipe(Effect.mapError((cause) => webhookOutboxStoreError(operation, cause)), Effect.map((rows) => rows[0] === undefined
2061
+ ? Option.none()
2062
+ : Option.some(decodeWebhookOutboxRecord(tables, rows[0]))));
2063
+ const claimDueWebhookOutboxRecords = (executor, tables, input) => Effect.gen(function* () {
2064
+ const now = input.now ?? (yield* currentUnixMillis);
2065
+ const base = Query.select(selectWebhookOutboxColumns(tables)).pipe(Query.from(tables.webhookOutbox.table), Query.where(queryLte(tables.webhookOutbox.select.nextAttemptAt, Number(now))));
2066
+ const query = input.endpointKey === undefined
2067
+ ? base
2068
+ : base.pipe(Query.where(queryEq(tables.webhookOutbox.select.endpointKey, input.endpointKey)));
2069
+ const rows = yield* executePlan(executor, query).pipe(Effect.mapError((cause) => webhookOutboxStoreError("claimDue", cause)));
2070
+ return filterDueWebhookOutboxRecords(rows.map((row) => decodeWebhookOutboxRecord(tables, row)), { ...input, now });
2071
+ });
2072
+ const deleteWebhookOutboxRecordsBefore = (executor, tables, input) => {
2073
+ const [firstStatus, ...remainingStatuses] = input.statuses;
2074
+ const base = Query.delete(tables.webhookOutbox.table).pipe(Query.where(queryLt(tables.webhookOutbox.select.updatedAt, Number(input.beforeUpdatedAt))), Query.where(queryIn(tables.webhookOutbox.select.status, firstStatus, ...remainingStatuses)));
2075
+ const query = input.endpointKey === undefined
2076
+ ? base
2077
+ : base.pipe(Query.where(queryEq(tables.webhookOutbox.select.endpointKey, input.endpointKey)));
2078
+ return executePlan(executor, query.pipe(Query.returning({ id: tables.webhookOutbox.select.id }))).pipe(Effect.mapError((cause) => webhookOutboxStoreError("deleteBefore", cause)), Effect.map((rows) => rows.length));
2079
+ };
2080
+ const deleteExpiredWebhookReplayRecords = (executor, tables, input) => Effect.gen(function* () {
2081
+ const now = input.now ?? (yield* currentUnixMillis);
2082
+ return yield* executePlan(executor, Query.delete(tables.webhookReplay.table).pipe(Query.where(queryLt(tables.webhookReplay.select.expiresAt, Number(now))), Query.returning({ id: tables.webhookReplay.select.id }))).pipe(Effect.mapError((cause) => webhookReplayStoreError("deleteExpired", cause)), Effect.map((rows) => rows.length));
2083
+ });
2084
+ const listAuditLogRecords = (executor, tables, input = {}) => {
2085
+ if (input.types !== undefined && input.types.length === 0) {
2086
+ return Effect.succeed([]);
2087
+ }
2088
+ const base = Query.select(selectAuditLogColumns(tables)).pipe(Query.from(tables.auditLog.table));
2089
+ const byUser = input.userId === undefined
2090
+ ? base
2091
+ : base.pipe(Query.where(queryEq(tables.auditLog.select.userId, input.userId)));
2092
+ const byOccurredAt = input.beforeOccurredAt === undefined
2093
+ ? byUser
2094
+ : byUser.pipe(Query.where(queryLt(tables.auditLog.select.occurredAt, Number(input.beforeOccurredAt))));
2095
+ const query = input.types === undefined
2096
+ ? byOccurredAt
2097
+ : byOccurredAt.pipe(Query.where(queryIn(tables.auditLog.select.type, input.types[0], ...input.types.slice(1))));
2098
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => auditLogStoreError("list", cause)), Effect.map((rows) => filterAuditLogEvents(rows.map((row) => decodeAuditLogEvent(tables, row)), input)));
2099
+ };
2100
+ const deleteAuditLogRecordsBefore = (executor, tables, input) => {
2101
+ const base = Query.delete(tables.auditLog.table).pipe(Query.where(queryLt(tables.auditLog.select.occurredAt, Number(input.beforeOccurredAt))));
2102
+ const query = input.userId === undefined
2103
+ ? base
2104
+ : base.pipe(Query.where(queryEq(tables.auditLog.select.userId, input.userId)));
2105
+ return executePlan(executor, query.pipe(Query.returning({ occurredAt: tables.auditLog.select.occurredAt }))).pipe(Effect.mapError((cause) => auditLogStoreError("deleteBefore", cause)), Effect.map((rows) => rows.length));
2106
+ };
2107
+ const defaultLoginRiskHistoryRecentWindowMillis = 15 * 60 * 1000;
2108
+ const defaultLoginRiskHistoryWindowMillis = 90 * 24 * 60 * 60 * 1000;
2109
+ const defaultLoginRiskImpossibleTravelWindowMillis = 24 * 60 * 60 * 1000;
2110
+ const defaultLoginRiskImpossibleTravelKmh = 900;
2111
+ const positiveWindowMillis = (value, defaultValue) => value === undefined || !Number.isFinite(value)
2112
+ ? defaultValue
2113
+ : Math.max(0, value);
2114
+ const loginRiskHistoryOptions = (options) => ({
2115
+ recentWindowMillis: positiveWindowMillis(options?.recentWindowMillis, defaultLoginRiskHistoryRecentWindowMillis),
2116
+ historyWindowMillis: positiveWindowMillis(options?.historyWindowMillis, defaultLoginRiskHistoryWindowMillis),
2117
+ impossibleTravelWindowMillis: positiveWindowMillis(options?.impossibleTravelWindowMillis, defaultLoginRiskImpossibleTravelWindowMillis),
2118
+ impossibleTravelKmh: options?.impossibleTravelKmh === undefined ||
2119
+ !Number.isFinite(options.impossibleTravelKmh)
2120
+ ? defaultLoginRiskImpossibleTravelKmh
2121
+ : Math.max(0, options.impossibleTravelKmh),
2122
+ });
2123
+ const toRadians = (degrees) => (degrees * Math.PI) / 180;
2124
+ const distanceKm = (first, second) => {
2125
+ const earthRadiusKm = 6371;
2126
+ const latitudeDelta = toRadians(second.latitude - first.latitude);
2127
+ const longitudeDelta = toRadians(second.longitude - first.longitude);
2128
+ const firstLatitude = toRadians(first.latitude);
2129
+ const secondLatitude = toRadians(second.latitude);
2130
+ const haversine = Math.sin(latitudeDelta / 2) ** 2 +
2131
+ Math.cos(firstLatitude) *
2132
+ Math.cos(secondLatitude) *
2133
+ Math.sin(longitudeDelta / 2) ** 2;
2134
+ return (2 * earthRadiusKm * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine)));
2135
+ };
2136
+ const hasCoordinates = (value) => value.latitude !== undefined &&
2137
+ Number.isFinite(value.latitude) &&
2138
+ value.longitude !== undefined &&
2139
+ Number.isFinite(value.longitude);
2140
+ const loginRiskHistoryLookupResult = (input, rows, options) => {
2141
+ const normalized = loginRiskHistoryOptions(options);
2142
+ const occurredAt = Number(input.occurredAt);
2143
+ const recentStart = occurredAt - normalized.recentWindowMillis;
2144
+ const historyStart = occurredAt - normalized.historyWindowMillis;
2145
+ const impossibleTravelStart = occurredAt - normalized.impossibleTravelWindowMillis;
2146
+ const previousRows = rows.filter((row) => Number(row.occurredAt) < occurredAt);
2147
+ const recentRows = previousRows.filter((row) => Number(row.occurredAt) >= recentStart);
2148
+ const historyRows = previousRows.filter((row) => Number(row.occurredAt) >= historyStart);
2149
+ const recentFailedLoginCount = recentRows.filter((row) => row.outcome === "failure").length;
2150
+ const recentSuccessfulLoginCount = recentRows.filter((row) => row.outcome === "success").length;
2151
+ const knownDevice = input.deviceKey === undefined
2152
+ ? undefined
2153
+ : historyRows.some((row) => row.deviceKey === input.deviceKey);
2154
+ const knownLocation = input.locationKey === undefined
2155
+ ? undefined
2156
+ : historyRows.some((row) => row.locationKey === input.locationKey);
2157
+ const currentLocation = {
2158
+ latitude: input.request?.latitude,
2159
+ longitude: input.request?.longitude,
2160
+ };
2161
+ const impossibleTravel = hasCoordinates(currentLocation)
2162
+ ? previousRows
2163
+ .filter((row) => row.outcome === "success" &&
2164
+ Number(row.occurredAt) >= impossibleTravelStart)
2165
+ .some((row) => {
2166
+ const previousLocation = {
2167
+ latitude: row.latitude,
2168
+ longitude: row.longitude,
2169
+ };
2170
+ if (!hasCoordinates(previousLocation)) {
2171
+ return false;
2172
+ }
2173
+ const elapsedHours = (occurredAt - Number(row.occurredAt)) / 3_600_000;
2174
+ return (elapsedHours > 0 &&
2175
+ distanceKm(previousLocation, currentLocation) / elapsedHours >
2176
+ normalized.impossibleTravelKmh);
2177
+ })
2178
+ : undefined;
2179
+ const recentRiskLevels = recentRows.flatMap((row) => row.riskLevel === undefined ? [] : [row.riskLevel]);
2180
+ const riskLevel = recentRiskLevels.length === 0
2181
+ ? undefined
2182
+ : maxLoginRiskLevel(recentRiskLevels, "unknown");
2183
+ const reasons = [
2184
+ ...(recentFailedLoginCount > 0 ? ["recent-failed-login"] : []),
2185
+ ...(knownDevice === false ? ["new-device"] : []),
2186
+ ...(knownLocation === false ? ["new-location"] : []),
2187
+ ...(impossibleTravel === true ? ["impossible-travel"] : []),
2188
+ ];
2189
+ return omitUndefined({
2190
+ recentLoginCount: recentRows.length,
2191
+ recentFailedLoginCount,
2192
+ recentSuccessfulLoginCount,
2193
+ knownDevice,
2194
+ newDevice: knownDevice === undefined ? undefined : !knownDevice,
2195
+ knownLocation,
2196
+ newLocation: knownLocation === undefined ? undefined : !knownLocation,
2197
+ impossibleTravel,
2198
+ riskLevel,
2199
+ reasons: reasons.length === 0 ? undefined : reasons,
2200
+ });
2201
+ };
2202
+ const lookupLoginRiskHistory = (executor, tables, input, options) => {
2203
+ const normalized = loginRiskHistoryOptions(options);
2204
+ const occurredAt = Number(input.occurredAt);
2205
+ const earliestOccurredAt = Math.min(occurredAt - normalized.recentWindowMillis, occurredAt - normalized.historyWindowMillis, occurredAt - normalized.impossibleTravelWindowMillis);
2206
+ return executePlan(executor, Query.select(selectLoginRiskHistoryColumns(tables)).pipe(Query.from(tables.loginRiskHistory.table), Query.where(queryEq(tables.loginRiskHistory.select.userId, input.userId)), Query.where(queryLt(tables.loginRiskHistory.select.occurredAt, occurredAt)), Query.where(queryGt(tables.loginRiskHistory.select.occurredAt, earliestOccurredAt - 1)))).pipe(Effect.mapError((cause) => loginRiskHistoryStoreError("lookup", cause)), Effect.map((rows) => loginRiskHistoryLookupResult(input, rows.map((row) => decodeLoginRiskHistoryRecord(tables, row)), options)));
2207
+ };
2208
+ const deleteLoginRiskHistoryRecordsBefore = (executor, tables, input) => {
2209
+ const base = Query.delete(tables.loginRiskHistory.table).pipe(Query.where(queryLt(tables.loginRiskHistory.select.occurredAt, Number(input.beforeOccurredAt))));
2210
+ const query = input.userId === undefined
2211
+ ? base
2212
+ : base.pipe(Query.where(queryEq(tables.loginRiskHistory.select.userId, input.userId)));
2213
+ return executePlan(executor, query.pipe(Query.returning({ id: tables.loginRiskHistory.select.id }))).pipe(Effect.mapError((cause) => loginRiskHistoryStoreError("deleteBefore", cause)), Effect.map((rows) => rows.length));
2214
+ };
2215
+ export const makeEffectQbSqliteUserStore = (executor, options = {}) => {
2216
+ const tables = options.tables ?? authSqliteTables;
2217
+ return UserStore.make({
2218
+ findById: (id) => findUserById(executor, tables, id),
2219
+ findByEmail: (email) => findUserByEmail(executor, tables, email),
2220
+ insert: (row) => executePlan(executor, queryInsert(tables.user.table, mutationValues(tables.user.insert(row)))).pipe(Effect.mapError((cause) => storageError("user", "insert", cause)), Effect.asVoid),
2221
+ markEmailVerified: (input) => executePlan(executor, queryUpdate(tables.user.table, mutationValues(tables.user.markEmailVerified(input))).pipe(Query.where(queryEq(tables.user.select.id, input.userId)), Query.returning(selectUserColumns(tables)))).pipe(Effect.mapError((cause) => storageError("user", "markEmailVerified", cause)), Effect.map((rows) => rows[0] === undefined
2222
+ ? Option.none()
2223
+ : Option.some(decodeUserRow(tables, rows[0])))),
2224
+ });
2225
+ };
2226
+ export const makeEffectQbSqliteCredentialStore = (executor, options = {}) => {
2227
+ const tables = options.tables ?? authSqliteTables;
2228
+ return CredentialStore.make({
2229
+ findPasswordByUserId: (userId) => findPasswordCredentialByUserId(executor, tables, userId),
2230
+ insertPassword: (row) => executePlan(executor, queryInsert(tables.credential.table, mutationValues(tables.credential.insertPassword(row)))).pipe(Effect.mapError((cause) => storageError("credential", "insert", cause)), Effect.asVoid),
2231
+ updatePassword: (input) => executePlan(executor, queryUpdate(tables.credential.table, mutationValues(tables.credential.updatePassword(input))).pipe(Query.where(queryEq(tables.credential.select.userId, input.userId)), Query.where(queryEq(tables.credential.select.type, "password")), Query.where(queryIsNull(tables.credential.select.revokedAt)), Query.returning({ id: tables.credential.select.id }))).pipe(Effect.mapError((cause) => storageError("credential", "updatePassword", cause)), Effect.flatMap((rows) => rows[0] === undefined
2232
+ ? Effect.succeed(Option.none())
2233
+ : findPasswordCredentialByUserId(executor, tables, input.userId, "updatePassword"))),
2234
+ });
2235
+ };
2236
+ export const makeEffectQbSqliteSessionStore = (executor, options = {}) => {
2237
+ const tables = options.tables ?? authSqliteTables;
2238
+ return SessionStore.make({
2239
+ findById: (id) => findSessionById(executor, tables, id),
2240
+ listByUser: (input) => listSessionsByUser(executor, tables, input),
2241
+ insert: (row) => executePlan(executor, queryInsert(tables.session.table, mutationValues(tables.session.insert(row)))).pipe(Effect.mapError((cause) => storageError("session", "insert", cause)), Effect.asVoid),
2242
+ refresh: (input) => {
2243
+ const query = queryUpdate(tables.session.table, mutationValues(tables.session.refresh(input))).pipe(Query.where(queryEq(tables.session.select.id, input.sessionId)), Query.returning(selectSessionColumns(tables)));
2244
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => storageError("session", "refresh", cause)), Effect.map((rows) => rows[0] === undefined
2245
+ ? Option.none()
2246
+ : Option.some(decodeSessionRow(tables, rows[0]))));
2247
+ },
2248
+ rotate: (input) => {
2249
+ const query = queryUpdate(tables.session.table, mutationValues(tables.session.rotate(input))).pipe(Query.where(queryEq(tables.session.select.id, input.sessionId)), Query.returning(selectSessionColumns(tables)));
2250
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => storageError("session", "rotate", cause)), Effect.map((rows) => rows[0] === undefined
2251
+ ? Option.none()
2252
+ : Option.some(decodeSessionRow(tables, rows[0]))));
2253
+ },
2254
+ updateClaims: (input) => findSessionById(executor, tables, input.sessionId, "updateClaims").pipe(Effect.flatMap((rowOption) => {
2255
+ if (Option.isNone(rowOption)) {
2256
+ return Effect.succeed(Option.none());
2257
+ }
2258
+ return executePlan(executor, queryUpdate(tables.session.table, mutationValues(tables.session.updateClaims(rowOption.value, input))).pipe(Query.where(queryEq(tables.session.select.id, input.sessionId)), Query.returning(selectSessionColumns(tables)))).pipe(Effect.mapError((cause) => storageError("session", "updateClaims", cause)), Effect.map((rows) => rows[0] === undefined
2259
+ ? Option.none()
2260
+ : Option.some(decodeSessionRow(tables, rows[0]))));
2261
+ })),
2262
+ revoke: (input) => executePlan(executor, queryUpdate(tables.session.table, mutationValues(tables.session.revoke(input))).pipe(Query.where(queryEq(tables.session.select.id, input.sessionId)))).pipe(Effect.mapError((cause) => storageError("session", "revoke", cause)), Effect.asVoid),
2263
+ revokeAllForUser: (input) => executePlan(executor, queryUpdate(tables.session.table, mutationValues(tables.session.revoke(input))).pipe(Query.where(queryEq(tables.session.select.userId, input.userId)))).pipe(Effect.mapError((cause) => storageError("session", "revokeAllForUser", cause)), Effect.asVoid),
2264
+ });
2265
+ };
2266
+ export const makeEffectQbSqliteVerificationStore = (executor, options = {}) => {
2267
+ const tables = options.tables ?? authSqliteTables;
2268
+ return VerificationStore.make({
2269
+ findById: (id) => findVerificationById(executor, tables, id),
2270
+ insert: (row) => executePlan(executor, queryInsert(tables.verification.table, mutationValues(tables.verification.insert(row)))).pipe(Effect.mapError((cause) => storageError("verification", "insert", cause)), Effect.asVoid),
2271
+ consume: (input) => {
2272
+ const base = queryUpdate(tables.verification.table, mutationValues(tables.verification.consume(input))).pipe(Query.where(queryEq(tables.verification.select.id, input.id)), Query.where(queryIsNull(tables.verification.select.consumedAt)), Query.where(queryGt(tables.verification.select.expiresAt, Number(input.consumedAt))));
2273
+ const plan = input.type === undefined
2274
+ ? base
2275
+ : base.pipe(Query.where(queryEq(tables.verification.select.type, input.type)));
2276
+ return executePlan(executor, plan.pipe(Query.returning({ id: tables.verification.select.id }))).pipe(Effect.mapError((cause) => storageError("verification", "consume", cause)), Effect.flatMap((rows) => rows[0] === undefined
2277
+ ? Effect.succeed(Option.none())
2278
+ : findVerificationById(executor, tables, input.id, "consume")));
2279
+ },
2280
+ deleteExpired: (input) => {
2281
+ if (input.limit === undefined) {
2282
+ return executePlan(executor, Query.delete(tables.verification.table).pipe(Query.where(queryLte(tables.verification.select.expiresAt, Number(input.now))), Query.returning({ id: tables.verification.select.id }))).pipe(Effect.mapError((cause) => storageError("verification", "deleteExpired", cause)), Effect.map((rows) => rows.length));
2283
+ }
2284
+ return executePlan(executor, Query.select({ id: tables.verification.select.id }).pipe(Query.from(tables.verification.table), Query.where(queryLte(tables.verification.select.expiresAt, Number(input.now))), Query.limit(input.limit))).pipe(Effect.mapError((cause) => storageError("verification", "deleteExpired", cause)), Effect.flatMap((rows) => {
2285
+ const [first, ...rest] = rows.map((row) => row.id);
2286
+ if (first === undefined) {
2287
+ return Effect.succeed(0);
2288
+ }
2289
+ return executePlan(executor, Query.delete(tables.verification.table).pipe(Query.where(queryIn(tables.verification.select.id, first, ...rest)), Query.returning({ id: tables.verification.select.id }))).pipe(Effect.mapError((cause) => storageError("verification", "deleteExpired", cause)), Effect.map((deleted) => deleted.length));
2290
+ }));
2291
+ },
2292
+ });
2293
+ };
2294
+ export const makeEffectQbSqliteAuditLogStore = (executor, options = {}) => {
2295
+ const tables = options.tables ?? authSqliteTables;
2296
+ return AuditLogStore.make({
2297
+ insert: (event) => Effect.gen(function* () {
2298
+ const createdAt = yield* currentUnixMillis;
2299
+ yield* executePlan(executor, queryInsert(tables.auditLog.table, mutationValues(tables.auditLog.insert(event, createdAt)))).pipe(Effect.mapError((cause) => auditLogStoreError("insert", cause)), Effect.asVoid);
2300
+ }),
2301
+ list: (input = {}) => listAuditLogRecords(executor, tables, input),
2302
+ deleteBefore: (input) => deleteAuditLogRecordsBefore(executor, tables, input),
2303
+ });
2304
+ };
2305
+ export const makeEffectQbSqliteLoginApprovalReviewStore = (executor, options = {}) => {
2306
+ const tables = options.tables ?? authSqliteTables;
2307
+ return LoginApprovalReviewStore.make({
2308
+ insertPending: (input) => executePlan(executor, queryInsert(tables.loginApprovalReview.table, mutationValues(tables.loginApprovalReview.insertPending(input)))).pipe(Effect.mapError((cause) => loginApprovalReviewStoreError("insert", cause)), Effect.as(input)),
2309
+ findByApprovalChallengeId: (input) => findLoginApprovalReviewByApprovalChallengeId(executor, tables, input),
2310
+ approve: (input) => executePlan(executor, queryUpdate(tables.loginApprovalReview.table, mutationValues(tables.loginApprovalReview.approve(input))).pipe(Query.where(queryEq(tables.loginApprovalReview.select.approvalChallengeId, input.approvalChallengeId)), Query.where(queryEq(tables.loginApprovalReview.select.status, "pending")), Query.returning(selectLoginApprovalReviewColumns(tables)))).pipe(Effect.mapError((cause) => loginApprovalReviewStoreError("approve", cause)), Effect.map((rows) => rows[0] === undefined
2311
+ ? Option.none()
2312
+ : Option.some(decodeLoginApprovalReviewRow(tables, rows[0])))),
2313
+ deny: (input) => executePlan(executor, queryUpdate(tables.loginApprovalReview.table, mutationValues(tables.loginApprovalReview.deny(input))).pipe(Query.where(queryEq(tables.loginApprovalReview.select.approvalChallengeId, input.approvalChallengeId)), Query.where(queryEq(tables.loginApprovalReview.select.status, "pending")), Query.returning(selectLoginApprovalReviewColumns(tables)))).pipe(Effect.mapError((cause) => loginApprovalReviewStoreError("deny", cause)), Effect.map((rows) => rows[0] === undefined
2314
+ ? Option.none()
2315
+ : Option.some(decodeLoginApprovalReviewRow(tables, rows[0])))),
2316
+ });
2317
+ };
2318
+ export const makeEffectQbSqliteLoginRiskHistoryStore = (executor, options = {}) => {
2319
+ const tables = options.tables ?? authSqliteTables;
2320
+ return LoginRiskHistory.make({
2321
+ lookup: (input) => lookupLoginRiskHistory(executor, tables, input, options.loginRiskHistory),
2322
+ record: (input) => Effect.gen(function* () {
2323
+ const createdAt = input.createdAt ?? (yield* currentUnixMillis);
2324
+ yield* executePlan(executor, queryInsert(tables.loginRiskHistory.table, mutationValues(tables.loginRiskHistory.insert({ ...input, createdAt })))).pipe(Effect.mapError((cause) => loginRiskHistoryStoreError("record", cause)), Effect.asVoid);
2325
+ }),
2326
+ deleteBefore: (input) => deleteLoginRiskHistoryRecordsBefore(executor, tables, input),
2327
+ });
2328
+ };
2329
+ export const makeEffectQbSqliteTrustedDeviceStore = (executor, options = {}) => {
2330
+ const tables = options.tables ?? authSqliteTables;
2331
+ return TrustedDeviceStore.make({
2332
+ find: (input) => findTrustedDevice(executor, tables, input),
2333
+ listForUser: (input) => listTrustedDevicesForUser(executor, tables, input),
2334
+ revokeForUser: (input) => executePlan(executor, Query.delete(tables.trustedDevice.table).pipe(Query.where(queryEq(tables.trustedDevice.select.userId, input.userId)), Query.where(queryEq(tables.trustedDevice.select.tokenHash, input.tokenHash)))).pipe(Effect.mapError((cause) => trustedDeviceStoreError("revoke", cause)), Effect.asVoid),
2335
+ upsert: (input) => findTrustedDeviceIncludingExpired(executor, tables, input).pipe(Effect.flatMap((existing) => {
2336
+ if (Option.isNone(existing)) {
2337
+ return executePlan(executor, queryInsert(tables.trustedDevice.table, mutationValues(tables.trustedDevice.insert(input, input.now)))).pipe(Effect.mapError((cause) => trustedDeviceStoreError("trust", cause)), Effect.asVoid);
2338
+ }
2339
+ return executePlan(executor, queryUpdate(tables.trustedDevice.table, mutationValues(tables.trustedDevice.update(input, existing.value))).pipe(Query.where(queryEq(tables.trustedDevice.select.userId, input.userId)), Query.where(queryEq(tables.trustedDevice.select.tokenHash, input.tokenHash)))).pipe(Effect.mapError((cause) => trustedDeviceStoreError("trust", cause)), Effect.asVoid);
2340
+ }), Effect.flatMap(() => findTrustedDeviceIncludingExpired(executor, tables, input)), Effect.flatMap((stored) => Option.isSome(stored)
2341
+ ? Effect.succeed(stored.value)
2342
+ : Effect.fail(trustedDeviceStoreError("trust", "missing row")))),
2343
+ });
2344
+ };
2345
+ export const makeEffectQbSqlitePasskeyCredentialStore = (executor, options = {}) => {
2346
+ const tables = options.tables ?? authSqliteTables;
2347
+ return PasskeyCredentialStore.make({
2348
+ insert: (row) => executePlan(executor, queryInsert(tables.passkeyCredential.table, mutationValues(tables.passkeyCredential.insert(row)))).pipe(Effect.mapError((cause) => passkeyCredentialStoreError("insert", cause)), Effect.asVoid),
2349
+ findByCredentialId: (credentialId) => findPasskeyCredentialByCredentialId(executor, tables, credentialId),
2350
+ listByUser: (input) => {
2351
+ const base = Query.select(selectPasskeyCredentialColumns(tables)).pipe(Query.from(tables.passkeyCredential.table), Query.where(queryEq(tables.passkeyCredential.select.userId, input.userId)));
2352
+ const query = input.includeRevoked === true
2353
+ ? base
2354
+ : base.pipe(Query.where(queryIsNull(tables.passkeyCredential.select.revokedAt)));
2355
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => passkeyCredentialStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodePasskeyCredentialRow(tables, row))));
2356
+ },
2357
+ updateSignCount: (input) => executePlan(executor, queryUpdate(tables.passkeyCredential.table, mutationValues(tables.passkeyCredential.updateSignCount(input))).pipe(Query.where(queryEq(tables.passkeyCredential.select.credentialId, input.credentialId)), Query.where(queryIsNull(tables.passkeyCredential.select.revokedAt)), Query.returning(selectPasskeyCredentialColumns(tables)))).pipe(Effect.mapError((cause) => passkeyCredentialStoreError("update-sign-count", cause)), Effect.map((rows) => rows[0] === undefined
2358
+ ? Option.none()
2359
+ : Option.some(decodePasskeyCredentialRow(tables, rows[0])))),
2360
+ revoke: (input) => findPasskeyCredentialByCredentialId(executor, tables, input.credentialId, "revoke").pipe(Effect.flatMap((row) => {
2361
+ if (Option.isNone(row)) {
2362
+ return Effect.void;
2363
+ }
2364
+ return executePlan(executor, queryUpdate(tables.passkeyCredential.table, mutationValues(tables.passkeyCredential.revoke(input, row.value))).pipe(Query.where(queryEq(tables.passkeyCredential.select.credentialId, input.credentialId)))).pipe(Effect.mapError((cause) => passkeyCredentialStoreError("revoke", cause)), Effect.asVoid);
2365
+ })),
2366
+ });
2367
+ };
2368
+ export const makeEffectQbSqliteTotpFactorStore = (executor, options = {}) => {
2369
+ const tables = options.tables ?? authSqliteTables;
2370
+ return TotpFactorStore.make({
2371
+ insert: (row) => executePlan(executor, queryInsert(tables.totpFactor.table, mutationValues(tables.totpFactor.insert(row)))).pipe(Effect.mapError((cause) => totpFactorStoreError("insert", cause)), Effect.asVoid),
2372
+ findById: (id) => findTotpFactorById(executor, tables, id),
2373
+ listByUser: (input) => {
2374
+ const byUser = Query.select(selectTotpFactorColumns(tables)).pipe(Query.from(tables.totpFactor.table), Query.where(queryEq(tables.totpFactor.select.userId, input.userId)));
2375
+ const byRevoked = input.includeRevoked === true
2376
+ ? byUser
2377
+ : byUser.pipe(Query.where(queryIsNull(tables.totpFactor.select.revokedAt)));
2378
+ const query = input.includeUnconfirmed === true
2379
+ ? byRevoked
2380
+ : byRevoked.pipe(Query.where(queryGt(tables.totpFactor.select.confirmedAt, 0)));
2381
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => totpFactorStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeTotpFactorRow(tables, row))));
2382
+ },
2383
+ confirm: (input) => executePlan(executor, queryUpdate(tables.totpFactor.table, mutationValues(tables.totpFactor.confirm(input))).pipe(Query.where(queryEq(tables.totpFactor.select.id, input.id)), Query.where(queryIsNull(tables.totpFactor.select.revokedAt)), Query.returning(selectTotpFactorColumns(tables)))).pipe(Effect.mapError((cause) => totpFactorStoreError("confirm", cause)), Effect.map((rows) => rows[0] === undefined
2384
+ ? Option.none()
2385
+ : Option.some(decodeTotpFactorRow(tables, rows[0])))),
2386
+ markUsed: (input) => executePlan(executor, queryUpdate(tables.totpFactor.table, mutationValues(tables.totpFactor.markUsed(input))).pipe(Query.where(queryEq(tables.totpFactor.select.id, input.id)), Query.where(queryIsNull(tables.totpFactor.select.revokedAt)), Query.where(queryGt(tables.totpFactor.select.confirmedAt, 0)), Query.returning(selectTotpFactorColumns(tables)))).pipe(Effect.mapError((cause) => totpFactorStoreError("mark-used", cause)), Effect.map((rows) => rows[0] === undefined
2387
+ ? Option.none()
2388
+ : Option.some(decodeTotpFactorRow(tables, rows[0])))),
2389
+ revoke: (input) => findTotpFactorById(executor, tables, input.id, "revoke").pipe(Effect.flatMap((row) => {
2390
+ if (Option.isNone(row)) {
2391
+ return Effect.void;
2392
+ }
2393
+ return executePlan(executor, queryUpdate(tables.totpFactor.table, mutationValues(tables.totpFactor.revoke(input, row.value))).pipe(Query.where(queryEq(tables.totpFactor.select.id, input.id)))).pipe(Effect.mapError((cause) => totpFactorStoreError("revoke", cause)), Effect.asVoid);
2394
+ })),
2395
+ });
2396
+ };
2397
+ export const makeEffectQbSqliteRecoveryCodeStore = (executor, options = {}) => {
2398
+ const tables = options.tables ?? authSqliteTables;
2399
+ return RecoveryCodeStore.make({
2400
+ insertMany: (rows) => Effect.forEach(rows, (row) => executePlan(executor, queryInsert(tables.recoveryCode.table, mutationValues(tables.recoveryCode.insert(row)))).pipe(Effect.mapError((cause) => recoveryCodeStoreError("insert", cause)), Effect.asVoid), { discard: true }),
2401
+ findById: (id) => findRecoveryCodeById(executor, tables, id),
2402
+ listByUser: (input) => {
2403
+ const byUser = Query.select(selectRecoveryCodeColumns(tables)).pipe(Query.from(tables.recoveryCode.table), Query.where(queryEq(tables.recoveryCode.select.userId, input.userId)));
2404
+ const byUsed = input.includeUsed === true
2405
+ ? byUser
2406
+ : byUser.pipe(Query.where(queryIsNull(tables.recoveryCode.select.usedAt)));
2407
+ const query = input.includeRevoked === true
2408
+ ? byUsed
2409
+ : byUsed.pipe(Query.where(queryIsNull(tables.recoveryCode.select.revokedAt)));
2410
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => recoveryCodeStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeRecoveryCodeRow(tables, row))));
2411
+ },
2412
+ markUsed: (input) => executePlan(executor, queryUpdate(tables.recoveryCode.table, mutationValues(tables.recoveryCode.markUsed(input))).pipe(Query.where(queryEq(tables.recoveryCode.select.id, input.id)), Query.where(queryIsNull(tables.recoveryCode.select.usedAt)), Query.where(queryIsNull(tables.recoveryCode.select.revokedAt)), Query.returning({ id: tables.recoveryCode.select.id }))).pipe(Effect.mapError((cause) => recoveryCodeStoreError("mark-used", cause)), Effect.flatMap((rows) => rows[0] === undefined
2413
+ ? Effect.succeed(Option.none())
2414
+ : findRecoveryCodeById(executor, tables, input.id, "mark-used"))),
2415
+ revoke: (input) => findRecoveryCodeById(executor, tables, input.id, "revoke").pipe(Effect.flatMap((row) => {
2416
+ if (Option.isNone(row)) {
2417
+ return Effect.void;
2418
+ }
2419
+ return executePlan(executor, queryUpdate(tables.recoveryCode.table, mutationValues(tables.recoveryCode.revoke(input, row.value))).pipe(Query.where(queryEq(tables.recoveryCode.select.id, input.id)))).pipe(Effect.mapError((cause) => recoveryCodeStoreError("revoke", cause)), Effect.asVoid);
2420
+ })),
2421
+ });
2422
+ };
2423
+ export const makeEffectQbSqliteApiKeyStore = (executor, options = {}) => {
2424
+ const tables = options.tables ?? authSqliteTables;
2425
+ return ApiKeyStore.make({
2426
+ insert: (row) => executePlan(executor, queryInsert(tables.apiKey.table, mutationValues(tables.apiKey.insert(row)))).pipe(Effect.mapError((cause) => apiKeyStoreError("insert", cause)), Effect.asVoid),
2427
+ findById: (id) => findApiKeyById(executor, tables, id),
2428
+ findByPrefix: (prefix) => findApiKeyByPrefix(executor, tables, prefix),
2429
+ listByUser: (input) => {
2430
+ const base = Query.select(selectApiKeyColumns(tables)).pipe(Query.from(tables.apiKey.table), Query.where(queryEq(tables.apiKey.select.userId, input.userId)));
2431
+ const query = input.includeRevoked === true
2432
+ ? base
2433
+ : base.pipe(Query.where(queryIsNull(tables.apiKey.select.revokedAt)));
2434
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => apiKeyStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeApiKeyRow(tables, row))));
2435
+ },
2436
+ markUsed: (input) => executePlan(executor, queryUpdate(tables.apiKey.table, mutationValues(tables.apiKey.markUsed(input))).pipe(Query.where(queryEq(tables.apiKey.select.id, input.id)), Query.where(queryIsNull(tables.apiKey.select.revokedAt)), Query.returning(selectApiKeyColumns(tables)))).pipe(Effect.mapError((cause) => apiKeyStoreError("mark-used", cause)), Effect.map((rows) => rows[0] === undefined
2437
+ ? Option.none()
2438
+ : Option.some(decodeApiKeyRow(tables, rows[0])))),
2439
+ revoke: (input) => findApiKeyById(executor, tables, input.id, "revoke").pipe(Effect.flatMap((row) => {
2440
+ if (Option.isNone(row)) {
2441
+ return Effect.void;
2442
+ }
2443
+ return executePlan(executor, queryUpdate(tables.apiKey.table, mutationValues(tables.apiKey.revoke(input, row.value))).pipe(Query.where(queryEq(tables.apiKey.select.id, input.id)))).pipe(Effect.mapError((cause) => apiKeyStoreError("revoke", cause)), Effect.asVoid);
2444
+ })),
2445
+ });
2446
+ };
2447
+ export const makeEffectQbSqliteRefreshTokenStore = (executor, options = {}) => {
2448
+ const tables = options.tables ?? authSqliteTables;
2449
+ return RefreshTokenStore.make({
2450
+ insert: (row) => executePlan(executor, queryInsert(tables.refreshToken.table, mutationValues(tables.refreshToken.insert(row)))).pipe(Effect.mapError((cause) => refreshTokenStoreError("insert", cause)), Effect.asVoid),
2451
+ findById: (id) => findRefreshTokenById(executor, tables, id),
2452
+ findBySecretHash: (hash) => findRefreshTokenBySecretHash(executor, tables, hash),
2453
+ listByUser: (input) => {
2454
+ const base = Query.select(selectRefreshTokenColumns(tables)).pipe(Query.from(tables.refreshToken.table), Query.where(queryEq(tables.refreshToken.select.userId, input.userId)));
2455
+ const query = input.includeRevoked === true
2456
+ ? base
2457
+ : base.pipe(Query.where(queryIsNull(tables.refreshToken.select.revokedAt)));
2458
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => refreshTokenStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeRefreshTokenRow(tables, row))));
2459
+ },
2460
+ listByFamily: (input) => {
2461
+ const base = Query.select(selectRefreshTokenColumns(tables)).pipe(Query.from(tables.refreshToken.table), Query.where(queryEq(tables.refreshToken.select.familyId, input.familyId)));
2462
+ const query = input.includeRevoked === true
2463
+ ? base
2464
+ : base.pipe(Query.where(queryIsNull(tables.refreshToken.select.revokedAt)));
2465
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => refreshTokenStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeRefreshTokenRow(tables, row))));
2466
+ },
2467
+ rotate: (input) => executePlan(executor, queryUpdate(tables.refreshToken.table, mutationValues(tables.refreshToken.rotate(input))).pipe(Query.where(queryEq(tables.refreshToken.select.id, input.id)), Query.where(queryIsNull(tables.refreshToken.select.rotatedAt)), Query.where(queryIsNull(tables.refreshToken.select.revokedAt)), Query.returning({ id: tables.refreshToken.select.id }))).pipe(Effect.mapError((cause) => refreshTokenStoreError("rotate", cause)), Effect.flatMap((rows) => {
2468
+ const [updated] = rows;
2469
+ if (updated === undefined) {
2470
+ return Effect.succeed(Option.none());
2471
+ }
2472
+ return findRefreshTokenById(executor, tables, RefreshTokenId(updated.id), "rotate").pipe(Effect.flatMap((previous) => {
2473
+ if (Option.isNone(previous)) {
2474
+ return Effect.succeed(Option.none());
2475
+ }
2476
+ return executePlan(executor, queryInsert(tables.refreshToken.table, mutationValues(tables.refreshToken.insert(input.replacement)))).pipe(Effect.mapError((cause) => refreshTokenStoreError("rotate", cause)), Effect.as(Option.some({
2477
+ previous: previous.value,
2478
+ replacement: input.replacement,
2479
+ })));
2480
+ }));
2481
+ })),
2482
+ markReuseDetected: (input) => executePlan(executor, queryUpdate(tables.refreshToken.table, mutationValues(tables.refreshToken.markReuseDetected(input))).pipe(Query.where(queryEq(tables.refreshToken.select.id, input.id)), Query.returning(selectRefreshTokenColumns(tables)))).pipe(Effect.mapError((cause) => refreshTokenStoreError("reuse", cause)), Effect.map((rows) => rows[0] === undefined
2483
+ ? Option.none()
2484
+ : Option.some(decodeRefreshTokenRow(tables, rows[0])))),
2485
+ revoke: (input) => findRefreshTokenById(executor, tables, input.id, "revoke").pipe(Effect.flatMap((row) => {
2486
+ if (Option.isNone(row)) {
2487
+ return Effect.void;
2488
+ }
2489
+ return executePlan(executor, queryUpdate(tables.refreshToken.table, mutationValues(tables.refreshToken.revoke(input, row.value))).pipe(Query.where(queryEq(tables.refreshToken.select.id, input.id)))).pipe(Effect.mapError((cause) => refreshTokenStoreError("revoke", cause)), Effect.asVoid);
2490
+ })),
2491
+ revokeFamily: (input) => executePlan(executor, Query.select(selectRefreshTokenColumns(tables)).pipe(Query.from(tables.refreshToken.table), Query.where(queryEq(tables.refreshToken.select.familyId, input.familyId)))).pipe(Effect.mapError((cause) => refreshTokenStoreError("revoke", cause)), Effect.flatMap((rows) => Effect.forEach(rows.map((row) => decodeRefreshTokenRow(tables, row)), (row) => executePlan(executor, queryUpdate(tables.refreshToken.table, mutationValues(tables.refreshToken.revokeFamily(input, row))).pipe(Query.where(queryEq(tables.refreshToken.select.id, row.id)))).pipe(Effect.mapError((cause) => refreshTokenStoreError("revoke", cause)), Effect.asVoid), { discard: true }))),
2492
+ });
2493
+ };
2494
+ export const makeEffectQbSqliteJwtRevocationStore = (executor, options = {}) => {
2495
+ const tables = options.tables ?? authSqliteTables;
2496
+ return JwtRevocationStore.make({
2497
+ revoke: (record) => findJwtRevocation(executor, tables, record.jwtId, "revoke").pipe(Effect.flatMap((existing) => {
2498
+ if (Option.isNone(existing)) {
2499
+ return executePlan(executor, queryInsert(tables.jwtRevocation.table, mutationValues(tables.jwtRevocation.insert(record))));
2500
+ }
2501
+ return executePlan(executor, queryUpdate(tables.jwtRevocation.table, mutationValues(tables.jwtRevocation.update(record))).pipe(Query.where(queryEq(tables.jwtRevocation.select.jwtId, record.jwtId))));
2502
+ }), Effect.mapError((cause) => cause instanceof JwtError
2503
+ ? cause
2504
+ : jwtRevocationStoreError("revoke", cause)), Effect.asVoid),
2505
+ find: (jwtId) => findJwtRevocation(executor, tables, jwtId),
2506
+ });
2507
+ };
2508
+ export const makeEffectQbSqliteOAuthAccountStore = (executor, options = {}) => {
2509
+ const tables = options.tables ?? authSqliteTables;
2510
+ return OAuthAccountStore.make({
2511
+ insert: (row) => executePlan(executor, queryInsert(tables.oauthAccount.table, mutationValues(tables.oauthAccount.insert(row)))).pipe(Effect.mapError((cause) => oauthAccountStoreError("insert", cause)), Effect.asVoid),
2512
+ findById: (id) => findOAuthAccountById(executor, tables, id),
2513
+ findByProviderAccount: (input) => findOAuthAccountByProviderAccount(executor, tables, input),
2514
+ listByUser: (input) => {
2515
+ const base = Query.select(selectOAuthAccountColumns(tables)).pipe(Query.from(tables.oauthAccount.table), Query.where(queryEq(tables.oauthAccount.select.userId, input.userId)));
2516
+ const query = input.includeUnlinked === true
2517
+ ? base
2518
+ : base.pipe(Query.where(queryIsNull(tables.oauthAccount.select.unlinkedAt)));
2519
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => oauthAccountStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeOAuthAccountRow(tables, row))));
2520
+ },
2521
+ unlink: (input) => findOAuthAccountByProviderAccount(executor, tables, {
2522
+ providerId: input.providerId,
2523
+ providerAccountId: input.providerAccountId,
2524
+ }, "unlink").pipe(Effect.flatMap((row) => {
2525
+ if (Option.isNone(row)) {
2526
+ return Effect.succeed(Option.none());
2527
+ }
2528
+ return executePlan(executor, queryUpdate(tables.oauthAccount.table, mutationValues(tables.oauthAccount.unlink(input, row.value))).pipe(Query.where(queryEq(tables.oauthAccount.select.id, row.value.id)), Query.returning(selectOAuthAccountColumns(tables)))).pipe(Effect.mapError((cause) => oauthAccountStoreError("unlink", cause)), Effect.map((rows) => rows[0] === undefined
2529
+ ? Option.none()
2530
+ : Option.some(decodeOAuthAccountRow(tables, rows[0]))));
2531
+ })),
2532
+ });
2533
+ };
2534
+ export const makeEffectQbSqliteOAuthClientStore = (executor, options = {}) => {
2535
+ const tables = options.tables ?? authSqliteTables;
2536
+ return OAuthClientStore.make({
2537
+ upsert: (record) => executePlan(executor, queryInsert(tables.oauthClient.table, mutationValues(tables.oauthClient.insert(record))).pipe(Query.onConflict("id", {
2538
+ update: mutationValues(tables.oauthClient.update(record)),
2539
+ }))).pipe(Effect.mapError((cause) => oauthClientStoreError("upsert", cause)), Effect.asVoid),
2540
+ find: (input) => findOAuthClientById(executor, tables, input),
2541
+ list: (input = {}) => {
2542
+ const base = Query.select(selectOAuthClientColumns(tables)).pipe(Query.from(tables.oauthClient.table));
2543
+ const query = input.includeDisabled === true
2544
+ ? base
2545
+ : base.pipe(Query.where(queryEq(tables.oauthClient.select.status, "active")));
2546
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => oauthClientStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeOAuthClientRow(tables, row))));
2547
+ },
2548
+ validateRedirectUri: (input) => findOAuthClientById(executor, tables, input, "validate-redirect-uri").pipe(Effect.map((client) => oauthClientRedirectUriValidationResult(Option.isNone(client) ? undefined : client.value, input))),
2549
+ });
2550
+ };
2551
+ export const makeEffectQbSqliteOAuthConsentStore = (executor, options = {}) => {
2552
+ const tables = options.tables ?? authSqliteTables;
2553
+ return OAuthConsentStore.make({
2554
+ upsert: (record) => executePlan(executor, queryInsert(tables.oauthConsent.table, mutationValues(tables.oauthConsent.insert(record))).pipe(Query.onConflict("id", {
2555
+ update: mutationValues(tables.oauthConsent.update(record)),
2556
+ }))).pipe(Effect.mapError((cause) => oauthConsentStoreError("upsert", cause)), Effect.asVoid),
2557
+ findActive: (input) => findOAuthConsentByUserAndClient(executor, tables, input).pipe(Effect.map((record) => Option.isNone(record) || !isOAuthConsentActive(record.value, input)
2558
+ ? Option.none()
2559
+ : Option.some(record.value))),
2560
+ listForUser: (input) => executePlan(executor, Query.select(selectOAuthConsentColumns(tables)).pipe(Query.from(tables.oauthConsent.table), Query.where(queryEq(tables.oauthConsent.select.userId, input.userId)))).pipe(Effect.mapError((cause) => oauthConsentStoreError("list-for-user", cause)), Effect.map((rows) => rows
2561
+ .map((row) => decodeOAuthConsentRow(tables, row))
2562
+ .filter((record) => input.includeInactive === true ||
2563
+ isOAuthConsentActive(record, { now: input.now })))),
2564
+ revoke: (input) => findOAuthConsentByUserAndClient(executor, tables, input, "revoke").pipe(Effect.flatMap((row) => {
2565
+ if (Option.isNone(row)) {
2566
+ return Effect.succeed(Option.none());
2567
+ }
2568
+ return executePlan(executor, queryUpdate(tables.oauthConsent.table, mutationValues(tables.oauthConsent.revoke(input, row.value))).pipe(Query.where(queryEq(tables.oauthConsent.select.userId, input.userId)), Query.where(queryEq(tables.oauthConsent.select.clientId, input.clientId)), Query.returning(selectOAuthConsentColumns(tables)))).pipe(Effect.mapError((cause) => oauthConsentStoreError("revoke", cause)), Effect.map((rows) => rows[0] === undefined
2569
+ ? Option.none()
2570
+ : Option.some(decodeOAuthConsentRow(tables, rows[0]))));
2571
+ })),
2572
+ deleteInactive: (input) => deleteOAuthInactiveConsents(executor, tables, input),
2573
+ });
2574
+ };
2575
+ export const makeEffectQbSqliteOAuthAuthorizationCodeStore = (executor, options = {}) => {
2576
+ const tables = options.tables ?? authSqliteTables;
2577
+ return OAuthAuthorizationCodeStore.make({
2578
+ upsert: (record) => executePlan(executor, queryInsert(tables.oauthAuthorizationCode.table, mutationValues(tables.oauthAuthorizationCode.insert(record))).pipe(Query.onConflict("code_hash", {
2579
+ update: mutationValues(tables.oauthAuthorizationCode.update(record)),
2580
+ }))).pipe(Effect.mapError((cause) => oauthAuthorizationCodeStoreError("upsert", cause)), Effect.asVoid),
2581
+ findByHash: (input) => findOAuthAuthorizationCodeByHash(executor, tables, input),
2582
+ markConsumed: (input) => executePlan(executor, queryUpdate(tables.oauthAuthorizationCode.table, mutationValues(tables.oauthAuthorizationCode.markConsumed(input))).pipe(Query.where(queryEq(tables.oauthAuthorizationCode.select.codeHash, input.codeHash)), Query.where(queryIsNull(tables.oauthAuthorizationCode.select.consumedAt)), Query.returning({ codeHash: tables.oauthAuthorizationCode.select.codeHash }))).pipe(Effect.mapError((cause) => oauthAuthorizationCodeStoreError("mark-consumed", cause)), Effect.flatMap((rows) => {
2583
+ const [consumed] = rows;
2584
+ if (consumed !== undefined) {
2585
+ return findOAuthAuthorizationCodeByHash(executor, tables, { codeHash: consumed.codeHash }, "mark-consumed").pipe(Effect.map((record) => Option.isNone(record)
2586
+ ? { status: "missing" }
2587
+ : {
2588
+ status: "consumed",
2589
+ record: record.value,
2590
+ }));
2591
+ }
2592
+ return findOAuthAuthorizationCodeByHash(executor, tables, { codeHash: input.codeHash }, "mark-consumed").pipe(Effect.map((record) => Option.isNone(record)
2593
+ ? { status: "missing" }
2594
+ : {
2595
+ status: "already_consumed",
2596
+ record: record.value,
2597
+ }));
2598
+ })),
2599
+ });
2600
+ };
2601
+ export const makeEffectQbSqliteOAuthClientSecretStore = (executor, options = {}) => {
2602
+ const tables = options.tables ?? authSqliteTables;
2603
+ return OAuthClientSecretStore.make({
2604
+ upsert: (record) => executePlan(executor, queryInsert(tables.oauthClientSecret.table, mutationValues(tables.oauthClientSecret.insert(record))).pipe(Query.onConflict("prefix", {
2605
+ update: mutationValues(tables.oauthClientSecret.update(record)),
2606
+ }))).pipe(Effect.mapError((cause) => oauthClientSecretStoreError("upsert", cause)), Effect.asVoid),
2607
+ findByClientIdAndPrefix: (input) => findOAuthClientSecretByClientIdAndPrefix(executor, tables, input),
2608
+ markUsed: (input) => executePlan(executor, queryUpdate(tables.oauthClientSecret.table, mutationValues(tables.oauthClientSecret.markUsed(input))).pipe(Query.where(queryEq(tables.oauthClientSecret.select.clientId, input.clientId)), Query.where(queryEq(tables.oauthClientSecret.select.prefix, input.prefix)), Query.where(queryIsNull(tables.oauthClientSecret.select.revokedAt)), Query.returning(selectOAuthClientSecretColumns(tables)))).pipe(Effect.mapError((cause) => oauthClientSecretStoreError("mark-used", cause)), Effect.map((rows) => rows[0] === undefined
2609
+ ? Option.none()
2610
+ : Option.some(decodeOAuthClientSecretRow(tables, rows[0])))),
2611
+ revoke: (input) => findOAuthClientSecretByClientIdAndPrefix(executor, tables, input, "revoke").pipe(Effect.flatMap((row) => {
2612
+ if (Option.isNone(row)) {
2613
+ return Effect.succeed(Option.none());
2614
+ }
2615
+ return executePlan(executor, queryUpdate(tables.oauthClientSecret.table, mutationValues(tables.oauthClientSecret.revoke(input, row.value))).pipe(Query.where(queryEq(tables.oauthClientSecret.select.clientId, input.clientId)), Query.where(queryEq(tables.oauthClientSecret.select.prefix, input.prefix)), Query.returning(selectOAuthClientSecretColumns(tables)))).pipe(Effect.mapError((cause) => oauthClientSecretStoreError("revoke", cause)), Effect.map((rows) => rows[0] === undefined
2616
+ ? Option.none()
2617
+ : Option.some(decodeOAuthClientSecretRow(tables, rows[0]))));
2618
+ })),
2619
+ });
2620
+ };
2621
+ export const makeEffectQbSqliteOAuthProviderModeTokenStore = (executor, options = {}) => {
2622
+ const tables = options.tables ?? authSqliteTables;
2623
+ return OAuthProviderModeTokenStore.make({
2624
+ upsert: (record) => executePlan(executor, queryInsert(tables.oauthProviderModeToken.table, mutationValues(tables.oauthProviderModeToken.insert(record))).pipe(Query.onConflict("token_hash", {
2625
+ update: mutationValues(tables.oauthProviderModeToken.update(record)),
2626
+ }))).pipe(Effect.mapError((cause) => oauthProviderModeTokenStoreError("upsert", cause)), Effect.asVoid),
2627
+ findByHash: (input) => findOAuthProviderModeTokenByHash(executor, tables, input),
2628
+ revokeByHash: (input) => findOAuthProviderModeTokenByHash(executor, tables, input, "revoke").pipe(Effect.flatMap((row) => {
2629
+ if (Option.isNone(row) ||
2630
+ (input.tokenTypeHint !== undefined &&
2631
+ row.value.tokenType !== input.tokenTypeHint)) {
2632
+ return Effect.succeed(Option.none());
2633
+ }
2634
+ return executePlan(executor, queryUpdate(tables.oauthProviderModeToken.table, mutationValues(tables.oauthProviderModeToken.revoke(input, row.value))).pipe(Query.where(queryEq(tables.oauthProviderModeToken.select.tokenHash, input.tokenHash)), Query.returning(selectOAuthProviderModeTokenColumns(tables)))).pipe(Effect.mapError((cause) => oauthProviderModeTokenStoreError("revoke", cause)), Effect.map((rows) => rows[0] === undefined
2635
+ ? Option.none()
2636
+ : Option.some(decodeOAuthProviderModeTokenRow(tables, rows[0]))));
2637
+ })),
2638
+ rotateRefreshToken: (input) => executePlan(executor, queryUpdate(tables.oauthProviderModeToken.table, mutationValues(tables.oauthProviderModeToken.rotate(input))).pipe(Query.where(queryEq(tables.oauthProviderModeToken.select.tokenHash, input.tokenHash)), Query.where(queryEq(tables.oauthProviderModeToken.select.tokenType, "refresh_token")), Query.where(queryIsNull(tables.oauthProviderModeToken.select.revokedAt)), Query.where(queryIsNull(tables.oauthProviderModeToken.select.rotatedAt)), Query.returning({
2639
+ tokenHash: tables.oauthProviderModeToken.select.tokenHash,
2640
+ }))).pipe(Effect.mapError((cause) => oauthProviderModeTokenStoreError("rotate", cause)), Effect.flatMap((rows) => rows[0] === undefined
2641
+ ? Effect.succeed(Option.none())
2642
+ : findOAuthProviderModeTokenByHash(executor, tables, { tokenHash: rows[0].tokenHash }, "rotate"))),
2643
+ deleteRetired: (input) => deleteOAuthProviderModeRetiredTokens(executor, tables, input),
2644
+ });
2645
+ };
2646
+ export const makeEffectQbSqliteOAuthProviderTokenVault = (executor, options = {}) => {
2647
+ const tables = options.tables ?? authSqliteTables;
2648
+ return OAuthProviderTokenVault.make({
2649
+ upsert: (record) => findOAuthProviderTokenVaultRecordByAccountId(executor, tables, { accountId: record.accountId }, "upsert", true).pipe(Effect.flatMap((existing) => Option.isNone(existing)
2650
+ ? executePlan(executor, queryInsert(tables.oauthProviderTokenVault.table, mutationValues(tables.oauthProviderTokenVault.insert(record))))
2651
+ : executePlan(executor, queryUpdate(tables.oauthProviderTokenVault.table, mutationValues(tables.oauthProviderTokenVault.update(record))).pipe(Query.where(queryEq(tables.oauthProviderTokenVault.select.accountId, record.accountId))))), Effect.mapError((cause) => cause instanceof OAuthProviderTokenVaultError
2652
+ ? cause
2653
+ : oauthProviderTokenVaultError("upsert", cause)), Effect.asVoid),
2654
+ refreshTokenForAccount: (input) => findOAuthProviderTokenVaultRecordByAccountId(executor, tables, input, "refresh-token").pipe(Effect.map((row) => Option.isNone(row) || row.value.refreshTokenCiphertext === undefined
2655
+ ? Option.none()
2656
+ : Option.some(row.value.refreshTokenCiphertext))),
2657
+ tokensForAccount: (input) => findOAuthProviderTokenVaultRecordByAccountId(executor, tables, input, "tokens").pipe(Effect.map((row) => Option.isNone(row)
2658
+ ? Option.none()
2659
+ : Option.some(providerTokenVaultTokens(row.value)))),
2660
+ markRevoked: (input) => executePlan(executor, queryUpdate(tables.oauthProviderTokenVault.table, mutationValues(tables.oauthProviderTokenVault.markRevoked(input))).pipe(Query.where(queryEq(tables.oauthProviderTokenVault.select.accountId, input.accountId)), Query.returning({
2661
+ accountId: tables.oauthProviderTokenVault.select.accountId,
2662
+ }))).pipe(Effect.mapError((cause) => oauthProviderTokenVaultError("mark-revoked", cause)), Effect.flatMap((rows) => {
2663
+ const [updated] = rows;
2664
+ if (updated === undefined) {
2665
+ return Effect.succeed(Option.none());
2666
+ }
2667
+ return findOAuthProviderTokenVaultRecordByAccountId(executor, tables, { accountId: OAuthAccountId(updated.accountId) }, "mark-revoked", true);
2668
+ })),
2669
+ });
2670
+ };
2671
+ export const makeEffectQbSqliteDomainVerificationStore = (executor, options = {}) => {
2672
+ const tables = options.tables ?? authSqliteTables;
2673
+ return DomainVerificationStore.make({
2674
+ upsert: (record) => findDomainVerificationByOwnerAndDomain(executor, tables, { ownerId: record.ownerId, domain: record.domain }, "upsert").pipe(Effect.flatMap((existing) => Option.isNone(existing)
2675
+ ? executePlan(executor, queryInsert(tables.domainVerification.table, mutationValues(tables.domainVerification.insert(record))))
2676
+ : executePlan(executor, queryUpdate(tables.domainVerification.table, mutationValues(tables.domainVerification.update(record))).pipe(Query.where(queryEq(tables.domainVerification.select.ownerId, record.ownerId)), Query.where(queryEq(tables.domainVerification.select.domain, record.domain))))), Effect.mapError((cause) => cause instanceof DomainVerificationStoreError
2677
+ ? cause
2678
+ : domainVerificationStoreError("upsert", cause)), Effect.asVoid),
2679
+ findById: (id) => findDomainVerificationById(executor, tables, id),
2680
+ findByOwnerAndDomain: (input) => findDomainVerificationByOwnerAndDomain(executor, tables, input),
2681
+ listByOwner: (input) => {
2682
+ const base = Query.select(selectDomainVerificationColumns(tables)).pipe(Query.from(tables.domainVerification.table), Query.where(queryEq(tables.domainVerification.select.ownerId, input.ownerId)));
2683
+ const query = input.includeRevoked === true
2684
+ ? base
2685
+ : base.pipe(Query.where(queryIsNull(tables.domainVerification.select.revokedAt)));
2686
+ return executePlan(executor, query).pipe(Effect.mapError((cause) => domainVerificationStoreError("list", cause)), Effect.map((rows) => rows.map((row) => decodeDomainVerificationRecord(tables, row))));
2687
+ },
2688
+ markVerified: (input) => executePlan(executor, queryUpdate(tables.domainVerification.table, mutationValues(tables.domainVerification.markVerified(input))).pipe(Query.where(queryEq(tables.domainVerification.select.id, input.id)), Query.where(queryEq(tables.domainVerification.select.status, "pending")), Query.returning(selectDomainVerificationColumns(tables)))).pipe(Effect.mapError((cause) => domainVerificationStoreError("mark-verified", cause)), Effect.map((rows) => rows[0] === undefined
2689
+ ? Option.none()
2690
+ : Option.some(decodeDomainVerificationRecord(tables, rows[0])))),
2691
+ revoke: (input) => findDomainVerificationById(executor, tables, input.id, "revoke").pipe(Effect.flatMap((record) => {
2692
+ if (Option.isNone(record)) {
2693
+ return Effect.void;
2694
+ }
2695
+ return executePlan(executor, queryUpdate(tables.domainVerification.table, mutationValues(tables.domainVerification.revoke(input, record.value))).pipe(Query.where(queryEq(tables.domainVerification.select.id, input.id)))).pipe(Effect.mapError((cause) => domainVerificationStoreError("revoke", cause)), Effect.asVoid);
2696
+ })),
2697
+ });
2698
+ };
2699
+ export const makeEffectQbSqliteSecurityTimelineStore = (executor, options = {}) => {
2700
+ const tables = options.tables ?? authSqliteTables;
2701
+ return SecurityTimelineStore.make({
2702
+ insert: (event) => executePlan(executor, queryInsert(tables.securityTimeline.table, mutationValues(tables.securityTimeline.insert(event)))).pipe(Effect.mapError((cause) => securityTimelineStoreError("insert", cause)), Effect.asVoid),
2703
+ listByUser: (input) => listSecurityTimelineByUser(executor, tables, input),
2704
+ deleteBefore: (input) => deleteSecurityTimelineBefore(executor, tables, input),
2705
+ });
2706
+ };
2707
+ export const makeEffectQbSqliteWebhookOutboxStore = (executor, options = {}) => {
2708
+ const tables = options.tables ?? authSqliteTables;
2709
+ return WebhookOutboxStore.make({
2710
+ enqueue: (input) => Effect.gen(function* () {
2711
+ const now = input.now ?? (yield* currentUnixMillis);
2712
+ const record = {
2713
+ id: input.id,
2714
+ endpointKey: input.endpointKey,
2715
+ event: input.event,
2716
+ status: "pending",
2717
+ attempts: 0,
2718
+ nextAttemptAt: input.nextAttemptAt ?? now,
2719
+ createdAt: now,
2720
+ updatedAt: now,
2721
+ };
2722
+ yield* executePlan(executor, queryInsert(tables.webhookOutbox.table, mutationValues(tables.webhookOutbox.insert(record)))).pipe(Effect.mapError((cause) => webhookOutboxStoreError("enqueue", cause)), Effect.asVoid);
2723
+ return record;
2724
+ }),
2725
+ claimDue: (input) => claimDueWebhookOutboxRecords(executor, tables, input),
2726
+ markDelivered: (input) => Effect.gen(function* () {
2727
+ const existing = yield* findWebhookOutboxRecordById(executor, tables, input.id, "markDelivered");
2728
+ if (Option.isNone(existing) || existing.value.status === "dead_lettered") {
2729
+ return;
2730
+ }
2731
+ const deliveredAt = input.deliveredAt ?? (yield* currentUnixMillis);
2732
+ yield* executePlan(executor, queryUpdate(tables.webhookOutbox.table, mutationValues(tables.webhookOutbox.markDelivered({ ...input, deliveredAt }))).pipe(Query.where(queryEq(tables.webhookOutbox.select.id, input.id)))).pipe(Effect.mapError((cause) => webhookOutboxStoreError("markDelivered", cause)), Effect.asVoid);
2733
+ }),
2734
+ markFailed: (input) => Effect.gen(function* () {
2735
+ const existing = yield* findWebhookOutboxRecordById(executor, tables, input.id, "markFailed");
2736
+ if (Option.isNone(existing) ||
2737
+ existing.value.status === "delivered" ||
2738
+ existing.value.status === "dead_lettered") {
2739
+ return;
2740
+ }
2741
+ const failedAt = input.failedAt ?? (yield* currentUnixMillis);
2742
+ yield* executePlan(executor, queryUpdate(tables.webhookOutbox.table, mutationValues(tables.webhookOutbox.markFailed({
2743
+ ...input,
2744
+ failedAt,
2745
+ attempts: existing.value.attempts + 1,
2746
+ }))).pipe(Query.where(queryEq(tables.webhookOutbox.select.id, input.id)))).pipe(Effect.mapError((cause) => webhookOutboxStoreError("markFailed", cause)), Effect.asVoid);
2747
+ }),
2748
+ markDeadLettered: (input) => Effect.gen(function* () {
2749
+ const existing = yield* findWebhookOutboxRecordById(executor, tables, input.id, "markDeadLettered");
2750
+ if (Option.isNone(existing) ||
2751
+ existing.value.status === "delivered" ||
2752
+ existing.value.status === "dead_lettered") {
2753
+ return;
2754
+ }
2755
+ const deadLetteredAt = input.deadLetteredAt ?? (yield* currentUnixMillis);
2756
+ yield* executePlan(executor, queryUpdate(tables.webhookOutbox.table, mutationValues(tables.webhookOutbox.markDeadLettered({
2757
+ ...input,
2758
+ deadLetteredAt,
2759
+ }))).pipe(Query.where(queryEq(tables.webhookOutbox.select.id, input.id)))).pipe(Effect.mapError((cause) => webhookOutboxStoreError("markDeadLettered", cause)), Effect.asVoid);
2760
+ }),
2761
+ deleteBefore: (input) => deleteWebhookOutboxRecordsBefore(executor, tables, input),
2762
+ });
2763
+ };
2764
+ export const makeEffectQbSqliteWebhookReplayStore = (executor, options = {}) => {
2765
+ const tables = options.tables ?? authSqliteTables;
2766
+ return WebhookReplayStore.make({
2767
+ claim: (input) => Effect.gen(function* () {
2768
+ const now = input.now ?? (yield* currentUnixMillis);
2769
+ const claim = { ...input, now };
2770
+ const rows = yield* executePlan(executor, queryInsert(tables.webhookReplay.table, mutationValues(tables.webhookReplay.insert(claim))).pipe(Query.onConflict("id", {
2771
+ update: mutationValues(tables.webhookReplay.update(claim)),
2772
+ where: queryLt(tables.webhookReplay.select.expiresAt, Number(now)),
2773
+ }), Query.returning(selectWebhookReplayColumns(tables)))).pipe(Effect.mapError((cause) => webhookReplayStoreError("claim", cause)));
2774
+ return rows.length > 0;
2775
+ }),
2776
+ deleteExpired: (input = {}) => deleteExpiredWebhookReplayRecords(executor, tables, input),
2777
+ });
2778
+ };
2779
+ export const makeEffectQbSqliteStorage = (executor, options = {}) => ({
2780
+ userStore: makeEffectQbSqliteUserStore(executor, options),
2781
+ credentialStore: makeEffectQbSqliteCredentialStore(executor, options),
2782
+ sessionStore: makeEffectQbSqliteSessionStore(executor, options),
2783
+ verificationStore: makeEffectQbSqliteVerificationStore(executor, options),
2784
+ auditLogStore: makeEffectQbSqliteAuditLogStore(executor, options),
2785
+ loginApprovalReviewStore: makeEffectQbSqliteLoginApprovalReviewStore(executor, options),
2786
+ loginRiskHistoryStore: makeEffectQbSqliteLoginRiskHistoryStore(executor, options),
2787
+ trustedDeviceStore: makeEffectQbSqliteTrustedDeviceStore(executor, options),
2788
+ passkeyCredentialStore: makeEffectQbSqlitePasskeyCredentialStore(executor, options),
2789
+ totpFactorStore: makeEffectQbSqliteTotpFactorStore(executor, options),
2790
+ recoveryCodeStore: makeEffectQbSqliteRecoveryCodeStore(executor, options),
2791
+ apiKeyStore: makeEffectQbSqliteApiKeyStore(executor, options),
2792
+ refreshTokenStore: makeEffectQbSqliteRefreshTokenStore(executor, options),
2793
+ jwtRevocationStore: makeEffectQbSqliteJwtRevocationStore(executor, options),
2794
+ oauthAccountStore: makeEffectQbSqliteOAuthAccountStore(executor, options),
2795
+ oauthClientStore: makeEffectQbSqliteOAuthClientStore(executor, options),
2796
+ oauthConsentStore: makeEffectQbSqliteOAuthConsentStore(executor, options),
2797
+ oauthAuthorizationCodeStore: makeEffectQbSqliteOAuthAuthorizationCodeStore(executor, options),
2798
+ oauthClientSecretStore: makeEffectQbSqliteOAuthClientSecretStore(executor, options),
2799
+ oauthProviderModeTokenStore: makeEffectQbSqliteOAuthProviderModeTokenStore(executor, options),
2800
+ oauthProviderTokenVault: makeEffectQbSqliteOAuthProviderTokenVault(executor, options),
2801
+ domainVerificationStore: makeEffectQbSqliteDomainVerificationStore(executor, options),
2802
+ securityTimelineStore: makeEffectQbSqliteSecurityTimelineStore(executor, options),
2803
+ webhookOutboxStore: makeEffectQbSqliteWebhookOutboxStore(executor, options),
2804
+ webhookReplayStore: makeEffectQbSqliteWebhookReplayStore(executor, options),
2805
+ });
2806
+ export const EffectQbSqliteAuthStorageLive = (executor, options = {}) => Layer.mergeAll(Layer.succeed(UserStore)(makeEffectQbSqliteUserStore(executor, options)), Layer.succeed(CredentialStore)(makeEffectQbSqliteCredentialStore(executor, options)), Layer.succeed(SessionStore)(makeEffectQbSqliteSessionStore(executor, options)), Layer.succeed(VerificationStore)(makeEffectQbSqliteVerificationStore(executor, options)), Layer.succeed(AuditLogStore)(makeEffectQbSqliteAuditLogStore(executor, options)), Layer.succeed(LoginApprovalReviewStore)(makeEffectQbSqliteLoginApprovalReviewStore(executor, options)), Layer.succeed(LoginRiskHistory)(makeEffectQbSqliteLoginRiskHistoryStore(executor, options)), Layer.succeed(TrustedDeviceStore)(makeEffectQbSqliteTrustedDeviceStore(executor, options)), Layer.succeed(PasskeyCredentialStore)(makeEffectQbSqlitePasskeyCredentialStore(executor, options)), Layer.succeed(TotpFactorStore)(makeEffectQbSqliteTotpFactorStore(executor, options)), Layer.succeed(RecoveryCodeStore)(makeEffectQbSqliteRecoveryCodeStore(executor, options)), Layer.succeed(ApiKeyStore)(makeEffectQbSqliteApiKeyStore(executor, options)), Layer.succeed(RefreshTokenStore)(makeEffectQbSqliteRefreshTokenStore(executor, options)), Layer.succeed(JwtRevocationStore)(makeEffectQbSqliteJwtRevocationStore(executor, options)), Layer.succeed(OAuthAccountStore)(makeEffectQbSqliteOAuthAccountStore(executor, options)), Layer.succeed(OAuthClientStore)(makeEffectQbSqliteOAuthClientStore(executor, options)), Layer.succeed(OAuthConsentStore)(makeEffectQbSqliteOAuthConsentStore(executor, options)), Layer.succeed(OAuthAuthorizationCodeStore)(makeEffectQbSqliteOAuthAuthorizationCodeStore(executor, options)), Layer.succeed(OAuthClientSecretStore)(makeEffectQbSqliteOAuthClientSecretStore(executor, options)), Layer.succeed(OAuthProviderModeTokenStore)(makeEffectQbSqliteOAuthProviderModeTokenStore(executor, options)), Layer.succeed(OAuthProviderTokenVault)(makeEffectQbSqliteOAuthProviderTokenVault(executor, options)), Layer.succeed(DomainVerificationStore)(makeEffectQbSqliteDomainVerificationStore(executor, options)), Layer.succeed(SecurityTimelineStore)(makeEffectQbSqliteSecurityTimelineStore(executor, options)), Layer.succeed(WebhookOutboxStore)(makeEffectQbSqliteWebhookOutboxStore(executor, options)), Layer.succeed(WebhookReplayStore)(makeEffectQbSqliteWebhookReplayStore(executor, options)));
2807
+ export const makeD1EffectQbSqliteExecutor = (database) => Executor.make({
2808
+ driver: Executor.driver((query) => Effect.tryPromise({
2809
+ try: () => database
2810
+ .prepare(query.sql)
2811
+ .bind(...query.params)
2812
+ .all(),
2813
+ catch: (cause) => new D1EffectQbError({ message: "D1 query failed", cause }),
2814
+ }).pipe(Effect.flatMap((result) => {
2815
+ if (result.success === false || result.error !== undefined) {
2816
+ return Effect.fail(new D1EffectQbError({
2817
+ message: result.error ?? "D1 query failed",
2818
+ }));
2819
+ }
2820
+ return Effect.succeed([...(result.results ?? [])]);
2821
+ }))),
2822
+ });
2823
+ export const D1EffectQbSqliteAuthStorageLive = (database, options = {}) => EffectQbSqliteAuthStorageLive(makeD1EffectQbSqliteExecutor(database), options);
2824
+ //# sourceMappingURL=EffectQbSqliteStorage.js.map