@tempoxyz/id 0.0.0-stage → 0.0.0
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 +80 -2
- 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-11GtFGrq.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 +79 -3
- 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,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Each user's Tempo Accounts: configurable accounts (TIP-1107), each in one realm and owned by one
|
|
3
|
+
* key. Each kind in {@link kinds}, such as Privy wallets and linked wallet.tempo passkeys, lists the
|
|
4
|
+
* keys of its kind, and a kind that creates keys creates a user's first account. Configurable
|
|
5
|
+
* accounts are on no Tempo chain yet, so the owner acts as the account until they ship.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { and, eq, inArray } from 'drizzle-orm'
|
|
9
|
+
import { AccountConfig } from 'viem/tempo'
|
|
10
|
+
import { z } from 'zod'
|
|
11
|
+
import * as Schema from '../app/db/schema.js'
|
|
12
|
+
import * as ErrorResponse from './ErrorResponse.js'
|
|
13
|
+
import * as Owner from './Owner.js'
|
|
14
|
+
import * as Passkey from './owners/Passkey.js'
|
|
15
|
+
import * as Privy from './owners/Privy.js'
|
|
16
|
+
import * as Secp256k1 from './owners/Secp256k1.js'
|
|
17
|
+
import type * as Realm from './Realm.js'
|
|
18
|
+
import * as Timing from './Timing.js'
|
|
19
|
+
|
|
20
|
+
/** The request names a Tempo Account that is not one of the user's in the app's realms. */
|
|
21
|
+
export class ForeignAccountError extends ErrorResponse.define(
|
|
22
|
+
'foreign_account',
|
|
23
|
+
) {
|
|
24
|
+
override readonly name = 'TempoAccount.ForeignAccountError'
|
|
25
|
+
|
|
26
|
+
constructor(options: ForeignAccountError.Options) {
|
|
27
|
+
super({
|
|
28
|
+
error_description: `Access denied to Tempo Account ${options.account}. Name one of the user's accounts in the app's realms.`,
|
|
29
|
+
field: options.field ?? 'account',
|
|
30
|
+
meta: { account: options.account },
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export declare namespace ForeignAccountError {
|
|
36
|
+
type Options = {
|
|
37
|
+
/** The address that the request named. */
|
|
38
|
+
account: string
|
|
39
|
+
/** The request field that named the address. Defaults to `account`. */
|
|
40
|
+
field?: string | undefined
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The kinds of owner keys, in the order that breaks a tie in creation time: a passkey comes before a
|
|
46
|
+
* Privy wallet created in the same second, and a Privy wallet before a secp256k1 key. The first kind
|
|
47
|
+
* that creates keys in a realm creates a user's first account there, so a realm with a Privy app
|
|
48
|
+
* creates Privy wallets even where it also holds secp256k1 owners.
|
|
49
|
+
*/
|
|
50
|
+
export const kinds = [Passkey.owner, Privy.owner, Secp256k1.owner] as const
|
|
51
|
+
|
|
52
|
+
/** A user's Tempo Account, as the API returns it. */
|
|
53
|
+
export type TempoAccount = z.output<typeof schema.tempoAccount>
|
|
54
|
+
|
|
55
|
+
/** The owner type in the API, such as `privy`, `secp256k1`, or `webAuthn`. */
|
|
56
|
+
export type Type = (typeof kinds)[number]['type']
|
|
57
|
+
|
|
58
|
+
/** Zod schemas for Tempo Accounts as the API returns them. */
|
|
59
|
+
export namespace schema {
|
|
60
|
+
const address = z
|
|
61
|
+
.templateLiteral(['0x', z.string().regex(/^[0-9a-fA-F]{40}$/)])
|
|
62
|
+
.meta({
|
|
63
|
+
description: 'A 20-byte address.',
|
|
64
|
+
examples: ['0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c'],
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
/** A realm, with its display name. */
|
|
68
|
+
export const realm = z
|
|
69
|
+
.object({
|
|
70
|
+
id: z.string().meta({
|
|
71
|
+
description: 'The realm ID, such as `default` or `tempo-cash`.',
|
|
72
|
+
examples: ['tempo-cash'],
|
|
73
|
+
}),
|
|
74
|
+
name: z.string().meta({
|
|
75
|
+
description: 'The realm display name, such as `Tempo Cash`.',
|
|
76
|
+
examples: ['Tempo Cash'],
|
|
77
|
+
}),
|
|
78
|
+
})
|
|
79
|
+
.meta({
|
|
80
|
+
description:
|
|
81
|
+
'A realm, which holds Tempo Accounts. An app reaches only the accounts of its realms.',
|
|
82
|
+
id: 'Realm',
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
/** A Tempo Account, with its configuration and its realm. */
|
|
86
|
+
export const tempoAccount = z
|
|
87
|
+
.object({
|
|
88
|
+
address: address.meta({
|
|
89
|
+
description:
|
|
90
|
+
'The account address. Until configurable accounts ship, the owner acts as the account.',
|
|
91
|
+
examples: ['0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c'],
|
|
92
|
+
}),
|
|
93
|
+
config: z
|
|
94
|
+
.object({
|
|
95
|
+
owners: z
|
|
96
|
+
.array(
|
|
97
|
+
z
|
|
98
|
+
.object({
|
|
99
|
+
owner: address.meta({
|
|
100
|
+
description: 'The address of the owner key.',
|
|
101
|
+
examples: ['0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c'],
|
|
102
|
+
}),
|
|
103
|
+
type: z.enum(kinds.map((kind) => kind.type)).meta({
|
|
104
|
+
description:
|
|
105
|
+
'Who holds the owner key: a Privy wallet (`privy`), a key that Tempo ID holds in development (`secp256k1`), or a passkey (`webAuthn`), which signs only in the browser.',
|
|
106
|
+
examples: ['webAuthn'],
|
|
107
|
+
}),
|
|
108
|
+
weight: z.number().meta({
|
|
109
|
+
description:
|
|
110
|
+
"The owner's signing weight, which counts toward `threshold`.",
|
|
111
|
+
examples: [1],
|
|
112
|
+
}),
|
|
113
|
+
})
|
|
114
|
+
.meta({ description: 'One key that signs for the account.' }),
|
|
115
|
+
)
|
|
116
|
+
.readonly()
|
|
117
|
+
.meta({ description: 'The keys that sign for the account.' }),
|
|
118
|
+
salt: z.templateLiteral(['0x', z.string()]).meta({
|
|
119
|
+
description:
|
|
120
|
+
'The 32-byte salt that the account address derives from, as hex.',
|
|
121
|
+
examples: [`0x${'0'.repeat(64)}`],
|
|
122
|
+
}),
|
|
123
|
+
threshold: z.number().meta({
|
|
124
|
+
description:
|
|
125
|
+
'The total owner weight that a signature needs to act for the account.',
|
|
126
|
+
examples: [1],
|
|
127
|
+
}),
|
|
128
|
+
version: z.templateLiteral(['0x', z.string()]).meta({
|
|
129
|
+
description: 'The configuration version, as a hex quantity.',
|
|
130
|
+
examples: ['0x0'],
|
|
131
|
+
}),
|
|
132
|
+
})
|
|
133
|
+
.meta({
|
|
134
|
+
description:
|
|
135
|
+
'The account configuration (TIP-1107): its owners, salt, threshold, and version.',
|
|
136
|
+
}),
|
|
137
|
+
realm,
|
|
138
|
+
})
|
|
139
|
+
.meta({
|
|
140
|
+
description:
|
|
141
|
+
'A configurable Tempo Account (TIP-1107) and its configuration.',
|
|
142
|
+
id: 'TempoAccount',
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Returns the keys that own the user's Tempo Accounts in `realms`, as {@link held} does, and creates
|
|
148
|
+
* one in the first realm for a user with none, when a kind creates keys in that realm. A user with a
|
|
149
|
+
* linked owner key, such as a wallet.tempo passkey, receives none. Concurrent calls, through apps
|
|
150
|
+
* whose realms overlap, and a link at the same time create one account. No database connection
|
|
151
|
+
* stays open while a kind creates the key.
|
|
152
|
+
*/
|
|
153
|
+
export async function create(
|
|
154
|
+
c: Timing.measure.Context,
|
|
155
|
+
options: create.Options,
|
|
156
|
+
): Promise<readonly Owner.Owner<Type>[]> {
|
|
157
|
+
const { db, realms, userId } = options
|
|
158
|
+
const loaded = await Timing.measure(c, load(c, options), 'TempoAccount.load')
|
|
159
|
+
|
|
160
|
+
const held = await Timing.measure(
|
|
161
|
+
c,
|
|
162
|
+
owners(c, { db, loaded }),
|
|
163
|
+
'TempoAccount.owners',
|
|
164
|
+
)
|
|
165
|
+
if (held.length > 0) return held
|
|
166
|
+
|
|
167
|
+
const creator = (realm: Realm.Realm) => {
|
|
168
|
+
for (const entry of loaded) {
|
|
169
|
+
const fn = entry.create?.(realm)
|
|
170
|
+
if (fn) return fn
|
|
171
|
+
}
|
|
172
|
+
return undefined
|
|
173
|
+
}
|
|
174
|
+
const realm = realms[0]
|
|
175
|
+
if (!realm || !creator(realm)) return []
|
|
176
|
+
|
|
177
|
+
// A short transaction under the user's lock picks the realm, so the kind's calls after it hold no
|
|
178
|
+
// database connection. A claim in these realms, from a request through an app whose realms
|
|
179
|
+
// overlap them, wins over the first realm. A linked key that a kind stored before the claim wins
|
|
180
|
+
// over both. A link after the claim adds the linked key's account beside the created one.
|
|
181
|
+
const target = await db.transaction(async (tx) => {
|
|
182
|
+
await Timing.measure(c, Owner.lock(tx, { userId }), 'db.account.lock')
|
|
183
|
+
const claims = await Timing.measure(
|
|
184
|
+
c,
|
|
185
|
+
tx
|
|
186
|
+
.select({ realmId: Schema.firstAccounts.realmId })
|
|
187
|
+
.from(Schema.firstAccounts)
|
|
188
|
+
.where(
|
|
189
|
+
and(
|
|
190
|
+
eq(Schema.firstAccounts.userId, userId),
|
|
191
|
+
inArray(
|
|
192
|
+
Schema.firstAccounts.realmId,
|
|
193
|
+
realms.map((entry) => entry.id),
|
|
194
|
+
),
|
|
195
|
+
),
|
|
196
|
+
),
|
|
197
|
+
'db.account.claims',
|
|
198
|
+
)
|
|
199
|
+
const claimed = realms.find(
|
|
200
|
+
(entry) =>
|
|
201
|
+
claims.some((claim) => claim.realmId === entry.id) && creator(entry),
|
|
202
|
+
)
|
|
203
|
+
if (claimed) return { realm: claimed }
|
|
204
|
+
|
|
205
|
+
const linked = await Timing.measure(
|
|
206
|
+
c,
|
|
207
|
+
owners(c, {
|
|
208
|
+
db: tx,
|
|
209
|
+
loaded: loaded.filter((entry) => !entry.create),
|
|
210
|
+
}),
|
|
211
|
+
'TempoAccount.linked',
|
|
212
|
+
)
|
|
213
|
+
if (linked.length > 0) return { linked }
|
|
214
|
+
|
|
215
|
+
await Timing.measure(
|
|
216
|
+
c,
|
|
217
|
+
tx
|
|
218
|
+
.insert(Schema.firstAccounts)
|
|
219
|
+
.values({ realmId: realm.id, userId })
|
|
220
|
+
.onConflictDoNothing(),
|
|
221
|
+
'db.account.claim',
|
|
222
|
+
)
|
|
223
|
+
return { realm }
|
|
224
|
+
})
|
|
225
|
+
if ('linked' in target) return target.linked
|
|
226
|
+
|
|
227
|
+
const owner = await Timing.measure(
|
|
228
|
+
c,
|
|
229
|
+
creator(target.realm)!(c),
|
|
230
|
+
'TempoAccount.createOwner',
|
|
231
|
+
)
|
|
232
|
+
return [owner]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export namespace create {
|
|
236
|
+
export type Options = list.Options
|
|
237
|
+
|
|
238
|
+
/** The refusals `create` throws, which `ErrorResponse.handle` responds with: each kind's failures. */
|
|
239
|
+
export const errors = [
|
|
240
|
+
...Passkey.owner.errors,
|
|
241
|
+
...Privy.owner.errors,
|
|
242
|
+
...Secp256k1.owner.errors,
|
|
243
|
+
] as const
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Returns the keys that own the user's Tempo Accounts in `realms`, oldest first, and creates none.
|
|
248
|
+
* Each kind reads its keys in parallel.
|
|
249
|
+
*/
|
|
250
|
+
export async function held(
|
|
251
|
+
c: Timing.measure.Context,
|
|
252
|
+
options: held.Options,
|
|
253
|
+
): Promise<readonly Owner.Owner<Type>[]> {
|
|
254
|
+
const loaded = await Timing.measure(c, load(c, options), 'TempoAccount.load')
|
|
255
|
+
return await Timing.measure(
|
|
256
|
+
c,
|
|
257
|
+
owners(c, { db: options.db, loaded }),
|
|
258
|
+
'TempoAccount.owners',
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export namespace held {
|
|
263
|
+
export type Options = list.Options
|
|
264
|
+
|
|
265
|
+
/** The refusals `held` throws, which `ErrorResponse.handle` responds with: each kind's failures. */
|
|
266
|
+
export const errors = create.errors
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Returns the user's Tempo Accounts in `realms`, oldest first, as the API returns them, and creates
|
|
271
|
+
* none. Their owners are those that {@link held} returns.
|
|
272
|
+
*/
|
|
273
|
+
export async function list(
|
|
274
|
+
c: Timing.measure.Context,
|
|
275
|
+
options: list.Options,
|
|
276
|
+
): Promise<readonly TempoAccount[]> {
|
|
277
|
+
const owned = await Timing.measure(c, held(c, options), 'TempoAccount.held')
|
|
278
|
+
return owned.map(serialize)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export namespace list {
|
|
282
|
+
export type Options = {
|
|
283
|
+
/** The database. */
|
|
284
|
+
db: Realm.Database
|
|
285
|
+
/** The deployment variables that the kinds read. */
|
|
286
|
+
env: Owner.Env
|
|
287
|
+
/** The realms that the request reaches, in order. The first holds a user's first account. */
|
|
288
|
+
realms: readonly Realm.Realm[]
|
|
289
|
+
/** The user's ID. */
|
|
290
|
+
userId: string
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** The refusals `list` throws, which `ErrorResponse.handle` responds with: each kind's failures. */
|
|
294
|
+
export const errors = create.errors
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/** Loads every kind in {@link kinds} for `realms`, in parallel, in the order of {@link kinds}. */
|
|
298
|
+
async function load(c: Timing.measure.Context, options: list.Options) {
|
|
299
|
+
return await Promise.all(
|
|
300
|
+
kinds.map((kind): Promise<Owner.Kind.Loaded<Type>> =>
|
|
301
|
+
kind.load(c, options),
|
|
302
|
+
),
|
|
303
|
+
)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Returns the keys that `loaded` lists, oldest first, and creates none. The kinds are read in
|
|
308
|
+
* parallel, and an earlier kind wins a tie.
|
|
309
|
+
*/
|
|
310
|
+
async function owners(
|
|
311
|
+
c: Timing.measure.Context,
|
|
312
|
+
options: owners.Options,
|
|
313
|
+
): Promise<readonly Owner.Owner<Type>[]> {
|
|
314
|
+
const { db } = options
|
|
315
|
+
const lists = await Promise.all(
|
|
316
|
+
options.loaded.map((entry) => entry.list(c, { db })),
|
|
317
|
+
)
|
|
318
|
+
return Owner.merge(lists)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
declare namespace owners {
|
|
322
|
+
type Options = {
|
|
323
|
+
/** The database or transaction to read. */
|
|
324
|
+
db: Realm.Database
|
|
325
|
+
/** The loaded kinds to list, in the order of {@link kinds}. */
|
|
326
|
+
loaded: readonly Owner.Kind.Loaded<Type>[]
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/** Returns the Tempo Account that `owner` owns, as the API returns it. */
|
|
331
|
+
export function serialize(owner: Owner.Owner): TempoAccount {
|
|
332
|
+
const config = AccountConfig.toRpc(owner.account.config)
|
|
333
|
+
return schema.tempoAccount.parse({
|
|
334
|
+
// The owner acts as the account until TIP-1107 is live, then `account.address`.
|
|
335
|
+
address: owner.account.owners[0]!.address,
|
|
336
|
+
config: {
|
|
337
|
+
...config,
|
|
338
|
+
owners: config.owners.map((entry) => ({ ...entry, type: owner.type })),
|
|
339
|
+
},
|
|
340
|
+
realm: { id: owner.realm.id, name: owner.realm.name },
|
|
341
|
+
})
|
|
342
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Selects the sign-in codes that a deployment sends to its test inbox instead of emailing them. A
|
|
3
|
+
* preview sets `TEST_EMAIL_DOMAIN` and binds `TEST_INBOX`, so the end-to-end suite reads the codes of
|
|
4
|
+
* its test addresses, while every other address still receives email. Only domains that RFC 2606
|
|
5
|
+
* reserves qualify, so no deployment can divert a real address.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** The domains that a test inbox can receive, which RFC 2606 reserves, so no real address uses them. */
|
|
10
|
+
export const domains = ['example.com', 'example.net', 'example.org'] as const
|
|
11
|
+
|
|
12
|
+
/** A domain that a test inbox can receive. */
|
|
13
|
+
export type Domain = (typeof domains)[number]
|
|
14
|
+
|
|
15
|
+
/** A message to a test inbox, in the shape of Void's development inbox. */
|
|
16
|
+
export type Message = {
|
|
17
|
+
/** The subject line. */
|
|
18
|
+
subject: string
|
|
19
|
+
/** The plain-text body. */
|
|
20
|
+
text: string
|
|
21
|
+
/** The recipients. */
|
|
22
|
+
to: readonly {
|
|
23
|
+
/** The recipient's address. */
|
|
24
|
+
email: string
|
|
25
|
+
}[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The test inbox's `Capture` entrypoint, which a deployment binds as `TEST_INBOX`. */
|
|
29
|
+
export type Service = {
|
|
30
|
+
/** Stores `message`. */
|
|
31
|
+
capture(message: Message): Promise<void>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns whether `email` belongs at the test inbox: `domain` is one of {@link domains}, and the
|
|
36
|
+
* address's domain is exactly `domain`. Returns `false` when `domain` is absent.
|
|
37
|
+
*/
|
|
38
|
+
export function matches(options: matches.Options) {
|
|
39
|
+
const { domain, email } = options
|
|
40
|
+
if (!domain || !domains.some((entry) => entry === domain)) return false
|
|
41
|
+
return email.toLowerCase().endsWith(`@${domain}`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare namespace matches {
|
|
45
|
+
type Options = {
|
|
46
|
+
/** The deployment's `TEST_EMAIL_DOMAIN`, or `undefined` when it sets none. */
|
|
47
|
+
domain?: string | undefined
|
|
48
|
+
/** The recipient's address. */
|
|
49
|
+
email: string
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request timings: how long each call that a request awaits takes. The calls range from Tempo ID's
|
|
3
|
+
* own steps to the Better Auth, database, and email calls inside them. The middleware sends them in
|
|
4
|
+
* a `Server-Timing` header, which browser developer tools show beside each request. Outside the Vite
|
|
5
|
+
* dev server, it also logs them with `Log.info`. Workers advance the clock only across I/O, so a span
|
|
6
|
+
* measures the I/O it awaits, and computation reads as zero.
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { createMiddleware } from 'hono/factory'
|
|
10
|
+
import type { Env } from './Env.js'
|
|
11
|
+
import * as Log from './Log.js'
|
|
12
|
+
|
|
13
|
+
/** One awaited call. */
|
|
14
|
+
export type Span = {
|
|
15
|
+
/** When the call settled, in the request's sequence of opens and settles. Pending spans hold `Infinity`. */
|
|
16
|
+
closed: number
|
|
17
|
+
/**
|
|
18
|
+
* What the header shows beside the span, such as an in-process call's path. Logs leave it out,
|
|
19
|
+
* since a path can carry a device's user code.
|
|
20
|
+
*/
|
|
21
|
+
description?: string | undefined
|
|
22
|
+
/** How long the call took, in milliseconds. */
|
|
23
|
+
duration: number
|
|
24
|
+
/**
|
|
25
|
+
* `service.operation` for a call to another service, such as `db.session.get`, or
|
|
26
|
+
* `Module.function` for a step of Tempo ID's own, such as `Session.get`.
|
|
27
|
+
*/
|
|
28
|
+
name: string
|
|
29
|
+
/** When the call's span opened, in the request's sequence of opens and settles. */
|
|
30
|
+
opened: number
|
|
31
|
+
/** When the call started, in milliseconds after the request did. */
|
|
32
|
+
start: number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A request's timings, which {@link middleware} creates and {@link measure} appends to. */
|
|
36
|
+
export type Timing = {
|
|
37
|
+
/** How many spans opened or settled so far, which orders spans that start at the same instant. */
|
|
38
|
+
events: number
|
|
39
|
+
/** The request's spans, in the order they opened. A span still pending has a zero duration. */
|
|
40
|
+
spans: Span[]
|
|
41
|
+
/** When the request started, from `performance.now()`. */
|
|
42
|
+
start: number
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Awaits `promise` as the span `name`, and returns its result. A rejection is timed too, then
|
|
47
|
+
* rethrown. Concurrent spans may share a name. The header shows `description` beside the span, and
|
|
48
|
+
* logs leave it out.
|
|
49
|
+
*/
|
|
50
|
+
export async function measure<promise extends PromiseLike<unknown>>(
|
|
51
|
+
c: measure.Context,
|
|
52
|
+
promise: promise,
|
|
53
|
+
name: string,
|
|
54
|
+
description?: string,
|
|
55
|
+
): Promise<Awaited<promise>> {
|
|
56
|
+
const timing = c.var.timing
|
|
57
|
+
const start = performance.now()
|
|
58
|
+
const span: Span = {
|
|
59
|
+
closed: Infinity,
|
|
60
|
+
...(description ? { description } : {}),
|
|
61
|
+
duration: 0,
|
|
62
|
+
name,
|
|
63
|
+
opened: timing.events++,
|
|
64
|
+
start: start - timing.start,
|
|
65
|
+
}
|
|
66
|
+
timing.spans.push(span)
|
|
67
|
+
try {
|
|
68
|
+
return await promise
|
|
69
|
+
} finally {
|
|
70
|
+
span.closed = timing.events++
|
|
71
|
+
span.duration = performance.now() - start
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export declare namespace measure {
|
|
76
|
+
/** A context that carries the request's timing, such as a route's or a page loader's. */
|
|
77
|
+
type Context = {
|
|
78
|
+
/** The request's variables. */
|
|
79
|
+
var: Pick<Env['Variables'], 'timing'>
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Times the request. Once the response is ready, it appends a `Server-Timing` header with the
|
|
85
|
+
* request's `total` and each span. Outside the Vite dev server, it also logs the same timings. A
|
|
86
|
+
* streamed page's `total` ends when its headers are ready.
|
|
87
|
+
*/
|
|
88
|
+
export const middleware = createMiddleware<Env>(async (c, next) => {
|
|
89
|
+
const timing: Timing = { events: 0, spans: [], start: performance.now() }
|
|
90
|
+
c.set('timing', timing)
|
|
91
|
+
await next()
|
|
92
|
+
|
|
93
|
+
const total = performance.now() - timing.start
|
|
94
|
+
const spans = order(timing.spans)
|
|
95
|
+
c.res.headers.append(
|
|
96
|
+
'server-timing',
|
|
97
|
+
[`total;dur=${round(total)}`, ...spans.map(serialize)].join(', '),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
// The dev server prints every entry to the terminal, and the header carries the same spans.
|
|
101
|
+
if (Log.dev()) return
|
|
102
|
+
|
|
103
|
+
// Without the context, `Log` leaves the request's path out, since callers control it and it can
|
|
104
|
+
// carry a user code. The route pattern stands in, and pages without a route share `/*`.
|
|
105
|
+
Log.info({
|
|
106
|
+
fields: {
|
|
107
|
+
duration: round(total),
|
|
108
|
+
errorCode: c.var.refusal?.error,
|
|
109
|
+
method: c.req.method,
|
|
110
|
+
reason: c.var.refusal?.reason,
|
|
111
|
+
requestId: c.var.requestId,
|
|
112
|
+
route: Log.route(c),
|
|
113
|
+
spans: spans
|
|
114
|
+
.map(
|
|
115
|
+
(span) =>
|
|
116
|
+
`${span.name};dur=${round(span.duration)};start=${round(span.start)}`,
|
|
117
|
+
)
|
|
118
|
+
.join(', '),
|
|
119
|
+
status: c.res.status,
|
|
120
|
+
},
|
|
121
|
+
message: 'The Worker timed a request.',
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Orders spans with each step before the calls inside it. The order reads only the sequence of
|
|
127
|
+
* opens and settles, since the clock can advance between the span of a call and the span of its
|
|
128
|
+
* step. Spans that open with no settle between them all overlap. Of those, the one that settles
|
|
129
|
+
* last encloses the others, since a step's promise is created before the step's span opens. Spans
|
|
130
|
+
* that open after a settle come after.
|
|
131
|
+
*/
|
|
132
|
+
function order(spans: readonly Span[]) {
|
|
133
|
+
// `spans` holds the spans in the order they opened, so each event before a span that is not an
|
|
134
|
+
// earlier span's open is a settle.
|
|
135
|
+
return spans
|
|
136
|
+
.map((span, index) => ({ settles: span.opened - index, span }))
|
|
137
|
+
.toSorted((a, b) => {
|
|
138
|
+
if (a.settles !== b.settles) return a.settles - b.settles
|
|
139
|
+
// Pending spans hold `Infinity`, which subtraction cannot compare.
|
|
140
|
+
if (a.span.closed !== b.span.closed)
|
|
141
|
+
return a.span.closed > b.span.closed ? -1 : 1
|
|
142
|
+
return a.span.opened - b.span.opened
|
|
143
|
+
})
|
|
144
|
+
.map((entry) => entry.span)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Rounds milliseconds to one decimal. */
|
|
148
|
+
function round(milliseconds: number) {
|
|
149
|
+
return Math.round(milliseconds * 10) / 10
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Serializes a span as a `Server-Timing` metric. */
|
|
153
|
+
function serialize(span: Span) {
|
|
154
|
+
const metric = `${span.name};dur=${round(span.duration)}`
|
|
155
|
+
if (!span.description) return metric
|
|
156
|
+
// The description is a quoted string, which escapes quotes and backslashes.
|
|
157
|
+
return `${metric};desc="${span.description.replace(/["\\]/g, '\\$&')}"`
|
|
158
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Turns a failed request validation into an `invalid_field` refusal that names each field. @module */
|
|
2
|
+
import * as ErrorResponse from './ErrorResponse.js'
|
|
3
|
+
|
|
4
|
+
/** A field is missing or malformed. Names each field the issues refused, with what it expects. `field` is the first. */
|
|
5
|
+
export class InvalidFieldError extends ErrorResponse.define('invalid_field') {
|
|
6
|
+
override readonly name = 'Validation.InvalidFieldError'
|
|
7
|
+
|
|
8
|
+
constructor(options: InvalidFieldError.Options) {
|
|
9
|
+
const { issues } = options
|
|
10
|
+
super({
|
|
11
|
+
error_description: `Invalid request. ${issues
|
|
12
|
+
.map(
|
|
13
|
+
(issue) =>
|
|
14
|
+
`${path(issue) ? `\`${path(issue)}\`` : 'Body'}: ${issue.message}.`,
|
|
15
|
+
)
|
|
16
|
+
.join(' ')}`,
|
|
17
|
+
field: issues[0] && path(issues[0]) ? path(issues[0]) : undefined,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export declare namespace InvalidFieldError {
|
|
23
|
+
type Options = {
|
|
24
|
+
/** The issues validation reported. */
|
|
25
|
+
issues: readonly Issue[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A Standard Schema issue, as Zod and Hono's validators report it. */
|
|
29
|
+
type Issue = {
|
|
30
|
+
/** The validator's description of the problem. */
|
|
31
|
+
message: string
|
|
32
|
+
/** The segments from the input's root to the refused value. Absent for the root itself. */
|
|
33
|
+
path?:
|
|
34
|
+
| readonly (
|
|
35
|
+
| PropertyKey
|
|
36
|
+
| {
|
|
37
|
+
/** The segment's property key. */
|
|
38
|
+
key: PropertyKey
|
|
39
|
+
}
|
|
40
|
+
)[]
|
|
41
|
+
| undefined
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The dotted path of the field `issue` refused. */
|
|
46
|
+
function path(issue: InvalidFieldError.Issue) {
|
|
47
|
+
return (issue.path ?? [])
|
|
48
|
+
.map((segment) =>
|
|
49
|
+
typeof segment === 'object' ? String(segment.key) : String(segment),
|
|
50
|
+
)
|
|
51
|
+
.join('.')
|
|
52
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads wallet.tempo's passkeys through the optional `WALLET` service binding to its `Credentials`
|
|
3
|
+
* entrypoint. Tempo ID never reads wallet.tempo's stores, and validates what the binding returns.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { Address, PublicKey } from 'ox'
|
|
7
|
+
import { z } from 'zod'
|
|
8
|
+
|
|
9
|
+
/** The part of wallet.tempo's `Credentials` entrypoint that Tempo ID calls. */
|
|
10
|
+
export type Service = {
|
|
11
|
+
/** Returns the passkey with `credentialId`, or `undefined` when wallet.tempo stores none. */
|
|
12
|
+
credential(options: { credentialId: string }): Promise<unknown>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A passkey that wallet.tempo stores. */
|
|
16
|
+
export type Credential = z.output<typeof schema.credential>
|
|
17
|
+
|
|
18
|
+
namespace schema {
|
|
19
|
+
export const credential = z.object({
|
|
20
|
+
address: z.string().regex(/^0x[0-9a-fA-F]{40}$/),
|
|
21
|
+
createdAt: z.number().int().min(0).max(8.64e15).nullable(),
|
|
22
|
+
email: z.email().nullable(),
|
|
23
|
+
publicKey: z.templateLiteral([
|
|
24
|
+
'0x04',
|
|
25
|
+
z.string().regex(/^[0-9a-fA-F]{128}$/),
|
|
26
|
+
]),
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns the passkey `id` that wallet.tempo stores, with its account's address, creation time in
|
|
32
|
+
* milliseconds, and verified email. Returns `undefined` when wallet.tempo does not store it,
|
|
33
|
+
* returns another shape, or names an address that its public key does not derive.
|
|
34
|
+
*/
|
|
35
|
+
export async function credential(wallet: Service, options: credential.Options) {
|
|
36
|
+
const result = schema.credential.safeParse(
|
|
37
|
+
await wallet.credential({ credentialId: options.id }),
|
|
38
|
+
)
|
|
39
|
+
if (!result.success) return undefined
|
|
40
|
+
|
|
41
|
+
// The stored address must be the account the public key owns, whatever wallet.tempo returns.
|
|
42
|
+
const derived = (() => {
|
|
43
|
+
try {
|
|
44
|
+
return Address.fromPublicKey(PublicKey.fromHex(result.data.publicKey))
|
|
45
|
+
} catch {
|
|
46
|
+
return undefined
|
|
47
|
+
}
|
|
48
|
+
})()
|
|
49
|
+
if (
|
|
50
|
+
!derived ||
|
|
51
|
+
!Address.isEqual(derived, result.data.address as Address.Address)
|
|
52
|
+
)
|
|
53
|
+
return undefined
|
|
54
|
+
return result.data
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export declare namespace credential {
|
|
58
|
+
type Options = {
|
|
59
|
+
/** The credential ID, base64url. */
|
|
60
|
+
id: string
|
|
61
|
+
}
|
|
62
|
+
}
|