@yielded/auth-persistence-drizzle 0.1.0-beta.25 → 0.1.0-beta.26

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 (383) hide show
  1. package/README.md +4 -2
  2. package/dist/D1.d.mts +495 -1151
  3. package/dist/D1.mjs +41 -19
  4. package/dist/D1.mjs.map +1 -1
  5. package/dist/Libsql.d.mts +385 -1996
  6. package/dist/Libsql.mjs +43 -47
  7. package/dist/Libsql.mjs.map +1 -1
  8. package/dist/Mysql2.d.mts +397 -1743
  9. package/dist/Mysql2.mjs +35 -41
  10. package/dist/Mysql2.mjs.map +1 -1
  11. package/dist/Pglite.d.mts +397 -1743
  12. package/dist/Pglite.mjs +42 -31
  13. package/dist/Pglite.mjs.map +1 -1
  14. package/dist/Postgres.d.mts +397 -1743
  15. package/dist/Postgres.mjs +42 -31
  16. package/dist/Postgres.mjs.map +1 -1
  17. package/dist/SqliteBun.d.mts +385 -1992
  18. package/dist/SqliteBun.mjs +43 -43
  19. package/dist/SqliteBun.mjs.map +1 -1
  20. package/dist/SqliteDo.d.mts +385 -1991
  21. package/dist/SqliteDo.mjs +42 -41
  22. package/dist/SqliteDo.mjs.map +1 -1
  23. package/dist/SqliteNode.d.mts +385 -1992
  24. package/dist/SqliteNode.mjs +43 -43
  25. package/dist/SqliteNode.mjs.map +1 -1
  26. package/dist/SqliteWasm.d.mts +385 -1992
  27. package/dist/SqliteWasm.mjs +43 -43
  28. package/dist/SqliteWasm.mjs.map +1 -1
  29. package/dist/drizzle/d1-identity.mjs +2 -2
  30. package/dist/drizzle/d1-identity.mjs.map +1 -1
  31. package/dist/drizzle/driver-types.d.mts +15 -0
  32. package/dist/drizzle/email-drivers.mjs +32 -0
  33. package/dist/drizzle/email-drivers.mjs.map +1 -0
  34. package/dist/drizzle/email-model.d.mts +9 -13
  35. package/dist/drizzle/email-target.d.mts +10 -11
  36. package/dist/drizzle/email-target.mjs +33 -70
  37. package/dist/drizzle/email-target.mjs.map +1 -1
  38. package/dist/drizzle/model.d.mts +1 -10
  39. package/dist/drizzle/model.mjs +1 -2
  40. package/dist/drizzle/model.mjs.map +1 -1
  41. package/dist/drizzle/mysql-identity.mjs +3 -6
  42. package/dist/drizzle/mysql-identity.mjs.map +1 -1
  43. package/dist/drizzle/native-clock.d.mts +9 -0
  44. package/dist/drizzle/native-clock.mjs +18 -0
  45. package/dist/drizzle/native-clock.mjs.map +1 -0
  46. package/dist/drizzle/native-database.d.mts +46 -0
  47. package/dist/drizzle/native-database.mjs +6 -5
  48. package/dist/drizzle/native-database.mjs.map +1 -1
  49. package/dist/drizzle/native-sql-table.mjs +13 -5
  50. package/dist/drizzle/native-sql-table.mjs.map +1 -1
  51. package/dist/drizzle/native-target.d.mts +6 -0
  52. package/dist/drizzle/native-target.mjs +44 -0
  53. package/dist/drizzle/native-target.mjs.map +1 -0
  54. package/dist/drizzle/oauth-connected-drivers.mjs +4 -56
  55. package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -1
  56. package/dist/drizzle/oauth-connected-model.d.mts +5 -22
  57. package/dist/drizzle/oauth-connected-model.mjs +1 -7
  58. package/dist/drizzle/oauth-connected-reference.d.mts +5 -7
  59. package/dist/drizzle/oauth-connected-reference.mjs +11 -3
  60. package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
  61. package/dist/drizzle/oauth-drivers.mjs +1 -2
  62. package/dist/drizzle/oauth-drivers.mjs.map +1 -1
  63. package/dist/drizzle/oauth-model.d.mts +11 -37
  64. package/dist/drizzle/oauth-model.mjs +3 -4
  65. package/dist/drizzle/oauth-model.mjs.map +1 -1
  66. package/dist/drizzle/oauth-proxy.d.mts +1 -1
  67. package/dist/drizzle/oauth-proxy.mjs +1 -1
  68. package/dist/drizzle/oauth-target.d.mts +9 -6
  69. package/dist/drizzle/oauth-target.mjs +47 -15
  70. package/dist/drizzle/oauth-target.mjs.map +1 -1
  71. package/dist/drizzle/passkey/target.d.mts +14 -0
  72. package/dist/drizzle/passkey/target.mjs +52 -0
  73. package/dist/drizzle/passkey/target.mjs.map +1 -0
  74. package/dist/drizzle/passkey/write-target.d.mts +11 -0
  75. package/dist/drizzle/passkey/write-target.mjs +28 -0
  76. package/dist/drizzle/passkey/write-target.mjs.map +1 -0
  77. package/dist/drizzle/passkey-drivers.mjs +2 -4
  78. package/dist/drizzle/passkey-drivers.mjs.map +1 -1
  79. package/dist/drizzle/passkey-model.d.mts +5 -26
  80. package/dist/drizzle/passkey-model.mjs +2 -8
  81. package/dist/drizzle/passkey-registration-ceremony-model.d.mts +3 -6
  82. package/dist/drizzle/passkey-write-drivers.mjs +2 -3
  83. package/dist/drizzle/passkey-write-drivers.mjs.map +1 -1
  84. package/dist/drizzle/passkey-write-model.d.mts +7 -9
  85. package/dist/drizzle/passkey-write-model.mjs +1 -3
  86. package/dist/drizzle/passkey-write-model.mjs.map +1 -1
  87. package/dist/drizzle/password-drivers.mjs +31 -0
  88. package/dist/drizzle/password-drivers.mjs.map +1 -0
  89. package/dist/drizzle/password-model.d.mts +7 -10
  90. package/dist/drizzle/password-target.d.mts +7 -8
  91. package/dist/drizzle/password-target.mjs +23 -68
  92. package/dist/drizzle/password-target.mjs.map +1 -1
  93. package/dist/drizzle/pg-identity.mjs +3 -6
  94. package/dist/drizzle/pg-identity.mjs.map +1 -1
  95. package/dist/drizzle/phone-drivers.mjs +24 -0
  96. package/dist/drizzle/phone-drivers.mjs.map +1 -0
  97. package/dist/drizzle/phone-model.d.mts +13 -104
  98. package/dist/drizzle/phone-model.mjs +5 -33
  99. package/dist/drizzle/phone-model.mjs.map +1 -1
  100. package/dist/drizzle/phone-target.mjs +22 -171
  101. package/dist/drizzle/phone-target.mjs.map +1 -1
  102. package/dist/drizzle/proof-drivers.mjs +24 -0
  103. package/dist/drizzle/proof-drivers.mjs.map +1 -0
  104. package/dist/drizzle/proof-model.d.mts +7 -15
  105. package/dist/drizzle/proof-target.d.mts +5 -5
  106. package/dist/drizzle/proof-target.mjs +14 -28
  107. package/dist/drizzle/proof-target.mjs.map +1 -1
  108. package/dist/drizzle/session-drivers.mjs +97 -0
  109. package/dist/drizzle/session-drivers.mjs.map +1 -0
  110. package/dist/drizzle/session-model.d.mts +11 -22
  111. package/dist/drizzle/sqlite-do-database.d.mts +3 -3
  112. package/dist/drizzle/sqlite-do-database.mjs +6 -1
  113. package/dist/drizzle/sqlite-do-database.mjs.map +1 -1
  114. package/dist/drizzle/sqlite-identity.mjs +3 -5
  115. package/dist/drizzle/sqlite-identity.mjs.map +1 -1
  116. package/dist/drizzle/step-up-model.d.mts +2 -5
  117. package/dist/drizzle/storage-validation.mjs +2 -1
  118. package/dist/drizzle/storage-validation.mjs.map +1 -1
  119. package/dist/drizzle/totp-model.d.mts +7 -74
  120. package/dist/drizzle/totp-model.mjs +1 -5
  121. package/dist/drizzle/totp-model.mjs.map +1 -1
  122. package/dist/drizzle/totp-target.mjs +39 -75
  123. package/dist/drizzle/totp-target.mjs.map +1 -1
  124. package/dist/drizzle/transaction-handle.mjs +13 -0
  125. package/dist/drizzle/transaction-handle.mjs.map +1 -0
  126. package/dist/drizzle/transaction-mysql.mjs +43 -12
  127. package/dist/drizzle/transaction-mysql.mjs.map +1 -1
  128. package/dist/index.d.mts +17 -22
  129. package/dist/index.mjs +10 -16
  130. package/dist/internal/drizzle-postgres.mjs +4 -6
  131. package/dist/internal/drizzle-postgres.mjs.map +1 -1
  132. package/dist/internal/drizzle-sqlite.mjs +4 -6
  133. package/dist/internal/drizzle-sqlite.mjs.map +1 -1
  134. package/package.json +1 -1
  135. package/src/D1.ts +77 -74
  136. package/src/Libsql.ts +65 -105
  137. package/src/Mysql2.ts +52 -87
  138. package/src/Pglite.ts +74 -81
  139. package/src/Postgres.ts +74 -81
  140. package/src/SqliteBun.ts +65 -113
  141. package/src/SqliteDo.ts +58 -106
  142. package/src/SqliteNode.ts +65 -113
  143. package/src/SqliteWasm.ts +65 -113
  144. package/src/drizzle/d1-identity.ts +2 -2
  145. package/src/drizzle/driver-types.ts +26 -0
  146. package/src/drizzle/email-drivers.ts +320 -0
  147. package/src/drizzle/email-model.ts +24 -78
  148. package/src/drizzle/email-target.ts +118 -211
  149. package/src/drizzle/model.ts +0 -2
  150. package/src/drizzle/mysql-identity.ts +4 -24
  151. package/src/drizzle/native-clock.ts +21 -0
  152. package/src/drizzle/native-database.ts +59 -18
  153. package/src/drizzle/native-sql-table.ts +104 -87
  154. package/src/drizzle/native-target.ts +120 -0
  155. package/src/drizzle/oauth-connected-drivers.ts +24 -233
  156. package/src/drizzle/oauth-connected-model.ts +3 -93
  157. package/src/drizzle/oauth-connected-reference.ts +16 -25
  158. package/src/drizzle/oauth-drivers.ts +58 -99
  159. package/src/drizzle/oauth-model.ts +27 -132
  160. package/src/drizzle/oauth-target.ts +250 -33
  161. package/src/drizzle/passkey/target.ts +205 -0
  162. package/src/drizzle/passkey/write-target.ts +91 -0
  163. package/src/drizzle/passkey-drivers.ts +35 -133
  164. package/src/drizzle/passkey-model.ts +3 -81
  165. package/src/drizzle/passkey-registration-ceremony-model.ts +5 -25
  166. package/src/drizzle/passkey-write-drivers.ts +32 -102
  167. package/src/drizzle/passkey-write-model.ts +10 -44
  168. package/src/drizzle/password-drivers.ts +286 -0
  169. package/src/drizzle/password-model.ts +10 -44
  170. package/src/drizzle/password-target.ts +85 -239
  171. package/src/drizzle/pg-identity.ts +4 -19
  172. package/src/drizzle/phone-drivers.ts +142 -0
  173. package/src/drizzle/phone-model.ts +22 -162
  174. package/src/drizzle/phone-target.ts +51 -493
  175. package/src/drizzle/proof-drivers.ts +123 -0
  176. package/src/drizzle/proof-model.ts +12 -123
  177. package/src/drizzle/proof-target.ts +38 -102
  178. package/src/drizzle/session-drivers.ts +696 -0
  179. package/src/drizzle/session-model.ts +54 -118
  180. package/src/drizzle/sqlite-do-database.ts +8 -0
  181. package/src/drizzle/sqlite-identity.ts +4 -22
  182. package/src/drizzle/step-up-model.ts +13 -37
  183. package/src/drizzle/storage-validation.ts +2 -1
  184. package/src/drizzle/totp-model.ts +20 -77
  185. package/src/drizzle/totp-target.ts +121 -261
  186. package/src/drizzle/transaction-handle.ts +41 -0
  187. package/src/drizzle/transaction-mysql.ts +90 -25
  188. package/src/index.ts +7 -122
  189. package/src/internal/drizzle-postgres.ts +4 -7
  190. package/src/internal/drizzle-sqlite.ts +4 -7
  191. package/dist/drizzle/crypto.mjs +0 -11
  192. package/dist/drizzle/crypto.mjs.map +0 -1
  193. package/dist/drizzle/d1-emails.d.mts +0 -62
  194. package/dist/drizzle/d1-emails.mjs +0 -626
  195. package/dist/drizzle/d1-emails.mjs.map +0 -1
  196. package/dist/drizzle/d1-generated-statement.mjs +0 -79
  197. package/dist/drizzle/d1-generated-statement.mjs.map +0 -1
  198. package/dist/drizzle/d1-oauth.d.mts +0 -331
  199. package/dist/drizzle/d1-oauth.mjs +0 -79
  200. package/dist/drizzle/d1-oauth.mjs.map +0 -1
  201. package/dist/drizzle/d1-passkey.d.mts +0 -37
  202. package/dist/drizzle/d1-passkey.mjs +0 -98
  203. package/dist/drizzle/d1-passkey.mjs.map +0 -1
  204. package/dist/drizzle/d1-password-prepared.d.mts +0 -25
  205. package/dist/drizzle/d1-password-prepared.mjs +0 -473
  206. package/dist/drizzle/d1-password-prepared.mjs.map +0 -1
  207. package/dist/drizzle/d1-passwords.d.mts +0 -70
  208. package/dist/drizzle/d1-passwords.mjs +0 -808
  209. package/dist/drizzle/d1-passwords.mjs.map +0 -1
  210. package/dist/drizzle/d1-phone.d.mts +0 -23
  211. package/dist/drizzle/d1-phone.mjs +0 -33
  212. package/dist/drizzle/d1-phone.mjs.map +0 -1
  213. package/dist/drizzle/d1-planning.d.mts +0 -11
  214. package/dist/drizzle/d1-planning.mjs +0 -43
  215. package/dist/drizzle/d1-planning.mjs.map +0 -1
  216. package/dist/drizzle/d1-proofs.d.mts +0 -80
  217. package/dist/drizzle/d1-proofs.mjs +0 -842
  218. package/dist/drizzle/d1-proofs.mjs.map +0 -1
  219. package/dist/drizzle/d1-sessions.d.mts +0 -68
  220. package/dist/drizzle/d1-sessions.mjs +0 -987
  221. package/dist/drizzle/d1-sessions.mjs.map +0 -1
  222. package/dist/drizzle/d1-totp.d.mts +0 -23
  223. package/dist/drizzle/d1-totp.mjs +0 -30
  224. package/dist/drizzle/d1-totp.mjs.map +0 -1
  225. package/dist/drizzle/email-registration.d.mts +0 -33
  226. package/dist/drizzle/email-registration.mjs +0 -281
  227. package/dist/drizzle/email-registration.mjs.map +0 -1
  228. package/dist/drizzle/email-sql.d.mts +0 -1
  229. package/dist/drizzle/email-sql.mjs +0 -9
  230. package/dist/drizzle/email-sql.mjs.map +0 -1
  231. package/dist/drizzle/mysql-emails.d.mts +0 -71
  232. package/dist/drizzle/mysql-emails.mjs +0 -43
  233. package/dist/drizzle/mysql-emails.mjs.map +0 -1
  234. package/dist/drizzle/mysql-password-prepared.d.mts +0 -30
  235. package/dist/drizzle/mysql-password-prepared.mjs +0 -21
  236. package/dist/drizzle/mysql-password-prepared.mjs.map +0 -1
  237. package/dist/drizzle/mysql-passwords.d.mts +0 -71
  238. package/dist/drizzle/mysql-passwords.mjs +0 -43
  239. package/dist/drizzle/mysql-passwords.mjs.map +0 -1
  240. package/dist/drizzle/mysql-proofs.d.mts +0 -75
  241. package/dist/drizzle/mysql-proofs.mjs +0 -28
  242. package/dist/drizzle/mysql-proofs.mjs.map +0 -1
  243. package/dist/drizzle/mysql-sessions.d.mts +0 -92
  244. package/dist/drizzle/mysql-sessions.mjs +0 -58
  245. package/dist/drizzle/mysql-sessions.mjs.map +0 -1
  246. package/dist/drizzle/oauth-connected-model.mjs.map +0 -1
  247. package/dist/drizzle/oauth-connected-target.d.mts +0 -6
  248. package/dist/drizzle/oauth-connected-target.mjs +0 -12
  249. package/dist/drizzle/oauth-connected-target.mjs.map +0 -1
  250. package/dist/drizzle/oauth-kernel.mjs +0 -11
  251. package/dist/drizzle/oauth-kernel.mjs.map +0 -1
  252. package/dist/drizzle/oauth-mysql.mjs +0 -8
  253. package/dist/drizzle/oauth-mysql.mjs.map +0 -1
  254. package/dist/drizzle/passkey-kernel.mjs +0 -8
  255. package/dist/drizzle/passkey-kernel.mjs.map +0 -1
  256. package/dist/drizzle/passkey-model.mjs.map +0 -1
  257. package/dist/drizzle/passkey-registration-ceremony-model.mjs +0 -2
  258. package/dist/drizzle/passkey-state.mjs +0 -7
  259. package/dist/drizzle/passkey-state.mjs.map +0 -1
  260. package/dist/drizzle/passkey-target.d.mts +0 -2
  261. package/dist/drizzle/passkey-target.mjs +0 -7
  262. package/dist/drizzle/passkey-target.mjs.map +0 -1
  263. package/dist/drizzle/passkey-write-target.d.mts +0 -5
  264. package/dist/drizzle/passkey-write-target.mjs +0 -7
  265. package/dist/drizzle/passkey-write-target.mjs.map +0 -1
  266. package/dist/drizzle/password-prepared-model.d.mts +0 -92
  267. package/dist/drizzle/password-prepared-model.mjs +0 -11
  268. package/dist/drizzle/password-prepared-model.mjs.map +0 -1
  269. package/dist/drizzle/password-prepared-sql.mjs +0 -395
  270. package/dist/drizzle/password-prepared-sql.mjs.map +0 -1
  271. package/dist/drizzle/password-prepared-state.mjs +0 -104
  272. package/dist/drizzle/password-prepared-state.mjs.map +0 -1
  273. package/dist/drizzle/password-prepared-target.d.mts +0 -13
  274. package/dist/drizzle/password-prepared-target.mjs +0 -62
  275. package/dist/drizzle/password-prepared-target.mjs.map +0 -1
  276. package/dist/drizzle/password-registration.d.mts +0 -7
  277. package/dist/drizzle/password-registration.mjs +0 -137
  278. package/dist/drizzle/password-registration.mjs.map +0 -1
  279. package/dist/drizzle/password-sql.d.mts +0 -1
  280. package/dist/drizzle/password-sql.mjs +0 -10
  281. package/dist/drizzle/password-sql.mjs.map +0 -1
  282. package/dist/drizzle/pg-emails.d.mts +0 -72
  283. package/dist/drizzle/pg-emails.mjs +0 -43
  284. package/dist/drizzle/pg-emails.mjs.map +0 -1
  285. package/dist/drizzle/pg-password-prepared.d.mts +0 -31
  286. package/dist/drizzle/pg-password-prepared.mjs +0 -21
  287. package/dist/drizzle/pg-password-prepared.mjs.map +0 -1
  288. package/dist/drizzle/pg-passwords.d.mts +0 -72
  289. package/dist/drizzle/pg-passwords.mjs +0 -43
  290. package/dist/drizzle/pg-passwords.mjs.map +0 -1
  291. package/dist/drizzle/pg-proofs.d.mts +0 -76
  292. package/dist/drizzle/pg-proofs.mjs +0 -27
  293. package/dist/drizzle/pg-proofs.mjs.map +0 -1
  294. package/dist/drizzle/pg-sessions.d.mts +0 -93
  295. package/dist/drizzle/pg-sessions.mjs +0 -58
  296. package/dist/drizzle/pg-sessions.mjs.map +0 -1
  297. package/dist/drizzle/phone-state.mjs +0 -14
  298. package/dist/drizzle/phone-state.mjs.map +0 -1
  299. package/dist/drizzle/phone-target.d.mts +0 -15
  300. package/dist/drizzle/proof-sql.d.mts +0 -1
  301. package/dist/drizzle/proof-sql.mjs +0 -8
  302. package/dist/drizzle/proof-sql.mjs.map +0 -1
  303. package/dist/drizzle/query-operations.mjs +0 -31
  304. package/dist/drizzle/query-operations.mjs.map +0 -1
  305. package/dist/drizzle/session-sql.d.mts +0 -1
  306. package/dist/drizzle/session-sql.mjs +0 -9
  307. package/dist/drizzle/session-sql.mjs.map +0 -1
  308. package/dist/drizzle/session-target.d.mts +0 -30
  309. package/dist/drizzle/session-target.mjs +0 -49
  310. package/dist/drizzle/session-target.mjs.map +0 -1
  311. package/dist/drizzle/sqlite-emails.mjs +0 -50
  312. package/dist/drizzle/sqlite-emails.mjs.map +0 -1
  313. package/dist/drizzle/sqlite-password-prepared.mjs +0 -26
  314. package/dist/drizzle/sqlite-password-prepared.mjs.map +0 -1
  315. package/dist/drizzle/sqlite-passwords.mjs +0 -54
  316. package/dist/drizzle/sqlite-passwords.mjs.map +0 -1
  317. package/dist/drizzle/sqlite-proofs.mjs +0 -34
  318. package/dist/drizzle/sqlite-proofs.mjs.map +0 -1
  319. package/dist/drizzle/sqlite-sessions.mjs +0 -79
  320. package/dist/drizzle/sqlite-sessions.mjs.map +0 -1
  321. package/dist/drizzle/standalone-guard.d.mts +0 -2
  322. package/dist/drizzle/standalone-guard.mjs +0 -21
  323. package/dist/drizzle/standalone-guard.mjs.map +0 -1
  324. package/dist/drizzle/totp-state.d.mts +0 -37
  325. package/dist/drizzle/totp-state.mjs +0 -287
  326. package/dist/drizzle/totp-state.mjs.map +0 -1
  327. package/dist/drizzle/totp-target.d.mts +0 -15
  328. package/dist/drizzle/transaction-execution.d.mts +0 -2
  329. package/dist/drizzle/transaction-execution.mjs +0 -11
  330. package/dist/drizzle/transaction-execution.mjs.map +0 -1
  331. package/dist/drizzle/transaction-owner.d.mts +0 -1
  332. package/dist/drizzle/transaction-owner.mjs +0 -8
  333. package/dist/drizzle/transaction-owner.mjs.map +0 -1
  334. package/src/drizzle/crypto.ts +0 -14
  335. package/src/drizzle/d1-emails.ts +0 -1945
  336. package/src/drizzle/d1-generated-statement.ts +0 -129
  337. package/src/drizzle/d1-oauth.ts +0 -360
  338. package/src/drizzle/d1-passkey.ts +0 -383
  339. package/src/drizzle/d1-password-prepared.ts +0 -1266
  340. package/src/drizzle/d1-passwords.ts +0 -2061
  341. package/src/drizzle/d1-phone.ts +0 -103
  342. package/src/drizzle/d1-planning.ts +0 -104
  343. package/src/drizzle/d1-proofs.ts +0 -2354
  344. package/src/drizzle/d1-sessions.ts +0 -2940
  345. package/src/drizzle/d1-totp.ts +0 -88
  346. package/src/drizzle/email-registration.ts +0 -850
  347. package/src/drizzle/email-sql.ts +0 -25
  348. package/src/drizzle/mysql-emails.ts +0 -343
  349. package/src/drizzle/mysql-password-prepared.ts +0 -198
  350. package/src/drizzle/mysql-passwords.ts +0 -343
  351. package/src/drizzle/mysql-proofs.ts +0 -196
  352. package/src/drizzle/mysql-sessions.ts +0 -780
  353. package/src/drizzle/oauth-connected-target.ts +0 -21
  354. package/src/drizzle/oauth-kernel.ts +0 -10
  355. package/src/drizzle/oauth-mysql.ts +0 -10
  356. package/src/drizzle/passkey-kernel.ts +0 -4
  357. package/src/drizzle/passkey-state.ts +0 -3
  358. package/src/drizzle/passkey-target.ts +0 -23
  359. package/src/drizzle/passkey-write-target.ts +0 -9
  360. package/src/drizzle/password-prepared-model.ts +0 -241
  361. package/src/drizzle/password-prepared-sql.ts +0 -1202
  362. package/src/drizzle/password-prepared-state.ts +0 -231
  363. package/src/drizzle/password-prepared-target.ts +0 -169
  364. package/src/drizzle/password-registration.ts +0 -369
  365. package/src/drizzle/password-sql.ts +0 -16
  366. package/src/drizzle/pg-emails.ts +0 -343
  367. package/src/drizzle/pg-password-prepared.ts +0 -199
  368. package/src/drizzle/pg-passwords.ts +0 -342
  369. package/src/drizzle/pg-proofs.ts +0 -206
  370. package/src/drizzle/pg-sessions.ts +0 -789
  371. package/src/drizzle/phone-state.ts +0 -21
  372. package/src/drizzle/proof-sql.ts +0 -10
  373. package/src/drizzle/query-operations.ts +0 -49
  374. package/src/drizzle/session-sql.ts +0 -15
  375. package/src/drizzle/session-target.ts +0 -337
  376. package/src/drizzle/sqlite-emails.ts +0 -393
  377. package/src/drizzle/sqlite-password-prepared.ts +0 -230
  378. package/src/drizzle/sqlite-passwords.ts +0 -497
  379. package/src/drizzle/sqlite-proofs.ts +0 -229
  380. package/src/drizzle/sqlite-sessions.ts +0 -1013
  381. package/src/drizzle/totp-state.ts +0 -525
  382. package/src/drizzle/transaction-execution.ts +0 -13
  383. package/src/drizzle/transaction-owner.ts +0 -11
