@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.
- 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 +90 -25
- 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 -1265
- package/src/drizzle/d1-passwords.ts +0 -2060
- 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 -1201
- 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-target.mjs","names":[],"sources":["../../src/drizzle/email-target.ts"],"sourcesContent":["import type { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport { EmailAddressPersistence, EmailSignInTargets, EmailUnavailable } from \"@yielded/auth/Email\";\nimport {\n coordinateCommit,\n hasCommitScope,\n LifecycleHooks,\n type HookConfigurationError,\n} from \"@yielded/auth/Hooks\";\n/* oxlint-disable no-explicit-any -- public driver wrappers restore concrete Drizzle generics. */\nimport { type Context, Effect, Layer } from \"effect\";\nimport type * as SqlError from \"effect/sql/SqlError\";\n\nimport {\n makeSqlEmailRegistrationAuthority,\n type EmailRegistrationAuthority,\n type EmailRegistrationConfiguration,\n} from \"./email-registration\";\nimport {\n CurrentEmailSql,\n makeSqlEmailAddressPersistence,\n makeSqlEmailSignInTargets,\n type EmailSqlConfiguration,\n type EmailSqlDatabase,\n type EmailSqlQuery,\n} from \"./email-sql\";\nimport type { ProofTargetConfiguration } from \"./proof-target\";\nimport { sqlClientStandaloneGuard, type TransactionService } from \"./standalone-guard\";\nimport { validateDrizzleStorage } from \"./storage-validation\";\n\nexport interface EmailTargetConfiguration {\n readonly mode: \"interactive\" | \"synchronous\";\n readonly locking: boolean;\n readonly standaloneGuard: Effect.Effect<void, EmailUnavailable>;\n readonly coordinatorGuard?: Effect.Effect<void, EmailUnavailable>;\n readonly generatedSubjectRows: (query: EmailSqlQuery) => EmailSqlQuery;\n readonly proof: ProofTargetConfiguration;\n}\n\ninterface TransactionOwner<Transaction> {\n readonly transaction: <A, E, R>(\n body: (transaction: Transaction) => Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E | SqlError.SqlError, R>;\n}\n\nexport type EmailCoordinatorError<E> =\n | E\n | EmailUnavailable\n | HookConfigurationError\n | SqlError.SqlError;\n\nexport const sqlClientEmailStandaloneGuard = (\n service: TransactionService | undefined,\n): Effect.Effect<void, EmailUnavailable> =>\n sqlClientStandaloneGuard(service, () => EmailUnavailable.make({}));\n\nconst proofConfiguration = (configuration: EmailTargetConfiguration, coordinated = false) => ({\n mode: configuration.proof.mode,\n locking: configuration.proof.locking,\n\n standaloneGuard: Effect.void,\n coordinated,\n insertIfAbsent: configuration.proof.insertIfAbsent,\n});\n\nconst addressOptions = (\n configuration: EmailTargetConfiguration,\n proofMapping: any,\n coordinated = false,\n): EmailSqlConfiguration => ({\n mode: configuration.mode,\n locking: configuration.locking,\n\n standaloneGuard: !coordinated ? configuration.standaloneGuard : Effect.void,\n coordinated,\n proof: {\n mapping: proofMapping,\n configuration: proofConfiguration(configuration, true),\n },\n});\n\nconst registrationOptions = (\n configuration: EmailTargetConfiguration,\n proofMapping: any,\n coordinated = false,\n): EmailRegistrationConfiguration => ({\n mode: configuration.mode,\n locking: configuration.locking,\n\n standaloneGuard: !coordinated ? configuration.standaloneGuard : Effect.void,\n generatedSubjectRows: configuration.generatedSubjectRows,\n coordinated,\n proof: {\n mapping: proofMapping,\n configuration: proofConfiguration(configuration, true),\n },\n});\n\nexport const makeTargetEmailSignInServices = (\n mapping: any,\n configuration: EmailTargetConfiguration,\n) =>\n Effect.gen(function* () {\n return {\n emailSignInTargets: yield* makeSqlEmailSignInTargets(mapping, {\n mode: configuration.mode,\n locking: false,\n standaloneGuard: configuration.standaloneGuard,\n }),\n };\n });\n\nexport const makeTargetEmailAddressServices = (\n mapping: any,\n proofMapping: any,\n configuration: EmailTargetConfiguration,\n) =>\n Effect.gen(function* () {\n return {\n emailAddressPersistence: yield* makeSqlEmailAddressPersistence(\n mapping,\n addressOptions(configuration, proofMapping),\n ),\n };\n });\n\nexport const makeTargetEmailRegistrationServices = <Registration>(\n mapping: any,\n proofMapping: any,\n configuration: EmailTargetConfiguration,\n) =>\n Effect.gen(function* () {\n return {\n registrationAuthority: yield* makeSqlEmailRegistrationAuthority<Registration>(\n mapping,\n registrationOptions(configuration, proofMapping),\n ),\n };\n });\n\nexport const coordinateTargetEmailAddress = <Transaction, A, E, R>(\n database: TransactionOwner<Transaction>,\n mapping: any,\n proofMapping: any,\n configuration: EmailTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly emailAddressPersistence: EmailAddressPersistence[\"Service\"] },\n ) => Effect.Effect<A, E, R>,\n): Effect.Effect<A, EmailCoordinatorError<E>, R | LifecycleHooks | NativeDatabase> =>\n Effect.gen(function* (): Effect.fn.Return<\n A,\n EmailCoordinatorError<E>,\n R | LifecycleHooks | NativeDatabase\n > {\n const hooks = yield* LifecycleHooks;\n\n if (yield* hasCommitScope) return yield* EmailUnavailable.make({});\n yield* configuration.coordinatorGuard ?? configuration.standaloneGuard;\n\n yield* validateDrizzleStorage({ ...mapping, proof: proofMapping }).pipe(\n Effect.mapError(() => EmailUnavailable.make({})),\n );\n\n const result = yield* coordinateCommit(\n () =>\n database.transaction((transaction) =>\n Effect.gen(function* () {\n return yield* owner(transaction, {\n emailAddressPersistence: yield* makeSqlEmailAddressPersistence(\n mapping,\n addressOptions(configuration, proofMapping, true),\n ).pipe(\n Effect.provideService(CurrentEmailSql, transaction as unknown as EmailSqlDatabase),\n ),\n });\n }),\n ),\n { mode: configuration.mode },\n ).pipe(Effect.provideService(LifecycleHooks, hooks));\n\n return result.value;\n });\n\nexport const coordinateTargetEmailRegistration = <Registration, Transaction, A, E, R>(\n database: TransactionOwner<Transaction>,\n mapping: any,\n proofMapping: any,\n configuration: EmailTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly registrationAuthority: EmailRegistrationAuthority<Registration> },\n ) => Effect.Effect<A, E, R>,\n): Effect.Effect<A, EmailCoordinatorError<E>, R | LifecycleHooks | NativeDatabase> =>\n Effect.gen(function* (): Effect.fn.Return<\n A,\n EmailCoordinatorError<E>,\n R | LifecycleHooks | NativeDatabase\n > {\n const hooks = yield* LifecycleHooks;\n\n if (yield* hasCommitScope) return yield* EmailUnavailable.make({});\n yield* configuration.coordinatorGuard ?? configuration.standaloneGuard;\n\n yield* validateDrizzleStorage({ ...mapping, proof: proofMapping }).pipe(\n Effect.mapError(() => EmailUnavailable.make({})),\n );\n\n const result = yield* coordinateCommit(\n () =>\n database.transaction((transaction) =>\n Effect.gen(function* () {\n return yield* owner(transaction, {\n registrationAuthority: yield* makeSqlEmailRegistrationAuthority<Registration>(\n mapping,\n registrationOptions(configuration, proofMapping, true),\n ).pipe(\n Effect.provideService(CurrentEmailSql, transaction as unknown as EmailSqlDatabase),\n ),\n });\n }),\n ),\n { mode: configuration.mode },\n ).pipe(Effect.provideService(LifecycleHooks, hooks));\n\n return result.value;\n });\n\nexport const emailSignInTargetsLayer = <E, R>(\n services: Effect.Effect<{ readonly emailSignInTargets: EmailSignInTargets[\"Service\"] }, E, R>,\n) =>\n Layer.effect(\n EmailSignInTargets,\n Effect.map(services, (value) => value.emailSignInTargets),\n );\n\nexport const emailAddressPersistenceLayer = <E, R>(\n services: Effect.Effect<\n { readonly emailAddressPersistence: EmailAddressPersistence[\"Service\"] },\n E,\n R\n >,\n) =>\n Layer.effect(\n EmailAddressPersistence,\n Effect.map(services, (value) => value.emailAddressPersistence),\n );\n\nexport const emailRegistrationLayer = <Id, Registration, E, R>(\n tag: Context.Key<Id, EmailRegistrationAuthority<Registration>>,\n services: Effect.Effect<\n { readonly registrationAuthority: EmailRegistrationAuthority<Registration> },\n E,\n R\n >,\n) =>\n Layer.effect(\n tag,\n Effect.map(services, (value) => value.registrationAuthority),\n );\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"email-target.mjs","names":[],"sources":["../../src/drizzle/email-target.ts"],"sourcesContent":["import {\n makeNativeEmailAddressServices,\n makeNativeEmailSignInServices,\n makeNativeEmailRegistrationServices,\n requireStandalone,\n type AnyEmailAddressMapping as SharedEmailMapping,\n type EmailRegistrationAuthority,\n} from \"@yielded/auth-persistence/Adapter\";\nimport { EmailAddressPersistence, EmailSignInTargets, EmailUnavailable } from \"@yielded/auth/Email\";\nimport { type Context, Effect, Layer } from \"effect\";\n\nimport type {\n AnyEmailAddressMapping,\n AnyEmailSignInMapping,\n AnyEmailRegistrationMapping,\n} from \"./email-model\";\nimport { nativeClock } from \"./native-clock\";\nimport type { NativeDatabaseHandle } from \"./native-database\";\nimport {\n nativeTarget,\n coordinateNativeTarget,\n type NativeTargetConfiguration,\n} from \"./native-target\";\nimport type { AnyProofPersistenceMapping } from \"./proof-model\";\nimport { nativeProofMapping } from \"./proof-target\";\nimport { validateDrizzleStorage } from \"./storage-validation\";\n\nconst unavailable = () => EmailUnavailable.make({});\n\nexport const sqlClientEmailStandaloneGuard = (marker: Parameters<typeof requireStandalone>[1]) =>\n requireStandalone(unavailable, marker);\n\nconst mapped = (value: AnyEmailAddressMapping): SharedEmailMapping => ({\n ...value,\n clock: nativeClock(value.clock),\n});\n\nexport const makeTargetEmailAddressServices = Effect.fnUntraced(function* (\n mapping: AnyEmailAddressMapping,\n configuration: NativeTargetConfiguration,\n proofs?: AnyProofPersistenceMapping,\n) {\n yield* validateDrizzleStorage(mapping).pipe(Effect.mapError(unavailable));\n if (proofs !== undefined)\n yield* validateDrizzleStorage(proofs).pipe(Effect.mapError(unavailable));\n if (\n configuration.mode === \"batch\" &&\n (mapping.d1?.primary !== true || (proofs !== undefined && proofs.d1?.primary !== true))\n )\n return yield* unavailable();\n const target = yield* nativeTarget(configuration);\n\n return yield* target.provide(\n makeNativeEmailAddressServices(\n target.tables,\n mapped(mapping),\n proofs === undefined ? undefined : nativeProofMapping(proofs),\n ),\n );\n});\n\nexport const makeTargetEmailRegistrationServices = Effect.fnUntraced(function* <Registration>(\n mapping: AnyEmailRegistrationMapping<Registration>,\n configuration: NativeTargetConfiguration,\n proofs: AnyProofPersistenceMapping,\n) {\n yield* validateDrizzleStorage(mapping).pipe(Effect.mapError(unavailable));\n yield* validateDrizzleStorage(proofs).pipe(Effect.mapError(unavailable));\n if (\n configuration.mode === \"batch\" &&\n (mapping.d1?.primary !== true || proofs.d1?.primary !== true)\n )\n return yield* unavailable();\n const target = yield* nativeTarget(configuration);\n\n return yield* target.provide(\n makeNativeEmailRegistrationServices(\n target.tables,\n {\n ...mapping,\n clock: nativeClock(mapping.clock),\n },\n nativeProofMapping(proofs),\n target.batch,\n ),\n );\n});\n\nexport const coordinateTargetEmailAddress = <Transaction, A, E, R>(\n database: NativeDatabaseHandle,\n mapping: AnyEmailAddressMapping,\n configuration: NativeTargetConfiguration,\n body: (\n transaction: Transaction,\n services: { readonly emailAddressPersistence: EmailAddressPersistence[\"Service\"] },\n ) => Effect.Effect<A, E, R>,\n proofs?: AnyProofPersistenceMapping,\n) =>\n coordinateNativeTarget(\n unavailable,\n database,\n configuration,\n makeTargetEmailAddressServices(mapping, configuration, proofs),\n body,\n );\n\nexport const coordinateTargetEmailRegistration = <Registration, Transaction, A, E, R>(\n database: NativeDatabaseHandle,\n mapping: AnyEmailRegistrationMapping<Registration>,\n configuration: NativeTargetConfiguration,\n proofs: AnyProofPersistenceMapping,\n body: (\n transaction: Transaction,\n services: { readonly registrationAuthority: EmailRegistrationAuthority<Registration> },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateNativeTarget(\n unavailable,\n database,\n configuration,\n makeTargetEmailRegistrationServices(mapping, configuration, proofs),\n body,\n );\n\nexport const emailAddressPersistenceLayer = <E, R>(\n services: Effect.Effect<\n { readonly emailAddressPersistence: EmailAddressPersistence[\"Service\"] },\n E,\n R\n >,\n) =>\n Layer.effect(\n EmailAddressPersistence,\n Effect.map(services, (value) => value.emailAddressPersistence),\n );\n\nexport const emailRegistrationLayer = <Id, Registration, E, R>(\n target: Context.Key<Id, EmailRegistrationAuthority<Registration>>,\n services: Effect.Effect<\n { readonly registrationAuthority: EmailRegistrationAuthority<Registration> },\n E,\n R\n >,\n) =>\n Layer.effect(\n target,\n Effect.map(services, (value) => value.registrationAuthority),\n );\n\nexport const makeTargetEmailSignInServices = Effect.fnUntraced(function* (\n mapping: AnyEmailSignInMapping,\n configuration: NativeTargetConfiguration,\n) {\n yield* validateDrizzleStorage(mapping).pipe(Effect.mapError(unavailable));\n const target = yield* nativeTarget(configuration);\n\n return yield* target.provide(makeNativeEmailSignInServices(target.tables, mapping));\n});\n\nexport const emailSignInTargetsLayer = <E, R>(\n services: Effect.Effect<{ readonly emailSignInTargets: EmailSignInTargets[\"Service\"] }, E, R>,\n) =>\n Layer.effect(\n EmailSignInTargets,\n Effect.map(services, (value) => value.emailSignInTargets),\n );\n"],"mappings":";;;;;;;;AA2BA,MAAM,oBAAoB,iBAAiB,KAAK,CAAC,CAAC;AAKlD,MAAM,UAAU,WAAuD;CACrE,GAAG;CACH,OAAO,YAAY,MAAM,KAAK;AAChC;AAEA,MAAa,iCAAiC,OAAO,WAAW,WAC9D,SACA,eACA,QACA;CACA,OAAO,uBAAuB,OAAO,CAAC,CAAC,KAAK,OAAO,SAAS,WAAW,CAAC;CACxE,IAAI,WAAW,KAAA,GACb,OAAO,uBAAuB,MAAM,CAAC,CAAC,KAAK,OAAO,SAAS,WAAW,CAAC;CACzE,IACE,cAAc,SAAS,YACtB,QAAQ,IAAI,YAAY,QAAS,WAAW,KAAA,KAAa,OAAO,IAAI,YAAY,OAEjF,OAAO,OAAO,YAAY;CAC5B,MAAM,SAAS,OAAO,aAAa,aAAa;CAEhD,OAAO,OAAO,OAAO,QACnB,+BACE,OAAO,QACP,OAAO,OAAO,GACd,WAAW,KAAA,IAAY,KAAA,IAAY,mBAAmB,MAAM,CAC9D,CACF;AACF,CAAC;AAED,MAAa,sCAAsC,OAAO,WAAW,WACnE,SACA,eACA,QACA;CACA,OAAO,uBAAuB,OAAO,CAAC,CAAC,KAAK,OAAO,SAAS,WAAW,CAAC;CACxE,OAAO,uBAAuB,MAAM,CAAC,CAAC,KAAK,OAAO,SAAS,WAAW,CAAC;CACvE,IACE,cAAc,SAAS,YACtB,QAAQ,IAAI,YAAY,QAAQ,OAAO,IAAI,YAAY,OAExD,OAAO,OAAO,YAAY;CAC5B,MAAM,SAAS,OAAO,aAAa,aAAa;CAEhD,OAAO,OAAO,OAAO,QACnB,oCACE,OAAO,QACP;EACE,GAAG;EACH,OAAO,YAAY,QAAQ,KAAK;CAClC,GACA,mBAAmB,MAAM,GACzB,OAAO,KACT,CACF;AACF,CAAC;AAED,MAAa,gCACX,UACA,SACA,eACA,MAIA,WAEA,uBACE,aACA,UACA,eACA,+BAA+B,SAAS,eAAe,MAAM,GAC7D,IACF;AAEF,MAAa,qCACX,UACA,SACA,eACA,QACA,SAKA,uBACE,aACA,UACA,eACA,oCAAoC,SAAS,eAAe,MAAM,GAClE,IACF;AAEF,MAAa,gCACX,aAMA,MAAM,OACJ,yBACA,OAAO,IAAI,WAAW,UAAU,MAAM,uBAAuB,CAC/D;AAEF,MAAa,0BACX,QACA,aAMA,MAAM,OACJ,QACA,OAAO,IAAI,WAAW,UAAU,MAAM,qBAAqB,CAC7D;AAEF,MAAa,gCAAgC,OAAO,WAAW,WAC7D,SACA,eACA;CACA,OAAO,uBAAuB,OAAO,CAAC,CAAC,KAAK,OAAO,SAAS,WAAW,CAAC;CACxE,MAAM,SAAS,OAAO,aAAa,aAAa;CAEhD,OAAO,OAAO,OAAO,QAAQ,8BAA8B,OAAO,QAAQ,OAAO,CAAC;AACpF,CAAC;AAED,MAAa,2BACX,aAEA,MAAM,OACJ,oBACA,OAAO,IAAI,WAAW,UAAU,MAAM,kBAAkB,CAC1D"}
|
package/dist/drizzle/model.d.mts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { PersistenceMappingError, PersistenceMappingError as PersistenceMappingError$1, SubjectIdCodec, SubjectIdCodec as SubjectIdCodec$1, isMappedConstraintConflict } from "@yielded/auth-persistence/Adapter";
|
|
2
2
|
import { ExternalIdentity, ExternalIdentityMutation, LoginIdentifier, SubjectProvisioner, SubjectProvisioningInput } from "@yielded/auth/Identity";
|
|
3
|
-
import {
|
|
3
|
+
import { InferInsertModel, Table } from "drizzle-orm";
|
|
4
4
|
import { DateTime, Effect, Layer } from "effect";
|
|
5
5
|
//#region src/drizzle/model.d.ts
|
|
6
|
-
export type CommitMode = "interactive" | "synchronous" | "batch";
|
|
7
6
|
export interface InstantCodec<NativeInstant> {
|
|
8
7
|
readonly encode: (instant: DateTime.Utc) => NativeInstant;
|
|
9
8
|
readonly decode: (native: NativeInstant) => Effect.Effect<DateTime.Utc, PersistenceMappingError>;
|
|
@@ -103,14 +102,6 @@ export interface D1ExternalIdentityMapping<Subject extends Table, External exten
|
|
|
103
102
|
export interface D1GeneratedIdentityMapping<Subject extends Table, Identifier extends Table, External extends Table, Request extends Table, NativeId> extends IdentityTables<Subject, Identifier, External, Request, NativeId> {
|
|
104
103
|
readonly d1: D1SubjectProvisioningMapping<Subject, Identifier, Request, NativeId>["d1"] & D1ExternalIdentityMapping<Subject, External, NativeId>["d1"];
|
|
105
104
|
}
|
|
106
|
-
export declare const provisioningFingerprint: (input: SubjectProvisioningInput) => string;
|
|
107
|
-
/**
|
|
108
|
-
* Drizzle wraps Effect SQL failures before adapters observe them. Give the
|
|
109
|
-
* consumer classifier each semantic wrapper in the short `cause`/`reason`
|
|
110
|
-
* chain without exposing query text or bound parameters through public errors.
|
|
111
|
-
*/
|
|
112
|
-
export declare const column: <T extends Table>(table: T, key: ColumnKey<T>) => AnyColumn;
|
|
113
|
-
export declare const updateValues: <T extends Table>(entries: ReadonlyArray<readonly [ColumnKey<T>, unknown]>) => Partial<InferInsertModel<T>>;
|
|
114
105
|
/** Acquire an application database in Effect and expose the identity services as one layer. */
|
|
115
106
|
export declare const identityServicesLayer: <E, R>(acquire: Effect.Effect<{
|
|
116
107
|
readonly subjectProvisioner: SubjectProvisioner["Service"];
|
package/dist/drizzle/model.mjs
CHANGED
|
@@ -27,10 +27,9 @@ const provisioningFingerprint = (input) => JSON.stringify(input.identifier === v
|
|
|
27
27
|
* chain without exposing query text or bound parameters through public errors.
|
|
28
28
|
*/
|
|
29
29
|
const column = (table, key) => getTableColumns(table)[key];
|
|
30
|
-
const updateValues = (entries) => Object.fromEntries(entries);
|
|
31
30
|
/** Acquire an application database in Effect and expose the identity services as one layer. */
|
|
32
31
|
const identityServicesLayer = (acquire) => Layer.effectContext(Effect.map(acquire, ({ subjectProvisioner, externalIdentityMutation }) => Context.make(SubjectProvisioner, subjectProvisioner).pipe(Context.add(ExternalIdentityMutation, externalIdentityMutation))));
|
|
33
32
|
//#endregion
|
|
34
|
-
export { PersistenceMappingError$1 as PersistenceMappingError, column, identityServicesLayer, isMappedConstraintConflict, provisioningFingerprint, requiredExternalIdentityConstraints, requiredIdentityConstraints, requiredSubjectProvisioningConstraints
|
|
33
|
+
export { PersistenceMappingError$1 as PersistenceMappingError, column, identityServicesLayer, isMappedConstraintConflict, provisioningFingerprint, requiredExternalIdentityConstraints, requiredIdentityConstraints, requiredSubjectProvisioningConstraints };
|
|
35
34
|
|
|
36
35
|
//# sourceMappingURL=model.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.mjs","names":[],"sources":["../../src/drizzle/model.ts"],"sourcesContent":["import {\n ExternalIdentityMutation,\n SubjectProvisioner,\n type SubjectProvisioningInput,\n type ExternalIdentity,\n type LoginIdentifier,\n} from \"@yielded/auth/Identity\";\nimport { getTableColumns, type AnyColumn, type InferInsertModel, type Table } from \"drizzle-orm\";\nimport { Context, DateTime, Effect, Layer } from \"effect\";\n\nexport
|
|
1
|
+
{"version":3,"file":"model.mjs","names":[],"sources":["../../src/drizzle/model.ts"],"sourcesContent":["import {\n ExternalIdentityMutation,\n SubjectProvisioner,\n type SubjectProvisioningInput,\n type ExternalIdentity,\n type LoginIdentifier,\n} from \"@yielded/auth/Identity\";\nimport { getTableColumns, type AnyColumn, type InferInsertModel, type Table } from \"drizzle-orm\";\nimport { Context, DateTime, Effect, Layer } from \"effect\";\n\nexport {\n PersistenceMappingError,\n isMappedConstraintConflict,\n} from \"@yielded/auth-persistence/Adapter\";\n\nimport type { PersistenceMappingError, SubjectIdCodec } from \"@yielded/auth-persistence/Adapter\";\n\nexport interface InstantCodec<NativeInstant> {\n readonly encode: (instant: DateTime.Utc) => NativeInstant;\n readonly decode: (native: NativeInstant) => Effect.Effect<DateTime.Utc, PersistenceMappingError>;\n}\n\ntype ColumnKey<T extends Table> = Extract<keyof T[\"_\"][\"columns\"], string>;\n\nexport interface RequiredIdentityConstraints {\n readonly identifier: \"unique(namespace,value)\";\n readonly externalIdentity: \"unique(provider,issuer,subject)\";\n readonly provisioningRequest: \"unique(requestId)\";\n readonly provisioningSubject: \"notNull(provisioningRequest.subjectId)\";\n}\n\nexport interface RequiredSubjectProvisioningConstraints {\n readonly identifier: \"unique(namespace,value)\";\n readonly provisioningRequest: \"unique(requestId)\";\n readonly provisioningSubject: \"notNull(provisioningRequest.subjectId)\";\n}\n\nexport interface RequiredExternalIdentityConstraints {\n readonly externalIdentity: \"unique(provider,issuer,subject)\";\n}\n\nexport const requiredIdentityConstraints: RequiredIdentityConstraints = {\n identifier: \"unique(namespace,value)\",\n externalIdentity: \"unique(provider,issuer,subject)\",\n provisioningRequest: \"unique(requestId)\",\n provisioningSubject: \"notNull(provisioningRequest.subjectId)\",\n};\n\nexport const requiredSubjectProvisioningConstraints: RequiredSubjectProvisioningConstraints = {\n identifier: \"unique(namespace,value)\",\n provisioningRequest: \"unique(requestId)\",\n provisioningSubject: \"notNull(provisioningRequest.subjectId)\",\n};\n\nexport const requiredExternalIdentityConstraints: RequiredExternalIdentityConstraints = {\n externalIdentity: \"unique(provider,issuer,subject)\",\n};\n\nexport type { SubjectIdCodec } from \"@yielded/auth-persistence/Adapter\";\n\nexport interface SubjectProvisioningTables<\n Subject extends Table,\n Identifier extends Table,\n Request extends Table,\n NativeId,\n> {\n readonly constraints: RequiredSubjectProvisioningConstraints;\n readonly subject: {\n readonly table: Subject;\n readonly id: ColumnKey<Subject>;\n readonly status: ColumnKey<Subject>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly encodeInsert: (\n input: SubjectProvisioningInput,\n allocatedId: NativeId | undefined,\n ) => InferInsertModel<Subject>;\n readonly allocateId?: Effect.Effect<NativeId, PersistenceMappingError>;\n /** Required instead of allocateId when a synchronous-only DO transaction preallocates IDs. */\n readonly allocateIdSync?: () => NativeId;\n /** Decodes MySQL `$returningId()` for an autoincrement/runtime-default key. */\n readonly decodeGeneratedId?: (\n rows: ReadonlyArray<unknown>,\n ) => Effect.Effect<NativeId, PersistenceMappingError>;\n };\n readonly identifier: {\n readonly table: Identifier;\n readonly namespace: ColumnKey<Identifier>;\n readonly value: ColumnKey<Identifier>;\n readonly subjectId: ColumnKey<Identifier>;\n readonly encodeInsert: (\n identifier: LoginIdentifier,\n subjectId: NativeId,\n verifiedAt: DateTime.Utc | undefined,\n ) => InferInsertModel<Identifier>;\n };\n readonly provisioningRequest: {\n readonly table: Request;\n readonly requestId: ColumnKey<Request>;\n readonly fingerprint: ColumnKey<Request>;\n readonly subjectId: ColumnKey<Request>;\n readonly encodeInsert: (\n requestId: string,\n fingerprint: string,\n subjectId: NativeId,\n ) => InferInsertModel<Request>;\n };\n readonly subjectId: SubjectIdCodec<NativeId>;\n /** Narrows only database constraint failures; every other cause is unavailable. */\n readonly isConstraintConflict: (cause: unknown) => boolean;\n}\n\nexport interface ExternalIdentityTables<Subject extends Table, External extends Table, NativeId> {\n readonly constraints: RequiredExternalIdentityConstraints;\n readonly subject: {\n readonly table: Subject;\n readonly id: ColumnKey<Subject>;\n readonly status: ColumnKey<Subject>;\n readonly isActiveStatus: (value: unknown) => boolean;\n };\n readonly externalIdentity: {\n readonly table: External;\n readonly provider: ColumnKey<External>;\n readonly issuer: ColumnKey<External>;\n readonly subject: ColumnKey<External>;\n readonly subjectId: ColumnKey<External>;\n readonly encodeInsert: (\n identity: ExternalIdentity,\n subjectId: NativeId,\n ) => InferInsertModel<External>;\n };\n readonly subjectId: SubjectIdCodec<NativeId>;\n readonly isConstraintConflict: (cause: unknown) => boolean;\n}\n\nexport interface IdentityTables<\n Subject extends Table,\n Identifier extends Table,\n External extends Table,\n Request extends Table,\n NativeId,\n> {\n readonly constraints: RequiredIdentityConstraints;\n readonly subject: SubjectProvisioningTables<Subject, Identifier, Request, NativeId>[\"subject\"];\n readonly identifier: SubjectProvisioningTables<\n Subject,\n Identifier,\n Request,\n NativeId\n >[\"identifier\"];\n readonly externalIdentity: ExternalIdentityTables<\n Subject,\n External,\n NativeId\n >[\"externalIdentity\"];\n readonly provisioningRequest: SubjectProvisioningTables<\n Subject,\n Identifier,\n Request,\n NativeId\n >[\"provisioningRequest\"];\n readonly subjectId: SubjectIdCodec<NativeId>;\n readonly isConstraintConflict: (cause: unknown) => boolean;\n}\n\n/** Extra encoders used by D1's ordered batch when the subject id is database-generated. */\nexport interface D1SubjectProvisioningMapping<\n Subject extends Table,\n Identifier extends Table,\n Request extends Table,\n NativeId,\n> extends SubjectProvisioningTables<Subject, Identifier, Request, NativeId> {\n readonly d1: {\n readonly requestInsertWithoutSubject: (\n requestId: string,\n fingerprint: string,\n ) => Partial<InferInsertModel<Request>>;\n readonly identifierInsertWithoutSubject: (\n identifier: LoginIdentifier,\n verifiedAt: DateTime.Utc | undefined,\n ) => Partial<InferInsertModel<Identifier>>;\n /** Unshadowed hidden-rowid alias; omit for WITHOUT ROWID or preallocated IDs. */\n readonly generatedRowIdAlias?: \"rowid\" | \"_rowid_\" | \"oid\";\n };\n}\n\nexport interface D1ExternalIdentityMapping<\n Subject extends Table,\n External extends Table,\n NativeId,\n> extends ExternalIdentityTables<Subject, External, NativeId> {\n readonly d1: {\n readonly activeStatusValue: unknown;\n };\n}\n\nexport interface D1GeneratedIdentityMapping<\n Subject extends Table,\n Identifier extends Table,\n External extends Table,\n Request extends Table,\n NativeId,\n> extends IdentityTables<Subject, Identifier, External, Request, NativeId> {\n readonly d1: D1SubjectProvisioningMapping<Subject, Identifier, Request, NativeId>[\"d1\"] &\n D1ExternalIdentityMapping<Subject, External, NativeId>[\"d1\"];\n}\n\nexport const provisioningFingerprint = (input: SubjectProvisioningInput): string =>\n // oxlint-disable-next-line no-restricted-properties -- stable internal provisioning fingerprint, never external JSON.\n JSON.stringify(\n input.identifier === undefined\n ? [\"v1\", null]\n : [\n \"v1\",\n input.identifier.namespace,\n input.identifier.value,\n input.verifiedAt === undefined ? null : DateTime.toEpochMillis(input.verifiedAt),\n ],\n );\n\n/**\n * Drizzle wraps Effect SQL failures before adapters observe them. Give the\n * consumer classifier each semantic wrapper in the short `cause`/`reason`\n * chain without exposing query text or bound parameters through public errors.\n */\n\nexport const column = <T extends Table>(table: T, key: ColumnKey<T>): AnyColumn =>\n getTableColumns(table)[key] as AnyColumn;\n\nexport const updateValues = <T extends Table>(\n entries: ReadonlyArray<readonly [ColumnKey<T>, unknown]>,\n): Partial<InferInsertModel<T>> => Object.fromEntries(entries) as Partial<InferInsertModel<T>>;\n\n/** Acquire an application database in Effect and expose the identity services as one layer. */\nexport const identityServicesLayer = <E, R>(\n acquire: Effect.Effect<\n {\n readonly subjectProvisioner: SubjectProvisioner[\"Service\"];\n readonly externalIdentityMutation: ExternalIdentityMutation[\"Service\"];\n },\n E,\n R\n >,\n) =>\n Layer.effectContext(\n Effect.map(acquire, ({ subjectProvisioner, externalIdentityMutation }) =>\n Context.make(SubjectProvisioner, subjectProvisioner).pipe(\n Context.add(ExternalIdentityMutation, externalIdentityMutation),\n ),\n ),\n );\n"],"mappings":";;;;;AAyCA,MAAa,8BAA2D;CACtE,YAAY;CACZ,kBAAkB;CAClB,qBAAqB;CACrB,qBAAqB;AACvB;AAEA,MAAa,yCAAiF;CAC5F,YAAY;CACZ,qBAAqB;CACrB,qBAAqB;AACvB;AAEA,MAAa,sCAA2E,EACtF,kBAAkB,kCACpB;AAsJA,MAAa,2BAA2B,UAEtC,KAAK,UACH,MAAM,eAAe,KAAA,IACjB,CAAC,MAAM,IAAI,IACX;CACE;CACA,MAAM,WAAW;CACjB,MAAM,WAAW;CACjB,MAAM,eAAe,KAAA,IAAY,OAAO,SAAS,cAAc,MAAM,UAAU;AACjF,CACN;;;;;;AAQF,MAAa,UAA2B,OAAU,QAChD,gBAAgB,KAAK,CAAC,CAAC;;AAOzB,MAAa,yBACX,YASA,MAAM,cACJ,OAAO,IAAI,UAAU,EAAE,oBAAoB,+BACzC,QAAQ,KAAK,oBAAoB,kBAAkB,CAAC,CAAC,KACnD,QAAQ,IAAI,0BAA0B,wBAAwB,CAChE,CACF,CACF"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { PersistenceMappingError as PersistenceMappingError$1, column, isMappedConstraintConflict, provisioningFingerprint } from "./model.mjs";
|
|
2
|
+
import { NativeDatabase, nativeDatabase } from "./native-database.mjs";
|
|
2
3
|
import { validateDrizzleStorage } from "./storage-validation.mjs";
|
|
3
|
-
import { nativeDatabase } from "./native-database.mjs";
|
|
4
4
|
import { Database } from "./mysql-database.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { withStorageValidation } from "@yielded/auth-persistence/Adapter";
|
|
6
6
|
import { ExternalIdentityMutation, IdentityConflict, IdentityUnavailable, SubjectProvisioned, SubjectProvisioner } from "@yielded/auth/Identity";
|
|
7
7
|
import { and, eq } from "drizzle-orm";
|
|
8
8
|
import { Cause, Effect, Schema } from "effect";
|
|
@@ -20,8 +20,6 @@ const makeMysqlSubjectProvisioningServices = Effect.fnUntraced(function* (mappin
|
|
|
20
20
|
const requestFingerprintColumn = column(requestTable, mapping.provisioningRequest.fingerprint);
|
|
21
21
|
const requestSubjectColumn = column(requestTable, mapping.provisioningRequest.subjectId);
|
|
22
22
|
const identifierTable = mapping.identifier.table;
|
|
23
|
-
const identifierNamespaceColumn = column(identifierTable, mapping.identifier.namespace);
|
|
24
|
-
const identifierValueColumn = column(identifierTable, mapping.identifier.value);
|
|
25
23
|
const findReceipt = Effect.fn("DrizzleMysqlIdentity.findReceipt")(function* (requestId) {
|
|
26
24
|
return (yield* db.select({
|
|
27
25
|
fingerprint: requestFingerprintColumn,
|
|
@@ -55,8 +53,7 @@ const makeMysqlSubjectProvisioningServices = Effect.fnUntraced(function* (mappin
|
|
|
55
53
|
if (cause.reasons.length === 0 || !cause.reasons.every((reason) => Cause.isFailReason(reason) && isMappedConstraintConflict(mapping.isConstraintConflict, reason.error))) return Effect.failCause(cause);
|
|
56
54
|
return findReceipt(input.requestId).pipe(Effect.flatMap((receipt) => {
|
|
57
55
|
if (receipt !== void 0 && receipt.fingerprint === fingerprint) return Effect.succeed(receipt.subjectId);
|
|
58
|
-
|
|
59
|
-
return db.select({ subjectId: column(identifierTable, mapping.identifier.subjectId) }).from(identifierTable).where(and(eq(identifierNamespaceColumn, input.identifier.namespace), eq(identifierValueColumn, input.identifier.value))).limit(1).pipe(Effect.flatMap(() => IdentityConflict.make()));
|
|
56
|
+
return IdentityConflict.make();
|
|
60
57
|
}));
|
|
61
58
|
}));
|
|
62
59
|
const subjectId = yield* mapping.subjectId.toSubject(nativeId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql-identity.mjs","names":["DatabaseService","PersistenceMappingError"],"sources":["../../src/drizzle/mysql-identity.ts"],"sourcesContent":["import { withStorageValidation, NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport {\n ExternalIdentityMutation,\n type ExternalIdentity,\n IdentityConflict,\n IdentityUnavailable,\n SubjectProvisioned,\n SubjectProvisioner,\n type SubjectProvisioningInput,\n} from \"@yielded/auth/Identity\";\nimport { reportPersistenceFailure } from \"@yielded/auth/Persistence\";\nimport type { SubjectId } from \"@yielded/auth/Schema\";\n/* oxlint-disable no-explicit-any -- Drizzle generic query types are narrowed at this technology boundary. */\nimport { and, eq } from \"drizzle-orm\";\nimport type { EffectMysql2Database } from \"drizzle-orm/effect-mysql2\";\nimport type { AnyMySqlTable, MySqlColumn } from \"drizzle-orm/mysql-core\";\nimport { Cause, Effect, Schema } from \"effect\";\n\nimport {\n column,\n isMappedConstraintConflict,\n PersistenceMappingError,\n provisioningFingerprint,\n type ExternalIdentityTables,\n type IdentityTables,\n type SubjectProvisioningTables,\n} from \"./model\";\nimport { Database as DatabaseService } from \"./mysql-database\";\nimport { nativeDatabase } from \"./native-database\";\nimport { validateDrizzleStorage } from \"./storage-validation\";\n\ntype RuntimeDatabase = EffectMysql2Database<any>;\nconst unavailable = () => IdentityUnavailable.make();\nconst isIdentityFailure = Schema.is(Schema.Union([IdentityConflict, IdentityUnavailable]));\n\nconst mapUnavailable = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n reportPersistenceFailure(effect, isIdentityFailure).pipe(\n Effect.catchCause((cause) =>\n Effect.failCause(\n Cause.map(cause, (error) => (isIdentityFailure(error) ? error : unavailable())),\n ),\n ),\n );\n\nexport const makeMysqlSubjectProvisioningServices = Effect.fnUntraced(function* <\n Subject extends AnyMySqlTable,\n Identifier extends AnyMySqlTable,\n Request extends AnyMySqlTable,\n NativeId,\n>(mapping: SubjectProvisioningTables<Subject, Identifier, Request, NativeId>) {\n const database = yield* DatabaseService;\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(DatabaseService)),\n Effect.mapError(() => IdentityUnavailable.make()),\n );\n\n const db = database as RuntimeDatabase;\n const requestTable = mapping.provisioningRequest.table;\n\n const requestIdColumn = column(\n requestTable,\n mapping.provisioningRequest.requestId,\n ) as MySqlColumn;\n\n const requestFingerprintColumn = column(\n requestTable,\n mapping.provisioningRequest.fingerprint,\n ) as MySqlColumn;\n\n const requestSubjectColumn = column(\n requestTable,\n mapping.provisioningRequest.subjectId,\n ) as MySqlColumn;\n\n const identifierTable = mapping.identifier.table;\n\n const identifierNamespaceColumn = column(\n identifierTable,\n mapping.identifier.namespace,\n ) as MySqlColumn;\n\n const identifierValueColumn = column(identifierTable, mapping.identifier.value) as MySqlColumn;\n\n const findReceipt = Effect.fn(\"DrizzleMysqlIdentity.findReceipt\")(function* (requestId: string) {\n const rows = yield* db\n .select({ fingerprint: requestFingerprintColumn, subjectId: requestSubjectColumn })\n .from(requestTable as any)\n .where(eq(requestIdColumn, requestId))\n .limit(1);\n\n return rows[0];\n });\n\n const provision = Effect.fn(\"DrizzleMysqlIdentity.provision\")(function* (\n input: SubjectProvisioningInput,\n ) {\n const fingerprint = provisioningFingerprint(input);\n const existing = yield* findReceipt(input.requestId);\n\n if (existing !== undefined) {\n if (existing.fingerprint !== fingerprint) return yield* IdentityConflict.make();\n const subjectId = yield* mapping.subjectId.toSubject(existing.subjectId as NativeId);\n\n return SubjectProvisioned.make({ subjectId });\n }\n\n const attempt = db.transaction((tx) =>\n Effect.gen(function* () {\n const allocated =\n mapping.subject.allocateId === undefined\n ? mapping.subject.allocateIdSync?.()\n : yield* mapping.subject.allocateId;\n\n const insert = tx\n .insert(mapping.subject.table as any)\n .values(mapping.subject.encodeInsert(input, allocated) as any);\n\n let nativeId = allocated;\n\n if (nativeId === undefined) {\n if (mapping.subject.decodeGeneratedId === undefined)\n return yield* PersistenceMappingError.make({\n operation: \"provisionSubject.generatedId\",\n cause: new Error(\"MySQL generated IDs require decodeGeneratedId\"),\n });\n const ids = yield* insert.$returningId();\n\n nativeId = yield* mapping.subject.decodeGeneratedId(ids as ReadonlyArray<unknown>);\n } else {\n yield* insert;\n }\n if (input.identifier !== undefined)\n yield* tx\n .insert(identifierTable as any)\n .values(\n mapping.identifier.encodeInsert(input.identifier, nativeId, input.verifiedAt) as any,\n );\n yield* tx\n .insert(requestTable as any)\n .values(\n mapping.provisioningRequest.encodeInsert(input.requestId, fingerprint, nativeId) as any,\n );\n\n return nativeId;\n }),\n );\n\n const nativeId = yield* attempt.pipe(\n Effect.catchCause(\n (\n cause,\n ): Effect.Effect<\n NativeId,\n | Effect.Error<typeof attempt>\n | Effect.Error<ReturnType<typeof findReceipt>>\n | IdentityConflict\n > => {\n if (\n cause.reasons.length === 0 ||\n !cause.reasons.every(\n (reason) =>\n Cause.isFailReason(reason) &&\n isMappedConstraintConflict(mapping.isConstraintConflict, reason.error),\n )\n )\n return Effect.failCause(cause);\n\n return findReceipt(input.requestId).pipe(\n Effect.flatMap((receipt) => {\n if (receipt !== undefined && receipt.fingerprint === fingerprint)\n return Effect.succeed(receipt.subjectId as NativeId);\n if (input.identifier === undefined) return IdentityConflict.make();\n\n return db\n .select({\n subjectId: column(identifierTable, mapping.identifier.subjectId) as MySqlColumn,\n })\n .from(identifierTable as any)\n .where(\n and(\n eq(identifierNamespaceColumn, input.identifier.namespace),\n eq(identifierValueColumn, input.identifier.value),\n ),\n )\n .limit(1)\n .pipe(Effect.flatMap(() => IdentityConflict.make()));\n }),\n );\n },\n ),\n );\n\n const subjectId = yield* mapping.subjectId.toSubject(nativeId);\n\n return SubjectProvisioned.make({ subjectId });\n }, mapUnavailable);\n\n return { subjectProvisioner: SubjectProvisioner.of({ provision }) } as const;\n});\n\nexport const makeMysqlExternalIdentityServices = Effect.fnUntraced(function* <\n Subject extends AnyMySqlTable,\n External extends AnyMySqlTable,\n NativeId,\n>(mapping: ExternalIdentityTables<Subject, External, NativeId>) {\n const database = yield* DatabaseService;\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(DatabaseService)),\n Effect.mapError(() => IdentityUnavailable.make()),\n );\n\n const db = database as RuntimeDatabase;\n const externalTable = mapping.externalIdentity.table;\n\n const externalProviderColumn = column(\n externalTable,\n mapping.externalIdentity.provider,\n ) as MySqlColumn;\n\n const externalIssuerColumn = column(\n externalTable,\n mapping.externalIdentity.issuer,\n ) as MySqlColumn;\n\n const externalSubjectColumn = column(\n externalTable,\n mapping.externalIdentity.subject,\n ) as MySqlColumn;\n\n const externalSubjectIdColumn = column(\n externalTable,\n mapping.externalIdentity.subjectId,\n ) as MySqlColumn;\n\n const subjectIdColumn = column(mapping.subject.table, mapping.subject.id) as MySqlColumn;\n const subjectStatusColumn = column(mapping.subject.table, mapping.subject.status) as MySqlColumn;\n\n const bind = Effect.fn(\"DrizzleMysqlIdentity.bindExternalIdentity\")(function* (\n subjectId: SubjectId,\n identity: ExternalIdentity,\n ) {\n const nativeId = yield* mapping.subjectId.toNative(subjectId);\n\n const decision = yield* db\n .transaction((tx) =>\n Effect.gen(function* () {\n const subjects = yield* tx\n .select({ status: subjectStatusColumn })\n .from(mapping.subject.table as any)\n .where(eq(subjectIdColumn, nativeId))\n .for(\"update\")\n .limit(1);\n\n if (subjects[0] === undefined || !mapping.subject.isActiveStatus(subjects[0].status))\n return { _tag: \"conflict\" } as const;\n\n const links = yield* tx\n .select({ subjectId: externalSubjectIdColumn })\n .from(externalTable as any)\n .where(\n and(\n eq(externalProviderColumn, identity.provider),\n eq(externalIssuerColumn, identity.issuer),\n eq(externalSubjectColumn, identity.subject),\n ),\n )\n .for(\"update\")\n .limit(1);\n\n if (links[0] !== undefined)\n return mapping.subjectId.equals(links[0].subjectId as NativeId, nativeId)\n ? ({ _tag: \"bound\" } as const)\n : ({ _tag: \"conflict\" } as const);\n yield* tx\n .insert(externalTable as any)\n .values(mapping.externalIdentity.encodeInsert(identity, nativeId) as any);\n\n return { _tag: \"bound\" } as const;\n }),\n )\n .pipe(\n Effect.catchCause((cause) => {\n if (\n cause.reasons.length === 0 ||\n !cause.reasons.every(\n (reason) =>\n Cause.isFailReason(reason) &&\n isMappedConstraintConflict(mapping.isConstraintConflict, reason.error),\n )\n )\n return Effect.failCause(cause);\n\n return db\n .select({ subjectId: externalSubjectIdColumn })\n .from(externalTable as any)\n .where(\n and(\n eq(externalProviderColumn, identity.provider),\n eq(externalIssuerColumn, identity.issuer),\n eq(externalSubjectColumn, identity.subject),\n ),\n )\n .limit(1)\n .pipe(\n Effect.map((rows) =>\n rows[0] !== undefined &&\n mapping.subjectId.equals(rows[0].subjectId as NativeId, nativeId)\n ? ({ _tag: \"bound\" } as const)\n : ({ _tag: \"conflict\" } as const),\n ),\n );\n }),\n );\n\n if (decision._tag === \"conflict\") return yield* IdentityConflict.make();\n }, mapUnavailable);\n\n return { externalIdentityMutation: ExternalIdentityMutation.of({ bind }) } as const;\n});\n\nexport const makeMysqlIdentityServices = Effect.fnUntraced(function* <\n Subject extends AnyMySqlTable,\n Identifier extends AnyMySqlTable,\n External extends AnyMySqlTable,\n Request extends AnyMySqlTable,\n NativeId,\n>(mapping: IdentityTables<Subject, Identifier, External, Request, NativeId>) {\n return {\n ...(yield* makeMysqlSubjectProvisioningServices(mapping)),\n ...(yield* makeMysqlExternalIdentityServices(mapping)),\n };\n}, withStorageValidation);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mysql-identity.mjs","names":["DatabaseService","PersistenceMappingError"],"sources":["../../src/drizzle/mysql-identity.ts"],"sourcesContent":["import { withStorageValidation } from \"@yielded/auth-persistence/Adapter\";\nimport {\n ExternalIdentityMutation,\n type ExternalIdentity,\n IdentityConflict,\n IdentityUnavailable,\n SubjectProvisioned,\n SubjectProvisioner,\n type SubjectProvisioningInput,\n} from \"@yielded/auth/Identity\";\nimport { reportPersistenceFailure } from \"@yielded/auth/Persistence\";\nimport type { SubjectId } from \"@yielded/auth/Schema\";\n/* oxlint-disable no-explicit-any -- Drizzle generic query types are narrowed at this technology boundary. */\nimport { and, eq } from \"drizzle-orm\";\nimport type { EffectMysql2Database } from \"drizzle-orm/effect-mysql2\";\nimport type { AnyMySqlTable, MySqlColumn } from \"drizzle-orm/mysql-core\";\nimport { Cause, Effect, Schema } from \"effect\";\n\nimport {\n column,\n isMappedConstraintConflict,\n PersistenceMappingError,\n provisioningFingerprint,\n type ExternalIdentityTables,\n type IdentityTables,\n type SubjectProvisioningTables,\n} from \"./model\";\nimport { Database as DatabaseService } from \"./mysql-database\";\nimport { NativeDatabase, nativeDatabase } from \"./native-database\";\nimport { validateDrizzleStorage } from \"./storage-validation\";\n\ntype RuntimeDatabase = EffectMysql2Database<any>;\nconst unavailable = () => IdentityUnavailable.make();\nconst isIdentityFailure = Schema.is(Schema.Union([IdentityConflict, IdentityUnavailable]));\n\nconst mapUnavailable = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n reportPersistenceFailure(effect, isIdentityFailure).pipe(\n Effect.catchCause((cause) =>\n Effect.failCause(\n Cause.map(cause, (error) => (isIdentityFailure(error) ? error : unavailable())),\n ),\n ),\n );\n\nexport const makeMysqlSubjectProvisioningServices = Effect.fnUntraced(function* <\n Subject extends AnyMySqlTable,\n Identifier extends AnyMySqlTable,\n Request extends AnyMySqlTable,\n NativeId,\n>(mapping: SubjectProvisioningTables<Subject, Identifier, Request, NativeId>) {\n const database = yield* DatabaseService;\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(DatabaseService)),\n Effect.mapError(() => IdentityUnavailable.make()),\n );\n\n const db = database as RuntimeDatabase;\n const requestTable = mapping.provisioningRequest.table;\n\n const requestIdColumn = column(\n requestTable,\n mapping.provisioningRequest.requestId,\n ) as MySqlColumn;\n\n const requestFingerprintColumn = column(\n requestTable,\n mapping.provisioningRequest.fingerprint,\n ) as MySqlColumn;\n\n const requestSubjectColumn = column(\n requestTable,\n mapping.provisioningRequest.subjectId,\n ) as MySqlColumn;\n\n const identifierTable = mapping.identifier.table;\n\n const findReceipt = Effect.fn(\"DrizzleMysqlIdentity.findReceipt\")(function* (requestId: string) {\n const rows = yield* db\n .select({ fingerprint: requestFingerprintColumn, subjectId: requestSubjectColumn })\n .from(requestTable as any)\n .where(eq(requestIdColumn, requestId))\n .limit(1);\n\n return rows[0];\n });\n\n const provision = Effect.fn(\"DrizzleMysqlIdentity.provision\")(function* (\n input: SubjectProvisioningInput,\n ) {\n const fingerprint = provisioningFingerprint(input);\n const existing = yield* findReceipt(input.requestId);\n\n if (existing !== undefined) {\n if (existing.fingerprint !== fingerprint) return yield* IdentityConflict.make();\n const subjectId = yield* mapping.subjectId.toSubject(existing.subjectId as NativeId);\n\n return SubjectProvisioned.make({ subjectId });\n }\n\n const attempt = db.transaction((tx) =>\n Effect.gen(function* () {\n const allocated =\n mapping.subject.allocateId === undefined\n ? mapping.subject.allocateIdSync?.()\n : yield* mapping.subject.allocateId;\n\n const insert = tx\n .insert(mapping.subject.table as any)\n .values(mapping.subject.encodeInsert(input, allocated) as any);\n\n let nativeId = allocated;\n\n if (nativeId === undefined) {\n if (mapping.subject.decodeGeneratedId === undefined)\n return yield* PersistenceMappingError.make({\n operation: \"provisionSubject.generatedId\",\n cause: new Error(\"MySQL generated IDs require decodeGeneratedId\"),\n });\n const ids = yield* insert.$returningId();\n\n nativeId = yield* mapping.subject.decodeGeneratedId(ids as ReadonlyArray<unknown>);\n } else {\n yield* insert;\n }\n if (input.identifier !== undefined)\n yield* tx\n .insert(identifierTable as any)\n .values(\n mapping.identifier.encodeInsert(input.identifier, nativeId, input.verifiedAt) as any,\n );\n yield* tx\n .insert(requestTable as any)\n .values(\n mapping.provisioningRequest.encodeInsert(input.requestId, fingerprint, nativeId) as any,\n );\n\n return nativeId;\n }),\n );\n\n const nativeId = yield* attempt.pipe(\n Effect.catchCause(\n (\n cause,\n ): Effect.Effect<\n NativeId,\n | Effect.Error<typeof attempt>\n | Effect.Error<ReturnType<typeof findReceipt>>\n | IdentityConflict\n > => {\n if (\n cause.reasons.length === 0 ||\n !cause.reasons.every(\n (reason) =>\n Cause.isFailReason(reason) &&\n isMappedConstraintConflict(mapping.isConstraintConflict, reason.error),\n )\n )\n return Effect.failCause(cause);\n\n return findReceipt(input.requestId).pipe(\n Effect.flatMap((receipt) => {\n if (receipt !== undefined && receipt.fingerprint === fingerprint)\n return Effect.succeed(receipt.subjectId as NativeId);\n\n return IdentityConflict.make();\n }),\n );\n },\n ),\n );\n\n const subjectId = yield* mapping.subjectId.toSubject(nativeId);\n\n return SubjectProvisioned.make({ subjectId });\n }, mapUnavailable);\n\n return { subjectProvisioner: SubjectProvisioner.of({ provision }) } as const;\n});\n\nexport const makeMysqlExternalIdentityServices = Effect.fnUntraced(function* <\n Subject extends AnyMySqlTable,\n External extends AnyMySqlTable,\n NativeId,\n>(mapping: ExternalIdentityTables<Subject, External, NativeId>) {\n const database = yield* DatabaseService;\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(DatabaseService)),\n Effect.mapError(() => IdentityUnavailable.make()),\n );\n\n const db = database as RuntimeDatabase;\n const externalTable = mapping.externalIdentity.table;\n\n const externalProviderColumn = column(\n externalTable,\n mapping.externalIdentity.provider,\n ) as MySqlColumn;\n\n const externalIssuerColumn = column(\n externalTable,\n mapping.externalIdentity.issuer,\n ) as MySqlColumn;\n\n const externalSubjectColumn = column(\n externalTable,\n mapping.externalIdentity.subject,\n ) as MySqlColumn;\n\n const externalSubjectIdColumn = column(\n externalTable,\n mapping.externalIdentity.subjectId,\n ) as MySqlColumn;\n\n const subjectIdColumn = column(mapping.subject.table, mapping.subject.id) as MySqlColumn;\n const subjectStatusColumn = column(mapping.subject.table, mapping.subject.status) as MySqlColumn;\n\n const bind = Effect.fn(\"DrizzleMysqlIdentity.bindExternalIdentity\")(function* (\n subjectId: SubjectId,\n identity: ExternalIdentity,\n ) {\n const nativeId = yield* mapping.subjectId.toNative(subjectId);\n\n const decision = yield* db\n .transaction((tx) =>\n Effect.gen(function* () {\n const subjects = yield* tx\n .select({ status: subjectStatusColumn })\n .from(mapping.subject.table as any)\n .where(eq(subjectIdColumn, nativeId))\n .for(\"update\")\n .limit(1);\n\n if (subjects[0] === undefined || !mapping.subject.isActiveStatus(subjects[0].status))\n return { _tag: \"conflict\" } as const;\n\n const links = yield* tx\n .select({ subjectId: externalSubjectIdColumn })\n .from(externalTable as any)\n .where(\n and(\n eq(externalProviderColumn, identity.provider),\n eq(externalIssuerColumn, identity.issuer),\n eq(externalSubjectColumn, identity.subject),\n ),\n )\n .for(\"update\")\n .limit(1);\n\n if (links[0] !== undefined)\n return mapping.subjectId.equals(links[0].subjectId as NativeId, nativeId)\n ? ({ _tag: \"bound\" } as const)\n : ({ _tag: \"conflict\" } as const);\n yield* tx\n .insert(externalTable as any)\n .values(mapping.externalIdentity.encodeInsert(identity, nativeId) as any);\n\n return { _tag: \"bound\" } as const;\n }),\n )\n .pipe(\n Effect.catchCause((cause) => {\n if (\n cause.reasons.length === 0 ||\n !cause.reasons.every(\n (reason) =>\n Cause.isFailReason(reason) &&\n isMappedConstraintConflict(mapping.isConstraintConflict, reason.error),\n )\n )\n return Effect.failCause(cause);\n\n return db\n .select({ subjectId: externalSubjectIdColumn })\n .from(externalTable as any)\n .where(\n and(\n eq(externalProviderColumn, identity.provider),\n eq(externalIssuerColumn, identity.issuer),\n eq(externalSubjectColumn, identity.subject),\n ),\n )\n .limit(1)\n .pipe(\n Effect.map((rows) =>\n rows[0] !== undefined &&\n mapping.subjectId.equals(rows[0].subjectId as NativeId, nativeId)\n ? ({ _tag: \"bound\" } as const)\n : ({ _tag: \"conflict\" } as const),\n ),\n );\n }),\n );\n\n if (decision._tag === \"conflict\") return yield* IdentityConflict.make();\n }, mapUnavailable);\n\n return { externalIdentityMutation: ExternalIdentityMutation.of({ bind }) } as const;\n});\n\nexport const makeMysqlIdentityServices = Effect.fnUntraced(function* <\n Subject extends AnyMySqlTable,\n Identifier extends AnyMySqlTable,\n External extends AnyMySqlTable,\n Request extends AnyMySqlTable,\n NativeId,\n>(mapping: IdentityTables<Subject, Identifier, External, Request, NativeId>) {\n return {\n ...(yield* makeMysqlSubjectProvisioningServices(mapping)),\n ...(yield* makeMysqlExternalIdentityServices(mapping)),\n };\n}, withStorageValidation);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ProofClock, SqlExpression } from "@yielded/auth-persistence/Adapter";
|
|
2
|
+
import { SQL } from "drizzle-orm";
|
|
3
|
+
//#region src/drizzle/native-clock.d.ts
|
|
4
|
+
export type MappedClock = ProofClock<SQL> | ProofClock<SqlExpression>;
|
|
5
|
+
export type ClockMapping<M> = Omit<M, "clock"> & {
|
|
6
|
+
readonly clock: MappedClock;
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
//# sourceMappingURL=native-clock.d.mts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SQL, is, sql } from "drizzle-orm";
|
|
2
|
+
//#region src/drizzle/native-clock.ts
|
|
3
|
+
/** Shared storage mappings already accept native expressions. Only a clock
|
|
4
|
+
* declared with a real Drizzle SQL expression needs the foreign parameter bridge.
|
|
5
|
+
* Never probe callbacks by executing and retrying them with another representation. */
|
|
6
|
+
const nativeClock = (clock) => {
|
|
7
|
+
if (!is(clock.engineNowMillis, SQL)) return clock;
|
|
8
|
+
const drizzle = clock;
|
|
9
|
+
return {
|
|
10
|
+
...drizzle,
|
|
11
|
+
toMillis: (value) => drizzle.toMillis(sql`${sql.param(value)}`),
|
|
12
|
+
fromMillis: (value) => drizzle.fromMillis(sql`${sql.param(value)}`)
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { nativeClock };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=native-clock.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-clock.mjs","names":[],"sources":["../../src/drizzle/native-clock.ts"],"sourcesContent":["import type { ProofClock, SqlExpression } from \"@yielded/auth-persistence/Adapter\";\nimport { is, SQL, sql } from \"drizzle-orm\";\n\nexport type MappedClock = ProofClock<SQL> | ProofClock<SqlExpression>;\nexport type ClockMapping<M> = Omit<M, \"clock\"> & { readonly clock: MappedClock };\n\n/** Shared storage mappings already accept native expressions. Only a clock\n * declared with a real Drizzle SQL expression needs the foreign parameter bridge.\n * Never probe callbacks by executing and retrying them with another representation. */\nexport const nativeClock = (clock: MappedClock): ProofClock<SqlExpression> => {\n if (!is(clock.engineNowMillis, SQL)) return clock as ProofClock<SqlExpression>;\n // The physical expression identifies the callback family. This erases only\n // foreign compiler variance; persisted times still use the declared codecs.\n const drizzle = clock as ProofClock<SQL>;\n\n return {\n ...drizzle,\n toMillis: (value) => drizzle.toMillis(sql`${sql.param(value)}`),\n fromMillis: (value) => drizzle.fromMillis(sql`${sql.param(value)}`),\n };\n};\n"],"mappings":";;;;;AASA,MAAa,eAAe,UAAkD;CAC5E,IAAI,CAAC,GAAG,MAAM,iBAAiB,GAAG,GAAG,OAAO;CAG5C,MAAM,UAAU;CAEhB,OAAO;EACL,GAAG;EACH,WAAW,UAAU,QAAQ,SAAS,GAAG,GAAG,IAAI,MAAM,KAAK,GAAG;EAC9D,aAAa,UAAU,QAAQ,WAAW,GAAG,GAAG,IAAI,MAAM,KAAK,GAAG;CACpE;AACF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SQL } from "drizzle-orm";
|
|
2
|
+
import { Context, Effect } from "effect";
|
|
3
|
+
import { Statement } from "effect/sql/Statement";
|
|
4
|
+
import { SqlClient } from "effect/sql/SqlClient";
|
|
5
|
+
import { EffectDrizzleQueryError } from "drizzle-orm/effect-core";
|
|
6
|
+
import { SqlError } from "effect/sql/SqlError";
|
|
7
|
+
//#region src/drizzle/native-database.d.ts
|
|
8
|
+
/** Only installed driver handles are erased; domain values keep their schemas. */
|
|
9
|
+
export interface NativePhysicalDatabase {
|
|
10
|
+
readonly $client: SqlClient & {
|
|
11
|
+
readonly batch: (statements: ReadonlyArray<Statement<unknown>>) => Effect.Effect<unknown, SqlError>;
|
|
12
|
+
};
|
|
13
|
+
readonly transaction: <A, E, R>(body: (transaction: NativeDatabaseHandle) => Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqlError, R>;
|
|
14
|
+
}
|
|
15
|
+
declare const NativeDatabase_base: Context.ServiceClass<NativeDatabase, "effect-auth/persistence/NativeDatabase", NativePhysicalDatabase>;
|
|
16
|
+
/** The captured native Drizzle owner; never a shared/raw SQL resource. */
|
|
17
|
+
export declare class NativeDatabase extends NativeDatabase_base {}
|
|
18
|
+
export type NativeDatabaseHandle = NativeSqlDatabase & NativePhysicalDatabase;
|
|
19
|
+
export interface NativeSqlQuery<A = ReadonlyArray<any>> extends Effect.Effect<A, EffectDrizzleQueryError | SqlError> {
|
|
20
|
+
readonly getSQL: () => SQL;
|
|
21
|
+
readonly toSQL: () => {
|
|
22
|
+
readonly sql: string;
|
|
23
|
+
readonly params: ReadonlyArray<unknown>;
|
|
24
|
+
};
|
|
25
|
+
readonly from: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
26
|
+
readonly where: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
27
|
+
readonly limit: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
28
|
+
readonly orderBy: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
29
|
+
readonly for: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
30
|
+
readonly set: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
31
|
+
readonly values: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
32
|
+
readonly returning: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
33
|
+
readonly $returningId: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
34
|
+
readonly innerJoin: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
35
|
+
readonly onConflictDoNothing: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
36
|
+
readonly onDuplicateKeyUpdate: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;
|
|
37
|
+
}
|
|
38
|
+
export interface NativeSqlDatabase {
|
|
39
|
+
readonly select: (...args: ReadonlyArray<any>) => NativeSqlQuery;
|
|
40
|
+
readonly insert: (...args: ReadonlyArray<any>) => NativeSqlQuery;
|
|
41
|
+
readonly update: (...args: ReadonlyArray<any>) => NativeSqlQuery;
|
|
42
|
+
readonly delete: (...args: ReadonlyArray<any>) => NativeSqlQuery;
|
|
43
|
+
readonly transaction: <A, E, R>(body: (transaction: NativeSqlDatabase) => Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqlError, R>;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//# sourceMappingURL=native-database.d.mts.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
1
|
+
import { Context, Effect } from "effect";
|
|
2
2
|
//#region src/drizzle/native-database.ts
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/** The captured native Drizzle owner; never a shared/raw SQL resource. */
|
|
4
|
+
var NativeDatabase = class extends Context.Service()("effect-auth/persistence/NativeDatabase") {};
|
|
5
|
+
/** Driver makers supply actual query objects and their captured native client.
|
|
6
|
+
* Drizzle class declarations omit that client and D1's batch method. */
|
|
6
7
|
const nativeDatabase = (acquire) => Effect.map(acquire, (database) => database);
|
|
7
8
|
//#endregion
|
|
8
|
-
export { nativeDatabase };
|
|
9
|
+
export { NativeDatabase, nativeDatabase };
|
|
9
10
|
|
|
10
11
|
//# sourceMappingURL=native-database.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-database.mjs","names":[],"sources":["../../src/drizzle/native-database.ts"],"sourcesContent":["import type {\
|
|
1
|
+
{"version":3,"file":"native-database.mjs","names":[],"sources":["../../src/drizzle/native-database.ts"],"sourcesContent":["import type { SQL } from \"drizzle-orm\";\nimport type { EffectDrizzleQueryError } from \"drizzle-orm/effect-core\";\nimport { Context, Effect } from \"effect\";\nimport type { SqlClient } from \"effect/sql/SqlClient\";\nimport type { SqlError } from \"effect/sql/SqlError\";\nimport type { Statement } from \"effect/sql/Statement\";\n\n/** Only installed driver handles are erased; domain values keep their schemas. */\nexport interface NativePhysicalDatabase {\n readonly $client: SqlClient & {\n readonly batch: (\n statements: ReadonlyArray<Statement<unknown>>,\n ) => Effect.Effect<unknown, SqlError>;\n };\n readonly transaction: <A, E, R>(\n body: (transaction: NativeDatabaseHandle) => Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E | SqlError, R>;\n}\n\n/** The captured native Drizzle owner; never a shared/raw SQL resource. */\nexport class NativeDatabase extends Context.Service<NativeDatabase, NativePhysicalDatabase>()(\n \"effect-auth/persistence/NativeDatabase\",\n) {}\n\nexport type NativeDatabaseHandle = NativeSqlDatabase & NativePhysicalDatabase;\n\n/* oxlint-disable no-explicit-any -- only native query-builder handles are erased; domain values use mapped codecs. */\nexport interface NativeSqlQuery<A = ReadonlyArray<any>> extends Effect.Effect<\n A,\n EffectDrizzleQueryError | SqlError\n> {\n readonly getSQL: () => SQL;\n readonly toSQL: () => { readonly sql: string; readonly params: ReadonlyArray<unknown> };\n readonly from: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly where: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly limit: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly orderBy: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly for: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly set: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly values: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly returning: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly $returningId: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly innerJoin: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly onConflictDoNothing: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n readonly onDuplicateKeyUpdate: (...args: ReadonlyArray<any>) => NativeSqlQuery<A>;\n}\n\nexport interface NativeSqlDatabase {\n readonly select: (...args: ReadonlyArray<any>) => NativeSqlQuery;\n readonly insert: (...args: ReadonlyArray<any>) => NativeSqlQuery;\n readonly update: (...args: ReadonlyArray<any>) => NativeSqlQuery;\n readonly delete: (...args: ReadonlyArray<any>) => NativeSqlQuery;\n readonly transaction: <A, E, R>(\n body: (transaction: NativeSqlDatabase) => Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E | SqlError, R>;\n}\n\n/** Driver makers supply actual query objects and their captured native client.\n * Drizzle class declarations omit that client and D1's batch method. */\nexport const nativeDatabase = <Database, E, R>(acquire: Effect.Effect<Database, E, R>) =>\n Effect.map(\n acquire,\n (database) => database as unknown as Database & NativePhysicalDatabase & NativeSqlDatabase,\n );\n"],"mappings":";;;AAoBA,IAAa,iBAAb,cAAoC,QAAQ,QAAgD,CAAC,CAC3F,wCACF,CAAC,CAAC,CAAC;;;AAqCH,MAAa,kBAAkC,YAC7C,OAAO,IACL,UACC,aAAa,QAChB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PersistenceMappingError, makeNativeSqlTables, nativeSqlAlias } from "@yielded/auth-persistence/Adapter";
|
|
2
|
-
import { Param, Placeholder, Table, getTableColumns, getTableName, is, sql } from "drizzle-orm";
|
|
2
|
+
import { Param, Placeholder, SQL, Table, getTableColumns, getTableName, is, sql } from "drizzle-orm";
|
|
3
3
|
import { Predicate } from "effect";
|
|
4
4
|
import { MySqlTable, getTableConfig } from "drizzle-orm/mysql-core";
|
|
5
5
|
import { PgTable, getTableConfig as getTableConfig$1 } from "drizzle-orm/pg-core";
|
|
@@ -86,10 +86,17 @@ const makeDrizzleSqlTables = (client, capturedDatabase) => {
|
|
|
86
86
|
const column = getColumn(key);
|
|
87
87
|
return alias === void 0 ? sql`${column}` : sql`${sql.identifier(alias)}.${sql.identifier(column.name)}`;
|
|
88
88
|
};
|
|
89
|
+
const selection = (key) => {
|
|
90
|
+
const column = getColumn(key);
|
|
91
|
+
return dialect.codecs === void 0 ? reference(key) : dialect.codecs.apply(column, "cast", reference(key));
|
|
92
|
+
};
|
|
89
93
|
return {
|
|
94
|
+
keys: entries.map(([key]) => key),
|
|
90
95
|
name: compile(alias === void 0 ? sql`${physical}` : sql`${physical} AS ${sql.identifier(alias)}`),
|
|
91
96
|
as: bind,
|
|
92
97
|
column: (key) => compile(reference(key)),
|
|
98
|
+
columnName: (key) => compile(sql`${sql.identifier(getColumn(key).name)}`),
|
|
99
|
+
selectedColumn: (key) => compile(sql`${selection(key)}`),
|
|
93
100
|
unencodedTextColumn: (key) => {
|
|
94
101
|
const column = getColumn(key);
|
|
95
102
|
return [
|
|
@@ -108,10 +115,7 @@ const makeDrizzleSqlTables = (client, capturedDatabase) => {
|
|
|
108
115
|
name: column.name
|
|
109
116
|
} : void 0;
|
|
110
117
|
},
|
|
111
|
-
fields: (prefix) => compile(sql.join(entries.map(([key
|
|
112
|
-
const selection = dialect.codecs === void 0 ? reference(key) : dialect.codecs.apply(column, "cast", reference(key));
|
|
113
|
-
return sql`${selection} as ${sql.identifier(nativeSqlAlias(prefix, index))}`;
|
|
114
|
-
}), sql`, `)),
|
|
118
|
+
fields: (prefix) => compile(sql.join(entries.map(([key], index) => sql`${selection(key)} as ${sql.identifier(nativeSqlAlias(prefix, index))}`), sql`, `)),
|
|
115
119
|
decode: (row, prefix) => Object.fromEntries(entries.map(([key, column], index) => {
|
|
116
120
|
const alias = nativeSqlAlias(prefix, index);
|
|
117
121
|
if (!Object.hasOwn(row, alias)) return invalid("Missing SQL projection field");
|
|
@@ -127,6 +131,10 @@ const makeDrizzleSqlTables = (client, capturedDatabase) => {
|
|
|
127
131
|
};
|
|
128
132
|
};
|
|
129
133
|
return bind();
|
|
134
|
+
}, (value) => {
|
|
135
|
+
if (Statement$1.isFragment(value)) return value;
|
|
136
|
+
if (!is(value, SQL)) return invalid("Expected a Drizzle SQL expression");
|
|
137
|
+
return compile(value);
|
|
130
138
|
});
|
|
131
139
|
};
|
|
132
140
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-sql-table.mjs","names":["Statement","getPgTableConfig","getMysqlTableConfig"],"sources":["../../src/drizzle/native-sql-table.ts"],"sourcesContent":["import {\n PersistenceMappingError,\n makeNativeSqlTables,\n nativeSqlAlias,\n type NativeSqlTables,\n type SqlTable,\n} from \"@yielded/auth-persistence/Adapter\";\nimport {\n getTableColumns,\n getTableName,\n is,\n Param,\n Placeholder,\n type SQL,\n Table,\n sql,\n type BuildQueryConfig,\n type SQLWrapper,\n} from \"drizzle-orm\";\nimport { getTableConfig as getMysqlTableConfig, MySqlTable } from \"drizzle-orm/mysql-core\";\nimport { getTableConfig as getPgTableConfig, PgTable } from \"drizzle-orm/pg-core\";\nimport { Predicate } from \"effect\";\nimport type { SqlClient } from \"effect/sql/SqlClient\";\nimport * as Statement from \"effect/sql/Statement\";\n\ntype CapturedDialect = Pick<BuildQueryConfig, \"escapeName\" | \"escapeString\" | \"codecs\">;\n\n/** Foreign compiler boundary only: builders are used to materialize SQL, never\n * executed. The select builder exposes the original dialect even through the\n * Durable Object database projection, which retains bound query methods. */\ninterface CapturedDatabase {\n readonly select: () => { readonly dialect: CapturedDialect };\n readonly insert: (table: Table) => {\n readonly values: (values: Record<string, unknown>) => SQLWrapper;\n };\n readonly update: (table: Table) => {\n readonly set: (values: Record<string, unknown>) => SQLWrapper;\n };\n}\n\nconst invalid = (cause: string): never => {\n throw PersistenceMappingError.make({ operation: \"mapping\", cause });\n};\n\nconst capture = (\n database: object,\n): { readonly database: CapturedDatabase; readonly dialect: CapturedDialect } => {\n if (\n !Predicate.hasProperty(database, \"select\") ||\n typeof database.select !== \"function\" ||\n !Predicate.hasProperty(database, \"insert\") ||\n typeof database.insert !== \"function\" ||\n !Predicate.hasProperty(database, \"update\") ||\n typeof database.update !== \"function\"\n )\n return invalid(\"Expected a captured Drizzle database\");\n\n const selection: unknown = database.select();\n\n if (!Predicate.hasProperty(selection, \"dialect\"))\n return invalid(\"Expected a captured Drizzle dialect\");\n const dialect = selection.dialect;\n\n if (\n !Predicate.hasProperty(dialect, \"escapeName\") ||\n typeof dialect.escapeName !== \"function\" ||\n !Predicate.hasProperty(dialect, \"escapeString\") ||\n typeof dialect.escapeString !== \"function\"\n )\n return invalid(\"Expected Drizzle dialect escaping methods\");\n\n if (\n Predicate.hasProperty(dialect, \"codecs\") &&\n dialect.codecs !== undefined &&\n (!Predicate.hasProperty(dialect.codecs, \"apply\") || typeof dialect.codecs.apply !== \"function\")\n )\n return invalid(\"Expected Drizzle dialect codecs\");\n\n // Drizzle's private dialect and generic query builders are erased only here.\n return { database: database as CapturedDatabase, dialect: dialect as CapturedDialect };\n};\n\nconst compileWith =\n (dialect: CapturedDialect) =>\n (expression: SQL): Statement.Fragment => {\n const slots: string[] = [];\n\n const query = expression.toQuery({\n escapeName: (name) => {\n if (name.includes(\"\\0\")) return invalid(\"NUL in SQL identifier\");\n\n return dialect.escapeName(name);\n },\n escapeString: (value) => {\n if (value.includes(\"\\0\")) return invalid(\"NUL in SQL literal\");\n\n return dialect.escapeString(value);\n },\n escapeParam: (index) => {\n if (index !== slots.length) return invalid(\"Invalid Drizzle parameter order\");\n const slot = `yielded_parameter_${index}`;\n\n slots.push(slot);\n\n return `\\0${slot}\\0`;\n },\n ...(dialect.codecs === undefined ? {} : { codecs: dialect.codecs }),\n });\n\n // Only compiler-emitted slots are translated. Native Statement parameters\n // receive their final positions when composed; SQL literals containing $1 or\n // ? are never inspected or rewritten. NUL is reserved for this compilation.\n const parts = query.sql.split(\"\\0\");\n\n if (parts.length !== slots.length * 2 + 1 || query.params.length !== slots.length)\n return invalid(\"NUL or parameter marker collision in Drizzle SQL\");\n\n const segments: Statement.Segment[] = [];\n const consumed = new Set<number>();\n\n for (let offset = 0; offset < parts.length; offset += 2) {\n segments.push(Statement.literal(parts[offset]));\n if (offset + 1 === parts.length) break;\n const index = slots.indexOf(parts[offset + 1]);\n\n if (index < 0 || consumed.has(index))\n return invalid(\"NUL or parameter marker collision in Drizzle SQL\");\n consumed.add(index);\n const value: unknown = query.params[index];\n\n if (is(value, Placeholder) || is(value, Param)) return invalid(\"Unbound Drizzle placeholder\");\n if (Statement.isFragment(value)) segments.push(...value.segments);\n else segments.push(Statement.parameter(value));\n }\n\n return Statement.fragment(segments);\n };\n\n/** Preserve native Statement expressions in writes without applying a column\n * codec to them. Ordinary values still pass through Drizzle's own builders. */\nconst writeValues = (values: Readonly<Record<string, unknown>>) =>\n Object.fromEntries(\n Object.entries(values).map(([key, value]) => [\n key,\n Statement.isFragment(value) ? sql`${sql.param(value)}` : value,\n ]),\n );\n\n/** Capture the root database's compiler, not a later transaction object's\n * client. Call insert/update inside the operation to materialize hooks once. */\nexport const makeDrizzleSqlTables = (\n client: SqlClient,\n capturedDatabase: object,\n): NativeSqlTables => {\n const { database, dialect } = capture(capturedDatabase);\n const compile = compileWith(dialect);\n\n return makeNativeSqlTables(client, (_client, physical): SqlTable => {\n if (!is(physical, Table)) return invalid(\"Expected a Drizzle table\");\n const columns = getTableColumns(physical);\n const entries = Object.entries(columns);\n\n const schema = is(physical, PgTable)\n ? getPgTableConfig(physical).schema\n : is(physical, MySqlTable)\n ? getMysqlTableConfig(physical).schema\n : undefined;\n\n const table = { name: getTableName(physical), ...(schema === undefined ? {} : { schema }) };\n\n const getColumn = (key: string) => {\n const column = Object.hasOwn(columns, key) ? columns[key] : undefined;\n\n if (column === undefined) return invalid(\"Missing Drizzle column\");\n\n return column;\n };\n\n const bind = (alias?: string): SqlTable => {\n const reference = (key: string) => {\n const column = getColumn(key);\n\n return alias === undefined\n ? sql`${column}`\n : sql`${sql.identifier(alias)}.${sql.identifier(column.name)}`;\n };\n\n return {\n name: compile(\n alias === undefined ? sql`${physical}` : sql`${physical} AS ${sql.identifier(alias)}`,\n ),\n as: bind,\n column: (key) => compile(reference(key)),\n unencodedTextColumn: (key) => {\n const column = getColumn(key);\n\n return [\"PgText\", \"PgVarchar\", \"SQLiteText\", \"MySqlText\", \"MySqlVarChar\"].includes(\n column.columnType,\n ) &&\n Predicate.hasProperty(column.mapToDriverValue, \"isNoop\") &&\n column.mapToDriverValue.isNoop === true &&\n Predicate.hasProperty(column.mapFromDriverValue, \"isNoop\") &&\n column.mapFromDriverValue.isNoop === true &&\n (dialect.codecs === undefined ||\n (Predicate.hasProperty(dialect.codecs, \"get\") &&\n typeof dialect.codecs.get === \"function\" &&\n ([\"cast\", \"normalize\", \"castParam\", \"normalizeParam\"] as const).every(\n (kind) => dialect.codecs?.get(column, kind) === undefined,\n )))\n ? { table, name: column.name }\n : undefined;\n },\n fields: (prefix) =>\n compile(\n sql.join(\n entries.map(([key, column], index) => {\n const selection =\n dialect.codecs === undefined\n ? reference(key)\n : dialect.codecs.apply(column, \"cast\", reference(key));\n\n return sql`${selection} as ${sql.identifier(nativeSqlAlias(prefix, index))}`;\n }),\n sql`, `,\n ),\n ),\n decode: (row, prefix) =>\n Object.fromEntries(\n entries.map(([key, column], index) => {\n const alias = nativeSqlAlias(prefix, index);\n\n if (!Object.hasOwn(row, alias)) return invalid(\"Missing SQL projection field\");\n const value = row[alias];\n\n return [\n key,\n value === null\n ? null\n : column.mapFromDriverValue(\n dialect.codecs === undefined\n ? value\n : dialect.codecs.apply(column, \"normalize\", value),\n ),\n ];\n }),\n ),\n value: (key, value) => {\n const column = getColumn(key);\n\n return Statement.isFragment(value) ? value : compile(sql`${sql.param(value, column)}`);\n },\n insert: (values) => compile(database.insert(physical).values(writeValues(values)).getSQL()),\n update: (values) => compile(database.update(physical).set(writeValues(values)).getSQL()),\n };\n };\n\n return bind();\n });\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"native-sql-table.mjs","names":["Statement","getPgTableConfig","getMysqlTableConfig"],"sources":["../../src/drizzle/native-sql-table.ts"],"sourcesContent":["import {\n PersistenceMappingError,\n makeNativeSqlTables,\n nativeSqlAlias,\n type NativeSqlTables,\n type SqlTable,\n} from \"@yielded/auth-persistence/Adapter\";\nimport {\n getTableColumns,\n getTableName,\n is,\n Param,\n Placeholder,\n SQL,\n Table,\n sql,\n type BuildQueryConfig,\n type SQLWrapper,\n} from \"drizzle-orm\";\nimport { getTableConfig as getMysqlTableConfig, MySqlTable } from \"drizzle-orm/mysql-core\";\nimport { getTableConfig as getPgTableConfig, PgTable } from \"drizzle-orm/pg-core\";\nimport { Predicate } from \"effect\";\nimport type { SqlClient } from \"effect/sql/SqlClient\";\nimport * as Statement from \"effect/sql/Statement\";\n\ntype CapturedDialect = Pick<BuildQueryConfig, \"escapeName\" | \"escapeString\" | \"codecs\">;\n\n/** Foreign compiler boundary only: builders are used to materialize SQL, never\n * executed. The select builder exposes the original dialect even through the\n * Durable Object database projection, which retains bound query methods. */\ninterface CapturedDatabase {\n readonly select: () => { readonly dialect: CapturedDialect };\n readonly insert: (table: Table) => {\n readonly values: (values: Record<string, unknown>) => SQLWrapper;\n };\n readonly update: (table: Table) => {\n readonly set: (values: Record<string, unknown>) => SQLWrapper;\n };\n}\n\nconst invalid = (cause: string): never => {\n throw PersistenceMappingError.make({ operation: \"mapping\", cause });\n};\n\nconst capture = (\n database: object,\n): { readonly database: CapturedDatabase; readonly dialect: CapturedDialect } => {\n if (\n !Predicate.hasProperty(database, \"select\") ||\n typeof database.select !== \"function\" ||\n !Predicate.hasProperty(database, \"insert\") ||\n typeof database.insert !== \"function\" ||\n !Predicate.hasProperty(database, \"update\") ||\n typeof database.update !== \"function\"\n )\n return invalid(\"Expected a captured Drizzle database\");\n\n const selection: unknown = database.select();\n\n if (!Predicate.hasProperty(selection, \"dialect\"))\n return invalid(\"Expected a captured Drizzle dialect\");\n const dialect = selection.dialect;\n\n if (\n !Predicate.hasProperty(dialect, \"escapeName\") ||\n typeof dialect.escapeName !== \"function\" ||\n !Predicate.hasProperty(dialect, \"escapeString\") ||\n typeof dialect.escapeString !== \"function\"\n )\n return invalid(\"Expected Drizzle dialect escaping methods\");\n\n if (\n Predicate.hasProperty(dialect, \"codecs\") &&\n dialect.codecs !== undefined &&\n (!Predicate.hasProperty(dialect.codecs, \"apply\") || typeof dialect.codecs.apply !== \"function\")\n )\n return invalid(\"Expected Drizzle dialect codecs\");\n\n // Drizzle's private dialect and generic query builders are erased only here.\n return { database: database as CapturedDatabase, dialect: dialect as CapturedDialect };\n};\n\nconst compileWith =\n (dialect: CapturedDialect) =>\n (expression: SQL): Statement.Fragment => {\n const slots: string[] = [];\n\n const query = expression.toQuery({\n escapeName: (name) => {\n if (name.includes(\"\\0\")) return invalid(\"NUL in SQL identifier\");\n\n return dialect.escapeName(name);\n },\n escapeString: (value) => {\n if (value.includes(\"\\0\")) return invalid(\"NUL in SQL literal\");\n\n return dialect.escapeString(value);\n },\n escapeParam: (index) => {\n if (index !== slots.length) return invalid(\"Invalid Drizzle parameter order\");\n const slot = `yielded_parameter_${index}`;\n\n slots.push(slot);\n\n return `\\0${slot}\\0`;\n },\n ...(dialect.codecs === undefined ? {} : { codecs: dialect.codecs }),\n });\n\n // Only compiler-emitted slots are translated. Native Statement parameters\n // receive their final positions when composed; SQL literals containing $1 or\n // ? are never inspected or rewritten. NUL is reserved for this compilation.\n const parts = query.sql.split(\"\\0\");\n\n if (parts.length !== slots.length * 2 + 1 || query.params.length !== slots.length)\n return invalid(\"NUL or parameter marker collision in Drizzle SQL\");\n\n const segments: Statement.Segment[] = [];\n const consumed = new Set<number>();\n\n for (let offset = 0; offset < parts.length; offset += 2) {\n segments.push(Statement.literal(parts[offset]));\n if (offset + 1 === parts.length) break;\n const index = slots.indexOf(parts[offset + 1]);\n\n if (index < 0 || consumed.has(index))\n return invalid(\"NUL or parameter marker collision in Drizzle SQL\");\n consumed.add(index);\n const value: unknown = query.params[index];\n\n if (is(value, Placeholder) || is(value, Param)) return invalid(\"Unbound Drizzle placeholder\");\n if (Statement.isFragment(value)) segments.push(...value.segments);\n else segments.push(Statement.parameter(value));\n }\n\n return Statement.fragment(segments);\n };\n\n/** Preserve native Statement expressions in writes without applying a column\n * codec to them. Ordinary values still pass through Drizzle's own builders. */\nconst writeValues = (values: Readonly<Record<string, unknown>>) =>\n Object.fromEntries(\n Object.entries(values).map(([key, value]) => [\n key,\n Statement.isFragment(value) ? sql`${sql.param(value)}` : value,\n ]),\n );\n\n/** Capture the root database's compiler, not a later transaction object's\n * client. Call insert/update inside the operation to materialize hooks once. */\nexport const makeDrizzleSqlTables = (\n client: SqlClient,\n capturedDatabase: object,\n): NativeSqlTables => {\n const { database, dialect } = capture(capturedDatabase);\n const compile = compileWith(dialect);\n\n return makeNativeSqlTables(\n client,\n (_client, physical): SqlTable => {\n if (!is(physical, Table)) return invalid(\"Expected a Drizzle table\");\n const columns = getTableColumns(physical);\n const entries = Object.entries(columns);\n\n const schema = is(physical, PgTable)\n ? getPgTableConfig(physical).schema\n : is(physical, MySqlTable)\n ? getMysqlTableConfig(physical).schema\n : undefined;\n\n const table = { name: getTableName(physical), ...(schema === undefined ? {} : { schema }) };\n\n const getColumn = (key: string) => {\n const column = Object.hasOwn(columns, key) ? columns[key] : undefined;\n\n if (column === undefined) return invalid(\"Missing Drizzle column\");\n\n return column;\n };\n\n const bind = (alias?: string): SqlTable => {\n const reference = (key: string) => {\n const column = getColumn(key);\n\n return alias === undefined\n ? sql`${column}`\n : sql`${sql.identifier(alias)}.${sql.identifier(column.name)}`;\n };\n\n const selection = (key: string) => {\n const column = getColumn(key);\n\n return dialect.codecs === undefined\n ? reference(key)\n : dialect.codecs.apply(column, \"cast\", reference(key));\n };\n\n return {\n keys: entries.map(([key]) => key),\n name: compile(\n alias === undefined ? sql`${physical}` : sql`${physical} AS ${sql.identifier(alias)}`,\n ),\n as: bind,\n column: (key) => compile(reference(key)),\n columnName: (key) => compile(sql`${sql.identifier(getColumn(key).name)}`),\n selectedColumn: (key) => compile(sql`${selection(key)}`),\n unencodedTextColumn: (key) => {\n const column = getColumn(key);\n\n return [\"PgText\", \"PgVarchar\", \"SQLiteText\", \"MySqlText\", \"MySqlVarChar\"].includes(\n column.columnType,\n ) &&\n Predicate.hasProperty(column.mapToDriverValue, \"isNoop\") &&\n column.mapToDriverValue.isNoop === true &&\n Predicate.hasProperty(column.mapFromDriverValue, \"isNoop\") &&\n column.mapFromDriverValue.isNoop === true &&\n (dialect.codecs === undefined ||\n (Predicate.hasProperty(dialect.codecs, \"get\") &&\n typeof dialect.codecs.get === \"function\" &&\n ([\"cast\", \"normalize\", \"castParam\", \"normalizeParam\"] as const).every(\n (kind) => dialect.codecs?.get(column, kind) === undefined,\n )))\n ? { table, name: column.name }\n : undefined;\n },\n fields: (prefix) =>\n compile(\n sql.join(\n entries.map(\n ([key], index) =>\n sql`${selection(key)} as ${sql.identifier(nativeSqlAlias(prefix, index))}`,\n ),\n sql`, `,\n ),\n ),\n decode: (row, prefix) =>\n Object.fromEntries(\n entries.map(([key, column], index) => {\n const alias = nativeSqlAlias(prefix, index);\n\n if (!Object.hasOwn(row, alias)) return invalid(\"Missing SQL projection field\");\n const value = row[alias];\n\n return [\n key,\n value === null\n ? null\n : column.mapFromDriverValue(\n dialect.codecs === undefined\n ? value\n : dialect.codecs.apply(column, \"normalize\", value),\n ),\n ];\n }),\n ),\n value: (key, value) => {\n const column = getColumn(key);\n\n return Statement.isFragment(value) ? value : compile(sql`${sql.param(value, column)}`);\n },\n insert: (values) =>\n compile(database.insert(physical).values(writeValues(values)).getSQL()),\n update: (values) => compile(database.update(physical).set(writeValues(values)).getSQL()),\n };\n };\n\n return bind();\n },\n (value) => {\n if (Statement.isFragment(value)) return value;\n if (!is(value, SQL)) return invalid(\"Expected a Drizzle SQL expression\");\n\n return compile(value);\n },\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import "./native-database.mjs";
|
|
2
|
+
import "./D1BatchStatements.mjs";
|
|
3
|
+
import { SqlBatchCommit } from "@yielded/auth-persistence/Adapter";
|
|
4
|
+
import { Effect } from "effect";
|
|
5
|
+
import { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
6
|
+
import { SqlClient } from "effect/sql";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { D1BatchStatements } from "./D1BatchStatements.mjs";
|
|
2
|
+
import { NativeDatabase } from "./native-database.mjs";
|
|
3
|
+
import { makeDrizzleSqlTables } from "./native-sql-table.mjs";
|
|
4
|
+
import { makeDrizzleTransactionHandle } from "./transaction-handle.mjs";
|
|
5
|
+
import { makeMysqlTransactionHandle, mysqlNativeCommit } from "./transaction-mysql.mjs";
|
|
6
|
+
import { SqlBatchCommit, SqlNativeCommit, captureSqlBatchStatements, makeSqlCommitExecutor, requireStandalone } from "@yielded/auth-persistence/Adapter";
|
|
7
|
+
import { Effect } from "effect";
|
|
8
|
+
import { hasCommitScope } from "@yielded/auth/Hooks";
|
|
9
|
+
import { SqlClient } from "effect/sql";
|
|
10
|
+
//#region src/drizzle/native-target.ts
|
|
11
|
+
const physical = (work, database, configuration) => configuration.dialect === "mysql" ? Effect.provideService(work, SqlNativeCommit, mysqlNativeCommit(database.$client)) : work;
|
|
12
|
+
/** Pure physical metadata and the exact driver's commit capability. Domain
|
|
13
|
+
* mappings, row codecs and decisions stay in their shared native workflow. */
|
|
14
|
+
const nativeTarget = Effect.fnUntraced(function* (configuration) {
|
|
15
|
+
const database = yield* NativeDatabase;
|
|
16
|
+
const batch = {
|
|
17
|
+
client: database.$client,
|
|
18
|
+
execute: (statements) => database.$client.batch(statements).pipe(Effect.asVoid)
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
tables: makeDrizzleSqlTables(database.$client, database),
|
|
22
|
+
batch: configuration.mode === "batch" ? batch : void 0,
|
|
23
|
+
provide: (work) => physical(work.pipe(Effect.provideService(SqlClient.SqlClient, database.$client), Effect.provideService(SqlBatchCommit, configuration.mode === "batch" ? batch : void 0)), database, configuration)
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
const coordinateNativeTarget = (unavailable, database, configuration, make, body) => physical(Effect.gen(function* () {
|
|
27
|
+
if (yield* hasCommitScope) return yield* Effect.fail(unavailable());
|
|
28
|
+
if (configuration.mode !== "batch") yield* requireStandalone(unavailable, database.$client.transactionService);
|
|
29
|
+
const executor = yield* makeSqlCommitExecutor(unavailable);
|
|
30
|
+
const work = Effect.gen(function* () {
|
|
31
|
+
const services = yield* make.pipe(Effect.mapError(unavailable), Effect.provideService(NativeDatabase, database));
|
|
32
|
+
const transaction = yield* Effect.suspend(() => configuration.mode === "batch" ? Effect.succeed(void 0) : configuration.dialect === "mysql" ? makeMysqlTransactionHandle(database) : Effect.succeed(configuration.transactionFactory?.(database) ?? makeDrizzleTransactionHandle(database, configuration.transactionConstructor))).pipe(Effect.mapError(unavailable));
|
|
33
|
+
const collector = yield* captureSqlBatchStatements;
|
|
34
|
+
return yield* body(transaction, services).pipe(Effect.provideService(D1BatchStatements, { append: (statement) => collector.append(statement).pipe(Effect.orDie) }));
|
|
35
|
+
});
|
|
36
|
+
return yield* configuration.mode === "batch" ? executor.coordinateBatch(work) : executor.coordinate(work);
|
|
37
|
+
}).pipe(Effect.provideService(SqlClient.SqlClient, database.$client), Effect.provideService(SqlBatchCommit, {
|
|
38
|
+
client: database.$client,
|
|
39
|
+
execute: (statements) => database.$client.batch(statements).pipe(Effect.asVoid)
|
|
40
|
+
})), database, configuration);
|
|
41
|
+
//#endregion
|
|
42
|
+
export { coordinateNativeTarget, nativeTarget };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=native-target.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-target.mjs","names":[],"sources":["../../src/drizzle/native-target.ts"],"sourcesContent":["import {\n captureSqlBatchStatements,\n makeSqlCommitExecutor,\n requireStandalone,\n SqlBatchCommit,\n SqlNativeCommit,\n} from \"@yielded/auth-persistence/Adapter\";\nimport { hasCommitScope, type LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport { Effect } from \"effect\";\nimport { SqlClient } from \"effect/sql\";\n\nimport { D1BatchStatements } from \"./D1BatchStatements\";\nimport { NativeDatabase, type NativeDatabaseHandle } from \"./native-database\";\nimport { makeDrizzleSqlTables } from \"./native-sql-table\";\nimport {\n makeDrizzleTransactionHandle,\n type DrizzleTransactionConstructor,\n type DrizzleTransactionFactory,\n} from \"./transaction-handle\";\nimport { makeMysqlTransactionHandle, mysqlNativeCommit } from \"./transaction-mysql\";\n\nexport interface NativeTargetConfiguration {\n readonly mode: \"native\" | \"batch\";\n readonly dialect: \"pg\" | \"sqlite\" | \"mysql\";\n readonly transactionConstructor?: DrizzleTransactionConstructor;\n readonly transactionFactory?: DrizzleTransactionFactory;\n}\n\nconst physical = <A, E, R>(\n work: Effect.Effect<A, E, R>,\n database: Pick<NativeDatabaseHandle, \"$client\">,\n configuration: NativeTargetConfiguration,\n) =>\n configuration.dialect === \"mysql\"\n ? Effect.provideService(work, SqlNativeCommit, mysqlNativeCommit(database.$client))\n : work;\n\n/** Pure physical metadata and the exact driver's commit capability. Domain\n * mappings, row codecs and decisions stay in their shared native workflow. */\nexport const nativeTarget = Effect.fnUntraced(function* (configuration: NativeTargetConfiguration) {\n const database = yield* NativeDatabase;\n\n const batch: SqlBatchCommit[\"Service\"] = {\n client: database.$client,\n execute: (statements) => database.$client.batch(statements).pipe(Effect.asVoid),\n };\n\n return {\n tables: makeDrizzleSqlTables(database.$client, database),\n batch: configuration.mode === \"batch\" ? batch : undefined,\n provide: <A, E, R>(work: Effect.Effect<A, E, R>) =>\n physical(\n work.pipe(\n Effect.provideService(SqlClient.SqlClient, database.$client),\n Effect.provideService(SqlBatchCommit, configuration.mode === \"batch\" ? batch : undefined),\n ),\n database,\n configuration,\n ),\n };\n});\n\nexport const coordinateNativeTarget = <Failure, Services, Transaction, A, E, R, ES, RS>(\n unavailable: () => Failure,\n database: NativeDatabaseHandle,\n configuration: NativeTargetConfiguration,\n make: Effect.Effect<Services, ES, RS>,\n body: (transaction: Transaction, services: Services) => Effect.Effect<A, E, R>,\n): Effect.Effect<\n A,\n E | Failure,\n Exclude<R, D1BatchStatements> | Exclude<RS, NativeDatabase> | LifecycleHooks\n> =>\n physical(\n Effect.gen(function* () {\n if (yield* hasCommitScope) return yield* Effect.fail(unavailable());\n if (configuration.mode !== \"batch\")\n yield* requireStandalone(unavailable, database.$client.transactionService);\n const executor = yield* makeSqlCommitExecutor(unavailable);\n\n const work = Effect.gen(function* () {\n const services = yield* make.pipe(\n Effect.mapError(unavailable),\n Effect.provideService(NativeDatabase, database),\n );\n\n const transaction = yield* Effect.suspend(() =>\n configuration.mode === \"batch\"\n ? Effect.succeed(undefined)\n : configuration.dialect === \"mysql\"\n ? makeMysqlTransactionHandle(database)\n : Effect.succeed(\n configuration.transactionFactory?.(database) ??\n makeDrizzleTransactionHandle(database, configuration.transactionConstructor),\n ),\n ).pipe(Effect.mapError(unavailable));\n\n const collector = yield* captureSqlBatchStatements;\n\n // The validated physical driver constructor owns this class boundary.\n return yield* body(transaction as Transaction, services).pipe(\n Effect.provideService(D1BatchStatements, {\n append: (statement) => collector.append(statement).pipe(Effect.orDie),\n }),\n );\n });\n\n return yield* configuration.mode === \"batch\"\n ? executor.coordinateBatch(work)\n : executor.coordinate(work);\n }).pipe(\n Effect.provideService(SqlClient.SqlClient, database.$client),\n Effect.provideService(SqlBatchCommit, {\n client: database.$client,\n execute: (statements) => database.$client.batch(statements).pipe(Effect.asVoid),\n }),\n ),\n database,\n configuration,\n );\n"],"mappings":";;;;;;;;;;AA4BA,MAAM,YACJ,MACA,UACA,kBAEA,cAAc,YAAY,UACtB,OAAO,eAAe,MAAM,iBAAiB,kBAAkB,SAAS,OAAO,CAAC,IAChF;;;AAIN,MAAa,eAAe,OAAO,WAAW,WAAW,eAA0C;CACjG,MAAM,WAAW,OAAO;CAExB,MAAM,QAAmC;EACvC,QAAQ,SAAS;EACjB,UAAU,eAAe,SAAS,QAAQ,MAAM,UAAU,CAAC,CAAC,KAAK,OAAO,MAAM;CAChF;CAEA,OAAO;EACL,QAAQ,qBAAqB,SAAS,SAAS,QAAQ;EACvD,OAAO,cAAc,SAAS,UAAU,QAAQ,KAAA;EAChD,UAAmB,SACjB,SACE,KAAK,KACH,OAAO,eAAe,UAAU,WAAW,SAAS,OAAO,GAC3D,OAAO,eAAe,gBAAgB,cAAc,SAAS,UAAU,QAAQ,KAAA,CAAS,CAC1F,GACA,UACA,aACF;CACJ;AACF,CAAC;AAED,MAAa,0BACX,aACA,UACA,eACA,MACA,SAMA,SACE,OAAO,IAAI,aAAa;CACtB,IAAI,OAAO,gBAAgB,OAAO,OAAO,OAAO,KAAK,YAAY,CAAC;CAClE,IAAI,cAAc,SAAS,SACzB,OAAO,kBAAkB,aAAa,SAAS,QAAQ,kBAAkB;CAC3E,MAAM,WAAW,OAAO,sBAAsB,WAAW;CAEzD,MAAM,OAAO,OAAO,IAAI,aAAa;EACnC,MAAM,WAAW,OAAO,KAAK,KAC3B,OAAO,SAAS,WAAW,GAC3B,OAAO,eAAe,gBAAgB,QAAQ,CAChD;EAEA,MAAM,cAAc,OAAO,OAAO,cAChC,cAAc,SAAS,UACnB,OAAO,QAAQ,KAAA,CAAS,IACxB,cAAc,YAAY,UACxB,2BAA2B,QAAQ,IACnC,OAAO,QACL,cAAc,qBAAqB,QAAQ,KACzC,6BAA6B,UAAU,cAAc,sBAAsB,CAC/E,CACR,CAAC,CAAC,KAAK,OAAO,SAAS,WAAW,CAAC;EAEnC,MAAM,YAAY,OAAO;EAGzB,OAAO,OAAO,KAAK,aAA4B,QAAQ,CAAC,CAAC,KACvD,OAAO,eAAe,mBAAmB,EACvC,SAAS,cAAc,UAAU,OAAO,SAAS,CAAC,CAAC,KAAK,OAAO,KAAK,EACtE,CAAC,CACH;CACF,CAAC;CAED,OAAO,OAAO,cAAc,SAAS,UACjC,SAAS,gBAAgB,IAAI,IAC7B,SAAS,WAAW,IAAI;AAC9B,CAAC,CAAC,CAAC,KACD,OAAO,eAAe,UAAU,WAAW,SAAS,OAAO,GAC3D,OAAO,eAAe,gBAAgB;CACpC,QAAQ,SAAS;CACjB,UAAU,eAAe,SAAS,QAAQ,MAAM,UAAU,CAAC,CAAC,KAAK,OAAO,MAAM;AAChF,CAAC,CACH,GACA,UACA,aACF"}
|