@tempoxyz/id 0.0.0-pr-187.sha-eed04d3
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 +81 -0
- package/dist/App.d.ts +20 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +26 -0
- package/dist/App.js.map +1 -0
- package/dist/app/client/.assetsignore +2 -0
- package/dist/app/client/assets/BRLA-CZvVDNYr.png +0 -0
- package/dist/app/client/assets/CHFAU-DCedc4aH.png +0 -0
- package/dist/app/client/assets/DLUSD-BnRXm3EI.png +0 -0
- package/dist/app/client/assets/PRIME-CiFp2-3e.svg +14 -0
- package/dist/app/client/assets/Pilat-Bold-C1t1eIrF.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Book-CbS8ofT8.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Demi-CADSbPAt.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Regular-Bx8vzE7q.woff2 +0 -0
- package/dist/app/client/assets/USD1-COVcO_PB.svg +30 -0
- package/dist/app/client/assets/YLDS-CRh8Zw0g.svg +3 -0
- package/dist/app/client/assets/ccip-Cq1mMiVl.js +1 -0
- package/dist/app/client/assets/frxUSD-n9pTpinR.svg +1 -0
- package/dist/app/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/app/client/assets/index-B7YJVP00.css +1 -0
- package/dist/app/client/assets/index-UXTxXCLk.js +55 -0
- package/dist/app/client/assets/pathUSD-BvaO6ooS.svg +25 -0
- package/dist/app/client/assets/reset-co-CHrff.css +1 -0
- package/dist/app/client/assets/wYLDS-CaCKDrO-.svg +10 -0
- package/dist/app/db/auth.d.ts +3207 -0
- package/dist/app/db/auth.d.ts.map +1 -0
- package/dist/app/db/auth.js +330 -0
- package/dist/app/db/auth.js.map +1 -0
- package/dist/app/db/schema.d.ts +932 -0
- package/dist/app/db/schema.d.ts.map +1 -0
- package/dist/app/db/schema.js +171 -0
- package/dist/app/db/schema.js.map +1 -0
- package/dist/app/server/.vite/manifest.json +489 -0
- package/dist/app/server/assets/BRLA-CZvVDNYr.png +0 -0
- package/dist/app/server/assets/CHFAU-DCedc4aH.png +0 -0
- package/dist/app/server/assets/DLUSD-BnRXm3EI.png +0 -0
- package/dist/app/server/assets/PRIME-CiFp2-3e.svg +14 -0
- package/dist/app/server/assets/Pilat-Bold-C1t1eIrF.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Book-CbS8ofT8.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Demi-CADSbPAt.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Regular-Bx8vzE7q.woff2 +0 -0
- package/dist/app/server/assets/USD1-COVcO_PB.svg +30 -0
- package/dist/app/server/assets/YLDS-CRh8Zw0g.svg +3 -0
- package/dist/app/server/assets/_tanstack-start-manifest_v-DjQNeRZp.js +1 -0
- package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js +2 -0
- package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js.map +1 -0
- package/dist/app/server/assets/authorize-C95F-9E1-CbESJKGU.js +31 -0
- package/dist/app/server/assets/authorize-C95F-9E1-CbESJKGU.js.map +1 -0
- package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js +2 -0
- package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js.map +1 -0
- package/dist/app/server/assets/call-UQamaCKN.js +32 -0
- package/dist/app/server/assets/call-UQamaCKN.js.map +1 -0
- package/dist/app/server/assets/ccip-CbNKFO4n.js +2 -0
- package/dist/app/server/assets/ccip-CbNKFO4n.js.map +1 -0
- package/dist/app/server/assets/compiled-query-Ds2NVcFT.js +2 -0
- package/dist/app/server/assets/compiled-query-Ds2NVcFT.js.map +1 -0
- package/dist/app/server/assets/convert-BIC8n32x.js +2 -0
- package/dist/app/server/assets/convert-BIC8n32x.js.map +1 -0
- package/dist/app/server/assets/cookie-CS900nSP.css +1 -0
- package/dist/app/server/assets/cookie-Cce9CrIP.js +10 -0
- package/dist/app/server/assets/cookie-Cce9CrIP.js.map +1 -0
- package/dist/app/server/assets/core-B1HCXUmx.js +56 -0
- package/dist/app/server/assets/core-B1HCXUmx.js.map +1 -0
- package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js +2 -0
- package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js.map +1 -0
- package/dist/app/server/assets/default-u_dwuiYb-BJJ9PwCi.js +2 -0
- package/dist/app/server/assets/default-u_dwuiYb-BJJ9PwCi.js.map +1 -0
- package/dist/app/server/assets/dist-BxSwugSY.js +1 -0
- package/dist/app/server/assets/dist-CZGFhmQd.js +2 -0
- package/dist/app/server/assets/dist-CZGFhmQd.js.map +1 -0
- package/dist/app/server/assets/dist-Dg3PQqiW.js +15 -0
- package/dist/app/server/assets/dist-Dg3PQqiW.js.map +1 -0
- package/dist/app/server/assets/effect-QlVUlMFu-2tSPDT2b.js +2 -0
- package/dist/app/server/assets/effect-QlVUlMFu-2tSPDT2b.js.map +1 -0
- package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js +2 -0
- package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js.map +1 -0
- package/dist/app/server/assets/factory-ipHlJXZY.js +5 -0
- package/dist/app/server/assets/factory-ipHlJXZY.js.map +1 -0
- package/dist/app/server/assets/frxUSD-n9pTpinR.svg +1 -0
- package/dist/app/server/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/app/server/assets/get-id-field-B0x109VU.js +6 -0
- package/dist/app/server/assets/get-id-field-B0x109VU.js.map +1 -0
- package/dist/app/server/assets/index-CLddUTqr-xpSuLpBt.js +2 -0
- package/dist/app/server/assets/index-CLddUTqr-xpSuLpBt.js.map +1 -0
- package/dist/app/server/assets/index-DZEfthgZ-8Uq5s5Pt.js +2 -0
- package/dist/app/server/assets/index-DZEfthgZ-8Uq5s5Pt.js.map +1 -0
- package/dist/app/server/assets/kysely-adapter-MkHAI9Jk.js +1 -0
- package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js +2 -0
- package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js.map +1 -0
- package/dist/app/server/assets/pathUSD-BvaO6ooS.svg +25 -0
- package/dist/app/server/assets/reset-co-CHrff.css +1 -0
- package/dist/app/server/assets/rolldown-runtime-B0Z9INg1.js +1 -0
- package/dist/app/server/assets/router-CcbyBCI4.css +1 -0
- package/dist/app/server/assets/router-xjZtEeaI.js +7 -0
- package/dist/app/server/assets/router-xjZtEeaI.js.map +1 -0
- package/dist/app/server/assets/schema-check-Cf7QOZZD.js +9 -0
- package/dist/app/server/assets/schema-check-Cf7QOZZD.js.map +1 -0
- package/dist/app/server/assets/schemas-C2lCYmR5.js +2 -0
- package/dist/app/server/assets/schemas-C2lCYmR5.js.map +1 -0
- package/dist/app/server/assets/secp256k1-buM5g4AL.js +2 -0
- package/dist/app/server/assets/secp256k1-buM5g4AL.js.map +1 -0
- package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js +2 -0
- package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js.map +1 -0
- package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js +6 -0
- package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js.map +1 -0
- package/dist/app/server/assets/standard-json-Cg1N07hM.js +2 -0
- package/dist/app/server/assets/standard-json-Cg1N07hM.js.map +1 -0
- package/dist/app/server/assets/standard-json-DY77efq0.js +2 -0
- package/dist/app/server/assets/standard-json-DY77efq0.js.map +1 -0
- package/dist/app/server/assets/standard-json-ig2t0wRt.js +2 -0
- package/dist/app/server/assets/standard-json-ig2t0wRt.js.map +1 -0
- package/dist/app/server/assets/standard-json-t-LNckA6.js +2 -0
- package/dist/app/server/assets/standard-json-t-LNckA6.js.map +1 -0
- package/dist/app/server/assets/standard-openapi-CONmVRl8.js +2 -0
- package/dist/app/server/assets/standard-openapi-CONmVRl8.js.map +1 -0
- package/dist/app/server/assets/start-C63VetBp.js +2 -0
- package/dist/app/server/assets/start-C63VetBp.js.map +1 -0
- package/dist/app/server/assets/sury-CWZTCd75-xt1mWc9f.js +2 -0
- package/dist/app/server/assets/sury-CWZTCd75-xt1mWc9f.js.map +1 -0
- package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js +2 -0
- package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js.map +1 -0
- package/dist/app/server/assets/utils-C4ZXZIZW.js +2 -0
- package/dist/app/server/assets/utils-C4ZXZIZW.js.map +1 -0
- package/dist/app/server/assets/valibot--1zFm7rT-NSoY2xTp.js +2 -0
- package/dist/app/server/assets/valibot--1zFm7rT-NSoY2xTp.js.map +1 -0
- package/dist/app/server/assets/valibot-D_HTw1Gn-CJwWeOUE.js +2 -0
- package/dist/app/server/assets/valibot-D_HTw1Gn-CJwWeOUE.js.map +1 -0
- package/dist/app/server/assets/wYLDS-CaCKDrO-.svg +10 -0
- package/dist/app/server/assets/zod-Bwrt9trS-CV38yPnQ.js +2 -0
- package/dist/app/server/assets/zod-Bwrt9trS-CV38yPnQ.js.map +1 -0
- package/dist/app/server/assets/zod-DSgpEGAE-BvlnBE2L.js +2 -0
- package/dist/app/server/assets/zod-DSgpEGAE-BvlnBE2L.js.map +1 -0
- package/dist/app/server/index.js +574 -0
- package/dist/app/server/index.js.map +1 -0
- package/dist/app/server/wrangler.json +1 -0
- package/dist/cli/Admin.d.ts +38 -0
- package/dist/cli/Admin.d.ts.map +1 -0
- package/dist/cli/Admin.js +62 -0
- package/dist/cli/Admin.js.map +1 -0
- package/dist/cli/Apps.d.ts +9 -0
- package/dist/cli/Apps.d.ts.map +1 -0
- package/dist/cli/Apps.js +36 -0
- package/dist/cli/Apps.js.map +1 -0
- package/dist/cli/Cli.d.ts +14 -0
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +27 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/Project.d.ts +20 -0
- package/dist/cli/Project.d.ts.map +1 -0
- package/dist/cli/Project.js +88 -0
- package/dist/cli/Project.js.map +1 -0
- package/dist/cli/Realms.d.ts +24 -0
- package/dist/cli/Realms.d.ts.map +1 -0
- package/dist/cli/Realms.js +49 -0
- package/dist/cli/Realms.js.map +1 -0
- package/dist/cli/Session.d.ts +85 -0
- package/dist/cli/Session.d.ts.map +1 -0
- package/dist/cli/Session.js +178 -0
- package/dist/cli/Session.js.map +1 -0
- package/dist/cli/User.d.ts +29 -0
- package/dist/cli/User.d.ts.map +1 -0
- package/dist/cli/User.js +39 -0
- package/dist/cli/User.js.map +1 -0
- package/dist/cli/V1.d.ts +35 -0
- package/dist/cli/V1.d.ts.map +1 -0
- package/dist/cli/V1.js +41 -0
- package/dist/cli/V1.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +46 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin/apps/create.d.ts +23 -0
- package/dist/cli/commands/admin/apps/create.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/create.js +89 -0
- package/dist/cli/commands/admin/apps/create.js.map +1 -0
- package/dist/cli/commands/admin/apps/delete.d.ts +14 -0
- package/dist/cli/commands/admin/apps/delete.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/delete.js +41 -0
- package/dist/cli/commands/admin/apps/delete.js.map +1 -0
- package/dist/cli/commands/admin/apps/index.d.ts +5 -0
- package/dist/cli/commands/admin/apps/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/index.js +14 -0
- package/dist/cli/commands/admin/apps/index.js.map +1 -0
- package/dist/cli/commands/admin/apps/list.d.ts +9 -0
- package/dist/cli/commands/admin/apps/list.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/list.js +26 -0
- package/dist/cli/commands/admin/apps/list.js.map +1 -0
- package/dist/cli/commands/admin/apps/rotate-secret.d.ts +16 -0
- package/dist/cli/commands/admin/apps/rotate-secret.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/rotate-secret.js +47 -0
- package/dist/cli/commands/admin/apps/rotate-secret.js.map +1 -0
- package/dist/cli/commands/admin/apps/update.d.ts +20 -0
- package/dist/cli/commands/admin/apps/update.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/update.js +76 -0
- package/dist/cli/commands/admin/apps/update.js.map +1 -0
- package/dist/cli/commands/admin/index.d.ts +5 -0
- package/dist/cli/commands/admin/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/index.js +13 -0
- package/dist/cli/commands/admin/index.js.map +1 -0
- package/dist/cli/commands/admin/migrate.d.ts +9 -0
- package/dist/cli/commands/admin/migrate.d.ts.map +1 -0
- package/dist/cli/commands/admin/migrate.js +17 -0
- package/dist/cli/commands/admin/migrate.js.map +1 -0
- package/dist/cli/commands/admin/realms/add.d.ts +12 -0
- package/dist/cli/commands/admin/realms/add.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/add.js +42 -0
- package/dist/cli/commands/admin/realms/add.js.map +1 -0
- package/dist/cli/commands/admin/realms/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/index.js +13 -0
- package/dist/cli/commands/admin/realms/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/list.d.ts +13 -0
- package/dist/cli/commands/admin/realms/list.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/list.js +36 -0
- package/dist/cli/commands/admin/realms/list.js.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/passkeys/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/index.js +13 -0
- package/dist/cli/commands/admin/realms/passkeys/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/set.d.ts +16 -0
- package/dist/cli/commands/admin/realms/passkeys/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/set.js +46 -0
- package/dist/cli/commands/admin/realms/passkeys/set.js.map +1 -0
- package/dist/cli/commands/admin/realms/privy/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/privy/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/privy/index.js +13 -0
- package/dist/cli/commands/admin/realms/privy/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/privy/set.d.ts +18 -0
- package/dist/cli/commands/admin/realms/privy/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/privy/set.js +66 -0
- package/dist/cli/commands/admin/realms/privy/set.js.map +1 -0
- package/dist/cli/commands/admin/realms/remove.d.ts +11 -0
- package/dist/cli/commands/admin/realms/remove.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/remove.js +35 -0
- package/dist/cli/commands/admin/realms/remove.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts +15 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.js +42 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts +15 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.js +42 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.d.ts +9 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.js +17 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/set.d.ts +16 -0
- package/dist/cli/commands/admin/realms/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/set.js +46 -0
- package/dist/cli/commands/admin/realms/set.js.map +1 -0
- package/dist/cli/commands/admin/rotate-key.d.ts +15 -0
- package/dist/cli/commands/admin/rotate-key.d.ts.map +1 -0
- package/dist/cli/commands/admin/rotate-key.js +46 -0
- package/dist/cli/commands/admin/rotate-key.js.map +1 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +34 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/login.d.ts +12 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +29 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/logout.d.ts +8 -0
- package/dist/cli/commands/logout.d.ts.map +1 -0
- package/dist/cli/commands/logout.js +19 -0
- package/dist/cli/commands/logout.js.map +1 -0
- package/dist/cli/commands/whoami.d.ts +12 -0
- package/dist/cli/commands/whoami.d.ts.map +1 -0
- package/dist/cli/commands/whoami.js +24 -0
- package/dist/cli/commands/whoami.js.map +1 -0
- package/dist/client/Actions.d.ts +101 -0
- package/dist/client/Actions.d.ts.map +1 -0
- package/dist/client/Actions.js +90 -0
- package/dist/client/Actions.js.map +1 -0
- package/dist/client/Auth.d.ts +161 -0
- package/dist/client/Auth.d.ts.map +1 -0
- package/dist/client/Auth.js +113 -0
- package/dist/client/Auth.js.map +1 -0
- package/dist/client/Authorization.d.ts +29 -0
- package/dist/client/Authorization.d.ts.map +1 -0
- package/dist/client/Authorization.js +12 -0
- package/dist/client/Authorization.js.map +1 -0
- package/dist/client/Decorator.d.ts +170 -0
- package/dist/client/Decorator.d.ts.map +1 -0
- package/dist/client/Decorator.js +227 -0
- package/dist/client/Decorator.js.map +1 -0
- package/dist/client/Key.d.ts +85 -0
- package/dist/client/Key.d.ts.map +1 -0
- package/dist/client/Key.js +83 -0
- package/dist/client/Key.js.map +1 -0
- package/dist/client/Pending.d.ts +39 -0
- package/dist/client/Pending.d.ts.map +1 -0
- package/dist/client/Pending.js +12 -0
- package/dist/client/Pending.js.map +1 -0
- package/dist/client/Permissions.d.ts +34 -0
- package/dist/client/Permissions.d.ts.map +1 -0
- package/dist/client/Permissions.js +16 -0
- package/dist/client/Permissions.js.map +1 -0
- package/dist/client/Provider.d.ts +16 -0
- package/dist/client/Provider.d.ts.map +1 -0
- package/dist/client/Provider.js +12 -0
- package/dist/client/Provider.js.map +1 -0
- package/dist/client/Step.d.ts +21 -0
- package/dist/client/Step.d.ts.map +1 -0
- package/dist/client/Step.js +16 -0
- package/dist/client/Step.js.map +1 -0
- package/dist/client/Storage.d.ts +27 -0
- package/dist/client/Storage.d.ts.map +1 -0
- package/dist/client/Storage.js +16 -0
- package/dist/client/Storage.js.map +1 -0
- package/dist/client/TempoAccount.d.ts +40 -0
- package/dist/client/TempoAccount.d.ts.map +1 -0
- package/dist/client/TempoAccount.js +16 -0
- package/dist/client/TempoAccount.js.map +1 -0
- package/dist/client/Tokens.d.ts +25 -0
- package/dist/client/Tokens.d.ts.map +1 -0
- package/dist/client/Tokens.js +12 -0
- package/dist/client/Tokens.js.map +1 -0
- package/dist/client/User.d.ts +21 -0
- package/dist/client/User.d.ts.map +1 -0
- package/dist/client/User.js +12 -0
- package/dist/client/User.js.map +1 -0
- package/dist/client/actions/account.d.ts +25 -0
- package/dist/client/actions/account.d.ts.map +1 -0
- package/dist/client/actions/account.js +34 -0
- package/dist/client/actions/account.js.map +1 -0
- package/dist/client/actions/device.d.ts +53 -0
- package/dist/client/actions/device.d.ts.map +1 -0
- package/dist/client/actions/device.js +79 -0
- package/dist/client/actions/device.js.map +1 -0
- package/dist/client/actions/email.d.ts +84 -0
- package/dist/client/actions/email.d.ts.map +1 -0
- package/dist/client/actions/email.js +63 -0
- package/dist/client/actions/email.js.map +1 -0
- package/dist/client/actions/oauth.d.ts +115 -0
- package/dist/client/actions/oauth.d.ts.map +1 -0
- package/dist/client/actions/oauth.js +105 -0
- package/dist/client/actions/oauth.js.map +1 -0
- package/dist/client/actions/passkey.d.ts +88 -0
- package/dist/client/actions/passkey.d.ts.map +1 -0
- package/dist/client/actions/passkey.js +60 -0
- package/dist/client/actions/passkey.js.map +1 -0
- package/dist/client/actions/provider.d.ts +49 -0
- package/dist/client/actions/provider.d.ts.map +1 -0
- package/dist/client/actions/provider.js +34 -0
- package/dist/client/actions/provider.js.map +1 -0
- package/dist/client/actions/realm.d.ts +24 -0
- package/dist/client/actions/realm.d.ts.map +1 -0
- package/dist/client/actions/realm.js +15 -0
- package/dist/client/actions/realm.js.map +1 -0
- package/dist/client/actions/redirect.d.ts +153 -0
- package/dist/client/actions/redirect.d.ts.map +1 -0
- package/dist/client/actions/redirect.js +236 -0
- package/dist/client/actions/redirect.js.map +1 -0
- package/dist/client/internal/accessKey.d.ts +21 -0
- package/dist/client/internal/accessKey.d.ts.map +1 -0
- package/dist/client/internal/accessKey.js +38 -0
- package/dist/client/internal/accessKey.js.map +1 -0
- package/dist/client/internal/account.d.ts +14 -0
- package/dist/client/internal/account.d.ts.map +1 -0
- package/dist/client/internal/account.js +3 -0
- package/dist/client/internal/account.js.map +1 -0
- package/dist/client/internal/api.d.ts +106 -0
- package/dist/client/internal/api.d.ts.map +1 -0
- package/dist/client/internal/api.js +129 -0
- package/dist/client/internal/api.js.map +1 -0
- package/dist/client/internal/headless.d.ts +33 -0
- package/dist/client/internal/headless.d.ts.map +1 -0
- package/dist/client/internal/headless.js +46 -0
- package/dist/client/internal/headless.js.map +1 -0
- package/dist/client/internal/indexedDb.d.ts +9 -0
- package/dist/client/internal/indexedDb.d.ts.map +1 -0
- package/dist/client/internal/indexedDb.js +32 -0
- package/dist/client/internal/indexedDb.js.map +1 -0
- package/dist/client/internal/request.d.ts +58 -0
- package/dist/client/internal/request.d.ts.map +1 -0
- package/dist/client/internal/request.js +45 -0
- package/dist/client/internal/request.js.map +1 -0
- package/dist/client/internal/store.d.ts +12 -0
- package/dist/client/internal/store.d.ts.map +1 -0
- package/dist/client/internal/store.js +15 -0
- package/dist/client/internal/store.js.map +1 -0
- package/dist/client.d.ts +20 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +20 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/Apps.d.ts +3051 -0
- package/dist/internal/Apps.d.ts.map +1 -0
- package/dist/internal/Apps.js +472 -0
- package/dist/internal/Apps.js.map +1 -0
- package/dist/internal/Auth.d.ts +4058 -0
- package/dist/internal/Auth.d.ts.map +1 -0
- package/dist/internal/Auth.js +137 -0
- package/dist/internal/Auth.js.map +1 -0
- package/dist/internal/Authorize.d.ts +532 -0
- package/dist/internal/Authorize.d.ts.map +1 -0
- package/dist/internal/Authorize.js +326 -0
- package/dist/internal/Authorize.js.map +1 -0
- package/dist/internal/Device.d.ts +371 -0
- package/dist/internal/Device.d.ts.map +1 -0
- package/dist/internal/Device.js +271 -0
- package/dist/internal/Device.js.map +1 -0
- package/dist/internal/Env.d.ts +57 -0
- package/dist/internal/Env.d.ts.map +1 -0
- package/dist/internal/Env.js +2 -0
- package/dist/internal/Env.js.map +1 -0
- package/dist/internal/ErrorResponse.d.ts +609 -0
- package/dist/internal/ErrorResponse.d.ts.map +1 -0
- package/dist/internal/ErrorResponse.js +679 -0
- package/dist/internal/ErrorResponse.js.map +1 -0
- package/dist/internal/Id.d.ts +10 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +34 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/KeyAuthorization.d.ts +1456 -0
- package/dist/internal/KeyAuthorization.d.ts.map +1 -0
- package/dist/internal/KeyAuthorization.js +1030 -0
- package/dist/internal/KeyAuthorization.js.map +1 -0
- package/dist/internal/Limits.d.ts +65 -0
- package/dist/internal/Limits.d.ts.map +1 -0
- package/dist/internal/Limits.js +35 -0
- package/dist/internal/Limits.js.map +1 -0
- package/dist/internal/Log.d.ts +49 -0
- package/dist/internal/Log.d.ts.map +1 -0
- package/dist/internal/Log.js +101 -0
- package/dist/internal/Log.js.map +1 -0
- package/dist/internal/LogLine.d.ts +33 -0
- package/dist/internal/LogLine.d.ts.map +1 -0
- package/dist/internal/LogLine.js +56 -0
- package/dist/internal/LogLine.js.map +1 -0
- package/dist/internal/Migrations.d.ts +19 -0
- package/dist/internal/Migrations.d.ts.map +1 -0
- package/dist/internal/Migrations.js +57 -0
- package/dist/internal/Migrations.js.map +1 -0
- package/dist/internal/Owner.d.ts +146 -0
- package/dist/internal/Owner.d.ts.map +1 -0
- package/dist/internal/Owner.js +65 -0
- package/dist/internal/Owner.js.map +1 -0
- package/dist/internal/Passkey.d.ts +528 -0
- package/dist/internal/Passkey.d.ts.map +1 -0
- package/dist/internal/Passkey.js +658 -0
- package/dist/internal/Passkey.js.map +1 -0
- package/dist/internal/PendingKey.d.ts +49 -0
- package/dist/internal/PendingKey.d.ts.map +1 -0
- package/dist/internal/PendingKey.js +58 -0
- package/dist/internal/PendingKey.js.map +1 -0
- package/dist/internal/Privy.d.ts +105 -0
- package/dist/internal/Privy.d.ts.map +1 -0
- package/dist/internal/Privy.js +224 -0
- package/dist/internal/Privy.js.map +1 -0
- package/dist/internal/RateLimit.d.ts +190 -0
- package/dist/internal/RateLimit.d.ts.map +1 -0
- package/dist/internal/RateLimit.js +148 -0
- package/dist/internal/RateLimit.js.map +1 -0
- package/dist/internal/Realm.d.ts +281 -0
- package/dist/internal/Realm.d.ts.map +1 -0
- package/dist/internal/Realm.js +477 -0
- package/dist/internal/Realm.js.map +1 -0
- package/dist/internal/RequestId.d.ts +16 -0
- package/dist/internal/RequestId.d.ts.map +1 -0
- package/dist/internal/RequestId.js +78 -0
- package/dist/internal/RequestId.js.map +1 -0
- package/dist/internal/SigningKey.d.ts +115 -0
- package/dist/internal/SigningKey.d.ts.map +1 -0
- package/dist/internal/SigningKey.js +197 -0
- package/dist/internal/SigningKey.js.map +1 -0
- package/dist/internal/TestInbox.d.ts +42 -0
- package/dist/internal/TestInbox.d.ts.map +1 -0
- package/dist/internal/TestInbox.js +20 -0
- package/dist/internal/TestInbox.js.map +1 -0
- package/dist/internal/Timing.d.ts +51 -0
- package/dist/internal/Timing.d.ts.map +1 -0
- package/dist/internal/Timing.js +103 -0
- package/dist/internal/Timing.js.map +1 -0
- package/dist/internal/Validation.d.ts +52 -0
- package/dist/internal/Validation.d.ts.map +1 -0
- package/dist/internal/Validation.js +22 -0
- package/dist/internal/Validation.js.map +1 -0
- package/dist/internal/Wallet.d.ts +37 -0
- package/dist/internal/Wallet.d.ts.map +1 -0
- package/dist/internal/Wallet.js +43 -0
- package/dist/internal/Wallet.js.map +1 -0
- package/dist/worker.d.ts +12 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +12 -0
- package/dist/worker.js.map +1 -0
- package/package.json +82 -0
- package/src/Api.ts +151 -0
- package/src/App.ts +56 -0
- package/src/api/account.ts +311 -0
- package/src/api/authenticate.ts +1290 -0
- package/src/api/authorize.ts +1030 -0
- package/src/api/device.ts +874 -0
- package/src/api/health.ts +72 -0
- package/src/api/lib/AccountStep.ts +335 -0
- package/src/api/lib/Auth.ts +134 -0
- package/src/api/lib/Consent.ts +339 -0
- package/src/api/lib/Cors.ts +107 -0
- package/src/api/lib/Database.ts +10 -0
- package/src/api/lib/DeviceRequest.ts +265 -0
- package/src/api/lib/FirstAccount.ts +90 -0
- package/src/api/lib/KeySigner.ts +393 -0
- package/src/api/lib/PasskeyLink.ts +162 -0
- package/src/api/lib/Session.ts +34 -0
- package/src/api/lib/SignInConsent.ts +316 -0
- package/src/api/oauth.ts +1282 -0
- package/src/api/provider.ts +441 -0
- package/src/app/components/Button.tsx +128 -0
- package/src/app/components/CodeInput.tsx +186 -0
- package/src/app/components/ErrorMessage.tsx +66 -0
- package/src/app/components/Grant.tsx +323 -0
- package/src/app/components/Input.tsx +48 -0
- package/src/app/components/Tooltip.tsx +45 -0
- package/src/app/components/icons/BRLA.png +0 -0
- package/src/app/components/icons/BRZ.svg +1 -0
- package/src/app/components/icons/CHFAU.png +0 -0
- package/src/app/components/icons/DLUSD.png +0 -0
- package/src/app/components/icons/EURAU.svg +1 -0
- package/src/app/components/icons/EURC.e.svg +1 -0
- package/src/app/components/icons/GBPA.svg +4 -0
- package/src/app/components/icons/GUSD.svg +1 -0
- package/src/app/components/icons/MACH.svg +4 -0
- package/src/app/components/icons/OUSD.svg +5 -0
- package/src/app/components/icons/PRIME.svg +14 -0
- package/src/app/components/icons/SBC.svg +1 -0
- package/src/app/components/icons/SEKAU.svg +5 -0
- package/src/app/components/icons/USD1.svg +30 -0
- package/src/app/components/icons/USDB.svg +11 -0
- package/src/app/components/icons/USDC.e.svg +1 -0
- package/src/app/components/icons/USDT0.svg +1 -0
- package/src/app/components/icons/USDY.svg +16 -0
- package/src/app/components/icons/USDe.svg +1 -0
- package/src/app/components/icons/YLDS.svg +3 -0
- package/src/app/components/icons/alphaUSD.svg +1 -0
- package/src/app/components/icons/betaUSD.svg +1 -0
- package/src/app/components/icons/cUSD.svg +1 -0
- package/src/app/components/icons/cbBTC.svg +1 -0
- package/src/app/components/icons/frxUSD.svg +1 -0
- package/src/app/components/icons/goUSD.svg +5 -0
- package/src/app/components/icons/iUSD.svg +1 -0
- package/src/app/components/icons/pathUSD.svg +25 -0
- package/src/app/components/icons/rUSD.svg +1 -0
- package/src/app/components/icons/reUSD.svg +1 -0
- package/src/app/components/icons/sUSDe.svg +1 -0
- package/src/app/components/icons/siUSD.svg +1 -0
- package/src/app/components/icons/stcUSD.svg +1 -0
- package/src/app/components/icons/syrupUSDC.svg +5 -0
- package/src/app/components/icons/thetaUSD.svg +1 -0
- package/src/app/components/icons/wYLDS.svg +10 -0
- package/src/app/components/icons/wsrUSD.svg +1 -0
- package/src/app/components/logos/OUSD.dark.svg +17 -0
- package/src/app/components/logos/OUSD.light.svg +17 -0
- package/src/app/crons/cleanup.ts +42 -0
- package/src/app/db/auth.ts +416 -0
- package/src/app/db/migrations/0000_better_auth.sql +53 -0
- package/src/app/db/migrations/0001_oauth_provider.sql +162 -0
- package/src/app/db/migrations/0002_device_code.sql +17 -0
- package/src/app/db/migrations/0003_realms.sql +27 -0
- package/src/app/db/migrations/0004_default_realm.sql +2 -0
- package/src/app/db/migrations/0005_passkeys.sql +30 -0
- package/src/app/db/migrations/0006_first_accounts.sql +9 -0
- package/src/app/db/migrations/0007_pending_keys.sql +13 -0
- package/src/app/db/migrations/0008_secp256k1_owners.sql +18 -0
- package/src/app/db/migrations/0009_device_requests.sql +8 -0
- package/src/app/db/migrations/0010_device_keys.sql +4 -0
- package/src/app/db/migrations/meta/0000_snapshot.json +362 -0
- package/src/app/db/migrations/meta/0001_snapshot.json +1487 -0
- package/src/app/db/migrations/meta/0002_snapshot.json +1603 -0
- package/src/app/db/migrations/meta/0003_snapshot.json +1760 -0
- package/src/app/db/migrations/meta/0004_snapshot.json +1760 -0
- package/src/app/db/migrations/meta/0005_snapshot.json +1911 -0
- package/src/app/db/migrations/meta/0006_snapshot.json +1967 -0
- package/src/app/db/migrations/meta/0007_snapshot.json +2047 -0
- package/src/app/db/migrations/meta/0008_snapshot.json +2157 -0
- package/src/app/db/migrations/meta/0009_snapshot.json +2207 -0
- package/src/app/db/migrations/meta/0010_snapshot.json +2231 -0
- package/src/app/db/migrations/meta/_journal.json +83 -0
- package/src/app/db/schema.ts +218 -0
- package/src/app/env.ts +49 -0
- package/src/app/lib/Client.ts +82 -0
- package/src/app/lib/Loader.ts +24 -0
- package/src/app/package.json +8 -0
- package/src/app/routeTree.gen.ts +198 -0
- package/src/app/router.tsx +48 -0
- package/src/app/routes/[_].flows.tsx +3001 -0
- package/src/app/routes/__root.tsx +91 -0
- package/src/app/routes/authorize.tsx +197 -0
- package/src/app/routes/choose-account.tsx +111 -0
- package/src/app/routes/deposit.tsx +105 -0
- package/src/app/routes/device.tsx +227 -0
- package/src/app/routes/index.tsx +115 -0
- package/src/app/routes/login.tsx +506 -0
- package/src/app/screens/Account.tsx +347 -0
- package/src/app/screens/Approval.tsx +276 -0
- package/src/app/screens/ChooseAccount.tsx +240 -0
- package/src/app/screens/Deposit.tsx +762 -0
- package/src/app/screens/DeviceApproval.tsx +480 -0
- package/src/app/screens/SignIn.tsx +362 -0
- package/src/app/screens/chains/base.svg +3 -0
- package/src/app/screens/chains/ethereum.svg +11 -0
- package/src/app/screens/chains/solana.svg +4 -0
- package/src/app/screens/chains/tempo.svg +4 -0
- package/src/app/server.ts +204 -0
- package/src/app/vite.config.ts +95 -0
- package/src/app/void.config.ts +29 -0
- package/src/app/zyzz.config.ts +274 -0
- package/src/cli/Admin.ts +73 -0
- package/src/cli/Apps.ts +29 -0
- package/src/cli/Cli.ts +42 -0
- package/src/cli/Project.ts +117 -0
- package/src/cli/Realms.ts +50 -0
- package/src/cli/Session.ts +239 -0
- package/src/cli/User.ts +45 -0
- package/src/cli/V1.ts +57 -0
- package/src/cli/bin.ts +44 -0
- package/src/cli/commands/admin/apps/create.ts +101 -0
- package/src/cli/commands/admin/apps/delete.ts +38 -0
- package/src/cli/commands/admin/apps/index.ts +15 -0
- package/src/cli/commands/admin/apps/list.ts +25 -0
- package/src/cli/commands/admin/apps/rotate-secret.ts +47 -0
- package/src/cli/commands/admin/apps/update.ts +86 -0
- package/src/cli/commands/admin/index.ts +14 -0
- package/src/cli/commands/admin/migrate.ts +16 -0
- package/src/cli/commands/admin/realms/add.ts +40 -0
- package/src/cli/commands/admin/realms/index.ts +14 -0
- package/src/cli/commands/admin/realms/list.ts +38 -0
- package/src/cli/commands/admin/realms/passkeys/index.ts +15 -0
- package/src/cli/commands/admin/realms/passkeys/set.ts +44 -0
- package/src/cli/commands/admin/realms/privy/index.ts +14 -0
- package/src/cli/commands/admin/realms/privy/set.ts +69 -0
- package/src/cli/commands/admin/realms/remove.ts +33 -0
- package/src/cli/commands/admin/realms/secp256k1/disable.ts +40 -0
- package/src/cli/commands/admin/realms/secp256k1/enable.ts +40 -0
- package/src/cli/commands/admin/realms/secp256k1/index.ts +19 -0
- package/src/cli/commands/admin/realms/set.ts +46 -0
- package/src/cli/commands/admin/rotate-key.ts +47 -0
- package/src/cli/commands/init.ts +42 -0
- package/src/cli/commands/login.ts +32 -0
- package/src/cli/commands/logout.ts +19 -0
- package/src/cli/commands/whoami.ts +23 -0
- package/src/client/Actions.ts +168 -0
- package/src/client/Auth.ts +285 -0
- package/src/client/Authorization.ts +34 -0
- package/src/client/Decorator.ts +410 -0
- package/src/client/Key.ts +140 -0
- package/src/client/Pending.ts +46 -0
- package/src/client/Permissions.ts +39 -0
- package/src/client/Provider.ts +18 -0
- package/src/client/Step.ts +24 -0
- package/src/client/Storage.ts +29 -0
- package/src/client/TempoAccount.ts +42 -0
- package/src/client/Tokens.ts +27 -0
- package/src/client/User.ts +23 -0
- package/src/client/actions/account.ts +57 -0
- package/src/client/actions/device.ts +151 -0
- package/src/client/actions/email.ts +141 -0
- package/src/client/actions/oauth.ts +182 -0
- package/src/client/actions/passkey.ts +141 -0
- package/src/client/actions/provider.ts +70 -0
- package/src/client/actions/realm.ts +36 -0
- package/src/client/actions/redirect.ts +408 -0
- package/src/client/internal/accessKey.ts +54 -0
- package/src/client/internal/account.ts +15 -0
- package/src/client/internal/api.ts +224 -0
- package/src/client/internal/headless.ts +77 -0
- package/src/client/internal/indexedDb.ts +44 -0
- package/src/client/internal/request.ts +71 -0
- package/src/client/internal/store.ts +20 -0
- package/src/client.ts +19 -0
- package/src/index.ts +6 -0
- package/src/internal/Apps.ts +718 -0
- package/src/internal/Auth.ts +203 -0
- package/src/internal/Authorize.ts +424 -0
- package/src/internal/Balance.ts +168 -0
- package/src/internal/BodyLimit.ts +36 -0
- package/src/internal/Chain.ts +16 -0
- package/src/internal/Device.ts +469 -0
- package/src/internal/Env.ts +58 -0
- package/src/internal/ErrorResponse.ts +854 -0
- package/src/internal/Id.ts +41 -0
- package/src/internal/KeyAuthorization.ts +1339 -0
- package/src/internal/Limits.ts +39 -0
- package/src/internal/Log.ts +178 -0
- package/src/internal/LogLine.ts +87 -0
- package/src/internal/Logout.ts +336 -0
- package/src/internal/Migrations.ts +86 -0
- package/src/internal/OpenApi.ts +300 -0
- package/src/internal/Owner.ts +211 -0
- package/src/internal/Passkey.ts +1052 -0
- package/src/internal/PendingKey.ts +104 -0
- package/src/internal/Privy.ts +402 -0
- package/src/internal/Provider.ts +125 -0
- package/src/internal/RateLimit.ts +259 -0
- package/src/internal/Realm.ts +768 -0
- package/src/internal/RequestId.ts +118 -0
- package/src/internal/SignInGrant.ts +168 -0
- package/src/internal/SigningKey.ts +286 -0
- package/src/internal/TempoAccount.ts +342 -0
- package/src/internal/TestInbox.ts +51 -0
- package/src/internal/Timing.ts +158 -0
- package/src/internal/Validation.ts +52 -0
- package/src/internal/Wallet.ts +62 -0
- package/src/internal/owners/Passkey.ts +72 -0
- package/src/internal/owners/Privy.ts +81 -0
- package/src/internal/owners/Secp256k1.ts +143 -0
- package/src/types/app.d.ts +19 -0
- package/src/worker.ts +11 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs a visitor in with an emailed code, Google, or a passkey. The sign-in then continues the app's
|
|
3
|
+
* authorization that sent the visitor here, returns to the device page, or opens the account. A wallet.tempo passkey without an
|
|
4
|
+
* email waits for the emailed code that links it. A failed Google sign-in returns here with `error`.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { useMutation } from '@tanstack/react-query'
|
|
8
|
+
import { createFileRoute, useRouter } from '@tanstack/react-router'
|
|
9
|
+
import { type InferResponseType, parseResponse } from 'hono/client'
|
|
10
|
+
import { type FormEvent, useEffect, useRef, useState } from 'react'
|
|
11
|
+
import { Authentication } from 'webauthx/client'
|
|
12
|
+
import * as Client from '../lib/Client.js'
|
|
13
|
+
import * as Loader from '../lib/Loader.js'
|
|
14
|
+
import { SignIn } from '../screens/SignIn.js'
|
|
15
|
+
import { style } from '../zyzz.config.js'
|
|
16
|
+
|
|
17
|
+
/** A signed passkey assertion, as the browser returns it. */
|
|
18
|
+
type Assertion = Awaited<ReturnType<typeof Authentication.sign>>
|
|
19
|
+
|
|
20
|
+
/** The response of a passkey verification: a signed-in user, or the email step. */
|
|
21
|
+
type PasskeyResult = InferResponseType<
|
|
22
|
+
Client.Client['v1']['auth']['passkey']['verify']['$post'],
|
|
23
|
+
200
|
|
24
|
+
>
|
|
25
|
+
|
|
26
|
+
/** The time in milliseconds between checks of an autofill request's deadline. */
|
|
27
|
+
const autofillInterval = 10 * 1000
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The wall-clock time in milliseconds that an autofill request waits for a passkey before a new one
|
|
31
|
+
* replaces it. It is one minute shorter than the 5-minute lifetime of a challenge.
|
|
32
|
+
*/
|
|
33
|
+
const autofillLifetime = 4 * 60 * 1000
|
|
34
|
+
|
|
35
|
+
/** Wraps a failure of the browser's passkey ceremony, which reaches no API. */
|
|
36
|
+
class CeremonyError extends Error {
|
|
37
|
+
override name = 'Page.CeremonyError'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const Route = createFileRoute('/login')({
|
|
41
|
+
// The route splitter drops the style namespace, so the component stays in this chunk.
|
|
42
|
+
codeSplitGroupings: [],
|
|
43
|
+
component: () => <Page {...Route.useLoaderData()} />,
|
|
44
|
+
/**
|
|
45
|
+
* Redirects a signed-in user to `return_to`, a path on the device page, or else to the account.
|
|
46
|
+
* Otherwise returns the sign-in methods that `GET /v1/auth/methods` reads, whether a Google
|
|
47
|
+
* sign-in failed (`error=access_denied`), and the page that sign-in returns to. An app's
|
|
48
|
+
* authorization that asks to sign in again (`prompt=login`) carries a signed `sig`, and shows the
|
|
49
|
+
* page with a session.
|
|
50
|
+
*/
|
|
51
|
+
loader: async (match): Promise<Page.Props> => {
|
|
52
|
+
const query = new URLSearchParams(match.location.searchStr)
|
|
53
|
+
const signed = query.has('sig')
|
|
54
|
+
const returnTo = query.get('return_to')
|
|
55
|
+
const client = Client.create()
|
|
56
|
+
const [session, methods] = await Promise.all([
|
|
57
|
+
parseResponse(client.v1.auth.session.$get()),
|
|
58
|
+
parseResponse(
|
|
59
|
+
client.v1.auth.methods.$get({
|
|
60
|
+
query: {
|
|
61
|
+
// The API names the app only from a signed authorization request.
|
|
62
|
+
...(signed ? { oauth_query: query.toString() } : {}),
|
|
63
|
+
...(returnTo ? { return_to: returnTo } : {}),
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
),
|
|
67
|
+
])
|
|
68
|
+
if (session.user && !signed)
|
|
69
|
+
Loader.redirect({ href: methods.return_to ?? '/' })
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
// Better Auth sends its other failures here too, with their own codes. Only the failed route of
|
|
73
|
+
// a provider sign-in sends `access_denied`.
|
|
74
|
+
failed: methods.google && query.get('error') === 'access_denied',
|
|
75
|
+
google: methods.google,
|
|
76
|
+
passkeys: methods.passkeys,
|
|
77
|
+
request: methods.request,
|
|
78
|
+
returnTo: methods.return_to,
|
|
79
|
+
userCode: methods.user_code,
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
// The loader reads the whole query, so a change to any parameter loads the page again.
|
|
83
|
+
loaderDeps: (match) => ({ search: match.search }),
|
|
84
|
+
server: {
|
|
85
|
+
handlers: {
|
|
86
|
+
// The sign-in form posts here only when it is submitted before the page hydrates, and the page
|
|
87
|
+
// then sends the code itself. The redirect keeps the query, so an app's signed authorization
|
|
88
|
+
// request stays on the page.
|
|
89
|
+
POST: (options) =>
|
|
90
|
+
new Response(null, {
|
|
91
|
+
headers: { location: `/login${new URL(options.request.url).search}` },
|
|
92
|
+
status: 303,
|
|
93
|
+
}),
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
/** Renders the page. */
|
|
99
|
+
function Page(props: Page.Props) {
|
|
100
|
+
const client = Client.use()
|
|
101
|
+
const router = useRouter()
|
|
102
|
+
// The email step's link, while a wallet.tempo passkey waits for the code that links it.
|
|
103
|
+
const [link, setLink] = useState<string | undefined>(undefined)
|
|
104
|
+
// The autofill request that waits for a passkey picked from the email field, if one runs.
|
|
105
|
+
const autofill = useRef<AbortController | undefined>(undefined)
|
|
106
|
+
const passkey = useMutation({
|
|
107
|
+
async mutationFn(variables: { assertion?: Assertion | undefined }) {
|
|
108
|
+
const assertion = variables.assertion ?? (await ceremony({}))
|
|
109
|
+
return parseResponse(
|
|
110
|
+
client.v1.auth.passkey.verify.$post({
|
|
111
|
+
json: { assertion, ...oauthQuery() },
|
|
112
|
+
}),
|
|
113
|
+
)
|
|
114
|
+
},
|
|
115
|
+
})
|
|
116
|
+
const resend = useMutation({ mutationFn: sendCode })
|
|
117
|
+
const send = useMutation({ mutationFn: sendCode })
|
|
118
|
+
const verify = useMutation({
|
|
119
|
+
async mutationFn(variables: { code: string; email: string }) {
|
|
120
|
+
// The link's passkey signs again, so a page left at the email step links nothing for the next
|
|
121
|
+
// person, who cannot sign with it.
|
|
122
|
+
const linked = link ? { assertion: await ceremony({ link }), link } : {}
|
|
123
|
+
return parseResponse(
|
|
124
|
+
client.v1.auth.code.verify.$post({
|
|
125
|
+
json: { ...variables, ...linked, ...oauthQuery() },
|
|
126
|
+
}),
|
|
127
|
+
)
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
const email = send.isSuccess ? send.variables.email : undefined
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Requests passkey options, and signs them in the browser. Options with `link` ask for the email
|
|
134
|
+
* step's passkey again. A conditional request waits for a passkey picked from the email field's
|
|
135
|
+
* autofill, until `signal` aborts it.
|
|
136
|
+
*/
|
|
137
|
+
async function ceremony(options: {
|
|
138
|
+
link?: string | undefined
|
|
139
|
+
mediation?: 'conditional' | undefined
|
|
140
|
+
signal?: AbortSignal | undefined
|
|
141
|
+
}) {
|
|
142
|
+
const { link, mediation, signal } = options
|
|
143
|
+
const response = await parseResponse(
|
|
144
|
+
client.v1.auth.passkey.options.$post({
|
|
145
|
+
json: {
|
|
146
|
+
...(link ? { link } : {}),
|
|
147
|
+
...(mediation ? { mediation } : {}),
|
|
148
|
+
...oauthQuery(),
|
|
149
|
+
// The API reads the device app from the code itself, so the code selects its realms.
|
|
150
|
+
...(props.userCode ? { user_code: props.userCode } : {}),
|
|
151
|
+
},
|
|
152
|
+
}),
|
|
153
|
+
)
|
|
154
|
+
// The response reads optional fields as possibly `undefined`, which the ceremony's options
|
|
155
|
+
// omit instead.
|
|
156
|
+
const { allowCredentials, ...publicKey } = response.options.publicKey
|
|
157
|
+
try {
|
|
158
|
+
return await Authentication.sign({
|
|
159
|
+
// ox types the request with optional members that the DOM types leave out when absent. The
|
|
160
|
+
// object is the one that ox built for `navigator.credentials.get`.
|
|
161
|
+
getFn: (request) =>
|
|
162
|
+
navigator.credentials.get({
|
|
163
|
+
...(request as CredentialRequestOptions),
|
|
164
|
+
...(signal ? { signal } : {}),
|
|
165
|
+
}),
|
|
166
|
+
options: {
|
|
167
|
+
publicKey: {
|
|
168
|
+
...publicKey,
|
|
169
|
+
...(allowCredentials ? { allowCredentials } : {}),
|
|
170
|
+
},
|
|
171
|
+
...(response.options.mediation
|
|
172
|
+
? { mediation: response.options.mediation }
|
|
173
|
+
: {}),
|
|
174
|
+
},
|
|
175
|
+
})
|
|
176
|
+
} catch (error) {
|
|
177
|
+
throw new CeremonyError('Passkey ceremony failed.', { cause: error })
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Autofill offers the browser's passkeys in the email field while the first step shows and no
|
|
182
|
+
// other sign-in runs. A passkey picked there signs in as the button does.
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
if (!props.passkeys || email || link || passkey.isPending || send.isPending)
|
|
185
|
+
return
|
|
186
|
+
const controller = new AbortController()
|
|
187
|
+
autofill.current = controller
|
|
188
|
+
void (async () => {
|
|
189
|
+
const available =
|
|
190
|
+
await window.PublicKeyCredential?.isConditionalMediationAvailable?.()
|
|
191
|
+
if (!available || controller.signal.aborted) return
|
|
192
|
+
// The browser holds a conditional request open with no time limit, but its challenge expires,
|
|
193
|
+
// so a new request replaces it before then.
|
|
194
|
+
while (!controller.signal.aborted) {
|
|
195
|
+
const round = new AbortController()
|
|
196
|
+
const abort = () => round.abort()
|
|
197
|
+
// The challenge expires by wall-clock time, which runs on while the device sleeps and timers
|
|
198
|
+
// stop, so the round checks a deadline when the page shows again and at a short interval.
|
|
199
|
+
const deadline = Date.now() + autofillLifetime
|
|
200
|
+
const check = () => {
|
|
201
|
+
if (Date.now() >= deadline) round.abort()
|
|
202
|
+
}
|
|
203
|
+
controller.signal.addEventListener('abort', abort)
|
|
204
|
+
document.addEventListener('visibilitychange', check)
|
|
205
|
+
window.addEventListener('pageshow', check)
|
|
206
|
+
const timer = setInterval(check, autofillInterval)
|
|
207
|
+
// A ceremony that the browser aborts, or that fails before a passkey is picked, offers the
|
|
208
|
+
// button instead, so its failure shows nothing.
|
|
209
|
+
const result = await ceremony({
|
|
210
|
+
mediation: 'conditional',
|
|
211
|
+
signal: round.signal,
|
|
212
|
+
}).then(
|
|
213
|
+
(assertion) => ({ assertion }),
|
|
214
|
+
(error: unknown) => ({ error }),
|
|
215
|
+
)
|
|
216
|
+
clearInterval(timer)
|
|
217
|
+
controller.signal.removeEventListener('abort', abort)
|
|
218
|
+
document.removeEventListener('visibilitychange', check)
|
|
219
|
+
window.removeEventListener('pageshow', check)
|
|
220
|
+
if (controller.signal.aborted) return
|
|
221
|
+
if ('assertion' in result) {
|
|
222
|
+
send.reset()
|
|
223
|
+
passkey.mutate(
|
|
224
|
+
{ assertion: result.assertion },
|
|
225
|
+
{ onSuccess: applyPasskey },
|
|
226
|
+
)
|
|
227
|
+
return
|
|
228
|
+
}
|
|
229
|
+
if (round.signal.aborted) continue
|
|
230
|
+
// A request that does not reach the API, as while a device reconnects after sleep, starts
|
|
231
|
+
// again. A refusal ends the autofill, so it does not repeat.
|
|
232
|
+
if (!(result.error instanceof TypeError)) return
|
|
233
|
+
await reconnect({ signal: controller.signal })
|
|
234
|
+
}
|
|
235
|
+
})()
|
|
236
|
+
return () => controller.abort()
|
|
237
|
+
// `ceremony`, `passkey.mutate`, and `send.reset` read current state when they run, so they are
|
|
238
|
+
// not dependencies.
|
|
239
|
+
}, [props.passkeys, email, link, passkey.isPending, send.isPending])
|
|
240
|
+
|
|
241
|
+
function sendCode(variables: { email: string }) {
|
|
242
|
+
return parseResponse(client.v1.auth.code.$post({ json: variables }))
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function submitEmail(event: FormEvent<HTMLFormElement>) {
|
|
246
|
+
event.preventDefault()
|
|
247
|
+
// One sign-in runs at a time, since a passkey sign-in sets its own session.
|
|
248
|
+
if (send.isPending || passkey.isPending) return
|
|
249
|
+
passkey.reset()
|
|
250
|
+
// A passkey picked from the autofill during the send would start a second sign-in.
|
|
251
|
+
autofill.current?.abort()
|
|
252
|
+
send.mutate({
|
|
253
|
+
email: String(new FormData(event.currentTarget).get('email')),
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function submitCode(event: FormEvent<HTMLFormElement>) {
|
|
258
|
+
event.preventDefault()
|
|
259
|
+
// A complete code submits the form, and Enter can submit it again before the first returns.
|
|
260
|
+
if (!email || verify.isPending || verify.isSuccess) return
|
|
261
|
+
const form = event.currentTarget
|
|
262
|
+
resend.reset()
|
|
263
|
+
verify.mutate(
|
|
264
|
+
{ code: String(new FormData(form).get('code')), email },
|
|
265
|
+
{
|
|
266
|
+
onError(error) {
|
|
267
|
+
// An expired link, or a passkey that does not sign again, leaves the code valid, so the next
|
|
268
|
+
// attempt signs in with email only.
|
|
269
|
+
if (linkFailed(error)) setLink(undefined)
|
|
270
|
+
// The refused code clears, so the next one can be typed at once.
|
|
271
|
+
const field = form.elements.namedItem('code')
|
|
272
|
+
if (!(field instanceof HTMLInputElement)) return
|
|
273
|
+
field.value = ''
|
|
274
|
+
field.focus()
|
|
275
|
+
},
|
|
276
|
+
onSuccess(data) {
|
|
277
|
+
// The accepted code shows green for a moment, so the sign-in confirms it before it
|
|
278
|
+
// continues. The router renders a failed navigation itself, so the timer need not wait.
|
|
279
|
+
window.setTimeout(() => continueTo(data), verifiedDelay)
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** Continues to the app's redirect, to the page that sent the visitor here, or to the account. */
|
|
286
|
+
function continueTo(data: { redirect: string | null }) {
|
|
287
|
+
if (data.redirect) window.location.assign(data.redirect)
|
|
288
|
+
// The device page loads as a document, so its loader reads the code on the server, where a
|
|
289
|
+
// refused lookup logs nothing in the browser.
|
|
290
|
+
else if (props.returnTo) window.location.assign(props.returnTo)
|
|
291
|
+
else void router.navigate({ to: '/' })
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Sends the browser to Google, and back to this page. With an app's authorization request, the
|
|
296
|
+
* callback continues it instead.
|
|
297
|
+
*/
|
|
298
|
+
function signInWithGoogle() {
|
|
299
|
+
const page = new URL(window.location.href)
|
|
300
|
+
// The next attempt drops the failure of the last one.
|
|
301
|
+
page.searchParams.delete('error')
|
|
302
|
+
const url = new URL('/v1/auth/oauth/google', window.location.origin)
|
|
303
|
+
// A path, which Tempo ID resolves against its own origin.
|
|
304
|
+
url.searchParams.set('return_to', page.pathname + page.search)
|
|
305
|
+
const { oauth_query } = oauthQuery()
|
|
306
|
+
if (oauth_query) url.searchParams.set('oauth_query', oauth_query)
|
|
307
|
+
window.location.assign(url)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function signInWithPasskey() {
|
|
311
|
+
if (passkey.isPending) return
|
|
312
|
+
send.reset()
|
|
313
|
+
// The result applies through the call's own callback, which a reset drops, so a sign-in that
|
|
314
|
+
// returns after the email path takes over sets no link.
|
|
315
|
+
// The browser runs one passkey request at a time, so the autofill request ends first.
|
|
316
|
+
autofill.current?.abort()
|
|
317
|
+
passkey.mutate({}, { onSuccess: applyPasskey })
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/** Continues a verified passkey sign-in, or asks for the email that links a wallet.tempo passkey. */
|
|
321
|
+
function applyPasskey(data: PasskeyResult) {
|
|
322
|
+
if ('step' in data) setLink(data.step.link)
|
|
323
|
+
else continueTo({ redirect: data.redirect })
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function sendAgain() {
|
|
327
|
+
if (!email || verify.isPending || verify.isSuccess) return
|
|
328
|
+
verify.reset()
|
|
329
|
+
resend.mutate({ email })
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// A reset mutation drops the callbacks of its request, so a result that returns after the
|
|
333
|
+
// address changes updates nothing. The passkey's link clears too, so the code of another address
|
|
334
|
+
// in a shared browser links nothing.
|
|
335
|
+
function changeEmail() {
|
|
336
|
+
passkey.reset()
|
|
337
|
+
resend.reset()
|
|
338
|
+
send.reset()
|
|
339
|
+
setLink(undefined)
|
|
340
|
+
verify.reset()
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// A tab left at the email step can reach the next person, who drops the passkey's link here. The
|
|
344
|
+
// reset drops a pending code request too, so its result does not open the code step.
|
|
345
|
+
function startOver() {
|
|
346
|
+
passkey.reset()
|
|
347
|
+
send.reset()
|
|
348
|
+
setLink(undefined)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const error = (() => {
|
|
352
|
+
if (email) return verify.error ?? resend.error
|
|
353
|
+
return send.error ?? passkey.error
|
|
354
|
+
})()
|
|
355
|
+
// The failure of a Google sign-in shows until another sign-in starts.
|
|
356
|
+
const failed = props.failed && send.isIdle && passkey.isIdle
|
|
357
|
+
|
|
358
|
+
return (
|
|
359
|
+
<main {...styles.page()}>
|
|
360
|
+
<SignIn
|
|
361
|
+
autoFocus
|
|
362
|
+
email={email}
|
|
363
|
+
error={(() => {
|
|
364
|
+
if (error) return message(error, { code: Boolean(email) })
|
|
365
|
+
if (failed)
|
|
366
|
+
return 'Sign-in with Google failed. Try again, or continue with email.'
|
|
367
|
+
return undefined
|
|
368
|
+
})()}
|
|
369
|
+
invalid={Boolean(email ? verify.error : send.error)}
|
|
370
|
+
linking={Boolean(link)}
|
|
371
|
+
onChangeEmail={changeEmail}
|
|
372
|
+
onGoogle={props.google ? signInWithGoogle : undefined}
|
|
373
|
+
onPasskey={props.passkeys ? signInWithPasskey : undefined}
|
|
374
|
+
onResend={sendAgain}
|
|
375
|
+
onStartOver={startOver}
|
|
376
|
+
onSubmitCode={submitCode}
|
|
377
|
+
onSubmitEmail={submitEmail}
|
|
378
|
+
passkeyPending={passkey.isPending}
|
|
379
|
+
request={props.request ?? undefined}
|
|
380
|
+
resend={(() => {
|
|
381
|
+
if (resend.isPending) return 'pending'
|
|
382
|
+
if (resend.isSuccess) return 'sent'
|
|
383
|
+
return 'idle'
|
|
384
|
+
})()}
|
|
385
|
+
sending={send.isPending}
|
|
386
|
+
verified={verify.isSuccess}
|
|
387
|
+
verifying={verify.isPending}
|
|
388
|
+
/>
|
|
389
|
+
</main>
|
|
390
|
+
)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
declare namespace Page {
|
|
394
|
+
type Props = {
|
|
395
|
+
/** Whether a Google sign-in returned here with `error`. */
|
|
396
|
+
failed: boolean
|
|
397
|
+
/** Whether the page offers Google sign-in, which the deployment configures. */
|
|
398
|
+
google: boolean
|
|
399
|
+
/** Whether the page offers passkey sign-in, which the loader decides from the app's realms. */
|
|
400
|
+
passkeys: boolean
|
|
401
|
+
/**
|
|
402
|
+
* The app's authorization request that the sign-in continues, with the key that the sign-in
|
|
403
|
+
* grants, or `null` without one.
|
|
404
|
+
*/
|
|
405
|
+
request: SignIn.Props['request'] | null
|
|
406
|
+
/** The page that sign-in returns to, a path on the device page, or `null` for the account. */
|
|
407
|
+
returnTo: string | null
|
|
408
|
+
/** The user code of the device page that sign-in returns to, or `null` without one. */
|
|
409
|
+
userCode: string | null
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** How long an accepted code shows green before the sign-in continues, in milliseconds. */
|
|
414
|
+
const verifiedDelay = 500
|
|
415
|
+
|
|
416
|
+
/** Returns whether `error` refused the email step's link, which leaves the code valid. */
|
|
417
|
+
function linkFailed(error: unknown) {
|
|
418
|
+
if (error instanceof CeremonyError) return true
|
|
419
|
+
const reason = Client.reason(error)
|
|
420
|
+
return (
|
|
421
|
+
reason === 'passkey_link_expired' ||
|
|
422
|
+
reason === 'passkey_not_permitted' ||
|
|
423
|
+
reason === 'webauthn_rejected'
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Returns the message to show for `error`. A ceremony that the user cancels, or that times out,
|
|
429
|
+
* fails with a `NotAllowedError` from the browser, which the passkey library wraps in its own error.
|
|
430
|
+
*/
|
|
431
|
+
function message(error: unknown, options: message.Options) {
|
|
432
|
+
// At the code step, only the link's passkey runs a ceremony, and its failure drops the link. An
|
|
433
|
+
// expired or refused link keeps the refusal's own message.
|
|
434
|
+
if (
|
|
435
|
+
options.code &&
|
|
436
|
+
(error instanceof CeremonyError ||
|
|
437
|
+
Client.reason(error) === 'webauthn_rejected')
|
|
438
|
+
)
|
|
439
|
+
return 'Your passkey did not confirm the sign-in. Enter the code again to sign in with email only.'
|
|
440
|
+
if (!(error instanceof CeremonyError)) return Client.message(error)
|
|
441
|
+
if (names(error).includes('NotAllowedError'))
|
|
442
|
+
return 'Passkey sign-in was canceled. Try again, or continue with email.'
|
|
443
|
+
return 'Passkey sign-in failed. Try again, or continue with email.'
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
declare namespace message {
|
|
447
|
+
type Options = {
|
|
448
|
+
/** Whether the page shows the code step, where a refusal of the link's passkey drops the link. */
|
|
449
|
+
code: boolean
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/** Returns the names of `error` and of each error in its chain of causes. */
|
|
454
|
+
function names(error: unknown): readonly string[] {
|
|
455
|
+
if (!(error instanceof Error)) return []
|
|
456
|
+
return [error.name, ...names(error.cause)]
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Returns the signed authorization request that `GET /oauth2/authorize` put in the page's query, as
|
|
461
|
+
* the verify request's `oauth_query`, or nothing when the visitor came without one. The `error` of a
|
|
462
|
+
* failed Google sign-in is not part of the signed request, so the request drops it.
|
|
463
|
+
*/
|
|
464
|
+
function oauthQuery(): { oauth_query?: string } {
|
|
465
|
+
const params = new URLSearchParams(window.location.search)
|
|
466
|
+
if (!params.has('sig')) return {}
|
|
467
|
+
params.delete('error')
|
|
468
|
+
return { oauth_query: params.toString() }
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Resolves after `autofillInterval`, when the browser comes back online, or when `signal` aborts,
|
|
473
|
+
* whichever comes first.
|
|
474
|
+
*/
|
|
475
|
+
function reconnect(options: reconnect.Options) {
|
|
476
|
+
const { signal } = options
|
|
477
|
+
return new Promise<void>((resolve) => {
|
|
478
|
+
const done = () => {
|
|
479
|
+
clearTimeout(timer)
|
|
480
|
+
window.removeEventListener('online', done)
|
|
481
|
+
signal.removeEventListener('abort', done)
|
|
482
|
+
resolve()
|
|
483
|
+
}
|
|
484
|
+
const timer = setTimeout(done, autofillInterval)
|
|
485
|
+
window.addEventListener('online', done)
|
|
486
|
+
signal.addEventListener('abort', done)
|
|
487
|
+
})
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
declare namespace reconnect {
|
|
491
|
+
type Options = {
|
|
492
|
+
/** Ends the wait early, when the autofill stops. */
|
|
493
|
+
signal: AbortSignal
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
namespace styles {
|
|
498
|
+
export const page = style({
|
|
499
|
+
alignItems: 'center',
|
|
500
|
+
display: 'flex',
|
|
501
|
+
justifyContent: 'center',
|
|
502
|
+
minHeight: 'screen',
|
|
503
|
+
paddingBlock: 16,
|
|
504
|
+
paddingInline: 4,
|
|
505
|
+
})
|
|
506
|
+
}
|