@@ -1,1266 +0,0 @@
1
- /* oxlint-disable no-explicit-any -- driver exports preserve concrete consumer mappings. */
2
- import type { D1Client } from "@effect/sql-d1/D1Client";
3
- import { NativeDatabase } from "@yielded/auth-persistence/Adapter";
4
- import {
5
- coordinateCommit,
6
- CurrentCommitJournal,
7
- hasCommitScope,
8
- type CommitJournal,
9
- type PreparedCommit,
10
- LifecycleHooks,
11
- HookConfigurationError,
12
- } from "@yielded/auth/Hooks";
13
- import {
14
- PasswordRejected,
15
- PasswordUnavailable,
16
- PasswordPreparedVersion,
17
- decodePasswordPreparedReady,
18
- encodePasswordPreparedReady,
19
- snapshotPasswordPreparedReady,
20
- snapshotPasswordPreparedReservation,
21
- type PasswordPreparedReady,
22
- type PasswordPreparedReservation,
23
- type PasswordMutationDecision,
24
- type PreparePasswordCommit,
25
- type PasswordPreparedMutation,
26
- type PasswordPreparedPersistence,
27
- } from "@yielded/auth/Password";
28
- import { reportPersistenceFailure } from "@yielded/auth/Persistence";
29
- import { type ProofCompletionPlan, ProofUnavailable, ProofBinding } from "@yielded/auth/Proofs";
30
- import { eq, is, isNotNull, lte, or, SQL, sql, type AnyRelations, type Table } from "drizzle-orm";
31
- import type { EffectSQLiteD1Database } from "drizzle-orm/effect-d1";
32
- import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
33
- import { Cause, DateTime, Effect, Predicate, Redacted, Schema, Context } from "effect";
34
- import type { Statement } from "effect/sql/Statement";
35
-
36
- import { Database as DatabaseService } from "./d1-database";
37
- import { balancedD1And as and, compactD1GeneratedStatement } from "./d1-generated-statement";
38
- import { passwordD1Kernel as kernel } from "./d1-passwords";
39
- import { CurrentD1PlanningDatabase, makeD1Owner } from "./d1-planning";
40
- import { checkD1ProofCompletion, compileD1ProofCompletionPlan } from "./d1-proofs";
41
- import { D1BatchStatements } from "./D1BatchStatements";
42
- import { PersistenceMappingError, column, updateValues } from "./model";
43
- import { nativeDatabase } from "./native-database";
44
- import type {
45
- D1PasswordPreparedPersistenceMapping,
46
- D1PasswordPreparedProofMapping,
47
- } from "./password-prepared-model";
48
- import { passwordPreparedSqlKernel as shared } from "./password-prepared-sql";
49
- import {
50
- ContextInput,
51
- CompletionInput,
52
- encodeReservation,
53
- evidenceCurrent,
54
- identifierScope,
55
- reservationOf,
56
- sameRevision,
57
- snapshotMutation,
58
- snapshotReserve,
59
- unavailable,
60
- } from "./password-prepared-state";
61
- import { CurrentPasswordSql, type PasswordSqlDatabase } from "./password-sql";
62
- import { validateDrizzleStorage } from "./storage-validation";
63
- import type { SuppliedService } from "./SuppliedService";
64
-
65
- type PlanPrepare<Method extends (...args: any[]) => any, A> = (
66
- value: Parameters<Parameters<Method>[1]>[0],
67
- journal: CommitJournal,
68
- ) => PreparedCommit<A>;
69
-
70
- type Database = EffectSQLiteD1Database<AnyRelations> & { readonly $client: D1Client };
71
- type Mapping = D1PasswordPreparedPersistenceMapping<
72
- Table,
73
- Table,
74
- Table,
75
- Table,
76
- Table,
77
- Table,
78
- Table,
79
- unknown
80
- >;
81
- interface Planned<A> {
82
- readonly retryable?: (cause: unknown) => boolean;
83
- readonly receipt: PreparedCommit<A>;
84
- readonly statements: ReadonlyArray<Statement<any>>;
85
- readonly postconditions?: ReadonlyArray<Statement<any>>;
86
- readonly journalGuard?: PreparedCommit<void>;
87
- }
88
-
89
- const everyFailureMatches = (
90
- cause: Cause.Cause<unknown>,
91
- classify: ((cause: unknown) => boolean) | undefined,
92
- ): boolean =>
93
- classify !== undefined &&
94
- cause.reasons.length > 0 &&
95
- cause.reasons.every((reason) => Cause.isFailReason(reason) && classify(Cause.fail(reason.error)));
96
-
97
- const bindingJson = Schema.encodeSync(Schema.fromJsonString(ProofBinding));
98
-
99
- const authorityCondition = (mapping: Mapping, current: any, moduleId: string) => {
100
- const p = mapping.password,
101
- s = kernel.subjectColumns(p),
102
- i = kernel.identifierColumns(p),
103
- c = kernel.credentialColumns(p),
104
- ac = kernel.authorityColumns(p);
105
-
106
- const snapshot = current.snapshot,
107
- native = current.nativeSubjectId;
108
-
109
- const identifier =
110
- snapshot === undefined
111
- ? sql`true`
112
- : and(
113
- p.identifier.d1CurrentCondition({
114
- identifier: snapshot.identifier,
115
- nativeSubjectId: native,
116
- }),
117
- sql`exists(select 1 from ${p.identifier.table} where ${i.namespace} = ${sql.param(snapshot.identifier.namespace, i.namespace)} and ${i.value} = ${sql.param(snapshot.identifier.value, i.value)} and ${i.subjectId} = ${sql.param(native, i.subjectId)} and ${i.bindingRevision} = ${sql.param(snapshot.identifierBindingRevision, i.bindingRevision)} and ${Predicate.isNullish(current.identifier[p.identifier.verifiedAt]) ? sql`${i.verifiedAt} is null` : sql`${i.verifiedAt} = ${sql.param(current.identifier[p.identifier.verifiedAt], i.verifiedAt)}`})`,
118
- )!;
119
-
120
- return and(
121
- sql`exists(select 1 from ${p.subject.table} where ${s.id} = ${sql.param(native, s.id)} and ${s.status} = ${sql.param(p.subject.d1ActiveStatusValue, s.status)} and ${s.securityRevision} = ${sql.param(current.revision.securityRevision, s.securityRevision)})`,
122
- identifier,
123
- snapshot === undefined
124
- ? sql`not exists(select 1 from ${p.credential.table} where ${c.moduleId} = ${sql.param(moduleId, c.moduleId)} and ${c.subjectId} = ${sql.param(native, c.subjectId)})`
125
- : sql`exists(select 1 from ${p.credential.table} where ${c.moduleId} = ${sql.param(moduleId, c.moduleId)} and ${c.subjectId} = ${sql.param(native, c.subjectId)} and ${c.credentialId} = ${sql.param(snapshot.credentialId, c.credentialId)} and ${c.credentialRevision} = ${sql.param(snapshot.credentialRevision, c.credentialRevision)} and ${c.verifierVersion} = ${sql.param(snapshot.verifierVersion, c.verifierVersion)} and ${c.verifier} = ${sql.param(Redacted.value(snapshot.verifier), c.verifier)} and ${c.normalization} = ${sql.param(snapshot.normalization, c.normalization)})`,
126
- ...current.revision.credentials.map(
127
- (entry: any) =>
128
- sql`exists(select 1 from ${p.authorityCredential.table} where ${ac.subjectId} = ${sql.param(native, ac.subjectId)} and ${ac.credentialId} = ${sql.param(entry.credentialId, ac.credentialId)} and ${ac.revision} = ${sql.param(entry.revision, ac.revision)}${ac.status === undefined ? sql`` : sql` and ${ac.status} = ${sql.param(p.authorityCredential.d1ActiveStatusValue, ac.status)}`})`,
129
- ),
130
- )!;
131
- };
132
-
133
- const existsRow = (mapping: Mapping, row: any) =>
134
- sql`exists(select 1 from ${mapping.intent.table} where ${shared.rowCondition(mapping, row)})`;
135
-
136
- const terminalStatements = Effect.fn(function* (
137
- mapping: Mapping,
138
- row: any,
139
- state: "Consumed" | "Cancelled" | "Expired",
140
- marker: string,
141
- ) {
142
- const database = yield* CurrentD1PlanningDatabase;
143
- const t = mapping.intent;
144
-
145
- return [
146
- yield* kernel.statement(
147
- database
148
- .update(t.table)
149
- .set(t.encodeTerminal(state))
150
- .where(shared.rowCondition(mapping, row)),
151
- ),
152
- yield* kernel.assertion(
153
- existsRow(mapping, {
154
- ...row,
155
- [t.state]: t.states[state],
156
- [t.snapshot]: null,
157
- [t.digest]: null,
158
- }),
159
- marker,
160
- ),
161
- ];
162
- });
163
-
164
- const selectInsert = Effect.fn(function* (table: Table, values: object, condition: SQL) {
165
- const database = yield* CurrentD1PlanningDatabase;
166
-
167
- const selected = Object.fromEntries(
168
- Object.entries(values)
169
- .filter(([, value]) => value !== undefined)
170
- .map(([key, value]) => [
171
- key,
172
- (is(value, SQL) ? value : sql`${sql.param(value, column(table, key as never))}`).as(key),
173
- ]),
174
- );
175
-
176
- return database.insert(table as any).select(
177
- database
178
- .select(selected)
179
- .from(sql`(select 1)`)
180
- .where(condition),
181
- );
182
- });
183
-
184
- const makePreparedPlans = (mapping: Mapping, proofMapping?: any) => {
185
- const p = mapping.password,
186
- t = mapping.intent,
187
- c = shared.columns(mapping),
188
- config = { locking: false };
189
-
190
- const readRows = Effect.fn(function* (condition: SQL) {
191
- const database = yield* CurrentD1PlanningDatabase;
192
-
193
- return yield* database.select().from(t.table).where(condition).limit(2);
194
- });
195
-
196
- const run = <A, E, R>(plan: Effect.Effect<Planned<A>, E, R>) =>
197
- Effect.gen(function* () {
198
- const database = yield* CurrentD1PlanningDatabase;
199
-
200
- return yield* shared.valid(mapping)
201
- ? plan.pipe(
202
- Effect.flatMap((planned) =>
203
- Effect.try({
204
- try: () => ({
205
- ...planned,
206
- statements: planned.statements.map((statement) =>
207
- compactD1GeneratedStatement(database.$client, statement, unavailable),
208
- ),
209
- ...(planned.postconditions === undefined
210
- ? {}
211
- : {
212
- postconditions: planned.postconditions.map((statement) =>
213
- compactD1GeneratedStatement(database.$client, statement, unavailable),
214
- ),
215
- }),
216
- }),
217
- catch: (cause) =>
218
- Schema.is(PasswordUnavailable)(cause)
219
- ? cause
220
- : PersistenceMappingError.make({ operation: "mapping", cause }),
221
- }),
222
- ),
223
- )
224
- : Effect.fail(unavailable());
225
- });
226
-
227
- const current = (record: PasswordPreparedReservation | PasswordPreparedReady) =>
228
- shared.currentAuthority(mapping, config, record);
229
-
230
- const complete = <A>(
231
- uncaptured: PasswordPreparedMutation & { readonly completion?: ProofCompletionPlan },
232
- prepare: PreparePasswordCommit<PasswordMutationDecision, A>,
233
- ) =>
234
- Effect.gen(function* () {
235
- const input = yield* snapshotMutation(uncaptured);
236
-
237
- const completion =
238
- uncaptured.completion === undefined
239
- ? undefined
240
- : {
241
- prepare: uncaptured.completion.prepare,
242
- input: yield* Schema.encodeEffect(Schema.fromJsonString(CompletionInput))(
243
- uncaptured.completion.input,
244
- ).pipe(
245
- Effect.flatMap(Schema.decodeEffect(Schema.fromJsonString(CompletionInput))),
246
- Effect.mapError(unavailable),
247
- ),
248
- };
249
-
250
- if (
251
- (input.intent.action === "reset-password") !== (completion !== undefined) ||
252
- (completion !== undefined && proofMapping === undefined)
253
- )
254
- return yield* unavailable();
255
-
256
- const credentialRevision = yield* kernel.allocate(p.allocateRevision, p.allocateRevisionSync),
257
- verifierVersion = yield* kernel.allocate(p.allocateRevision, p.allocateRevisionSync),
258
- nextSecurityRevision = yield* kernel.allocateNextSecurityRevision(
259
- p,
260
- input.intent.revision.securityRevision,
261
- );
262
-
263
- if (
264
- nextSecurityRevision === input.intent.revision.securityRevision ||
265
- credentialRevision === input.intent.credential?.credentialRevision ||
266
- verifierVersion === input.intent.credential?.verifierVersion
267
- )
268
- return yield* unavailable();
269
-
270
- const credentialId =
271
- input.intent.action === "add-password"
272
- ? yield* kernel.allocate(p.allocateCredentialId, p.allocateCredentialIdSync)
273
- : undefined;
274
-
275
- return yield* run(
276
- Effect.gen(function* () {
277
- const journal = yield* CurrentCommitJournal;
278
-
279
- const authority = yield* current(input.intent),
280
- rows = yield* readRows(
281
- and(eq(c.moduleId, input.intent.moduleId), eq(c.intentId, input.intent.intentId))!,
282
- ),
283
- row = rows[0],
284
- now = yield* kernel.readEngineNowMillis(p);
285
-
286
- if (
287
- authority === undefined ||
288
- rows.length !== 1 ||
289
- !(yield* shared.recordMatches(
290
- mapping,
291
- row,
292
- input.intent,
293
- authority.nativeSubjectId,
294
- yield* encodePasswordPreparedReady(input.intent),
295
- )) ||
296
- !evidenceCurrent(input, authority.requirement, now)
297
- )
298
- return { receipt: prepare("rejected", journal), statements: [] };
299
- const marker = `effect-auth-password-prepared:complete:${input.intent.intentId}`;
300
-
301
- const requirements = [
302
- input.mutation.authorization.requirement,
303
- input.intent.capturedRequirement,
304
- input.capturedRequirement,
305
- authority.requirement,
306
- input.currentRequirement,
307
- ];
308
-
309
- const age = Math.min(...requirements.map((value) => value.maximumAgeMillis));
310
-
311
- const live = and(
312
- existsRow(mapping, row),
313
- authorityCondition(mapping, authority, input.intent.moduleId),
314
- sql`${p.d1.engineNowMillis} >= ${input.intent.issuedAtMillis} and ${p.d1.engineNowMillis} < ${input.intent.expiresAtMillis}`,
315
- ...requirements.map((requirement) =>
316
- kernel.assuranceCondition(p, input.mutation.authorization.evidence, requirement),
317
- ),
318
- ...(input.intent.baseEvidence?.proofs ?? []).map(
319
- (proof) =>
320
- sql`${p.d1.engineNowMillis} >= ${DateTime.toEpochMillis(proof.verifiedAt)} and ${p.d1.engineNowMillis} < ${DateTime.toEpochMillis(proof.verifiedAt) + age}`,
321
- ),
322
- )!;
323
-
324
- let mutation: ReadonlyArray<Statement<any>>;
325
- let passwordApplied: SQL;
326
- let mutationGuard: ((cause: unknown) => boolean) | undefined;
327
-
328
- if (input.intent.action === "add-password") {
329
- const compiled = yield* kernel.compileAddMutation(p, input.mutation, {
330
- credentialId: credentialId!,
331
- credentialRevision,
332
- verifierVersion,
333
- nextSecurityRevision,
334
- });
335
-
336
- if (compiled === undefined)
337
- return { receipt: prepare("rejected", journal), statements: [] };
338
- mutation = compiled.statements;
339
- mutationGuard = compiled.retryable;
340
- passwordApplied = compiled.appliedCondition;
341
- } else {
342
- const compiled = yield* kernel.compileReplacementMutation(
343
- p,
344
- input.mutation,
345
- input.intent.action,
346
- { credentialRevision, verifierVersion, nextSecurityRevision },
347
- );
348
-
349
- if (compiled === undefined)
350
- return { receipt: prepare("rejected", journal), statements: [] };
351
- passwordApplied = compiled.protectedMutation.appliedCondition;
352
- mutationGuard = (cause) => kernel.isGuardFailure(cause, compiled.marker);
353
- mutation = [
354
- ...compiled.protectedMutation.statements,
355
- yield* kernel.assertion(compiled.protectedMutation.appliedCondition, marker),
356
- ];
357
- }
358
-
359
- const terminal = {
360
- ...row,
361
- [t.state]: t.states.Consumed,
362
- [t.snapshot]: null,
363
- [t.digest]: null,
364
- };
365
-
366
- const protectedMutation = {
367
- statements: [
368
- yield* kernel.assertion(live, marker),
369
- ...mutation,
370
- ...(yield* terminalStatements(mapping, row, "Consumed", marker)),
371
- ],
372
- appliedCondition: and(
373
- passwordApplied,
374
- existsRow(mapping, terminal),
375
- sql`${p.d1.engineNowMillis} >= ${input.intent.issuedAtMillis} and ${p.d1.engineNowMillis} < ${input.intent.expiresAtMillis}`,
376
- ...(input.intent.baseEvidence?.proofs ?? []).map(
377
- (proof) =>
378
- sql`${p.d1.engineNowMillis} >= ${DateTime.toEpochMillis(proof.verifiedAt)} and ${p.d1.engineNowMillis} < ${DateTime.toEpochMillis(proof.verifiedAt) + age}`,
379
- ),
380
- ...requirements.map((requirement) =>
381
- kernel.assuranceCondition(p, input.mutation.authorization.evidence, requirement),
382
- ),
383
- )!,
384
- };
385
-
386
- if (completion !== undefined) {
387
- if (
388
- input.intent.reset === undefined ||
389
- completion.input.continuationId !== input.intent.reset.continuationId ||
390
- bindingJson(completion.input.binding) !== bindingJson(input.intent.reset.binding) ||
391
- !kernel.completionMatchesPassword({ ...input.mutation, completion })
392
- )
393
- return { receipt: prepare("rejected", journal), statements: [] };
394
- let receipt: PreparedCommit<A> | undefined;
395
-
396
- const compiled = yield* compileD1ProofCompletionPlan(
397
- proofMapping,
398
- completion,
399
- protectedMutation,
400
- (decision) => {
401
- receipt = prepare(decision === "completed" ? "changed" : "rejected", journal);
402
-
403
- return decision;
404
- },
405
- );
406
-
407
- return {
408
- retryable: (cause: unknown) =>
409
- kernel.isGuardFailure(cause, marker) ||
410
- mutationGuard?.(cause) === true ||
411
- (completion !== undefined &&
412
- (kernel.isGuardFailure(
413
- cause,
414
- `effect-auth-proof-guard:complete:${completion.input.continuationId}`,
415
- ) ||
416
- kernel.isGuardFailure(
417
- cause,
418
- `effect-auth-proof-guard:protected:${completion.input.continuationId}`,
419
- ))),
420
- receipt: receipt ?? prepare("rejected", journal),
421
- statements: compiled.statements,
422
- ...(compiled.postconditions === undefined
423
- ? {}
424
- : { postconditions: compiled.postconditions }),
425
- };
426
- }
427
-
428
- const postconditions = [
429
- yield* kernel.assertion(protectedMutation.appliedCondition, marker),
430
- ];
431
-
432
- return {
433
- retryable: (cause: unknown) =>
434
- kernel.isGuardFailure(cause, marker) || mutationGuard?.(cause) === true,
435
- receipt: prepare("changed", journal),
436
- statements: [...protectedMutation.statements, ...postconditions],
437
- postconditions,
438
- };
439
- }),
440
- );
441
- });
442
-
443
- const services = {
444
- reserve: <A>(
445
- uncaptured: Parameters<PasswordPreparedPersistence["reserve"]>[0],
446
- prepare: PlanPrepare<PasswordPreparedPersistence["reserve"], A>,
447
- ) =>
448
- Effect.gen(function* () {
449
- const database = yield* CurrentD1PlanningDatabase;
450
-
451
- const input = yield* snapshotReserve(uncaptured);
452
-
453
- if (
454
- (input.action === "reset-password") !==
455
- (input.reset !== undefined && input.completion !== undefined) ||
456
- (input.action === "reset-password" && proofMapping === undefined) ||
457
- input.generation !== input.policy.generation ||
458
- input.policy.retentionMillis <
459
- Math.max(
460
- input.policy.preparationLifetimeMillis + input.policy.lifetimeMillis,
461
- input.policy.admission.action.windowMillis,
462
- input.policy.admission.subject.windowMillis,
463
- input.policy.admission.identifier.windowMillis,
464
- ) ||
465
- ((input.invalidation.existingSessions === "immediate" ||
466
- input.invalidation.existingSessions === "cache-expiry") &&
467
- p.sessionInvalidation !== "same-authority-immediate")
468
- )
469
- return yield* unavailable();
470
-
471
- const version = PasswordPreparedVersion.make(
472
- yield* kernel.allocate(mapping.allocateVersion, mapping.allocateVersionSync),
473
- );
474
-
475
- return yield* run(
476
- Effect.gen(function* () {
477
- const journal = yield* CurrentCommitJournal;
478
-
479
- const authority = yield* shared.captureAuthority(mapping, config, input);
480
-
481
- if (authority === undefined) return yield* unavailable();
482
- let proofCondition: SQL = sql`true`;
483
-
484
- if (input.reset !== undefined) {
485
- if (
486
- input.completion === undefined ||
487
- input.completion.moduleId !== `${input.moduleId}/reset` ||
488
- input.completion.purpose !== "password-reset" ||
489
- input.reset.continuationId !== input.completion.continuationId ||
490
- bindingJson(input.reset.binding) !== bindingJson(input.completion.binding) ||
491
- input.reset.binding._tag !== "Subject" ||
492
- !sameRevision(input.reset.binding.revision, authority.revision) ||
493
- authority.snapshot?.identifierVerifiedAtMillis === undefined
494
- )
495
- return yield* unavailable();
496
- const inspected = yield* checkD1ProofCompletion(proofMapping, input.completion);
497
-
498
- if (!inspected.accepted) return yield* unavailable();
499
- proofCondition = inspected.condition;
500
- }
501
-
502
- const ownerCurrent = and(
503
- authorityCondition(mapping, authority, input.moduleId),
504
- proofCondition,
505
- )!;
506
-
507
- const marker = `effect-auth-password-prepared:reserve:${input.intentId}`;
508
-
509
- const existing = yield* readRows(
510
- and(eq(c.moduleId, input.moduleId), eq(c.commandId, input.commandId))!,
511
- );
512
-
513
- if (existing.length)
514
- return {
515
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
516
- receipt: prepare({ _tag: "Existing" }, journal),
517
- statements: [
518
- yield* kernel.assertion(
519
- and(ownerCurrent, existsRow(mapping, existing[0]))!,
520
- marker,
521
- ),
522
- ],
523
- };
524
-
525
- const now = yield* kernel.readEngineNowMillis(p),
526
- scope = identifierScope({
527
- ...(authority.snapshot === undefined ? {} : { credential: authority.snapshot }),
528
- revision: authority.revision,
529
- });
530
-
531
- const reservation = yield* snapshotPasswordPreparedReservation({
532
- _tag: "Preparing",
533
- moduleId: input.moduleId,
534
- generation: input.generation,
535
- intentId: input.intentId,
536
- version,
537
- commandId: input.commandId,
538
- action: input.action,
539
- revision: authority.revision,
540
- ...(authority.snapshot === undefined ? {} : { credential: authority.snapshot }),
541
- capturedRequirement: authority.requirement,
542
- ...(input.reset === undefined ? {} : { reset: input.reset }),
543
- invalidation: input.invalidation,
544
- createdAtMillis: now,
545
- preparationExpiresAtMillis: now + input.policy.preparationLifetimeMillis,
546
- retainUntilMillis: now + input.policy.retentionMillis,
547
- });
548
-
549
- const snapshot = yield* encodeReservation(reservation),
550
- window = Math.max(
551
- input.policy.admission.action.windowMillis,
552
- input.policy.admission.identifier.windowMillis,
553
- input.policy.admission.subject.windowMillis,
554
- );
555
-
556
- const a = mapping.admission,
557
- am = column(a.table, a.moduleId),
558
- ai = column(a.table, a.intentId),
559
- at = column(a.table, a.admittedAt),
560
- ar = column(a.table, a.admissionRetainUntil);
561
-
562
- const stamp = sql`(select ${at} from ${a.table} where ${am} = ${sql.param(input.moduleId, am)})`,
563
- retention = sql`(select ${ar} from ${a.table} where ${am} = ${sql.param(input.moduleId, am)})`;
564
-
565
- const active = sql`(select count(*) from ${t.table} where ${c.moduleId} = ${sql.param(input.moduleId, c.moduleId)} and ${c.subjectId} = ${sql.param(authority.nativeSubjectId, c.subjectId)} and ((${c.state} = ${sql.param(t.states.Preparing, c.state)} and ${c.preparationExpiresAt} > ${p.d1.engineNow}) or (${c.state} = ${sql.param(t.states.Ready, c.state)} and ${c.expiresAt} > ${p.d1.engineNow}))) < ${input.policy.maximumPendingPerSubject}`;
566
-
567
- const budgets = [
568
- [eq(c.action, input.action), input.policy.admission.action],
569
- [eq(c.identifierScope, scope), input.policy.admission.identifier],
570
- [eq(c.subjectId, authority.nativeSubjectId), input.policy.admission.subject],
571
- ] as const;
572
-
573
- const admissionDecision = and(
574
- ownerCurrent,
575
- active,
576
- ...budgets.map(
577
- ([condition, budget]) =>
578
- sql`(select count(*) from ${t.table} where ${c.moduleId} = ${sql.param(input.moduleId, c.moduleId)} and ${condition} and ${c.admittedAt} > ${p.d1.engineInstantMinus(budget.windowMillis)}) < ${budget.limit}`,
579
- ),
580
- sql`not exists(select 1 from ${t.table} where ${c.moduleId} = ${sql.param(input.moduleId, c.moduleId)} and ${c.commandId} = ${sql.param(input.commandId, c.commandId)})`,
581
- sql`${p.d1.engineNowMillis} >= ${now} and ${p.d1.engineNowMillis} < ${reservation.preparationExpiresAtMillis}`,
582
- )!;
583
-
584
- const admittedMillis = mapping.admissionClock.toMillis(stamp),
585
- retainedMillis = mapping.admissionClock.toMillis(retention);
586
-
587
- const clockGuard = and(
588
- sql`exists(select 1 from ${a.table} where ${am} = ${sql.param(input.moduleId, am)} and ${ai} = ${sql.param(input.intentId, ai)})`,
589
- sql`${admittedMillis} >= ${now} and ${admittedMillis} <= ${p.d1.engineNowMillis}`,
590
- sql`${retainedMillis} = ${admittedMillis} + ${window}`,
591
- )!;
592
-
593
- const guard = and(sql`changes() = 1`, clockGuard)!;
594
-
595
- const values = {
596
- ...t.encodeInsert({
597
- reservation,
598
- nativeSubjectId: authority.nativeSubjectId,
599
- identifierScope: scope,
600
- snapshot,
601
- admittedAtMillis: now,
602
- admissionRetainUntilMillis: now + window,
603
- }),
604
- [t.admittedAt]: stamp,
605
- [t.admissionRetainUntil]: retention,
606
- };
607
-
608
- const expected = {
609
- [t.moduleId]: input.moduleId,
610
- [t.intentId]: input.intentId,
611
- [t.commandId]: input.commandId,
612
- [t.subjectId]: authority.nativeSubjectId,
613
- [t.action]: input.action,
614
- [t.generation]: input.generation,
615
- [t.version]: version,
616
- [t.state]: t.states.Preparing,
617
- [t.digest]: null,
618
- [t.snapshot]: snapshot,
619
- [t.identifierScope]: scope,
620
- [t.createdAt]: p.encodeInstant(now),
621
- [t.preparationExpiresAt]: p.encodeInstant(reservation.preparationExpiresAtMillis),
622
- [t.expiresAt]: null,
623
- [t.retainUntil]: p.encodeInstant(reservation.retainUntilMillis),
624
- [t.admittedAt]: stamp,
625
- [t.admissionRetainUntil]: retention,
626
- };
627
-
628
- return {
629
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
630
- receipt: prepare({ _tag: "Reserved", reservation }, journal),
631
- statements: [
632
- yield* kernel.statement(
633
- database
634
- .insert(a.table)
635
- .values(a.encodeInsert(input.moduleId))
636
- .onConflictDoNothing(),
637
- ),
638
- yield* kernel.statement(
639
- database
640
- .update(a.table)
641
- .set(
642
- updateValues([
643
- [a.intentId, input.intentId],
644
- [a.admittedAt, p.d1.engineNow],
645
- [a.admissionRetainUntil, p.d1.engineInstantPlus(window)],
646
- ]),
647
- )
648
- .where(and(eq(am, input.moduleId), admissionDecision)),
649
- ),
650
- yield* kernel.statement(yield* selectInsert(t.table, values, guard)),
651
- yield* kernel.assertion(existsRow(mapping, expected), marker),
652
- yield* kernel.assertion(
653
- and(
654
- ownerCurrent,
655
- clockGuard,
656
- sql`${p.d1.engineNowMillis} < ${reservation.preparationExpiresAtMillis}`,
657
- sql`(select count(*) from ${t.table} where ${c.moduleId} = ${sql.param(input.moduleId, c.moduleId)} and ${c.subjectId} = ${sql.param(authority.nativeSubjectId, c.subjectId)} and ((${c.state} = ${sql.param(t.states.Preparing, c.state)} and ${c.preparationExpiresAt} > ${p.d1.engineNow}) or (${c.state} = ${sql.param(t.states.Ready, c.state)} and ${c.expiresAt} > ${p.d1.engineNow}))) <= ${input.policy.maximumPendingPerSubject}`,
658
- ...budgets.map(
659
- ([condition, budget]) =>
660
- sql`(select count(*) from ${t.table} where ${c.moduleId} = ${sql.param(input.moduleId, c.moduleId)} and ${condition} and ${c.admittedAt} > ${p.d1.engineInstantMinus(budget.windowMillis)}) <= ${budget.limit}`,
661
- ),
662
- )!,
663
- marker,
664
- ),
665
- ],
666
- };
667
- }),
668
- );
669
- }),
670
- publishReady: <A>(
671
- uncaptured: Parameters<PasswordPreparedPersistence["publishReady"]>[0],
672
- prepare: PlanPrepare<PasswordPreparedPersistence["publishReady"], A>,
673
- ) =>
674
- Effect.gen(function* () {
675
- const database = yield* CurrentD1PlanningDatabase;
676
-
677
- const reservation = yield* snapshotPasswordPreparedReservation(uncaptured.reservation),
678
- ready = yield* snapshotPasswordPreparedReady(uncaptured.ready),
679
- snapshot = yield* encodeReservation(reservation),
680
- readySnapshot = yield* encodePasswordPreparedReady(ready);
681
-
682
- if ((yield* encodeReservation(reservationOf(ready))) !== snapshot)
683
- return yield* unavailable();
684
-
685
- return yield* run(
686
- Effect.gen(function* () {
687
- const journal = yield* CurrentCommitJournal;
688
-
689
- const authority = yield* current(reservation),
690
- rows = yield* readRows(
691
- and(eq(c.moduleId, reservation.moduleId), eq(c.intentId, reservation.intentId))!,
692
- ),
693
- row = rows[0];
694
-
695
- if (
696
- authority === undefined ||
697
- rows.length !== 1 ||
698
- !(yield* shared.recordMatches(
699
- mapping,
700
- row,
701
- reservation,
702
- authority.nativeSubjectId,
703
- snapshot,
704
- ))
705
- )
706
- return { receipt: prepare("rejected", journal), statements: [] };
707
-
708
- const marker = `effect-auth-password-prepared:ready:${ready.intentId}`,
709
- live = and(
710
- authorityCondition(mapping, authority, ready.moduleId),
711
- sql`${p.d1.engineNowMillis} >= ${ready.issuedAtMillis} and ${p.d1.engineNowMillis} < ${reservation.preparationExpiresAtMillis} and ${p.d1.engineNowMillis} < ${ready.expiresAtMillis}`,
712
- )!;
713
-
714
- const expected = {
715
- ...row,
716
- [t.state]: t.states.Ready,
717
- [t.snapshot]: readySnapshot,
718
- [t.digest]: ready.digest,
719
- [t.expiresAt]: p.encodeInstant(ready.expiresAtMillis),
720
- };
721
-
722
- return {
723
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
724
- receipt: prepare("published", journal),
725
- statements: [
726
- yield* kernel.assertion(and(live, existsRow(mapping, row))!, marker),
727
- yield* kernel.statement(
728
- database
729
- .update(t.table)
730
- .set(t.encodeReady({ ready, snapshot: readySnapshot }))
731
- .where(shared.rowCondition(mapping, row)),
732
- ),
733
- yield* kernel.assertion(and(live, existsRow(mapping, expected))!, marker),
734
- ],
735
- };
736
- }),
737
- );
738
- }),
739
- context: (uncaptured: Parameters<PasswordPreparedPersistence["context"]>[0]) =>
740
- Effect.gen(function* () {
741
- const database = yield* CurrentD1PlanningDatabase;
742
-
743
- if (yield* hasCommitScope) return yield* unavailable();
744
-
745
- const input = yield* Schema.decodeEffect(ContextInput)({ ...uncaptured }).pipe(
746
- Effect.mapError(unavailable),
747
- ),
748
- rows = yield* readRows(
749
- and(
750
- eq(c.moduleId, input.moduleId),
751
- eq(c.generation, input.generation),
752
- eq(c.digest, input.digest),
753
- eq(c.state, t.states.Ready),
754
- )!,
755
- );
756
-
757
- if (rows.length !== 1) return yield* PasswordRejected.make({});
758
-
759
- const record = yield* decodePasswordPreparedReady(rows[0][t.snapshot]),
760
- authority = yield* current(record);
761
-
762
- if (
763
- authority === undefined ||
764
- record.moduleId !== input.moduleId ||
765
- record.generation !== input.generation ||
766
- record.digest !== input.digest ||
767
- !(yield* shared.recordMatches(
768
- mapping,
769
- rows[0],
770
- record,
771
- authority.nativeSubjectId,
772
- yield* encodePasswordPreparedReady(record),
773
- ))
774
- )
775
- return yield* PasswordRejected.make({});
776
-
777
- const condition = and(
778
- shared.rowCondition(mapping, rows[0]),
779
- authorityCondition(mapping, authority, record.moduleId),
780
- sql`${p.d1.engineNowMillis} >= ${record.issuedAtMillis} and ${p.d1.engineNowMillis} < ${record.expiresAtMillis}`,
781
- )!;
782
-
783
- const guardStatement = yield* kernel.assertion(
784
- sql`exists(select 1 from ${t.table} where ${condition})`,
785
- `effect-auth-password-prepared:context:${record.intentId}`,
786
- );
787
-
788
- const guard = yield* Effect.try({
789
- try: () => compactD1GeneratedStatement(database.$client, guardStatement, unavailable),
790
- catch: (cause) =>
791
- Schema.is(PasswordUnavailable)(cause)
792
- ? cause
793
- : PersistenceMappingError.make({ operation: "mapping", cause }),
794
- });
795
-
796
- yield* database.$client
797
- .batch([guard])
798
- .pipe(
799
- Effect.catchCause(
800
- (
801
- cause,
802
- ): Effect.Effect<never, PasswordRejected | import("effect/sql/SqlError").SqlError> =>
803
- everyFailureMatches(cause, (failure) =>
804
- kernel.isGuardFailure(
805
- failure,
806
- `effect-auth-password-prepared:context:${record.intentId}`,
807
- ),
808
- )
809
- ? Effect.fail(PasswordRejected.make({}))
810
- : Effect.failCause(cause),
811
- ),
812
- );
813
-
814
- return { record, currentRequirement: authority.requirement };
815
- }),
816
- complete,
817
- resetWithProof: complete,
818
- cancel: <A>(
819
- uncaptured: Parameters<PasswordPreparedPersistence["cancel"]>[0],
820
- prepare: PlanPrepare<PasswordPreparedPersistence["cancel"], A>,
821
- ) =>
822
- Effect.gen(function* () {
823
- const record = yield* snapshotPasswordPreparedReady(uncaptured.record);
824
-
825
- return yield* run(
826
- Effect.gen(function* () {
827
- const journal = yield* CurrentCommitJournal;
828
-
829
- const authority = yield* current(record),
830
- rows = yield* readRows(
831
- and(eq(c.moduleId, record.moduleId), eq(c.intentId, record.intentId))!,
832
- ),
833
- row = rows[0];
834
-
835
- if (
836
- authority === undefined ||
837
- rows.length !== 1 ||
838
- !(yield* shared.recordMatches(
839
- mapping,
840
- row,
841
- record,
842
- authority.nativeSubjectId,
843
- yield* encodePasswordPreparedReady(record),
844
- ))
845
- )
846
- return { receipt: prepare(false, journal), statements: [] };
847
- const marker = `effect-auth-password-prepared:cancel:${record.intentId}`;
848
-
849
- return {
850
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
851
- receipt: prepare(true, journal),
852
- statements: [
853
- yield* kernel.assertion(
854
- and(
855
- existsRow(mapping, row),
856
- authorityCondition(mapping, authority, record.moduleId),
857
- sql`${p.d1.engineNowMillis} >= ${record.issuedAtMillis} and ${p.d1.engineNowMillis} < ${record.expiresAtMillis}`,
858
- )!,
859
- marker,
860
- ),
861
- ...(yield* terminalStatements(mapping, row, "Cancelled", marker)),
862
- ],
863
- };
864
- }),
865
- );
866
- }),
867
- cleanup: <A>(
868
- uncaptured: Parameters<PasswordPreparedPersistence["cleanup"]>[0],
869
- prepare: PlanPrepare<PasswordPreparedPersistence["cleanup"], A>,
870
- ) =>
871
- Effect.gen(function* () {
872
- const database = yield* CurrentD1PlanningDatabase;
873
-
874
- const input = { ...uncaptured };
875
-
876
- if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 1000)
877
- return yield* unavailable();
878
-
879
- return yield* run(
880
- Effect.gen(function* () {
881
- const journal = yield* CurrentCommitJournal;
882
-
883
- const due = and(
884
- eq(c.moduleId, input.moduleId),
885
- or(
886
- and(
887
- lte(c.retainUntil, p.d1.engineNow),
888
- lte(c.admissionRetainUntil, p.d1.engineNow),
889
- ),
890
- and(
891
- isNotNull(c.snapshot),
892
- or(
893
- and(
894
- eq(c.state, t.states.Preparing),
895
- lte(c.preparationExpiresAt, p.d1.engineNow),
896
- ),
897
- and(eq(c.state, t.states.Ready), lte(c.expiresAt, p.d1.engineNow)),
898
- ),
899
- ),
900
- ),
901
- )!;
902
-
903
- const rows = yield* database
904
- .select()
905
- .from(t.table)
906
- .where(due)
907
- .orderBy(c.createdAt, c.intentId)
908
- .limit(input.limit + 1);
909
-
910
- const now = yield* kernel.readEngineNowMillis(p),
911
- statements: Statement<any>[] = [],
912
- marker = `effect-auth-password-prepared:cleanup:${input.moduleId}`;
913
-
914
- let removed = 0;
915
-
916
- for (const row of rows.slice(0, input.limit)) {
917
- const retained = yield* p.decodeInstant(row[t.retainUntil]),
918
- charge = yield* p.decodeInstant(row[t.admissionRetainUntil]);
919
-
920
- statements.push(
921
- yield* kernel.assertion(
922
- and(
923
- existsRow(mapping, row),
924
- sql`exists(select 1 from ${t.table} where ${shared.rowCondition(mapping, row)} and ${due})`,
925
- )!,
926
- marker,
927
- ),
928
- );
929
- if (retained <= now && charge <= now) {
930
- statements.push(
931
- yield* kernel.statement(
932
- database
933
- .delete(t.table)
934
- .where(
935
- and(
936
- shared.rowCondition(mapping, row),
937
- lte(c.retainUntil, p.d1.engineNow),
938
- lte(c.admissionRetainUntil, p.d1.engineNow),
939
- ),
940
- ),
941
- ),
942
- yield* kernel.assertion(
943
- sql`not exists(select 1 from ${t.table} where ${c.moduleId} = ${sql.param(input.moduleId, c.moduleId)} and ${c.intentId} = ${sql.param(row[t.intentId], c.intentId)})`,
944
- marker,
945
- ),
946
- );
947
- removed++;
948
- } else
949
- statements.push(...(yield* terminalStatements(mapping, row, "Expired", marker)));
950
- }
951
- const hasMore = rows.length > input.limit;
952
-
953
- statements.push(
954
- yield* kernel.assertion(
955
- hasMore
956
- ? sql`exists(select 1 from ${t.table} where ${due})`
957
- : sql`not exists(select 1 from ${t.table} where ${due})`,
958
- marker,
959
- ),
960
- );
961
-
962
- return {
963
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
964
- receipt: prepare({ removed, hasMore }, journal),
965
- statements,
966
- };
967
- }),
968
- );
969
- }),
970
- };
971
-
972
- return services;
973
- };
974
-
975
- export const makeD1PasswordPreparedPersistenceServices = Effect.fnUntraced(function* <
976
- S extends AnySQLiteTable,
977
- I extends AnySQLiteTable,
978
- C extends AnySQLiteTable,
979
- AC extends AnySQLiteTable,
980
- M extends AnySQLiteTable,
981
- T extends AnySQLiteTable,
982
- B extends AnySQLiteTable,
983
- NativeId,
984
- PS extends AnySQLiteTable = AnySQLiteTable,
985
- PC extends AnySQLiteTable = AnySQLiteTable,
986
- PM extends AnySQLiteTable = AnySQLiteTable,
987
- PSub extends AnySQLiteTable = AnySQLiteTable,
988
- PI extends AnySQLiteTable = AnySQLiteTable,
989
- PCr extends AnySQLiteTable = AnySQLiteTable,
990
- PNativeId = unknown,
991
- >(
992
- mapping: D1PasswordPreparedPersistenceMapping<S, I, C, AC, M, T, B, NativeId>,
993
- proofMapping?: D1PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>,
994
- ) {
995
- const database = yield* DatabaseService;
996
-
997
- yield* validateDrizzleStorage({ ...mapping, proof: proofMapping }).pipe(
998
- Effect.provideServiceEffect(NativeDatabase, nativeDatabase(DatabaseService)),
999
- Effect.mapError(unavailable),
1000
- );
1001
-
1002
- const hooks = yield* LifecycleHooks;
1003
- const plans = makePreparedPlans(mapping as unknown as Mapping, proofMapping);
1004
-
1005
- const run = <Out, Err, Env>(plan: Effect.Effect<Planned<Out>, Err, Env>) =>
1006
- Effect.gen(function* () {
1007
- if (yield* hasCommitScope) return yield* unavailable();
1008
-
1009
- return yield* executeStandalone(plan);
1010
- }).pipe(
1011
- Effect.provideService(CurrentD1PlanningDatabase, database),
1012
- Effect.provideService(CurrentPasswordSql, database as unknown as PasswordSqlDatabase),
1013
- Effect.provideService(LifecycleHooks, hooks),
1014
- );
1015
-
1016
- const service: PasswordPreparedPersistence = {
1017
- reserve: (input, prepare) => run(plans.reserve(input, prepare)).pipe(translateFailure),
1018
- publishReady: (input, prepare) =>
1019
- run(plans.publishReady(input, prepare)).pipe(translateFailure),
1020
- context: (input) =>
1021
- plans
1022
- .context(input)
1023
- .pipe(
1024
- Effect.provideService(CurrentD1PlanningDatabase, database),
1025
- Effect.provideService(CurrentPasswordSql, database as unknown as PasswordSqlDatabase),
1026
- Effect.provideService(LifecycleHooks, hooks),
1027
- translateContextFailure,
1028
- ),
1029
- complete: (input, prepare) => run(plans.complete(input, prepare)).pipe(translateFailure),
1030
- resetWithProof: (input, prepare) =>
1031
- run(plans.resetWithProof(input, prepare)).pipe(translateFailure),
1032
- cancel: (input, prepare) => run(plans.cancel(input, prepare)).pipe(translateFailure),
1033
- cleanup: (input, prepare) => run(plans.cleanup(input, prepare)).pipe(translateFailure),
1034
- };
1035
-
1036
- return { passwordPreparedPersistence: service };
1037
- });
1038
-
1039
- export function coordinateD1PasswordPreparedPersistence<
1040
- TargetId,
1041
- S extends AnySQLiteTable,
1042
- I extends AnySQLiteTable,
1043
- C extends AnySQLiteTable,
1044
- AC extends AnySQLiteTable,
1045
- M extends AnySQLiteTable,
1046
- T extends AnySQLiteTable,
1047
- B extends AnySQLiteTable,
1048
- NativeId,
1049
- PS extends AnySQLiteTable,
1050
- PC extends AnySQLiteTable,
1051
- PM extends AnySQLiteTable,
1052
- PSub extends AnySQLiteTable,
1053
- PI extends AnySQLiteTable,
1054
- PCr extends AnySQLiteTable,
1055
- PNativeId,
1056
- A,
1057
- E,
1058
- R,
1059
- DatabaseError,
1060
- DatabaseRequirements,
1061
- >(
1062
- acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,
1063
- options: {
1064
- readonly mapping: D1PasswordPreparedPersistenceMapping<S, I, C, AC, M, T, B, NativeId>;
1065
- readonly proofMapping?:
1066
- | D1PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
1067
- | undefined;
1068
- readonly target: SuppliedService<TargetId, PasswordPreparedPersistence>;
1069
- },
1070
- body: Effect.Effect<A, E, R>,
1071
- ): Effect.Effect<
1072
- A,
1073
- E | PasswordUnavailable | HookConfigurationError | DatabaseError,
1074
- Exclude<R, TargetId | D1BatchStatements> | LifecycleHooks | DatabaseRequirements
1075
- > {
1076
- return Effect.flatMap(nativeDatabase(acquire), (database) =>
1077
- Effect.gen(function* () {
1078
- yield* validateDrizzleStorage({
1079
- ...options.mapping,
1080
- proof: options.proofMapping,
1081
- }).pipe(Effect.mapError(unavailable));
1082
- const hooks = yield* LifecycleHooks;
1083
-
1084
- if (yield* hasCommitScope) return yield* unavailable();
1085
-
1086
- const result = yield* coordinateCommit(
1087
- () =>
1088
- Effect.gen(function* () {
1089
- const statements: Statement<any>[] = [];
1090
- let mutation: Planned<any> | undefined;
1091
- let poisoned = false;
1092
-
1093
- const nativeCollector = D1BatchStatements.of({
1094
- append: (statement) => Effect.sync(() => statements.push(statement)),
1095
- });
1096
-
1097
- const owner = yield* makeD1Owner(unavailable()).pipe(
1098
- Effect.provideService(D1BatchStatements, nativeCollector),
1099
- );
1100
-
1101
- const protect = <Out, Err, Env>(effect: Effect.Effect<Out, Err, Env>) =>
1102
- effect.pipe(
1103
- Effect.onError(() =>
1104
- Effect.sync(() => {
1105
- poisoned = true;
1106
- }),
1107
- ),
1108
- );
1109
-
1110
- const plans = makePreparedPlans(
1111
- options.mapping as unknown as Mapping,
1112
- options.proofMapping,
1113
- );
1114
-
1115
- const run = <Out, Err, Env>(plan: Effect.Effect<Planned<Out>, Err, Env>) =>
1116
- coordinateCommit(
1117
- () =>
1118
- Effect.gen(function* () {
1119
- const journal = yield* CurrentCommitJournal;
1120
- const planned = yield* plan;
1121
-
1122
- yield* owner.check;
1123
- if (mutation !== undefined) return yield* unavailable();
1124
- const guarded = { ...planned, journalGuard: journal.prepare(undefined) };
1125
-
1126
- mutation = guarded;
1127
- statements.push(...guarded.statements);
1128
-
1129
- return guarded.receipt;
1130
- }),
1131
- { mode: "batch" },
1132
- ).pipe(
1133
- Effect.map((result) => result.value),
1134
- Effect.provideService(CurrentD1PlanningDatabase, database),
1135
- Effect.provideService(
1136
- CurrentPasswordSql,
1137
- database as unknown as PasswordSqlDatabase,
1138
- ),
1139
- Effect.provideService(LifecycleHooks, hooks),
1140
- );
1141
-
1142
- const service: PasswordPreparedPersistence = {
1143
- reserve: (input, prepare) =>
1144
- owner.run(protect(run(plans.reserve(input, prepare)).pipe(translateFailure))),
1145
- publishReady: (input, prepare) =>
1146
- owner.run(protect(run(plans.publishReady(input, prepare)).pipe(translateFailure))),
1147
- context: (input) =>
1148
- owner.run(
1149
- protect(
1150
- plans
1151
- .context(input)
1152
- .pipe(
1153
- Effect.provideService(CurrentD1PlanningDatabase, database),
1154
- Effect.provideService(
1155
- CurrentPasswordSql,
1156
- database as unknown as PasswordSqlDatabase,
1157
- ),
1158
- Effect.provideService(LifecycleHooks, hooks),
1159
- translateContextFailure,
1160
- ),
1161
- ),
1162
- ),
1163
- complete: (input, prepare) =>
1164
- owner.run(protect(run(plans.complete(input, prepare)).pipe(translateFailure))),
1165
- resetWithProof: (input, prepare) =>
1166
- owner.run(
1167
- protect(run(plans.resetWithProof(input, prepare)).pipe(translateFailure)),
1168
- ),
1169
- cancel: (input, prepare) =>
1170
- owner.run(protect(run(plans.cancel(input, prepare)).pipe(translateFailure))),
1171
- cleanup: (input, prepare) =>
1172
- owner.run(protect(run(plans.cleanup(input, prepare)).pipe(translateFailure))),
1173
- };
1174
-
1175
- const provided = Context.make(options.target, service).pipe(
1176
- Context.add(D1BatchStatements, owner.collector),
1177
- );
1178
-
1179
- const value = yield* owner.close(Effect.provideContext(body, provided));
1180
-
1181
- if (poisoned) return yield* unavailable();
1182
- if (mutation?.journalGuard !== undefined) {
1183
- const status = yield* Effect.result(mutation.journalGuard.read);
1184
-
1185
- if (status._tag === "Success" || status.failure._tag !== "CommitPending")
1186
- return yield* unavailable();
1187
- }
1188
- yield* database.$client
1189
- .batch([...statements, ...(mutation?.postconditions ?? [])])
1190
- .pipe(
1191
- Effect.catchCause((cause) =>
1192
- Effect.failCause(
1193
- Cause.map(cause, (error) =>
1194
- everyFailureMatches(cause, mutation?.retryable) ? unavailable() : error,
1195
- ),
1196
- ),
1197
- ),
1198
- translateFailure,
1199
- );
1200
-
1201
- return value;
1202
- }),
1203
- { mode: "batch" },
1204
- ).pipe(Effect.provideService(LifecycleHooks, hooks));
1205
-
1206
- return result.value;
1207
- }).pipe(Effect.provideService(NativeDatabase, database)),
1208
- );
1209
- }
1210
-
1211
- const translateFailure = <A, E, R>(
1212
- effect: Effect.Effect<A, E, R>,
1213
- ): Effect.Effect<A, PasswordUnavailable, R> =>
1214
- reportPersistenceFailure(
1215
- effect,
1216
- (error) =>
1217
- Schema.is(PasswordUnavailable)(error) ||
1218
- Schema.is(ProofUnavailable)(error) ||
1219
- Schema.is(HookConfigurationError)(error),
1220
- ).pipe(Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, () => unavailable()))));
1221
-
1222
- const translateContextFailure = <A, E, R>(
1223
- effect: Effect.Effect<A, E, R>,
1224
- ): Effect.Effect<A, PasswordUnavailable | PasswordRejected, R> =>
1225
- reportPersistenceFailure(
1226
- effect,
1227
- (error) =>
1228
- Schema.is(PasswordUnavailable)(error) ||
1229
- Schema.is(PasswordRejected)(error) ||
1230
- Schema.is(ProofUnavailable)(error) ||
1231
- Schema.is(HookConfigurationError)(error),
1232
- ).pipe(
1233
- Effect.catchCause((cause) =>
1234
- Effect.failCause(
1235
- Cause.map(cause, (error) => (Schema.is(PasswordRejected)(error) ? error : unavailable())),
1236
- ),
1237
- ),
1238
- );
1239
-
1240
- const executeStandalone = <A, E, R>(plan: Effect.Effect<Planned<A>, E, R>) =>
1241
- Effect.suspend(() => {
1242
- let retryable: ((cause: unknown) => boolean) | undefined;
1243
-
1244
- return coordinateCommit(
1245
- () =>
1246
- Effect.gen(function* () {
1247
- const database = yield* CurrentD1PlanningDatabase;
1248
- const planned = yield* plan;
1249
-
1250
- retryable = planned.retryable;
1251
- yield* database.$client.batch([...planned.statements, ...(planned.postconditions ?? [])]);
1252
-
1253
- return planned.receipt;
1254
- }),
1255
- { mode: "batch" },
1256
- ).pipe(
1257
- Effect.map((result) => result.value),
1258
- Effect.catchCause((cause) =>
1259
- Effect.failCause(
1260
- Cause.map(cause, (error) =>
1261
- everyFailureMatches(cause, retryable) ? unavailable() : error,
1262
- ),
1263
- ),
1264
- ),
1265
- );
1266
- });