@yielded/auth-persistence-drizzle 0.1.0-beta.25 → 0.1.0-beta.27
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.
- package/README.md +4 -2
- package/dist/D1.d.mts +495 -1151
- package/dist/D1.mjs +41 -19
- package/dist/D1.mjs.map +1 -1
- package/dist/Libsql.d.mts +385 -1996
- package/dist/Libsql.mjs +43 -47
- package/dist/Libsql.mjs.map +1 -1
- package/dist/Mysql2.d.mts +397 -1743
- package/dist/Mysql2.mjs +35 -41
- package/dist/Mysql2.mjs.map +1 -1
- package/dist/Pglite.d.mts +397 -1743
- package/dist/Pglite.mjs +42 -31
- package/dist/Pglite.mjs.map +1 -1
- package/dist/Postgres.d.mts +397 -1743
- package/dist/Postgres.mjs +42 -31
- package/dist/Postgres.mjs.map +1 -1
- package/dist/SqliteBun.d.mts +385 -1992
- package/dist/SqliteBun.mjs +43 -43
- package/dist/SqliteBun.mjs.map +1 -1
- package/dist/SqliteDo.d.mts +385 -1991
- package/dist/SqliteDo.mjs +42 -41
- package/dist/SqliteDo.mjs.map +1 -1
- package/dist/SqliteNode.d.mts +385 -1992
- package/dist/SqliteNode.mjs +43 -43
- package/dist/SqliteNode.mjs.map +1 -1
- package/dist/SqliteWasm.d.mts +385 -1992
- package/dist/SqliteWasm.mjs +43 -43
- package/dist/SqliteWasm.mjs.map +1 -1
- package/dist/drizzle/d1-identity.mjs +2 -2
- package/dist/drizzle/d1-identity.mjs.map +1 -1
- package/dist/drizzle/driver-types.d.mts +15 -0
- package/dist/drizzle/email-drivers.mjs +32 -0
- package/dist/drizzle/email-drivers.mjs.map +1 -0
- package/dist/drizzle/email-model.d.mts +9 -13
- package/dist/drizzle/email-target.d.mts +10 -11
- package/dist/drizzle/email-target.mjs +33 -70
- package/dist/drizzle/email-target.mjs.map +1 -1
- package/dist/drizzle/model.d.mts +1 -10
- package/dist/drizzle/model.mjs +1 -2
- package/dist/drizzle/model.mjs.map +1 -1
- package/dist/drizzle/mysql-identity.mjs +3 -6
- package/dist/drizzle/mysql-identity.mjs.map +1 -1
- package/dist/drizzle/native-clock.d.mts +9 -0
- package/dist/drizzle/native-clock.mjs +18 -0
- package/dist/drizzle/native-clock.mjs.map +1 -0
- package/dist/drizzle/native-database.d.mts +46 -0
- package/dist/drizzle/native-database.mjs +6 -5
- package/dist/drizzle/native-database.mjs.map +1 -1
- package/dist/drizzle/native-sql-table.mjs +13 -5
- package/dist/drizzle/native-sql-table.mjs.map +1 -1
- package/dist/drizzle/native-target.d.mts +6 -0
- package/dist/drizzle/native-target.mjs +44 -0
- package/dist/drizzle/native-target.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-drivers.mjs +4 -56
- package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-model.d.mts +5 -22
- package/dist/drizzle/oauth-connected-model.mjs +1 -7
- package/dist/drizzle/oauth-connected-reference.d.mts +5 -7
- package/dist/drizzle/oauth-connected-reference.mjs +11 -3
- package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
- package/dist/drizzle/oauth-drivers.mjs +1 -2
- package/dist/drizzle/oauth-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-model.d.mts +11 -37
- package/dist/drizzle/oauth-model.mjs +3 -4
- package/dist/drizzle/oauth-model.mjs.map +1 -1
- package/dist/drizzle/oauth-proxy.d.mts +1 -1
- package/dist/drizzle/oauth-proxy.mjs +1 -1
- package/dist/drizzle/oauth-target.d.mts +9 -6
- package/dist/drizzle/oauth-target.mjs +47 -15
- package/dist/drizzle/oauth-target.mjs.map +1 -1
- package/dist/drizzle/passkey/target.d.mts +14 -0
- package/dist/drizzle/passkey/target.mjs +52 -0
- package/dist/drizzle/passkey/target.mjs.map +1 -0
- package/dist/drizzle/passkey/write-target.d.mts +11 -0
- package/dist/drizzle/passkey/write-target.mjs +28 -0
- package/dist/drizzle/passkey/write-target.mjs.map +1 -0
- package/dist/drizzle/passkey-drivers.mjs +2 -4
- package/dist/drizzle/passkey-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-model.d.mts +5 -26
- package/dist/drizzle/passkey-model.mjs +2 -8
- package/dist/drizzle/passkey-registration-ceremony-model.d.mts +3 -6
- package/dist/drizzle/passkey-write-drivers.mjs +2 -3
- package/dist/drizzle/passkey-write-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-write-model.d.mts +7 -9
- package/dist/drizzle/passkey-write-model.mjs +1 -3
- package/dist/drizzle/passkey-write-model.mjs.map +1 -1
- package/dist/drizzle/password-drivers.mjs +31 -0
- package/dist/drizzle/password-drivers.mjs.map +1 -0
- package/dist/drizzle/password-model.d.mts +7 -10
- package/dist/drizzle/password-target.d.mts +7 -8
- package/dist/drizzle/password-target.mjs +23 -68
- package/dist/drizzle/password-target.mjs.map +1 -1
- package/dist/drizzle/pg-identity.mjs +3 -6
- package/dist/drizzle/pg-identity.mjs.map +1 -1
- package/dist/drizzle/phone-drivers.mjs +24 -0
- package/dist/drizzle/phone-drivers.mjs.map +1 -0
- package/dist/drizzle/phone-model.d.mts +13 -104
- package/dist/drizzle/phone-model.mjs +5 -33
- package/dist/drizzle/phone-model.mjs.map +1 -1
- package/dist/drizzle/phone-target.mjs +22 -171
- package/dist/drizzle/phone-target.mjs.map +1 -1
- package/dist/drizzle/proof-drivers.mjs +24 -0
- package/dist/drizzle/proof-drivers.mjs.map +1 -0
- package/dist/drizzle/proof-model.d.mts +7 -15
- package/dist/drizzle/proof-target.d.mts +5 -5
- package/dist/drizzle/proof-target.mjs +14 -28
- package/dist/drizzle/proof-target.mjs.map +1 -1
- package/dist/drizzle/session-drivers.mjs +97 -0
- package/dist/drizzle/session-drivers.mjs.map +1 -0
- package/dist/drizzle/session-model.d.mts +11 -22
- package/dist/drizzle/sqlite-do-database.d.mts +3 -3
- package/dist/drizzle/sqlite-do-database.mjs +6 -1
- package/dist/drizzle/sqlite-do-database.mjs.map +1 -1
- package/dist/drizzle/sqlite-identity.mjs +3 -5
- package/dist/drizzle/sqlite-identity.mjs.map +1 -1
- package/dist/drizzle/step-up-model.d.mts +2 -5
- package/dist/drizzle/storage-validation.mjs +2 -1
- package/dist/drizzle/storage-validation.mjs.map +1 -1
- package/dist/drizzle/totp-model.d.mts +7 -74
- package/dist/drizzle/totp-model.mjs +1 -5
- package/dist/drizzle/totp-model.mjs.map +1 -1
- package/dist/drizzle/totp-target.mjs +39 -75
- package/dist/drizzle/totp-target.mjs.map +1 -1
- package/dist/drizzle/transaction-handle.mjs +13 -0
- package/dist/drizzle/transaction-handle.mjs.map +1 -0
- package/dist/drizzle/transaction-mysql.mjs +43 -12
- package/dist/drizzle/transaction-mysql.mjs.map +1 -1
- package/dist/index.d.mts +17 -22
- package/dist/index.mjs +10 -16
- package/dist/internal/drizzle-postgres.mjs +4 -6
- package/dist/internal/drizzle-postgres.mjs.map +1 -1
- package/dist/internal/drizzle-sqlite.mjs +4 -6
- package/dist/internal/drizzle-sqlite.mjs.map +1 -1
- package/package.json +1 -1
- package/src/D1.ts +77 -74
- package/src/Libsql.ts +65 -105
- package/src/Mysql2.ts +52 -87
- package/src/Pglite.ts +74 -81
- package/src/Postgres.ts +74 -81
- package/src/SqliteBun.ts +65 -113
- package/src/SqliteDo.ts +58 -106
- package/src/SqliteNode.ts +65 -113
- package/src/SqliteWasm.ts +65 -113
- package/src/drizzle/d1-identity.ts +2 -2
- package/src/drizzle/driver-types.ts +26 -0
- package/src/drizzle/email-drivers.ts +320 -0
- package/src/drizzle/email-model.ts +24 -78
- package/src/drizzle/email-target.ts +118 -211
- package/src/drizzle/model.ts +0 -2
- package/src/drizzle/mysql-identity.ts +4 -24
- package/src/drizzle/native-clock.ts +21 -0
- package/src/drizzle/native-database.ts +59 -18
- package/src/drizzle/native-sql-table.ts +104 -87
- package/src/drizzle/native-target.ts +120 -0
- package/src/drizzle/oauth-connected-drivers.ts +24 -233
- package/src/drizzle/oauth-connected-model.ts +3 -93
- package/src/drizzle/oauth-connected-reference.ts +16 -25
- package/src/drizzle/oauth-drivers.ts +58 -99
- package/src/drizzle/oauth-model.ts +27 -132
- package/src/drizzle/oauth-target.ts +250 -33
- package/src/drizzle/passkey/target.ts +205 -0
- package/src/drizzle/passkey/write-target.ts +91 -0
- package/src/drizzle/passkey-drivers.ts +35 -133
- package/src/drizzle/passkey-model.ts +3 -81
- package/src/drizzle/passkey-registration-ceremony-model.ts +5 -25
- package/src/drizzle/passkey-write-drivers.ts +32 -102
- package/src/drizzle/passkey-write-model.ts +10 -44
- package/src/drizzle/password-drivers.ts +286 -0
- package/src/drizzle/password-model.ts +10 -44
- package/src/drizzle/password-target.ts +85 -239
- package/src/drizzle/pg-identity.ts +4 -19
- package/src/drizzle/phone-drivers.ts +142 -0
- package/src/drizzle/phone-model.ts +22 -162
- package/src/drizzle/phone-target.ts +51 -493
- package/src/drizzle/proof-drivers.ts +123 -0
- package/src/drizzle/proof-model.ts +12 -123
- package/src/drizzle/proof-target.ts +38 -102
- package/src/drizzle/session-drivers.ts +696 -0
- package/src/drizzle/session-model.ts +54 -118
- package/src/drizzle/sqlite-do-database.ts +8 -0
- package/src/drizzle/sqlite-identity.ts +4 -22
- package/src/drizzle/step-up-model.ts +13 -37
- package/src/drizzle/storage-validation.ts +2 -1
- package/src/drizzle/totp-model.ts +20 -77
- package/src/drizzle/totp-target.ts +121 -261
- package/src/drizzle/transaction-handle.ts +41 -0
- package/src/drizzle/transaction-mysql.ts +91 -26
- package/src/index.ts +7 -122
- package/src/internal/drizzle-postgres.ts +4 -7
- package/src/internal/drizzle-sqlite.ts +4 -7
- package/dist/drizzle/crypto.mjs +0 -11
- package/dist/drizzle/crypto.mjs.map +0 -1
- package/dist/drizzle/d1-emails.d.mts +0 -62
- package/dist/drizzle/d1-emails.mjs +0 -626
- package/dist/drizzle/d1-emails.mjs.map +0 -1
- package/dist/drizzle/d1-generated-statement.mjs +0 -79
- package/dist/drizzle/d1-generated-statement.mjs.map +0 -1
- package/dist/drizzle/d1-oauth.d.mts +0 -331
- package/dist/drizzle/d1-oauth.mjs +0 -79
- package/dist/drizzle/d1-oauth.mjs.map +0 -1
- package/dist/drizzle/d1-passkey.d.mts +0 -37
- package/dist/drizzle/d1-passkey.mjs +0 -98
- package/dist/drizzle/d1-passkey.mjs.map +0 -1
- package/dist/drizzle/d1-password-prepared.d.mts +0 -25
- package/dist/drizzle/d1-password-prepared.mjs +0 -473
- package/dist/drizzle/d1-password-prepared.mjs.map +0 -1
- package/dist/drizzle/d1-passwords.d.mts +0 -70
- package/dist/drizzle/d1-passwords.mjs +0 -808
- package/dist/drizzle/d1-passwords.mjs.map +0 -1
- package/dist/drizzle/d1-phone.d.mts +0 -23
- package/dist/drizzle/d1-phone.mjs +0 -33
- package/dist/drizzle/d1-phone.mjs.map +0 -1
- package/dist/drizzle/d1-planning.d.mts +0 -11
- package/dist/drizzle/d1-planning.mjs +0 -43
- package/dist/drizzle/d1-planning.mjs.map +0 -1
- package/dist/drizzle/d1-proofs.d.mts +0 -80
- package/dist/drizzle/d1-proofs.mjs +0 -842
- package/dist/drizzle/d1-proofs.mjs.map +0 -1
- package/dist/drizzle/d1-sessions.d.mts +0 -68
- package/dist/drizzle/d1-sessions.mjs +0 -987
- package/dist/drizzle/d1-sessions.mjs.map +0 -1
- package/dist/drizzle/d1-totp.d.mts +0 -23
- package/dist/drizzle/d1-totp.mjs +0 -30
- package/dist/drizzle/d1-totp.mjs.map +0 -1
- package/dist/drizzle/email-registration.d.mts +0 -33
- package/dist/drizzle/email-registration.mjs +0 -281
- package/dist/drizzle/email-registration.mjs.map +0 -1
- package/dist/drizzle/email-sql.d.mts +0 -1
- package/dist/drizzle/email-sql.mjs +0 -9
- package/dist/drizzle/email-sql.mjs.map +0 -1
- package/dist/drizzle/mysql-emails.d.mts +0 -71
- package/dist/drizzle/mysql-emails.mjs +0 -43
- package/dist/drizzle/mysql-emails.mjs.map +0 -1
- package/dist/drizzle/mysql-password-prepared.d.mts +0 -30
- package/dist/drizzle/mysql-password-prepared.mjs +0 -21
- package/dist/drizzle/mysql-password-prepared.mjs.map +0 -1
- package/dist/drizzle/mysql-passwords.d.mts +0 -71
- package/dist/drizzle/mysql-passwords.mjs +0 -43
- package/dist/drizzle/mysql-passwords.mjs.map +0 -1
- package/dist/drizzle/mysql-proofs.d.mts +0 -75
- package/dist/drizzle/mysql-proofs.mjs +0 -28
- package/dist/drizzle/mysql-proofs.mjs.map +0 -1
- package/dist/drizzle/mysql-sessions.d.mts +0 -92
- package/dist/drizzle/mysql-sessions.mjs +0 -58
- package/dist/drizzle/mysql-sessions.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-model.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-target.d.mts +0 -6
- package/dist/drizzle/oauth-connected-target.mjs +0 -12
- package/dist/drizzle/oauth-connected-target.mjs.map +0 -1
- package/dist/drizzle/oauth-kernel.mjs +0 -11
- package/dist/drizzle/oauth-kernel.mjs.map +0 -1
- package/dist/drizzle/oauth-mysql.mjs +0 -8
- package/dist/drizzle/oauth-mysql.mjs.map +0 -1
- package/dist/drizzle/passkey-kernel.mjs +0 -8
- package/dist/drizzle/passkey-kernel.mjs.map +0 -1
- package/dist/drizzle/passkey-model.mjs.map +0 -1
- package/dist/drizzle/passkey-registration-ceremony-model.mjs +0 -2
- package/dist/drizzle/passkey-state.mjs +0 -7
- package/dist/drizzle/passkey-state.mjs.map +0 -1
- package/dist/drizzle/passkey-target.d.mts +0 -2
- package/dist/drizzle/passkey-target.mjs +0 -7
- package/dist/drizzle/passkey-target.mjs.map +0 -1
- package/dist/drizzle/passkey-write-target.d.mts +0 -5
- package/dist/drizzle/passkey-write-target.mjs +0 -7
- package/dist/drizzle/passkey-write-target.mjs.map +0 -1
- package/dist/drizzle/password-prepared-model.d.mts +0 -92
- package/dist/drizzle/password-prepared-model.mjs +0 -11
- package/dist/drizzle/password-prepared-model.mjs.map +0 -1
- package/dist/drizzle/password-prepared-sql.mjs +0 -395
- package/dist/drizzle/password-prepared-sql.mjs.map +0 -1
- package/dist/drizzle/password-prepared-state.mjs +0 -104
- package/dist/drizzle/password-prepared-state.mjs.map +0 -1
- package/dist/drizzle/password-prepared-target.d.mts +0 -13
- package/dist/drizzle/password-prepared-target.mjs +0 -62
- package/dist/drizzle/password-prepared-target.mjs.map +0 -1
- package/dist/drizzle/password-registration.d.mts +0 -7
- package/dist/drizzle/password-registration.mjs +0 -137
- package/dist/drizzle/password-registration.mjs.map +0 -1
- package/dist/drizzle/password-sql.d.mts +0 -1
- package/dist/drizzle/password-sql.mjs +0 -10
- package/dist/drizzle/password-sql.mjs.map +0 -1
- package/dist/drizzle/pg-emails.d.mts +0 -72
- package/dist/drizzle/pg-emails.mjs +0 -43
- package/dist/drizzle/pg-emails.mjs.map +0 -1
- package/dist/drizzle/pg-password-prepared.d.mts +0 -31
- package/dist/drizzle/pg-password-prepared.mjs +0 -21
- package/dist/drizzle/pg-password-prepared.mjs.map +0 -1
- package/dist/drizzle/pg-passwords.d.mts +0 -72
- package/dist/drizzle/pg-passwords.mjs +0 -43
- package/dist/drizzle/pg-passwords.mjs.map +0 -1
- package/dist/drizzle/pg-proofs.d.mts +0 -76
- package/dist/drizzle/pg-proofs.mjs +0 -27
- package/dist/drizzle/pg-proofs.mjs.map +0 -1
- package/dist/drizzle/pg-sessions.d.mts +0 -93
- package/dist/drizzle/pg-sessions.mjs +0 -58
- package/dist/drizzle/pg-sessions.mjs.map +0 -1
- package/dist/drizzle/phone-state.mjs +0 -14
- package/dist/drizzle/phone-state.mjs.map +0 -1
- package/dist/drizzle/phone-target.d.mts +0 -15
- package/dist/drizzle/proof-sql.d.mts +0 -1
- package/dist/drizzle/proof-sql.mjs +0 -8
- package/dist/drizzle/proof-sql.mjs.map +0 -1
- package/dist/drizzle/query-operations.mjs +0 -31
- package/dist/drizzle/query-operations.mjs.map +0 -1
- package/dist/drizzle/session-sql.d.mts +0 -1
- package/dist/drizzle/session-sql.mjs +0 -9
- package/dist/drizzle/session-sql.mjs.map +0 -1
- package/dist/drizzle/session-target.d.mts +0 -30
- package/dist/drizzle/session-target.mjs +0 -49
- package/dist/drizzle/session-target.mjs.map +0 -1
- package/dist/drizzle/sqlite-emails.mjs +0 -50
- package/dist/drizzle/sqlite-emails.mjs.map +0 -1
- package/dist/drizzle/sqlite-password-prepared.mjs +0 -26
- package/dist/drizzle/sqlite-password-prepared.mjs.map +0 -1
- package/dist/drizzle/sqlite-passwords.mjs +0 -54
- package/dist/drizzle/sqlite-passwords.mjs.map +0 -1
- package/dist/drizzle/sqlite-proofs.mjs +0 -34
- package/dist/drizzle/sqlite-proofs.mjs.map +0 -1
- package/dist/drizzle/sqlite-sessions.mjs +0 -79
- package/dist/drizzle/sqlite-sessions.mjs.map +0 -1
- package/dist/drizzle/standalone-guard.d.mts +0 -2
- package/dist/drizzle/standalone-guard.mjs +0 -21
- package/dist/drizzle/standalone-guard.mjs.map +0 -1
- package/dist/drizzle/totp-state.d.mts +0 -37
- package/dist/drizzle/totp-state.mjs +0 -287
- package/dist/drizzle/totp-state.mjs.map +0 -1
- package/dist/drizzle/totp-target.d.mts +0 -15
- package/dist/drizzle/transaction-execution.d.mts +0 -2
- package/dist/drizzle/transaction-execution.mjs +0 -11
- package/dist/drizzle/transaction-execution.mjs.map +0 -1
- package/dist/drizzle/transaction-owner.d.mts +0 -1
- package/dist/drizzle/transaction-owner.mjs +0 -8
- package/dist/drizzle/transaction-owner.mjs.map +0 -1
- package/src/drizzle/crypto.ts +0 -14
- package/src/drizzle/d1-emails.ts +0 -1945
- package/src/drizzle/d1-generated-statement.ts +0 -129
- package/src/drizzle/d1-oauth.ts +0 -360
- package/src/drizzle/d1-passkey.ts +0 -383
- package/src/drizzle/d1-password-prepared.ts +0 -1266
- package/src/drizzle/d1-passwords.ts +0 -2061
- package/src/drizzle/d1-phone.ts +0 -103
- package/src/drizzle/d1-planning.ts +0 -104
- package/src/drizzle/d1-proofs.ts +0 -2354
- package/src/drizzle/d1-sessions.ts +0 -2940
- package/src/drizzle/d1-totp.ts +0 -88
- package/src/drizzle/email-registration.ts +0 -850
- package/src/drizzle/email-sql.ts +0 -25
- package/src/drizzle/mysql-emails.ts +0 -343
- package/src/drizzle/mysql-password-prepared.ts +0 -198
- package/src/drizzle/mysql-passwords.ts +0 -343
- package/src/drizzle/mysql-proofs.ts +0 -196
- package/src/drizzle/mysql-sessions.ts +0 -780
- package/src/drizzle/oauth-connected-target.ts +0 -21
- package/src/drizzle/oauth-kernel.ts +0 -10
- package/src/drizzle/oauth-mysql.ts +0 -10
- package/src/drizzle/passkey-kernel.ts +0 -4
- package/src/drizzle/passkey-state.ts +0 -3
- package/src/drizzle/passkey-target.ts +0 -23
- package/src/drizzle/passkey-write-target.ts +0 -9
- package/src/drizzle/password-prepared-model.ts +0 -241
- package/src/drizzle/password-prepared-sql.ts +0 -1202
- package/src/drizzle/password-prepared-state.ts +0 -231
- package/src/drizzle/password-prepared-target.ts +0 -169
- package/src/drizzle/password-registration.ts +0 -369
- package/src/drizzle/password-sql.ts +0 -16
- package/src/drizzle/pg-emails.ts +0 -343
- package/src/drizzle/pg-password-prepared.ts +0 -199
- package/src/drizzle/pg-passwords.ts +0 -342
- package/src/drizzle/pg-proofs.ts +0 -206
- package/src/drizzle/pg-sessions.ts +0 -789
- package/src/drizzle/phone-state.ts +0 -21
- package/src/drizzle/proof-sql.ts +0 -10
- package/src/drizzle/query-operations.ts +0 -49
- package/src/drizzle/session-sql.ts +0 -15
- package/src/drizzle/session-target.ts +0 -337
- package/src/drizzle/sqlite-emails.ts +0 -393
- package/src/drizzle/sqlite-password-prepared.ts +0 -230
- package/src/drizzle/sqlite-passwords.ts +0 -497
- package/src/drizzle/sqlite-proofs.ts +0 -229
- package/src/drizzle/sqlite-sessions.ts +0 -1013
- package/src/drizzle/totp-state.ts +0 -525
- package/src/drizzle/transaction-execution.ts +0 -13
- package/src/drizzle/transaction-owner.ts +0 -11
|
@@ -1,327 +1,187 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
1
|
+
import { makeNativeTotpServices, type NativeTotpMapping } from "@yielded/auth-persistence/Adapter";
|
|
2
|
+
import type { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
3
3
|
import {
|
|
4
4
|
TotpConfigurationError,
|
|
5
|
-
|
|
6
|
-
TotpMutation,
|
|
5
|
+
TotpUnavailable,
|
|
7
6
|
TotpPolicy,
|
|
8
7
|
TotpPersistence,
|
|
9
8
|
} from "@yielded/auth/Totp";
|
|
10
9
|
import type { Table } from "drizzle-orm";
|
|
11
|
-
|
|
12
|
-
import { type Crypto, Context, Effect, Schema } from "effect";
|
|
13
|
-
import type { Statement } from "effect/sql/Statement";
|
|
10
|
+
import { Effect, Schema, type Context, type Crypto } from "effect";
|
|
14
11
|
|
|
15
|
-
import {
|
|
12
|
+
import type { D1BatchStatements } from "./D1BatchStatements";
|
|
13
|
+
import type { NativeDriverDatabase, NativeDriverTransaction } from "./driver-types";
|
|
16
14
|
import type { PersistenceMappingError } from "./model";
|
|
17
|
-
import {
|
|
15
|
+
import { nativeClock } from "./native-clock";
|
|
16
|
+
import { NativeDatabase, nativeDatabase } from "./native-database";
|
|
17
|
+
import {
|
|
18
|
+
nativeTarget,
|
|
19
|
+
coordinateNativeTarget,
|
|
20
|
+
type NativeTargetConfiguration,
|
|
21
|
+
} from "./native-target";
|
|
18
22
|
import { validateDrizzleStorage } from "./storage-validation";
|
|
19
23
|
import type { SuppliedService } from "./SuppliedService";
|
|
20
|
-
import {
|
|
21
|
-
type TotpMapping,
|
|
22
|
-
type TotpMappingSource,
|
|
23
|
-
type TotpPersistenceServices,
|
|
24
|
-
requiredTotpConstraints,
|
|
25
|
-
} from "./totp-model";
|
|
26
|
-
import {
|
|
27
|
-
captureTotp,
|
|
28
|
-
CurrentTotpTransaction,
|
|
29
|
-
invariant,
|
|
30
|
-
mutateTotp,
|
|
31
|
-
unavailable,
|
|
32
|
-
} from "./totp-state";
|
|
33
|
-
import {
|
|
34
|
-
coordinateTransactionOwner,
|
|
35
|
-
makeTransactionExecution,
|
|
36
|
-
sqlClientTransactionStandaloneGuard,
|
|
37
|
-
type TransactionExecution,
|
|
38
|
-
type TransactionTargetConfiguration,
|
|
39
|
-
type TransactionCoordinatorError,
|
|
40
|
-
} from "./transaction-execution";
|
|
41
|
-
import type { TransactionNativeDatabase } from "./transaction-owner";
|
|
42
|
-
export type TotpTargetConfiguration = TransactionTargetConfiguration<TotpUnavailable>;
|
|
43
|
-
|
|
44
|
-
export type TotpCoordinatorError<E> =
|
|
45
|
-
| TransactionCoordinatorError<E, TotpUnavailable>
|
|
46
|
-
| TotpConfigurationError
|
|
47
|
-
| PersistenceMappingError;
|
|
48
|
-
|
|
49
|
-
export const sqlClientTotpStandaloneGuard = (
|
|
50
|
-
service: Parameters<typeof sqlClientTransactionStandaloneGuard>[1],
|
|
51
|
-
) => sqlClientTransactionStandaloneGuard(unavailable, service);
|
|
52
|
-
|
|
53
|
-
const validateMapping = <M>(original: M, configuration: TotpTargetConfiguration): M => {
|
|
54
|
-
const mapping = original as any;
|
|
55
|
-
|
|
56
|
-
invariant(mapping.moduleId.length > 0);
|
|
57
|
-
Schema.decodeSync(TotpPolicy)(mapping.policy);
|
|
58
|
-
for (const [key, value] of Object.entries(requiredTotpConstraints))
|
|
59
|
-
invariant(mapping.constraints?.[key] === value);
|
|
60
|
-
if (configuration.mode === "batch") invariant(mapping.d1?.primary === true);
|
|
61
|
-
|
|
62
|
-
return Object.freeze({
|
|
63
|
-
...mapping,
|
|
64
|
-
policy: Object.freeze({ ...mapping.policy }),
|
|
65
|
-
subject: Object.freeze({ ...mapping.subject }),
|
|
66
|
-
factor: Object.freeze({ ...mapping.factor }),
|
|
67
|
-
credential: Object.freeze({ ...mapping.credential }),
|
|
68
|
-
subjectIds: Object.freeze({ ...mapping.subjectIds }),
|
|
69
|
-
});
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const services = Effect.fnUntraced(function* (
|
|
73
|
-
mapping: any,
|
|
74
|
-
execution: TransactionExecution<TotpUnavailable, CurrentTotpTransaction>,
|
|
75
|
-
): Effect.fn.Return<TotpPersistenceServices, never, LifecycleHooks> {
|
|
76
|
-
const hooks = yield* LifecycleHooks;
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
totpPersistence: TotpPersistence.of({
|
|
80
|
-
snapshot: Effect.fn("TotpNative.snapshot")(
|
|
81
|
-
function* (input) {
|
|
82
|
-
const captured = { ...input };
|
|
83
|
-
|
|
84
|
-
invariant(captured.moduleId === mapping.moduleId);
|
|
85
|
-
yield* execution.admit;
|
|
86
|
-
|
|
87
|
-
return yield* execution
|
|
88
|
-
.run(
|
|
89
|
-
Effect.map(captureTotp(mapping, captured.subjectId), (value) => value?.snapshot),
|
|
90
|
-
false,
|
|
91
|
-
)
|
|
92
|
-
.pipe(Effect.provideService(LifecycleHooks, hooks));
|
|
93
|
-
},
|
|
94
|
-
Effect.catchDefect(() => Effect.fail(unavailable())),
|
|
95
|
-
),
|
|
96
|
-
mutate: (original, prepare) =>
|
|
97
|
-
Effect.suspend(() => {
|
|
98
|
-
// Detach caller-owned payloads before any driver or hook can suspend.
|
|
99
|
-
const codec = Schema.toCodecIso(TotpMutation);
|
|
100
|
-
const input = Schema.decodeSync(codec)(Schema.encodeSync(codec)(original));
|
|
101
|
-
|
|
102
|
-
return execution.admit.pipe(
|
|
103
|
-
Effect.andThen(
|
|
104
|
-
execution.run(
|
|
105
|
-
Effect.gen(function* () {
|
|
106
|
-
const decision = yield* mutateTotp(mapping, input),
|
|
107
|
-
owner = yield* CurrentTotpTransaction;
|
|
108
|
-
|
|
109
|
-
owner.guards.push(owner.journal.prepare(undefined));
|
|
110
|
-
const receipt = prepare(decision, owner.journal);
|
|
111
|
-
|
|
112
|
-
invariant(receipt?._tag === "PreparedCommit" && Effect.isEffect(receipt.read));
|
|
113
|
-
owner.guards.push(receipt as any);
|
|
114
|
-
|
|
115
|
-
return receipt;
|
|
116
|
-
}),
|
|
117
|
-
),
|
|
118
|
-
),
|
|
119
|
-
Effect.provideService(LifecycleHooks, hooks),
|
|
120
|
-
);
|
|
121
|
-
}).pipe(Effect.catchDefect(() => Effect.fail(unavailable()))),
|
|
122
|
-
}),
|
|
123
|
-
};
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
export const makeTargetTotpPersistence = <
|
|
127
|
-
S extends Table,
|
|
128
|
-
F extends Table,
|
|
129
|
-
C extends Table,
|
|
130
|
-
N,
|
|
131
|
-
RSetup = never,
|
|
132
|
-
>(
|
|
133
|
-
source: TotpMappingSource<TotpMapping<S, F, C, N>, RSetup>,
|
|
134
|
-
configuration: TotpTargetConfiguration,
|
|
135
|
-
) =>
|
|
136
|
-
Effect.gen(function* () {
|
|
137
|
-
const original = yield* Effect.isEffect(source) ? source : Effect.succeed(source);
|
|
138
|
-
|
|
139
|
-
const mapping = yield* Effect.try({
|
|
140
|
-
try: () => validateMapping(original, configuration),
|
|
141
|
-
catch: () => TotpConfigurationError.make({}),
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
yield* validateDrizzleStorage(mapping).pipe(
|
|
145
|
-
Effect.mapError(() => TotpConfigurationError.make({})),
|
|
146
|
-
);
|
|
24
|
+
import type { TotpMapping, TotpMappingSource } from "./totp-model";
|
|
147
25
|
|
|
148
|
-
|
|
149
|
-
CurrentTotpTransaction,
|
|
150
|
-
configuration,
|
|
151
|
-
unavailable,
|
|
152
|
-
randomId,
|
|
153
|
-
);
|
|
26
|
+
const unavailable = () => TotpUnavailable.make({});
|
|
154
27
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const original = yield* Effect.isEffect(source) ? source : Effect.succeed(source);
|
|
174
|
-
|
|
175
|
-
const mapping = yield* Effect.try({
|
|
176
|
-
try: () => validateMapping(original, configuration),
|
|
177
|
-
catch: () => TotpConfigurationError.make({}),
|
|
178
|
-
});
|
|
28
|
+
/** Driver metadata is compiled once; the factor workflow and commit owner are shared. */
|
|
29
|
+
export const makeTotpTarget = <DatabaseId, D extends NativeDriverDatabase>(
|
|
30
|
+
databaseService: Context.Service<DatabaseId, D>,
|
|
31
|
+
configuration: NativeTargetConfiguration,
|
|
32
|
+
) => {
|
|
33
|
+
const validate = Effect.fnUntraced(
|
|
34
|
+
function* (mapping: NativeTotpMapping) {
|
|
35
|
+
yield* validateDrizzleStorage(mapping);
|
|
36
|
+
yield* Schema.decodeEffect(TotpPolicy)(mapping.policy);
|
|
37
|
+
if (
|
|
38
|
+
mapping.moduleId.length === 0 ||
|
|
39
|
+
(configuration.mode === "batch" &&
|
|
40
|
+
(mapping.d1?.primary !== true || mapping.subject.requirementColumns === undefined))
|
|
41
|
+
)
|
|
42
|
+
return yield* TotpConfigurationError.make({});
|
|
43
|
+
},
|
|
44
|
+
Effect.mapError(() => TotpConfigurationError.make({})),
|
|
45
|
+
);
|
|
179
46
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
);
|
|
47
|
+
const services = Effect.fnUntraced(function* (mapping: NativeTotpMapping) {
|
|
48
|
+
const target = yield* nativeTarget(configuration);
|
|
183
49
|
|
|
184
|
-
return yield*
|
|
185
|
-
database,
|
|
186
|
-
CurrentTotpTransaction,
|
|
187
|
-
configuration,
|
|
188
|
-
Effect.void,
|
|
189
|
-
unavailable,
|
|
190
|
-
randomId,
|
|
191
|
-
(execution) => services(mapping, execution),
|
|
192
|
-
(transaction, acquireServices, append) =>
|
|
193
|
-
Effect.flatMap(acquireServices, (boundServices) =>
|
|
194
|
-
body(transaction, boundServices, append),
|
|
195
|
-
),
|
|
196
|
-
);
|
|
50
|
+
return yield* target.provide(makeNativeTotpServices(target.tables, mapping));
|
|
197
51
|
});
|
|
198
52
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
:
|
|
53
|
+
const mapping = <S extends Table, F extends Table, C extends Table, N, P extends Table>(
|
|
54
|
+
value: TotpMapping<S, F, C, N, P>,
|
|
55
|
+
): NativeTotpMapping =>
|
|
56
|
+
({
|
|
57
|
+
...value,
|
|
58
|
+
...(value.pending === undefined
|
|
59
|
+
? {}
|
|
60
|
+
: { pending: { ...value.pending, clock: nativeClock(value.pending.clock) } }),
|
|
61
|
+
}) as unknown as NativeTotpMapping;
|
|
202
62
|
|
|
203
|
-
/** Concrete driver wrappers select transaction mode. */
|
|
204
|
-
export const makeTotpTarget = <
|
|
205
|
-
DatabaseId,
|
|
206
|
-
D extends { readonly transaction: any },
|
|
207
|
-
T extends Table,
|
|
208
|
-
Extra = unknown,
|
|
209
|
-
Synchronous extends boolean = false,
|
|
210
|
-
>(
|
|
211
|
-
databaseService: Context.Service<DatabaseId, D>,
|
|
212
|
-
configuration: TotpTargetConfiguration,
|
|
213
|
-
) => {
|
|
214
63
|
function coordinateTotpPersistence<
|
|
215
|
-
|
|
216
|
-
S extends
|
|
217
|
-
F extends
|
|
218
|
-
C extends
|
|
64
|
+
DB extends D,
|
|
65
|
+
S extends Table,
|
|
66
|
+
F extends Table,
|
|
67
|
+
C extends Table,
|
|
219
68
|
N,
|
|
69
|
+
P extends Table,
|
|
220
70
|
A,
|
|
221
71
|
E,
|
|
222
72
|
R,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
73
|
+
DE,
|
|
74
|
+
DR,
|
|
75
|
+
RS = never,
|
|
226
76
|
>(
|
|
227
|
-
acquire: Effect.Effect<
|
|
77
|
+
acquire: Effect.Effect<DB, DE, DR>,
|
|
228
78
|
options: {
|
|
229
|
-
readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N
|
|
79
|
+
readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>;
|
|
230
80
|
readonly transaction?: never;
|
|
231
81
|
},
|
|
232
|
-
body: Effect.Effect<A, E,
|
|
82
|
+
body: Effect.Effect<A, E, R>,
|
|
233
83
|
): Effect.Effect<
|
|
234
84
|
A,
|
|
235
|
-
|
|
236
|
-
|
|
|
237
|
-
| Crypto.Crypto
|
|
238
|
-
| LifecycleHooks
|
|
239
|
-
| RSetup
|
|
240
|
-
| DatabaseRequirements
|
|
85
|
+
E | DE | TotpUnavailable | TotpConfigurationError | PersistenceMappingError,
|
|
86
|
+
Exclude<R, TotpPersistence | D1BatchStatements> | DR | RS | LifecycleHooks | Crypto.Crypto
|
|
241
87
|
>;
|
|
242
88
|
function coordinateTotpPersistence<
|
|
243
|
-
|
|
244
|
-
S extends
|
|
245
|
-
F extends
|
|
246
|
-
C extends
|
|
89
|
+
DB extends D,
|
|
90
|
+
S extends Table,
|
|
91
|
+
F extends Table,
|
|
92
|
+
C extends Table,
|
|
247
93
|
N,
|
|
94
|
+
P extends Table,
|
|
248
95
|
A,
|
|
249
96
|
E,
|
|
250
97
|
R,
|
|
98
|
+
DE,
|
|
99
|
+
DR,
|
|
251
100
|
TxId,
|
|
252
101
|
TxShape,
|
|
253
|
-
|
|
254
|
-
DatabaseError = never,
|
|
255
|
-
DatabaseRequirements = never,
|
|
102
|
+
RS = never,
|
|
256
103
|
>(
|
|
257
|
-
acquire: Effect.Effect<
|
|
104
|
+
acquire: Effect.Effect<DB, DE, DR>,
|
|
258
105
|
options: {
|
|
259
|
-
readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N
|
|
260
|
-
readonly transaction: SuppliedService<TxId, NoInfer<
|
|
106
|
+
readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>;
|
|
107
|
+
readonly transaction: SuppliedService<TxId, NoInfer<NativeDriverTransaction<DB>>, TxShape>;
|
|
261
108
|
},
|
|
262
|
-
body: Effect.Effect<A, E,
|
|
109
|
+
body: Effect.Effect<A, E, R>,
|
|
263
110
|
): Effect.Effect<
|
|
264
111
|
A,
|
|
265
|
-
|
|
266
|
-
|
|
|
267
|
-
|
|
|
112
|
+
E | DE | TotpUnavailable | TotpConfigurationError | PersistenceMappingError,
|
|
113
|
+
| Exclude<R, TotpPersistence | D1BatchStatements | TxId>
|
|
114
|
+
| DR
|
|
115
|
+
| RS
|
|
268
116
|
| LifecycleHooks
|
|
269
|
-
|
|
|
270
|
-
| DatabaseRequirements
|
|
117
|
+
| Crypto.Crypto
|
|
271
118
|
>;
|
|
272
119
|
function coordinateTotpPersistence<
|
|
273
|
-
|
|
274
|
-
S extends
|
|
275
|
-
F extends
|
|
276
|
-
C extends
|
|
120
|
+
DB extends D,
|
|
121
|
+
S extends Table,
|
|
122
|
+
F extends Table,
|
|
123
|
+
C extends Table,
|
|
277
124
|
N,
|
|
125
|
+
P extends Table,
|
|
278
126
|
A,
|
|
279
127
|
E,
|
|
280
128
|
R,
|
|
129
|
+
DE,
|
|
130
|
+
DR,
|
|
281
131
|
TxId,
|
|
282
132
|
TxShape,
|
|
283
|
-
|
|
284
|
-
DatabaseError = never,
|
|
285
|
-
DatabaseRequirements = never,
|
|
133
|
+
RS = never,
|
|
286
134
|
>(
|
|
287
|
-
acquire: Effect.Effect<
|
|
135
|
+
acquire: Effect.Effect<DB, DE, DR>,
|
|
288
136
|
options: {
|
|
289
|
-
readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N
|
|
290
|
-
readonly transaction?: SuppliedService<TxId, NoInfer<
|
|
137
|
+
readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>;
|
|
138
|
+
readonly transaction?: SuppliedService<TxId, NoInfer<NativeDriverTransaction<DB>>, TxShape>;
|
|
291
139
|
},
|
|
292
140
|
body: Effect.Effect<A, E, R>,
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
141
|
+
) {
|
|
142
|
+
return Effect.gen(function* () {
|
|
143
|
+
const value = mapping(
|
|
144
|
+
yield* Effect.isEffect(options.mapping) ? options.mapping : Effect.succeed(options.mapping),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const database = yield* nativeDatabase(acquire);
|
|
148
|
+
|
|
149
|
+
yield* validate(value).pipe(Effect.provideService(NativeDatabase, database));
|
|
150
|
+
|
|
151
|
+
return yield* coordinateNativeTarget(
|
|
152
|
+
unavailable,
|
|
153
|
+
database,
|
|
302
154
|
configuration,
|
|
303
|
-
(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
): Effect.Effect<A, E, Exclude<R, TotpPersistence>> => {
|
|
307
|
-
const provided = Context.make(TotpPersistence, services.totpPersistence);
|
|
308
|
-
const work = Effect.provideContext(body, provided);
|
|
155
|
+
services(value),
|
|
156
|
+
(transaction: NativeDriverTransaction<DB>, bound) => {
|
|
157
|
+
const work = body.pipe(Effect.provideService(TotpPersistence, bound.totpPersistence));
|
|
309
158
|
|
|
310
159
|
return options.transaction === undefined
|
|
311
160
|
? work
|
|
312
161
|
: Effect.provideService(work, options.transaction, options.transaction.of(transaction));
|
|
313
162
|
},
|
|
314
|
-
)
|
|
315
|
-
);
|
|
163
|
+
);
|
|
164
|
+
});
|
|
316
165
|
}
|
|
317
166
|
|
|
318
167
|
return {
|
|
319
|
-
makeTotpPersistenceServices: <S extends T, F extends T, C extends T, N, RSetup = never>(
|
|
320
|
-
mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>,
|
|
321
|
-
) =>
|
|
322
|
-
makeTargetTotpPersistence(mapping, configuration).pipe(
|
|
323
|
-
Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),
|
|
324
|
-
),
|
|
325
168
|
coordinateTotpPersistence,
|
|
169
|
+
makeTotpPersistenceServices: <
|
|
170
|
+
S extends Table,
|
|
171
|
+
F extends Table,
|
|
172
|
+
C extends Table,
|
|
173
|
+
N,
|
|
174
|
+
P extends Table = Table,
|
|
175
|
+
RS = never,
|
|
176
|
+
>(
|
|
177
|
+
source: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>,
|
|
178
|
+
) =>
|
|
179
|
+
Effect.gen(function* () {
|
|
180
|
+
const value = mapping(yield* Effect.isEffect(source) ? source : Effect.succeed(source));
|
|
181
|
+
|
|
182
|
+
yield* validate(value);
|
|
183
|
+
|
|
184
|
+
return yield* services(value);
|
|
185
|
+
}).pipe(Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService))),
|
|
326
186
|
};
|
|
327
187
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PasskeyConfigurationError } from "@yielded/auth/Passkey";
|
|
2
|
+
import { Predicate } from "effect";
|
|
3
|
+
|
|
4
|
+
/** Only foreign constructor types are erased; this creates Drizzle's actual
|
|
5
|
+
* transaction handle while the shared SqlClient owner holds the transaction. */
|
|
6
|
+
// oxlint-disable-next-line no-explicit-any
|
|
7
|
+
// oxlint-disable-next-line no-explicit-any
|
|
8
|
+
export type DrizzleTransactionFactory = (database: any) => object;
|
|
9
|
+
|
|
10
|
+
// oxlint-disable-next-line no-explicit-any
|
|
11
|
+
export type DrizzleTransactionConstructor = new (...arguments_: any[]) => object;
|
|
12
|
+
|
|
13
|
+
export const makeDrizzleTransactionHandle = (
|
|
14
|
+
database: object,
|
|
15
|
+
constructor: DrizzleTransactionConstructor | undefined,
|
|
16
|
+
): object => {
|
|
17
|
+
if (
|
|
18
|
+
constructor === undefined ||
|
|
19
|
+
!Predicate.hasProperty(database, "_") ||
|
|
20
|
+
!Predicate.hasProperty(database._, "session") ||
|
|
21
|
+
!Predicate.hasProperty(database._, "relations") ||
|
|
22
|
+
!Predicate.hasProperty(database, "select") ||
|
|
23
|
+
typeof database.select !== "function"
|
|
24
|
+
)
|
|
25
|
+
throw PasskeyConfigurationError.make({});
|
|
26
|
+
const selection: unknown = database.select();
|
|
27
|
+
|
|
28
|
+
if (!Predicate.hasProperty(selection, "dialect")) throw PasskeyConfigurationError.make({});
|
|
29
|
+
|
|
30
|
+
return new constructor(
|
|
31
|
+
selection.dialect,
|
|
32
|
+
database._.session,
|
|
33
|
+
database._.relations,
|
|
34
|
+
0,
|
|
35
|
+
Predicate.hasProperty(database, "forbidJsonb")
|
|
36
|
+
? database.forbidJsonb
|
|
37
|
+
: Predicate.hasProperty(database, "parseRqbJson")
|
|
38
|
+
? database.parseRqbJson
|
|
39
|
+
: undefined,
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -1,20 +1,77 @@
|
|
|
1
1
|
/* oxlint-disable no-explicit-any -- this private acquisition preserves the installed native transaction; public wrappers retain its exact type. */
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import type { SqlNativeCommit } from "@yielded/auth-persistence/Adapter";
|
|
3
|
+
import { PersistenceMappingError } from "@yielded/auth-persistence/Adapter";
|
|
4
|
+
import { EffectMysql2Transaction } from "drizzle-orm/effect-mysql2/session";
|
|
5
|
+
import { Context, Effect, Option } from "effect";
|
|
4
6
|
import { makeWithTransaction, type SqlClient } from "effect/sql/SqlClient";
|
|
7
|
+
import type { SqlError } from "effect/sql/SqlError";
|
|
8
|
+
|
|
9
|
+
interface MysqlTransactionScope {
|
|
10
|
+
readonly client: SqlClient;
|
|
11
|
+
readonly transaction: SqlClient["withTransaction"];
|
|
12
|
+
active: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class CurrentMysqlTransaction extends Context.Service<
|
|
16
|
+
CurrentMysqlTransaction,
|
|
17
|
+
MysqlTransactionScope
|
|
18
|
+
>()("@yielded/auth-persistence-drizzle/CurrentMysqlTransaction") {}
|
|
19
|
+
|
|
20
|
+
/** The native handle reuses the physical owner's exact savepoint closure. */
|
|
21
|
+
export const makeMysqlTransactionHandle = (
|
|
22
|
+
database: any,
|
|
23
|
+
): Effect.Effect<EffectMysql2Transaction<any, any>> =>
|
|
24
|
+
Effect.map(Effect.serviceOption(CurrentMysqlTransaction), (current) => {
|
|
25
|
+
if (Option.isNone(current))
|
|
26
|
+
throw PersistenceMappingError.make({
|
|
27
|
+
operation: "transaction",
|
|
28
|
+
cause: "MySQL transaction owner is required",
|
|
29
|
+
});
|
|
30
|
+
const scope = current.value;
|
|
31
|
+
|
|
32
|
+
class NativeTransaction extends EffectMysql2Transaction<any, any> {
|
|
33
|
+
override transaction<A, E, R>(body: (transaction: any) => Effect.Effect<A, E, R>) {
|
|
34
|
+
return Effect.gen(function* () {
|
|
35
|
+
const current = yield* Effect.serviceOption(CurrentMysqlTransaction);
|
|
36
|
+
|
|
37
|
+
if (
|
|
38
|
+
!scope.active ||
|
|
39
|
+
Option.isNone(current) ||
|
|
40
|
+
current.value !== scope ||
|
|
41
|
+
scope.client.transactionService !== database.$client.transactionService
|
|
42
|
+
)
|
|
43
|
+
return yield* Effect.die(
|
|
44
|
+
PersistenceMappingError.make({
|
|
45
|
+
operation: "transaction",
|
|
46
|
+
cause: "MySQL transaction handle escaped its owner",
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return yield* scope.transaction(
|
|
51
|
+
Effect.suspend(() =>
|
|
52
|
+
body(
|
|
53
|
+
new NativeTransaction(database.dialect, database._.session, database._.relations),
|
|
54
|
+
),
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return new NativeTransaction(database.dialect, database._.session, database._.relations);
|
|
62
|
+
});
|
|
5
63
|
|
|
6
64
|
/** Locking discovery and later SQL policy predicates must see the same current
|
|
7
65
|
* authority. MySQL's default repeatable-read snapshot is unsuitable after a
|
|
8
66
|
* contended authority lock. Own one connection and one-shot transaction mode;
|
|
9
67
|
* the pooled connection's session default is never changed. */
|
|
10
|
-
|
|
68
|
+
const withMysqlTransaction = <A, E, R, Failure>(
|
|
11
69
|
unavailable: () => Failure,
|
|
12
|
-
|
|
13
|
-
body: (transaction:
|
|
14
|
-
) =>
|
|
70
|
+
client: SqlClient,
|
|
71
|
+
body: (transaction: SqlClient["withTransaction"]) => Effect.Effect<A, E, R>,
|
|
72
|
+
): Effect.Effect<A, E | Failure | SqlError, R> =>
|
|
15
73
|
Effect.scoped(
|
|
16
74
|
Effect.gen(function* () {
|
|
17
|
-
const client: SqlClient = database.$client;
|
|
18
75
|
const connection = yield* client.reserve;
|
|
19
76
|
|
|
20
77
|
// Installed @effect/sql-mysql2 ConnectionImpl exposes its reserved native
|
|
@@ -71,31 +128,24 @@ export const mysqlTransaction = <A, E, R, Failure>(
|
|
|
71
128
|
statement(`ROLLBACK TO SAVEPOINT effect_auth_oauth_${id}`),
|
|
72
129
|
});
|
|
73
130
|
|
|
74
|
-
class NativeTransaction extends EffectMysql2Transaction<any, any> {
|
|
75
|
-
override transaction<A2, E2, R2>(nested: (tx: any) => Effect.Effect<A2, E2, R2>) {
|
|
76
|
-
return transaction(
|
|
77
|
-
Effect.suspend(() =>
|
|
78
|
-
nested(
|
|
79
|
-
new NativeTransaction(database.dialect, database._.session, database._.relations),
|
|
80
|
-
),
|
|
81
|
-
),
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const native = new NativeTransaction(
|
|
87
|
-
database.dialect,
|
|
88
|
-
database._.session,
|
|
89
|
-
database._.relations,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
131
|
const cleanup = statement("ROLLBACK").pipe(
|
|
93
132
|
Effect.andThen(statement(`SET TRANSACTION ISOLATION LEVEL ${isolation}`)),
|
|
94
133
|
Effect.onExit((exit) => (exit._tag === "Failure" ? Effect.sync(destroy) : Effect.void)),
|
|
95
134
|
Effect.orDie,
|
|
96
135
|
);
|
|
97
136
|
|
|
98
|
-
|
|
137
|
+
const scope: MysqlTransactionScope = { client, transaction, active: true };
|
|
138
|
+
|
|
139
|
+
return yield* transaction(
|
|
140
|
+
Effect.suspend(() => body(transaction)).pipe(
|
|
141
|
+
Effect.provideService(CurrentMysqlTransaction, scope),
|
|
142
|
+
),
|
|
143
|
+
).pipe(
|
|
144
|
+
Effect.ensuring(
|
|
145
|
+
Effect.sync(() => {
|
|
146
|
+
scope.active = false;
|
|
147
|
+
}),
|
|
148
|
+
),
|
|
99
149
|
// BEGIN/COMMIT acknowledgments can be lost after the server acted.
|
|
100
150
|
// Roll back any surviving transaction before resetting one-shot mode.
|
|
101
151
|
// Failed cleanup destroys the connection before its reserve is released;
|
|
@@ -104,3 +154,18 @@ export const mysqlTransaction = <A, E, R, Failure>(
|
|
|
104
154
|
);
|
|
105
155
|
}),
|
|
106
156
|
);
|
|
157
|
+
|
|
158
|
+
/** Shared owner capability: one reserved connection, one-shot READ COMMITTED. */
|
|
159
|
+
export const mysqlNativeCommit = (client: SqlClient): SqlNativeCommit["Service"] => ({
|
|
160
|
+
client,
|
|
161
|
+
withTransaction: (effect) =>
|
|
162
|
+
withMysqlTransaction(
|
|
163
|
+
() =>
|
|
164
|
+
PersistenceMappingError.make({
|
|
165
|
+
operation: "transaction",
|
|
166
|
+
cause: "Unable to acquire MySQL transaction ownership",
|
|
167
|
+
}),
|
|
168
|
+
client,
|
|
169
|
+
() => effect,
|
|
170
|
+
),
|
|
171
|
+
});
|