@yielded/auth-persistence-drizzle 0.1.0-beta.24 → 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 -1265
  340. package/src/drizzle/d1-passwords.ts +0 -2060
  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 -1201
  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,1265 +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
- p.sessionInvalidation !== "same-authority-immediate")
467
- )
468
- return yield* unavailable();
469
-
470
- const version = PasswordPreparedVersion.make(
471
- yield* kernel.allocate(mapping.allocateVersion, mapping.allocateVersionSync),
472
- );
473
-
474
- return yield* run(
475
- Effect.gen(function* () {
476
- const journal = yield* CurrentCommitJournal;
477
-
478
- const authority = yield* shared.captureAuthority(mapping, config, input);
479
-
480
- if (authority === undefined) return yield* unavailable();
481
- let proofCondition: SQL = sql`true`;
482
-
483
- if (input.reset !== undefined) {
484
- if (
485
- input.completion === undefined ||
486
- input.completion.moduleId !== `${input.moduleId}/reset` ||
487
- input.completion.purpose !== "password-reset" ||
488
- input.reset.continuationId !== input.completion.continuationId ||
489
- bindingJson(input.reset.binding) !== bindingJson(input.completion.binding) ||
490
- input.reset.binding._tag !== "Subject" ||
491
- !sameRevision(input.reset.binding.revision, authority.revision) ||
492
- authority.snapshot?.identifierVerifiedAtMillis === undefined
493
- )
494
- return yield* unavailable();
495
- const inspected = yield* checkD1ProofCompletion(proofMapping, input.completion);
496
-
497
- if (!inspected.accepted) return yield* unavailable();
498
- proofCondition = inspected.condition;
499
- }
500
-
501
- const ownerCurrent = and(
502
- authorityCondition(mapping, authority, input.moduleId),
503
- proofCondition,
504
- )!;
505
-
506
- const marker = `effect-auth-password-prepared:reserve:${input.intentId}`;
507
-
508
- const existing = yield* readRows(
509
- and(eq(c.moduleId, input.moduleId), eq(c.commandId, input.commandId))!,
510
- );
511
-
512
- if (existing.length)
513
- return {
514
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
515
- receipt: prepare({ _tag: "Existing" }, journal),
516
- statements: [
517
- yield* kernel.assertion(
518
- and(ownerCurrent, existsRow(mapping, existing[0]))!,
519
- marker,
520
- ),
521
- ],
522
- };
523
-
524
- const now = yield* kernel.readEngineNowMillis(p),
525
- scope = identifierScope({
526
- ...(authority.snapshot === undefined ? {} : { credential: authority.snapshot }),
527
- revision: authority.revision,
528
- });
529
-
530
- const reservation = yield* snapshotPasswordPreparedReservation({
531
- _tag: "Preparing",
532
- moduleId: input.moduleId,
533
- generation: input.generation,
534
- intentId: input.intentId,
535
- version,
536
- commandId: input.commandId,
537
- action: input.action,
538
- revision: authority.revision,
539
- ...(authority.snapshot === undefined ? {} : { credential: authority.snapshot }),
540
- capturedRequirement: authority.requirement,
541
- ...(input.reset === undefined ? {} : { reset: input.reset }),
542
- invalidation: input.invalidation,
543
- createdAtMillis: now,
544
- preparationExpiresAtMillis: now + input.policy.preparationLifetimeMillis,
545
- retainUntilMillis: now + input.policy.retentionMillis,
546
- });
547
-
548
- const snapshot = yield* encodeReservation(reservation),
549
- window = Math.max(
550
- input.policy.admission.action.windowMillis,
551
- input.policy.admission.identifier.windowMillis,
552
- input.policy.admission.subject.windowMillis,
553
- );
554
-
555
- const a = mapping.admission,
556
- am = column(a.table, a.moduleId),
557
- ai = column(a.table, a.intentId),
558
- at = column(a.table, a.admittedAt),
559
- ar = column(a.table, a.admissionRetainUntil);
560
-
561
- const stamp = sql`(select ${at} from ${a.table} where ${am} = ${sql.param(input.moduleId, am)})`,
562
- retention = sql`(select ${ar} from ${a.table} where ${am} = ${sql.param(input.moduleId, am)})`;
563
-
564
- 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}`;
565
-
566
- const budgets = [
567
- [eq(c.action, input.action), input.policy.admission.action],
568
- [eq(c.identifierScope, scope), input.policy.admission.identifier],
569
- [eq(c.subjectId, authority.nativeSubjectId), input.policy.admission.subject],
570
- ] as const;
571
-
572
- const admissionDecision = and(
573
- ownerCurrent,
574
- active,
575
- ...budgets.map(
576
- ([condition, budget]) =>
577
- 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}`,
578
- ),
579
- 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)})`,
580
- sql`${p.d1.engineNowMillis} >= ${now} and ${p.d1.engineNowMillis} < ${reservation.preparationExpiresAtMillis}`,
581
- )!;
582
-
583
- const admittedMillis = mapping.admissionClock.toMillis(stamp),
584
- retainedMillis = mapping.admissionClock.toMillis(retention);
585
-
586
- const clockGuard = and(
587
- sql`exists(select 1 from ${a.table} where ${am} = ${sql.param(input.moduleId, am)} and ${ai} = ${sql.param(input.intentId, ai)})`,
588
- sql`${admittedMillis} >= ${now} and ${admittedMillis} <= ${p.d1.engineNowMillis}`,
589
- sql`${retainedMillis} = ${admittedMillis} + ${window}`,
590
- )!;
591
-
592
- const guard = and(sql`changes() = 1`, clockGuard)!;
593
-
594
- const values = {
595
- ...t.encodeInsert({
596
- reservation,
597
- nativeSubjectId: authority.nativeSubjectId,
598
- identifierScope: scope,
599
- snapshot,
600
- admittedAtMillis: now,
601
- admissionRetainUntilMillis: now + window,
602
- }),
603
- [t.admittedAt]: stamp,
604
- [t.admissionRetainUntil]: retention,
605
- };
606
-
607
- const expected = {
608
- [t.moduleId]: input.moduleId,
609
- [t.intentId]: input.intentId,
610
- [t.commandId]: input.commandId,
611
- [t.subjectId]: authority.nativeSubjectId,
612
- [t.action]: input.action,
613
- [t.generation]: input.generation,
614
- [t.version]: version,
615
- [t.state]: t.states.Preparing,
616
- [t.digest]: null,
617
- [t.snapshot]: snapshot,
618
- [t.identifierScope]: scope,
619
- [t.createdAt]: p.encodeInstant(now),
620
- [t.preparationExpiresAt]: p.encodeInstant(reservation.preparationExpiresAtMillis),
621
- [t.expiresAt]: null,
622
- [t.retainUntil]: p.encodeInstant(reservation.retainUntilMillis),
623
- [t.admittedAt]: stamp,
624
- [t.admissionRetainUntil]: retention,
625
- };
626
-
627
- return {
628
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
629
- receipt: prepare({ _tag: "Reserved", reservation }, journal),
630
- statements: [
631
- yield* kernel.statement(
632
- database
633
- .insert(a.table)
634
- .values(a.encodeInsert(input.moduleId))
635
- .onConflictDoNothing(),
636
- ),
637
- yield* kernel.statement(
638
- database
639
- .update(a.table)
640
- .set(
641
- updateValues([
642
- [a.intentId, input.intentId],
643
- [a.admittedAt, p.d1.engineNow],
644
- [a.admissionRetainUntil, p.d1.engineInstantPlus(window)],
645
- ]),
646
- )
647
- .where(and(eq(am, input.moduleId), admissionDecision)),
648
- ),
649
- yield* kernel.statement(yield* selectInsert(t.table, values, guard)),
650
- yield* kernel.assertion(existsRow(mapping, expected), marker),
651
- yield* kernel.assertion(
652
- and(
653
- ownerCurrent,
654
- clockGuard,
655
- sql`${p.d1.engineNowMillis} < ${reservation.preparationExpiresAtMillis}`,
656
- 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}`,
657
- ...budgets.map(
658
- ([condition, budget]) =>
659
- 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}`,
660
- ),
661
- )!,
662
- marker,
663
- ),
664
- ],
665
- };
666
- }),
667
- );
668
- }),
669
- publishReady: <A>(
670
- uncaptured: Parameters<PasswordPreparedPersistence["publishReady"]>[0],
671
- prepare: PlanPrepare<PasswordPreparedPersistence["publishReady"], A>,
672
- ) =>
673
- Effect.gen(function* () {
674
- const database = yield* CurrentD1PlanningDatabase;
675
-
676
- const reservation = yield* snapshotPasswordPreparedReservation(uncaptured.reservation),
677
- ready = yield* snapshotPasswordPreparedReady(uncaptured.ready),
678
- snapshot = yield* encodeReservation(reservation),
679
- readySnapshot = yield* encodePasswordPreparedReady(ready);
680
-
681
- if ((yield* encodeReservation(reservationOf(ready))) !== snapshot)
682
- return yield* unavailable();
683
-
684
- return yield* run(
685
- Effect.gen(function* () {
686
- const journal = yield* CurrentCommitJournal;
687
-
688
- const authority = yield* current(reservation),
689
- rows = yield* readRows(
690
- and(eq(c.moduleId, reservation.moduleId), eq(c.intentId, reservation.intentId))!,
691
- ),
692
- row = rows[0];
693
-
694
- if (
695
- authority === undefined ||
696
- rows.length !== 1 ||
697
- !(yield* shared.recordMatches(
698
- mapping,
699
- row,
700
- reservation,
701
- authority.nativeSubjectId,
702
- snapshot,
703
- ))
704
- )
705
- return { receipt: prepare("rejected", journal), statements: [] };
706
-
707
- const marker = `effect-auth-password-prepared:ready:${ready.intentId}`,
708
- live = and(
709
- authorityCondition(mapping, authority, ready.moduleId),
710
- sql`${p.d1.engineNowMillis} >= ${ready.issuedAtMillis} and ${p.d1.engineNowMillis} < ${reservation.preparationExpiresAtMillis} and ${p.d1.engineNowMillis} < ${ready.expiresAtMillis}`,
711
- )!;
712
-
713
- const expected = {
714
- ...row,
715
- [t.state]: t.states.Ready,
716
- [t.snapshot]: readySnapshot,
717
- [t.digest]: ready.digest,
718
- [t.expiresAt]: p.encodeInstant(ready.expiresAtMillis),
719
- };
720
-
721
- return {
722
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
723
- receipt: prepare("published", journal),
724
- statements: [
725
- yield* kernel.assertion(and(live, existsRow(mapping, row))!, marker),
726
- yield* kernel.statement(
727
- database
728
- .update(t.table)
729
- .set(t.encodeReady({ ready, snapshot: readySnapshot }))
730
- .where(shared.rowCondition(mapping, row)),
731
- ),
732
- yield* kernel.assertion(and(live, existsRow(mapping, expected))!, marker),
733
- ],
734
- };
735
- }),
736
- );
737
- }),
738
- context: (uncaptured: Parameters<PasswordPreparedPersistence["context"]>[0]) =>
739
- Effect.gen(function* () {
740
- const database = yield* CurrentD1PlanningDatabase;
741
-
742
- if (yield* hasCommitScope) return yield* unavailable();
743
-
744
- const input = yield* Schema.decodeEffect(ContextInput)({ ...uncaptured }).pipe(
745
- Effect.mapError(unavailable),
746
- ),
747
- rows = yield* readRows(
748
- and(
749
- eq(c.moduleId, input.moduleId),
750
- eq(c.generation, input.generation),
751
- eq(c.digest, input.digest),
752
- eq(c.state, t.states.Ready),
753
- )!,
754
- );
755
-
756
- if (rows.length !== 1) return yield* PasswordRejected.make({});
757
-
758
- const record = yield* decodePasswordPreparedReady(rows[0][t.snapshot]),
759
- authority = yield* current(record);
760
-
761
- if (
762
- authority === undefined ||
763
- record.moduleId !== input.moduleId ||
764
- record.generation !== input.generation ||
765
- record.digest !== input.digest ||
766
- !(yield* shared.recordMatches(
767
- mapping,
768
- rows[0],
769
- record,
770
- authority.nativeSubjectId,
771
- yield* encodePasswordPreparedReady(record),
772
- ))
773
- )
774
- return yield* PasswordRejected.make({});
775
-
776
- const condition = and(
777
- shared.rowCondition(mapping, rows[0]),
778
- authorityCondition(mapping, authority, record.moduleId),
779
- sql`${p.d1.engineNowMillis} >= ${record.issuedAtMillis} and ${p.d1.engineNowMillis} < ${record.expiresAtMillis}`,
780
- )!;
781
-
782
- const guardStatement = yield* kernel.assertion(
783
- sql`exists(select 1 from ${t.table} where ${condition})`,
784
- `effect-auth-password-prepared:context:${record.intentId}`,
785
- );
786
-
787
- const guard = yield* Effect.try({
788
- try: () => compactD1GeneratedStatement(database.$client, guardStatement, unavailable),
789
- catch: (cause) =>
790
- Schema.is(PasswordUnavailable)(cause)
791
- ? cause
792
- : PersistenceMappingError.make({ operation: "mapping", cause }),
793
- });
794
-
795
- yield* database.$client
796
- .batch([guard])
797
- .pipe(
798
- Effect.catchCause(
799
- (
800
- cause,
801
- ): Effect.Effect<never, PasswordRejected | import("effect/sql/SqlError").SqlError> =>
802
- everyFailureMatches(cause, (failure) =>
803
- kernel.isGuardFailure(
804
- failure,
805
- `effect-auth-password-prepared:context:${record.intentId}`,
806
- ),
807
- )
808
- ? Effect.fail(PasswordRejected.make({}))
809
- : Effect.failCause(cause),
810
- ),
811
- );
812
-
813
- return { record, currentRequirement: authority.requirement };
814
- }),
815
- complete,
816
- resetWithProof: complete,
817
- cancel: <A>(
818
- uncaptured: Parameters<PasswordPreparedPersistence["cancel"]>[0],
819
- prepare: PlanPrepare<PasswordPreparedPersistence["cancel"], A>,
820
- ) =>
821
- Effect.gen(function* () {
822
- const record = yield* snapshotPasswordPreparedReady(uncaptured.record);
823
-
824
- return yield* run(
825
- Effect.gen(function* () {
826
- const journal = yield* CurrentCommitJournal;
827
-
828
- const authority = yield* current(record),
829
- rows = yield* readRows(
830
- and(eq(c.moduleId, record.moduleId), eq(c.intentId, record.intentId))!,
831
- ),
832
- row = rows[0];
833
-
834
- if (
835
- authority === undefined ||
836
- rows.length !== 1 ||
837
- !(yield* shared.recordMatches(
838
- mapping,
839
- row,
840
- record,
841
- authority.nativeSubjectId,
842
- yield* encodePasswordPreparedReady(record),
843
- ))
844
- )
845
- return { receipt: prepare(false, journal), statements: [] };
846
- const marker = `effect-auth-password-prepared:cancel:${record.intentId}`;
847
-
848
- return {
849
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
850
- receipt: prepare(true, journal),
851
- statements: [
852
- yield* kernel.assertion(
853
- and(
854
- existsRow(mapping, row),
855
- authorityCondition(mapping, authority, record.moduleId),
856
- sql`${p.d1.engineNowMillis} >= ${record.issuedAtMillis} and ${p.d1.engineNowMillis} < ${record.expiresAtMillis}`,
857
- )!,
858
- marker,
859
- ),
860
- ...(yield* terminalStatements(mapping, row, "Cancelled", marker)),
861
- ],
862
- };
863
- }),
864
- );
865
- }),
866
- cleanup: <A>(
867
- uncaptured: Parameters<PasswordPreparedPersistence["cleanup"]>[0],
868
- prepare: PlanPrepare<PasswordPreparedPersistence["cleanup"], A>,
869
- ) =>
870
- Effect.gen(function* () {
871
- const database = yield* CurrentD1PlanningDatabase;
872
-
873
- const input = { ...uncaptured };
874
-
875
- if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 1000)
876
- return yield* unavailable();
877
-
878
- return yield* run(
879
- Effect.gen(function* () {
880
- const journal = yield* CurrentCommitJournal;
881
-
882
- const due = and(
883
- eq(c.moduleId, input.moduleId),
884
- or(
885
- and(
886
- lte(c.retainUntil, p.d1.engineNow),
887
- lte(c.admissionRetainUntil, p.d1.engineNow),
888
- ),
889
- and(
890
- isNotNull(c.snapshot),
891
- or(
892
- and(
893
- eq(c.state, t.states.Preparing),
894
- lte(c.preparationExpiresAt, p.d1.engineNow),
895
- ),
896
- and(eq(c.state, t.states.Ready), lte(c.expiresAt, p.d1.engineNow)),
897
- ),
898
- ),
899
- ),
900
- )!;
901
-
902
- const rows = yield* database
903
- .select()
904
- .from(t.table)
905
- .where(due)
906
- .orderBy(c.createdAt, c.intentId)
907
- .limit(input.limit + 1);
908
-
909
- const now = yield* kernel.readEngineNowMillis(p),
910
- statements: Statement<any>[] = [],
911
- marker = `effect-auth-password-prepared:cleanup:${input.moduleId}`;
912
-
913
- let removed = 0;
914
-
915
- for (const row of rows.slice(0, input.limit)) {
916
- const retained = yield* p.decodeInstant(row[t.retainUntil]),
917
- charge = yield* p.decodeInstant(row[t.admissionRetainUntil]);
918
-
919
- statements.push(
920
- yield* kernel.assertion(
921
- and(
922
- existsRow(mapping, row),
923
- sql`exists(select 1 from ${t.table} where ${shared.rowCondition(mapping, row)} and ${due})`,
924
- )!,
925
- marker,
926
- ),
927
- );
928
- if (retained <= now && charge <= now) {
929
- statements.push(
930
- yield* kernel.statement(
931
- database
932
- .delete(t.table)
933
- .where(
934
- and(
935
- shared.rowCondition(mapping, row),
936
- lte(c.retainUntil, p.d1.engineNow),
937
- lte(c.admissionRetainUntil, p.d1.engineNow),
938
- ),
939
- ),
940
- ),
941
- yield* kernel.assertion(
942
- 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)})`,
943
- marker,
944
- ),
945
- );
946
- removed++;
947
- } else
948
- statements.push(...(yield* terminalStatements(mapping, row, "Expired", marker)));
949
- }
950
- const hasMore = rows.length > input.limit;
951
-
952
- statements.push(
953
- yield* kernel.assertion(
954
- hasMore
955
- ? sql`exists(select 1 from ${t.table} where ${due})`
956
- : sql`not exists(select 1 from ${t.table} where ${due})`,
957
- marker,
958
- ),
959
- );
960
-
961
- return {
962
- retryable: (cause: unknown) => kernel.isGuardFailure(cause, marker),
963
- receipt: prepare({ removed, hasMore }, journal),
964
- statements,
965
- };
966
- }),
967
- );
968
- }),
969
- };
970
-
971
- return services;
972
- };
973
-
974
- export const makeD1PasswordPreparedPersistenceServices = Effect.fnUntraced(function* <
975
- S extends AnySQLiteTable,
976
- I extends AnySQLiteTable,
977
- C extends AnySQLiteTable,
978
- AC extends AnySQLiteTable,
979
- M extends AnySQLiteTable,
980
- T extends AnySQLiteTable,
981
- B extends AnySQLiteTable,
982
- NativeId,
983
- PS extends AnySQLiteTable = AnySQLiteTable,
984
- PC extends AnySQLiteTable = AnySQLiteTable,
985
- PM extends AnySQLiteTable = AnySQLiteTable,
986
- PSub extends AnySQLiteTable = AnySQLiteTable,
987
- PI extends AnySQLiteTable = AnySQLiteTable,
988
- PCr extends AnySQLiteTable = AnySQLiteTable,
989
- PNativeId = unknown,
990
- >(
991
- mapping: D1PasswordPreparedPersistenceMapping<S, I, C, AC, M, T, B, NativeId>,
992
- proofMapping?: D1PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>,
993
- ) {
994
- const database = yield* DatabaseService;
995
-
996
- yield* validateDrizzleStorage({ ...mapping, proof: proofMapping }).pipe(
997
- Effect.provideServiceEffect(NativeDatabase, nativeDatabase(DatabaseService)),
998
- Effect.mapError(unavailable),
999
- );
1000
-
1001
- const hooks = yield* LifecycleHooks;
1002
- const plans = makePreparedPlans(mapping as unknown as Mapping, proofMapping);
1003
-
1004
- const run = <Out, Err, Env>(plan: Effect.Effect<Planned<Out>, Err, Env>) =>
1005
- Effect.gen(function* () {
1006
- if (yield* hasCommitScope) return yield* unavailable();
1007
-
1008
- return yield* executeStandalone(plan);
1009
- }).pipe(
1010
- Effect.provideService(CurrentD1PlanningDatabase, database),
1011
- Effect.provideService(CurrentPasswordSql, database as unknown as PasswordSqlDatabase),
1012
- Effect.provideService(LifecycleHooks, hooks),
1013
- );
1014
-
1015
- const service: PasswordPreparedPersistence = {
1016
- reserve: (input, prepare) => run(plans.reserve(input, prepare)).pipe(translateFailure),
1017
- publishReady: (input, prepare) =>
1018
- run(plans.publishReady(input, prepare)).pipe(translateFailure),
1019
- context: (input) =>
1020
- plans
1021
- .context(input)
1022
- .pipe(
1023
- Effect.provideService(CurrentD1PlanningDatabase, database),
1024
- Effect.provideService(CurrentPasswordSql, database as unknown as PasswordSqlDatabase),
1025
- Effect.provideService(LifecycleHooks, hooks),
1026
- translateContextFailure,
1027
- ),
1028
- complete: (input, prepare) => run(plans.complete(input, prepare)).pipe(translateFailure),
1029
- resetWithProof: (input, prepare) =>
1030
- run(plans.resetWithProof(input, prepare)).pipe(translateFailure),
1031
- cancel: (input, prepare) => run(plans.cancel(input, prepare)).pipe(translateFailure),
1032
- cleanup: (input, prepare) => run(plans.cleanup(input, prepare)).pipe(translateFailure),
1033
- };
1034
-
1035
- return { passwordPreparedPersistence: service };
1036
- });
1037
-
1038
- export function coordinateD1PasswordPreparedPersistence<
1039
- TargetId,
1040
- S extends AnySQLiteTable,
1041
- I extends AnySQLiteTable,
1042
- C extends AnySQLiteTable,
1043
- AC extends AnySQLiteTable,
1044
- M extends AnySQLiteTable,
1045
- T extends AnySQLiteTable,
1046
- B extends AnySQLiteTable,
1047
- NativeId,
1048
- PS extends AnySQLiteTable,
1049
- PC extends AnySQLiteTable,
1050
- PM extends AnySQLiteTable,
1051
- PSub extends AnySQLiteTable,
1052
- PI extends AnySQLiteTable,
1053
- PCr extends AnySQLiteTable,
1054
- PNativeId,
1055
- A,
1056
- E,
1057
- R,
1058
- DatabaseError,
1059
- DatabaseRequirements,
1060
- >(
1061
- acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,
1062
- options: {
1063
- readonly mapping: D1PasswordPreparedPersistenceMapping<S, I, C, AC, M, T, B, NativeId>;
1064
- readonly proofMapping?:
1065
- | D1PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
1066
- | undefined;
1067
- readonly target: SuppliedService<TargetId, PasswordPreparedPersistence>;
1068
- },
1069
- body: Effect.Effect<A, E, R>,
1070
- ): Effect.Effect<
1071
- A,
1072
- E | PasswordUnavailable | HookConfigurationError | DatabaseError,
1073
- Exclude<R, TargetId | D1BatchStatements> | LifecycleHooks | DatabaseRequirements
1074
- > {
1075
- return Effect.flatMap(nativeDatabase(acquire), (database) =>
1076
- Effect.gen(function* () {
1077
- yield* validateDrizzleStorage({
1078
- ...options.mapping,
1079
- proof: options.proofMapping,
1080
- }).pipe(Effect.mapError(unavailable));
1081
- const hooks = yield* LifecycleHooks;
1082
-
1083
- if (yield* hasCommitScope) return yield* unavailable();
1084
-
1085
- const result = yield* coordinateCommit(
1086
- () =>
1087
- Effect.gen(function* () {
1088
- const statements: Statement<any>[] = [];
1089
- let mutation: Planned<any> | undefined;
1090
- let poisoned = false;
1091
-
1092
- const nativeCollector = D1BatchStatements.of({
1093
- append: (statement) => Effect.sync(() => statements.push(statement)),
1094
- });
1095
-
1096
- const owner = yield* makeD1Owner(unavailable()).pipe(
1097
- Effect.provideService(D1BatchStatements, nativeCollector),
1098
- );
1099
-
1100
- const protect = <Out, Err, Env>(effect: Effect.Effect<Out, Err, Env>) =>
1101
- effect.pipe(
1102
- Effect.onError(() =>
1103
- Effect.sync(() => {
1104
- poisoned = true;
1105
- }),
1106
- ),
1107
- );
1108
-
1109
- const plans = makePreparedPlans(
1110
- options.mapping as unknown as Mapping,
1111
- options.proofMapping,
1112
- );
1113
-
1114
- const run = <Out, Err, Env>(plan: Effect.Effect<Planned<Out>, Err, Env>) =>
1115
- coordinateCommit(
1116
- () =>
1117
- Effect.gen(function* () {
1118
- const journal = yield* CurrentCommitJournal;
1119
- const planned = yield* plan;
1120
-
1121
- yield* owner.check;
1122
- if (mutation !== undefined) return yield* unavailable();
1123
- const guarded = { ...planned, journalGuard: journal.prepare(undefined) };
1124
-
1125
- mutation = guarded;
1126
- statements.push(...guarded.statements);
1127
-
1128
- return guarded.receipt;
1129
- }),
1130
- { mode: "batch" },
1131
- ).pipe(
1132
- Effect.map((result) => result.value),
1133
- Effect.provideService(CurrentD1PlanningDatabase, database),
1134
- Effect.provideService(
1135
- CurrentPasswordSql,
1136
- database as unknown as PasswordSqlDatabase,
1137
- ),
1138
- Effect.provideService(LifecycleHooks, hooks),
1139
- );
1140
-
1141
- const service: PasswordPreparedPersistence = {
1142
- reserve: (input, prepare) =>
1143
- owner.run(protect(run(plans.reserve(input, prepare)).pipe(translateFailure))),
1144
- publishReady: (input, prepare) =>
1145
- owner.run(protect(run(plans.publishReady(input, prepare)).pipe(translateFailure))),
1146
- context: (input) =>
1147
- owner.run(
1148
- protect(
1149
- plans
1150
- .context(input)
1151
- .pipe(
1152
- Effect.provideService(CurrentD1PlanningDatabase, database),
1153
- Effect.provideService(
1154
- CurrentPasswordSql,
1155
- database as unknown as PasswordSqlDatabase,
1156
- ),
1157
- Effect.provideService(LifecycleHooks, hooks),
1158
- translateContextFailure,
1159
- ),
1160
- ),
1161
- ),
1162
- complete: (input, prepare) =>
1163
- owner.run(protect(run(plans.complete(input, prepare)).pipe(translateFailure))),
1164
- resetWithProof: (input, prepare) =>
1165
- owner.run(
1166
- protect(run(plans.resetWithProof(input, prepare)).pipe(translateFailure)),
1167
- ),
1168
- cancel: (input, prepare) =>
1169
- owner.run(protect(run(plans.cancel(input, prepare)).pipe(translateFailure))),
1170
- cleanup: (input, prepare) =>
1171
- owner.run(protect(run(plans.cleanup(input, prepare)).pipe(translateFailure))),
1172
- };
1173
-
1174
- const provided = Context.make(options.target, service).pipe(
1175
- Context.add(D1BatchStatements, owner.collector),
1176
- );
1177
-
1178
- const value = yield* owner.close(Effect.provideContext(body, provided));
1179
-
1180
- if (poisoned) return yield* unavailable();
1181
- if (mutation?.journalGuard !== undefined) {
1182
- const status = yield* Effect.result(mutation.journalGuard.read);
1183
-
1184
- if (status._tag === "Success" || status.failure._tag !== "CommitPending")
1185
- return yield* unavailable();
1186
- }
1187
- yield* database.$client
1188
- .batch([...statements, ...(mutation?.postconditions ?? [])])
1189
- .pipe(
1190
- Effect.catchCause((cause) =>
1191
- Effect.failCause(
1192
- Cause.map(cause, (error) =>
1193
- everyFailureMatches(cause, mutation?.retryable) ? unavailable() : error,
1194
- ),
1195
- ),
1196
- ),
1197
- translateFailure,
1198
- );
1199
-
1200
- return value;
1201
- }),
1202
- { mode: "batch" },
1203
- ).pipe(Effect.provideService(LifecycleHooks, hooks));
1204
-
1205
- return result.value;
1206
- }).pipe(Effect.provideService(NativeDatabase, database)),
1207
- );
1208
- }
1209
-
1210
- const translateFailure = <A, E, R>(
1211
- effect: Effect.Effect<A, E, R>,
1212
- ): Effect.Effect<A, PasswordUnavailable, R> =>
1213
- reportPersistenceFailure(
1214
- effect,
1215
- (error) =>
1216
- Schema.is(PasswordUnavailable)(error) ||
1217
- Schema.is(ProofUnavailable)(error) ||
1218
- Schema.is(HookConfigurationError)(error),
1219
- ).pipe(Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, () => unavailable()))));
1220
-
1221
- const translateContextFailure = <A, E, R>(
1222
- effect: Effect.Effect<A, E, R>,
1223
- ): Effect.Effect<A, PasswordUnavailable | PasswordRejected, R> =>
1224
- reportPersistenceFailure(
1225
- effect,
1226
- (error) =>
1227
- Schema.is(PasswordUnavailable)(error) ||
1228
- Schema.is(PasswordRejected)(error) ||
1229
- Schema.is(ProofUnavailable)(error) ||
1230
- Schema.is(HookConfigurationError)(error),
1231
- ).pipe(
1232
- Effect.catchCause((cause) =>
1233
- Effect.failCause(
1234
- Cause.map(cause, (error) => (Schema.is(PasswordRejected)(error) ? error : unavailable())),
1235
- ),
1236
- ),
1237
- );
1238
-
1239
- const executeStandalone = <A, E, R>(plan: Effect.Effect<Planned<A>, E, R>) =>
1240
- Effect.suspend(() => {
1241
- let retryable: ((cause: unknown) => boolean) | undefined;
1242
-
1243
- return coordinateCommit(
1244
- () =>
1245
- Effect.gen(function* () {
1246
- const database = yield* CurrentD1PlanningDatabase;
1247
- const planned = yield* plan;
1248
-
1249
- retryable = planned.retryable;
1250
- yield* database.$client.batch([...planned.statements, ...(planned.postconditions ?? [])]);
1251
-
1252
- return planned.receipt;
1253
- }),
1254
- { mode: "batch" },
1255
- ).pipe(
1256
- Effect.map((result) => result.value),
1257
- Effect.catchCause((cause) =>
1258
- Effect.failCause(
1259
- Cause.map(cause, (error) =>
1260
- everyFailureMatches(cause, retryable) ? unavailable() : error,
1261
- ),
1262
- ),
1263
- ),
1264
- );
1265
- });