tapimo 0.11.0 → 0.13.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/dist/App.d.ts +6396 -4575
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +39 -4
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +15 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +7 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Scope.d.ts +2 -0
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +17 -0
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +176 -78
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +84 -4
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +54 -0
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +123 -9
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +60 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +4 -2
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +90 -90
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +71 -71
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/Zones.d.ts +16 -16
- package/dist/apps/Zones.js +4 -4
- package/dist/apps/data/App.d.ts +1699 -749
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +58 -9
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +62 -0
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
- package/dist/apps/data/ZoneSelection.js +44 -0
- package/dist/apps/data/ZoneSelection.js.map +1 -0
- package/dist/apps/data/routes/activities.d.ts +2417 -50
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +1896 -1293
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +471 -340
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +12 -12
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +44 -17
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +42 -42
- package/dist/apps/data/routes/blocks.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.js +22 -12
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +179 -179
- package/dist/apps/data/routes/earn.d.ts +144 -19
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +160 -28
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +719 -13
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +16 -13
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +2 -2
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +9 -11
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +34 -34
- package/dist/apps/data/routes/receipts.d.ts +363 -263
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +29 -11
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.js +24 -10
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +13 -13
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +16 -15
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +112 -98
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +85 -35
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +7 -2
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +38 -18
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +1 -1
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +25 -21
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +1 -1
- package/dist/apps/data/routes/valuation.d.ts.map +1 -1
- package/dist/apps/data/routes/valuation.js +12 -7
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +3 -3
- package/dist/apps/data/routes/webhooks.d.ts +15 -15
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +2 -2
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +32 -32
- package/dist/apps/data/routes/zones.js +1 -1
- package/dist/apps/funding/App.d.ts +38 -27
- package/dist/apps/funding/App.d.ts.map +1 -1
- package/dist/apps/funding/routes/chains.d.ts.map +1 -1
- package/dist/apps/funding/routes/chains.js +5 -4
- package/dist/apps/funding/routes/chains.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +16 -16
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +24 -19
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/providers.d.ts +13 -13
- package/dist/apps/funding/routes/providers.d.ts.map +1 -1
- package/dist/apps/funding/routes/providers.js +3 -2
- package/dist/apps/funding/routes/providers.js.map +1 -1
- package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
- package/dist/apps/funding/routes/quotes.js +2 -2
- package/dist/apps/funding/routes/quotes.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +60 -48
- package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
- package/dist/apps/funding/routes/transfers.js +27 -19
- package/dist/apps/funding/routes/transfers.js.map +1 -1
- package/dist/apps/management/App.d.ts +4558 -3700
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +19 -6
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +786 -175
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +312 -34
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +103 -30
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +91 -32
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +35 -35
- package/dist/apps/management/routes/faucet.d.ts.map +1 -1
- package/dist/apps/management/routes/faucet.js +23 -12
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +46 -13
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +79 -29
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +120 -75
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +100 -41
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +5 -5
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +14 -10
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +99 -78
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +37 -18
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +48 -8
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +48 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +108 -46
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +72 -21
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +8 -5
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +82 -82
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +41 -31
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +35 -7
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +36 -17
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +200 -183
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +80 -35
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +12 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/db/Db.d.ts +2 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +52 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +26 -3
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +24 -5
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +5 -0
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/fundingCatalog.d.ts +4 -2
- package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
- package/dist/db/tables/fundingCatalog.js +5 -1
- package/dist/db/tables/fundingCatalog.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +10 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
- package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
- package/dist/db/tables/webhookQueueCompletions.js +32 -0
- package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
- package/dist/db/tables/webhookQueueEvents.d.ts +14 -20
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +68 -47
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +29 -5
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +9 -0
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/internal/Auth.d.ts +11 -2
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +19 -6
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +11 -7
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +43 -4
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +167 -0
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/Fetch.d.ts +23 -0
- package/dist/internal/Fetch.d.ts.map +1 -0
- package/dist/internal/Fetch.js +26 -0
- package/dist/internal/Fetch.js.map +1 -0
- package/dist/internal/Log.d.ts +3 -1
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +16 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +30 -24
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +140 -41
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +14 -9
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +16 -5
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +11 -10
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +14 -9
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +28 -6
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +121 -25
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +2 -0
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +23 -6
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Timeout.d.ts +36 -0
- package/dist/internal/Timeout.d.ts.map +1 -0
- package/dist/internal/Timeout.js +37 -0
- package/dist/internal/Timeout.js.map +1 -0
- package/dist/internal/Timing.d.ts +9 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +7 -0
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/WebhookDestination.d.ts.map +1 -1
- package/dist/internal/WebhookDestination.js +3 -0
- package/dist/internal/WebhookDestination.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +29 -12
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +37 -20
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/funding/Action.d.ts +9 -0
- package/dist/internal/funding/Action.d.ts.map +1 -1
- package/dist/internal/funding/Action.js +16 -8
- package/dist/internal/funding/Action.js.map +1 -1
- package/dist/internal/funding/Catalog.d.ts +9 -2
- package/dist/internal/funding/Catalog.d.ts.map +1 -1
- package/dist/internal/funding/Catalog.js +19 -8
- package/dist/internal/funding/Catalog.js.map +1 -1
- package/dist/internal/funding/Deposit.d.ts +2 -2
- package/dist/internal/funding/Deposit.d.ts.map +1 -1
- package/dist/internal/funding/Deposit.js +9 -8
- package/dist/internal/funding/Deposit.js.map +1 -1
- package/dist/internal/funding/DepositAddress.d.ts +4 -4
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
- package/dist/internal/funding/DepositAddress.js +9 -8
- package/dist/internal/funding/DepositAddress.js.map +1 -1
- package/dist/internal/funding/Provider.d.ts +68 -13
- package/dist/internal/funding/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Provider.js +42 -20
- package/dist/internal/funding/Provider.js.map +1 -1
- package/dist/internal/funding/Transfer.d.ts +13 -12
- package/dist/internal/funding/Transfer.d.ts.map +1 -1
- package/dist/internal/funding/Transfer.js +23 -21
- package/dist/internal/funding/Transfer.js.map +1 -1
- package/dist/internal/funding/providers/stargate.d.ts +38 -0
- package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
- package/dist/internal/funding/providers/stargate.js +277 -0
- package/dist/internal/funding/providers/stargate.js.map +1 -0
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1 -0
- package/dist/internal/index.js.map +1 -1
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +3 -3
- package/src/App.test.ts +148 -0
- package/src/App.ts +45 -4
- package/src/Assets.test.ts +18 -0
- package/src/Assets.ts +22 -0
- package/src/Client.test-d.ts +311 -16
- package/src/Scope.test.ts +20 -0
- package/src/Scope.ts +16 -0
- package/src/admin/apps/api-keys.test.ts +75 -0
- package/src/admin/apps/api-keys.ts +64 -0
- package/src/admin/apps/earn-vaults.test.ts +143 -0
- package/src/admin/apps/earn-vaults.ts +84 -7
- package/src/admin/apps/organizations.ts +6 -2
- package/src/admin/ui/src/lib/api-keys.ts +19 -0
- package/src/admin/ui/src/routes/api-keys.tsx +125 -2
- package/src/admin/ui.generated.ts +71 -71
- package/src/apps/Zones.test.ts +4 -4
- package/src/apps/Zones.ts +4 -4
- package/src/apps/composition.test.ts +1 -1
- package/src/apps/data/App.test.ts +72 -0
- package/src/apps/data/App.ts +58 -10
- package/src/apps/data/ZoneSelection.test.ts +196 -0
- package/src/apps/data/ZoneSelection.ts +108 -0
- package/src/apps/data/routes/activities.test.ts +1843 -2
- package/src/apps/data/routes/activities.ts +2211 -1388
- package/src/apps/data/routes/balances.ts +134 -98
- package/src/apps/data/routes/blocks.test.ts +533 -0
- package/src/apps/data/routes/blocks.ts +36 -17
- package/src/apps/data/routes/earn.test.ts +187 -25
- package/src/apps/data/routes/earn.ts +228 -32
- package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
- package/src/apps/data/routes/exchanges.test.ts +31 -1
- package/src/apps/data/routes/exchanges.ts +19 -15
- package/src/apps/data/routes/fee-amm.ts +18 -11
- package/src/apps/data/routes/receipts.ts +48 -17
- package/src/apps/data/routes/rpc.test.ts +75 -0
- package/src/apps/data/routes/rpc.ts +23 -9
- package/src/apps/data/routes/tokenlist.ts +21 -18
- package/src/apps/data/routes/tokens.test.ts +607 -0
- package/src/apps/data/routes/tokens.ts +312 -231
- package/src/apps/data/routes/transactions.ts +69 -30
- package/src/apps/data/routes/transfers.test.ts +424 -3
- package/src/apps/data/routes/transfers.ts +57 -36
- package/src/apps/data/routes/valuation.ts +94 -78
- package/src/apps/data/routes/webhooks.ts +6 -2
- package/src/apps/data/routes/zones.test.ts +21 -15
- package/src/apps/data/routes/zones.ts +1 -1
- package/src/apps/funding/routes/chains.test.ts +211 -7
- package/src/apps/funding/routes/chains.ts +19 -12
- package/src/apps/funding/routes/deposit-addresses.test.ts +416 -0
- package/src/apps/funding/routes/deposit-addresses.ts +101 -84
- package/src/apps/funding/routes/providers.ts +9 -5
- package/src/apps/funding/routes/quotes.test.ts +42 -0
- package/src/apps/funding/routes/quotes.ts +8 -5
- package/src/apps/funding/routes/transfers.test.ts +430 -40
- package/src/apps/funding/routes/transfers.ts +76 -59
- package/src/apps/management/Billing.test.ts +26 -0
- package/src/apps/management/Billing.ts +24 -7
- package/src/apps/management/routes/api-keys.test.ts +398 -0
- package/src/apps/management/routes/api-keys.ts +481 -145
- package/src/apps/management/routes/billing.test.ts +209 -0
- package/src/apps/management/routes/billing.ts +254 -177
- package/src/apps/management/routes/faucet.test.ts +39 -0
- package/src/apps/management/routes/faucet.ts +75 -41
- package/src/apps/management/routes/invitations.test.ts +216 -0
- package/src/apps/management/routes/invitations.ts +186 -109
- package/src/apps/management/routes/invite-links.test.ts +263 -1
- package/src/apps/management/routes/invite-links.ts +295 -214
- package/src/apps/management/routes/me.test.ts +49 -0
- package/src/apps/management/routes/me.ts +42 -32
- package/src/apps/management/routes/members.test.ts +124 -1
- package/src/apps/management/routes/members.ts +81 -51
- package/src/apps/management/routes/orgs.test.ts +176 -0
- package/src/apps/management/routes/orgs.ts +101 -59
- package/src/apps/management/routes/projects.test.ts +183 -0
- package/src/apps/management/routes/projects.ts +124 -60
- package/src/apps/management/routes/scopes.test.ts +44 -0
- package/src/apps/management/routes/scopes.ts +37 -28
- package/src/apps/management/routes/usage.test.ts +92 -0
- package/src/apps/management/routes/usage.ts +186 -151
- package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
- package/src/apps/management/routes/verified-token-requests.ts +166 -133
- package/src/apps/management/routes/webhooks.test.ts +234 -0
- package/src/apps/management/routes/webhooks.ts +191 -78
- package/src/apps/mpp/internal/Adapter.ts +13 -1
- package/src/db/Db.test.ts +41 -0
- package/src/db/Db.ts +75 -1
- package/src/db/Schema.ts +33 -5
- package/src/db/tables/earnVaults.test.ts +22 -0
- package/src/db/tables/earnVaults.ts +11 -1
- package/src/db/tables/fundingCatalog.test.ts +16 -2
- package/src/db/tables/fundingCatalog.ts +9 -3
- package/src/db/tables/webhookDeliveries.ts +13 -0
- package/src/db/tables/webhookQueueCompletions.ts +55 -0
- package/src/db/tables/webhookQueueEvents.ts +95 -61
- package/src/db/tables/webhookSubscriptions.ts +45 -6
- package/src/handlers/internal/utils.test.ts +53 -0
- package/src/handlers/internal/utils.ts +15 -0
- package/src/internal/Auth.ts +35 -9
- package/src/internal/Cache.ts +14 -7
- package/src/internal/EarnVaults.capabilities.test.ts +33 -0
- package/src/internal/EarnVaults.test.ts +79 -0
- package/src/internal/EarnVaults.ts +277 -0
- package/src/internal/Fetch.test.ts +46 -0
- package/src/internal/Fetch.ts +56 -0
- package/src/internal/Log.test.ts +21 -0
- package/src/internal/Log.ts +20 -5
- package/src/internal/OpenApi.ts +177 -51
- package/src/internal/Response.test.ts +95 -0
- package/src/internal/Response.ts +41 -3
- package/src/internal/Schema.test.ts +18 -0
- package/src/internal/Schema.ts +19 -9
- package/src/internal/Store.test.ts +364 -0
- package/src/internal/Store.ts +153 -27
- package/src/internal/Tidx.test.ts +21 -1
- package/src/internal/Tidx.ts +23 -6
- package/src/internal/Timeout.test.ts +35 -0
- package/src/internal/Timeout.ts +73 -0
- package/src/internal/Timing.ts +16 -0
- package/src/internal/WebhookDestination.ts +3 -0
- package/src/internal/Webhooks.test.ts +122 -8
- package/src/internal/Webhooks.ts +59 -29
- package/src/internal/funding/Action.test.ts +41 -1
- package/src/internal/funding/Action.ts +69 -41
- package/src/internal/funding/Catalog.test.ts +34 -0
- package/src/internal/funding/Catalog.ts +28 -11
- package/src/internal/funding/Deposit.ts +71 -64
- package/src/internal/funding/DepositAddress.ts +50 -43
- package/src/internal/funding/Provider.test.ts +73 -0
- package/src/internal/funding/Provider.ts +246 -170
- package/src/internal/funding/Transfer.ts +133 -110
- package/src/internal/funding/providers/index.test.ts +22 -0
- package/src/internal/funding/providers/relay.test.ts +2 -2
- package/src/internal/funding/providers/stargate.test.ts +163 -0
- package/src/internal/funding/providers/stargate.ts +409 -0
- package/src/internal/index.test.ts +1 -0
- package/src/internal/index.ts +1 -0
- package/src/providers/index.test.ts +1 -0
- package/src/providers/index.ts +9 -0
package/src/internal/Store.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Json } from 'ox'
|
|
2
2
|
|
|
3
|
+
import * as Timeout from './Timeout.js'
|
|
4
|
+
|
|
3
5
|
/** Key-to-value map used by typed stores. */
|
|
4
6
|
export type StoreItemMap = Record<string, unknown>
|
|
5
7
|
|
|
@@ -575,26 +577,78 @@ export declare namespace durableObject {
|
|
|
575
577
|
}
|
|
576
578
|
}
|
|
577
579
|
|
|
580
|
+
/** Associates request cache directives with a store used by request handlers. */
|
|
581
|
+
export function withRequest(
|
|
582
|
+
store: Store,
|
|
583
|
+
request: withRequest.Request,
|
|
584
|
+
options: withRequest.Options = {},
|
|
585
|
+
): Store {
|
|
586
|
+
const source = requestStores.get(store)?.store ?? store
|
|
587
|
+
const scoped = {
|
|
588
|
+
delete: source.delete.bind(source),
|
|
589
|
+
...(source.deleteIf ? { deleteIf: source.deleteIf.bind(source) } : {}),
|
|
590
|
+
get: source.get.bind(source),
|
|
591
|
+
...(source.increment ? { increment: source.increment.bind(source) } : {}),
|
|
592
|
+
list: source.list.bind(source),
|
|
593
|
+
put: source.put.bind(source),
|
|
594
|
+
...(source.swap ? { swap: source.swap.bind(source) } : {}),
|
|
595
|
+
type: source.type,
|
|
596
|
+
}
|
|
597
|
+
requestStores.set(scoped, { request, store: source, waitUntil: options.waitUntil })
|
|
598
|
+
return scoped
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export declare namespace withRequest {
|
|
602
|
+
/** Request-scoped cache behavior. */
|
|
603
|
+
export type Options = {
|
|
604
|
+
/** Keeps asynchronous cache persistence alive after the response returns. */
|
|
605
|
+
waitUntil?: ((promise: Promise<unknown>) => void) | undefined
|
|
606
|
+
}
|
|
607
|
+
/** Request surface needed to read cache directives. */
|
|
608
|
+
export type Request = {
|
|
609
|
+
/** Reads one request header. */
|
|
610
|
+
header(name: string): string | undefined
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
578
614
|
/**
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
* returned without being cached.
|
|
615
|
+
* Returns a cached value when present. Otherwise, runs `fetch` and stores its
|
|
616
|
+
* result unless undefined or rejected by `shouldCache`. Cache persistence is
|
|
617
|
+
* best-effort and never delays the fetched value.
|
|
583
618
|
*/
|
|
584
619
|
export async function memoize<value>(
|
|
585
|
-
fetch: () => Promise<value>,
|
|
586
|
-
options: memoize.Options
|
|
620
|
+
fetch: (signal?: AbortSignal) => Promise<value>,
|
|
621
|
+
options: memoize.Options<value>,
|
|
587
622
|
): Promise<value> {
|
|
588
|
-
const
|
|
623
|
+
const scoped = requestStores.get(options.store)
|
|
624
|
+
const { key, ttl } = options
|
|
625
|
+
const flightTimeout = options.flightTimeout ?? Timeout.duration
|
|
626
|
+
const request = scoped?.request
|
|
627
|
+
const store = scoped?.store ?? options.store
|
|
628
|
+
const waitUntil = scoped?.waitUntil
|
|
629
|
+
|
|
630
|
+
// Request cache directives follow the same semantics as the response cache:
|
|
631
|
+
// no-cache refreshes the entry, while no-store bypasses it entirely.
|
|
632
|
+
const cacheControl = request?.header('cache-control')
|
|
633
|
+
const directives = (cacheControl ?? request?.header('pragma') ?? '').toLowerCase()
|
|
634
|
+
const noStore = directives.includes('no-store')
|
|
635
|
+
const noCache = noStore || directives.includes('no-cache')
|
|
636
|
+
if (noStore)
|
|
637
|
+
return Timeout.run((signal) => fetch(signal), {
|
|
638
|
+
error: new MemoizeTimeoutError(flightTimeout),
|
|
639
|
+
timeout: flightTimeout,
|
|
640
|
+
})
|
|
589
641
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
642
|
+
if (!noCache) {
|
|
643
|
+
const raw = await store.get(key)
|
|
644
|
+
// Old cache entries used ambiguous untagged bigint strings. Refresh them
|
|
645
|
+
// instead of guessing whether a matching string was originally a bigint.
|
|
646
|
+
if (raw?.startsWith(jsonCodecPrefix)) {
|
|
647
|
+
try {
|
|
648
|
+
return jsonDecode(raw) as value
|
|
649
|
+
} catch {
|
|
650
|
+
// Corrupt entries are treated as misses so the next call refreshes.
|
|
651
|
+
}
|
|
598
652
|
}
|
|
599
653
|
}
|
|
600
654
|
|
|
@@ -605,26 +659,81 @@ export async function memoize<value>(
|
|
|
605
659
|
// Coalesce concurrent misses for this process. The store remains the cache
|
|
606
660
|
// boundary; this only prevents a local cold-key stampede while the first
|
|
607
661
|
// fetch is still in flight.
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
662
|
+
let mutating = noCache
|
|
663
|
+
let settled = false
|
|
664
|
+
const work = async (signal?: AbortSignal) => {
|
|
665
|
+
if (noCache) {
|
|
666
|
+
try {
|
|
667
|
+
await store.delete(key)
|
|
668
|
+
} finally {
|
|
669
|
+
mutating = false
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
signal?.throwIfAborted()
|
|
673
|
+
mutating = false
|
|
674
|
+
const value = await fetch(signal)
|
|
675
|
+
signal?.throwIfAborted()
|
|
676
|
+
if (value === undefined || options.shouldCache?.(value) === false) return value
|
|
677
|
+
mutating = true
|
|
678
|
+
if (store.type === 'cache') {
|
|
679
|
+
// A lossy cache write cannot turn a successful origin read into an error.
|
|
680
|
+
const persist = Promise.resolve()
|
|
681
|
+
.then(() => store.put(key, jsonEncode(value), { ttl }))
|
|
682
|
+
.catch(() => {})
|
|
683
|
+
if (waitUntil)
|
|
684
|
+
try {
|
|
685
|
+
waitUntil(persist)
|
|
686
|
+
mutating = false
|
|
687
|
+
return value
|
|
688
|
+
} catch {}
|
|
689
|
+
try {
|
|
690
|
+
await persist
|
|
691
|
+
} finally {
|
|
692
|
+
mutating = false
|
|
693
|
+
}
|
|
694
|
+
return value
|
|
695
|
+
}
|
|
696
|
+
try {
|
|
697
|
+
await store.put(key, jsonEncode(value), { ttl })
|
|
698
|
+
} finally {
|
|
699
|
+
mutating = false
|
|
700
|
+
}
|
|
612
701
|
return value
|
|
613
|
-
})()
|
|
614
|
-
flights.set(key, flight)
|
|
615
|
-
|
|
616
|
-
try {
|
|
617
|
-
return await flight
|
|
618
|
-
} finally {
|
|
619
|
-
flights.delete(key)
|
|
620
702
|
}
|
|
703
|
+
let flight!: Promise<value>
|
|
704
|
+
const release = () => {
|
|
705
|
+
// A canceled fetch cannot mutate the cache after its next abort check.
|
|
706
|
+
// Non-cancelable cache mutations retain ownership until they settle.
|
|
707
|
+
if ((settled || !mutating) && flights.get(key) === flight) flights.delete(key)
|
|
708
|
+
}
|
|
709
|
+
flight = Timeout.run(
|
|
710
|
+
async (signal) => {
|
|
711
|
+
signal.addEventListener('abort', release, { once: true })
|
|
712
|
+
try {
|
|
713
|
+
return await work(signal)
|
|
714
|
+
} finally {
|
|
715
|
+
settled = true
|
|
716
|
+
release()
|
|
717
|
+
}
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
error: new MemoizeTimeoutError(flightTimeout),
|
|
721
|
+
timeout: flightTimeout,
|
|
722
|
+
},
|
|
723
|
+
)
|
|
724
|
+
flights.set(key, flight)
|
|
725
|
+
return flight
|
|
621
726
|
}
|
|
622
727
|
|
|
623
728
|
export declare namespace memoize {
|
|
624
729
|
/** Options for {@link memoize}. */
|
|
625
|
-
type Options = {
|
|
730
|
+
type Options<value = unknown> = {
|
|
731
|
+
/** Maximum shared cache-miss flight duration in milliseconds. Defaults to 15 seconds. */
|
|
732
|
+
flightTimeout?: number | undefined
|
|
626
733
|
/** Cache key. Callers are responsible for namespacing/versioning. */
|
|
627
734
|
key: string
|
|
735
|
+
/** Returns whether a fetched value should be stored. Single-flight callers still share it. */
|
|
736
|
+
shouldCache?: ((value: value) => boolean) | undefined
|
|
628
737
|
/** Store used to persist cache entries. */
|
|
629
738
|
store: Store
|
|
630
739
|
/** Time-to-live in milliseconds. */
|
|
@@ -632,6 +741,14 @@ export declare namespace memoize {
|
|
|
632
741
|
}
|
|
633
742
|
}
|
|
634
743
|
|
|
744
|
+
const requestStores = new WeakMap<
|
|
745
|
+
Store,
|
|
746
|
+
{
|
|
747
|
+
request: withRequest.Request
|
|
748
|
+
store: Store
|
|
749
|
+
waitUntil?: ((promise: Promise<unknown>) => void) | undefined
|
|
750
|
+
}
|
|
751
|
+
>()
|
|
635
752
|
const flights = new WeakMap<Store, Map<string, Promise<unknown>>>()
|
|
636
753
|
|
|
637
754
|
function flightsFor(store: Store) {
|
|
@@ -829,6 +946,15 @@ function isDurableObjectValue(value: unknown): value is DurableObjectValue {
|
|
|
829
946
|
)
|
|
830
947
|
}
|
|
831
948
|
|
|
949
|
+
/** Thrown when a shared memoized cache-miss flight exceeds its configured deadline. */
|
|
950
|
+
export class MemoizeTimeoutError extends Error {
|
|
951
|
+
override name = 'Store.MemoizeTimeoutError'
|
|
952
|
+
|
|
953
|
+
constructor(timeout: number) {
|
|
954
|
+
super(`Memoized cache-miss flight timed out after ${timeout}ms.`)
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
832
958
|
/** Thrown when {@link update} exhausts its compare-and-swap attempts. */
|
|
833
959
|
export class UpdateContentionError extends Error {
|
|
834
960
|
override name = 'Store.UpdateContentionError'
|
|
@@ -59,10 +59,16 @@ describe('providerFailure', () => {
|
|
|
59
59
|
|
|
60
60
|
test('classifies timeout and rate-limit statuses', () => {
|
|
61
61
|
expect([
|
|
62
|
+
Tidx.providerFailure(appError('query timed out')),
|
|
62
63
|
Tidx.providerFailure(appError('secret upstream detail', 408)),
|
|
63
64
|
Tidx.providerFailure(appError('secret upstream detail', 429)),
|
|
64
65
|
]).toMatchInlineSnapshot(`
|
|
65
66
|
[
|
|
67
|
+
{
|
|
68
|
+
"failure": "timeout",
|
|
69
|
+
"id": "tidx",
|
|
70
|
+
"operation": "query",
|
|
71
|
+
},
|
|
66
72
|
{
|
|
67
73
|
"failure": "timeout",
|
|
68
74
|
"id": "tidx",
|
|
@@ -135,6 +141,19 @@ describe('isQueryRejection', () => {
|
|
|
135
141
|
})
|
|
136
142
|
})
|
|
137
143
|
|
|
144
|
+
describe('isQueryTimeout', () => {
|
|
145
|
+
test('matches explicit indexer query timeout failures only', () => {
|
|
146
|
+
expect([
|
|
147
|
+
Tidx.isQueryTimeout(appError('Request timeout', 408)),
|
|
148
|
+
Tidx.isQueryTimeout(appError('query timed out')),
|
|
149
|
+
Tidx.isQueryTimeout(appError('error sending request for url (...)')),
|
|
150
|
+
Tidx.isQueryTimeout(appError('db error')),
|
|
151
|
+
Tidx.isQueryTimeout(appError('Request timeout', 429)),
|
|
152
|
+
Tidx.isQueryTimeout(new DOMException('query timed out', 'TimeoutError')),
|
|
153
|
+
]).toEqual([true, true, true, false, false, false])
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
138
157
|
describe('escape', () => {
|
|
139
158
|
test('doubles quotes for ANSI string literals, leaving backslashes alone', () => {
|
|
140
159
|
expect(Tidx.escape('USD')).toMatchInlineSnapshot(`"USD"`)
|
|
@@ -212,7 +231,8 @@ describe('withTransientRetry', () => {
|
|
|
212
231
|
|
|
213
232
|
await client.fetch({ chainId: 42431, query: 'SELECT 1' })
|
|
214
233
|
|
|
215
|
-
|
|
234
|
+
const { signal: _signal, ...options } = fetch.mock.calls[0]![0]
|
|
235
|
+
expect(options).toMatchInlineSnapshot(`
|
|
216
236
|
{
|
|
217
237
|
"chainId": 42431,
|
|
218
238
|
"query": "SELECT 1",
|
package/src/internal/Tidx.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type * as Auth from './Auth.js'
|
|
|
5
5
|
import * as Credential from './Credential.js'
|
|
6
6
|
import * as Errors from './Errors.js'
|
|
7
7
|
import type * as Log from './Log.js'
|
|
8
|
+
import * as Timeout from './Timeout.js'
|
|
8
9
|
import * as Viem from './Viem.js'
|
|
9
10
|
|
|
10
11
|
/** Default Tempo indexer (TIDX) base URLs. */
|
|
@@ -142,8 +143,10 @@ const transientRetryDelay = 250
|
|
|
142
143
|
* dropped at the server's execution cap — typically a cold object-storage
|
|
143
144
|
* cache read that warms across attempts, so retrying genuinely helps.
|
|
144
145
|
*/
|
|
145
|
-
const transientErrorPattern =
|
|
146
|
-
|
|
146
|
+
const transientErrorPattern = /db error|connection reset|connection refused/i
|
|
147
|
+
|
|
148
|
+
/** Indexer failures caused by the query execution deadline. */
|
|
149
|
+
const queryTimeoutPattern = /timeout|timed out|error sending request/i
|
|
147
150
|
|
|
148
151
|
/**
|
|
149
152
|
* Escapes a free-form string for safe embedding inside a single-quoted SQL
|
|
@@ -182,17 +185,21 @@ export function withTransientRetry(client: Client): Client {
|
|
|
182
185
|
return {
|
|
183
186
|
...client,
|
|
184
187
|
fetch: async (options) => {
|
|
188
|
+
const signal = Timeout.signal({ signal: options.signal })
|
|
185
189
|
let lastError: unknown
|
|
186
190
|
for (let attempt = 0; attempt <= transientRetryCount; attempt++) {
|
|
187
191
|
try {
|
|
188
192
|
// `retryCount: 1` caps the inner client at a single HTTP attempt so
|
|
189
193
|
// the combined budget stays this wrapper's alone.
|
|
190
|
-
return await fetch({ ...options, retryCount: 1 })
|
|
194
|
+
return await fetch({ ...options, retryCount: 1, signal })
|
|
191
195
|
} catch (error) {
|
|
192
196
|
if (!isTransientError(error)) throw error
|
|
193
197
|
lastError = error
|
|
194
198
|
if (attempt < transientRetryCount)
|
|
195
|
-
await
|
|
199
|
+
await Timeout.wait({
|
|
200
|
+
milliseconds: transientRetryDelay * 2 ** attempt,
|
|
201
|
+
signal,
|
|
202
|
+
})
|
|
196
203
|
}
|
|
197
204
|
}
|
|
198
205
|
throw lastError
|
|
@@ -239,8 +246,11 @@ export function providerFailure(cause: unknown): Log.ProviderFailure {
|
|
|
239
246
|
return { ...base, failure: 'timeout' }
|
|
240
247
|
|
|
241
248
|
const status = Errors.getStatus(cause)
|
|
249
|
+
if (isQueryTimeout(cause))
|
|
250
|
+
return status === 408
|
|
251
|
+
? { ...base, failure: 'timeout', status }
|
|
252
|
+
: { ...base, failure: 'timeout' }
|
|
242
253
|
if (status !== undefined && status >= 200 && status < 300) return { ...base, failure: 'payload' }
|
|
243
|
-
if (status === 408) return { ...base, failure: 'timeout', status }
|
|
244
254
|
if (status === 422) return { ...base, failure: 'query', status }
|
|
245
255
|
if (status === 429) return { ...base, failure: 'rate_limit', status }
|
|
246
256
|
if (status !== undefined) return { ...base, failure: 'http', status }
|
|
@@ -270,6 +280,13 @@ export function isQueryRejection(cause: unknown): boolean {
|
|
|
270
280
|
return status === 400 || status === 422
|
|
271
281
|
}
|
|
272
282
|
|
|
283
|
+
/** Whether a failed TIDX request exhausted its query execution deadline. */
|
|
284
|
+
export function isQueryTimeout(cause: unknown): boolean {
|
|
285
|
+
if (!(cause instanceof Tidx.FetchRequestError)) return false
|
|
286
|
+
if (cause.status === 408) return true
|
|
287
|
+
return cause.status >= 200 && cause.status < 300 && queryTimeoutPattern.test(cause.message)
|
|
288
|
+
}
|
|
289
|
+
|
|
273
290
|
/**
|
|
274
291
|
* True for deterministic indexer failures a retry cannot fix: a
|
|
275
292
|
* `FetchRequestError` outside {@link isTransientError}'s transient classes,
|
|
@@ -294,7 +311,7 @@ export function isDeterministicError(error: unknown): boolean {
|
|
|
294
311
|
*/
|
|
295
312
|
function isTransientError(error: unknown): boolean {
|
|
296
313
|
if (!(error instanceof Tidx.FetchRequestError)) return false
|
|
297
|
-
if (error
|
|
314
|
+
if (isQueryTimeout(error) || error.status === 429 || error.status >= 500) return true
|
|
298
315
|
return error.status >= 200 && error.status < 300 && transientErrorPattern.test(error.message)
|
|
299
316
|
}
|
|
300
317
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as Timeout from './Timeout.js'
|
|
2
|
+
|
|
3
|
+
describe('duration', () => {
|
|
4
|
+
test('uses a 15 second default', () => {
|
|
5
|
+
expect(Timeout.duration).toBe(15_000)
|
|
6
|
+
})
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
describe('signal', () => {
|
|
10
|
+
test('preserves a caller signal and otherwise creates a deadline', () => {
|
|
11
|
+
const caller = new AbortController().signal
|
|
12
|
+
|
|
13
|
+
expect(Timeout.signal({ signal: caller })).toBe(caller)
|
|
14
|
+
expect(Timeout.signal()).toBeInstanceOf(AbortSignal)
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('wait', () => {
|
|
19
|
+
test('rejects with the abort reason and clears its timer', async () => {
|
|
20
|
+
vi.useFakeTimers()
|
|
21
|
+
try {
|
|
22
|
+
const controller = new AbortController()
|
|
23
|
+
const reason = new DOMException('deadline exceeded', 'TimeoutError')
|
|
24
|
+
const waiting = Timeout.wait({ milliseconds: 1_000, signal: controller.signal })
|
|
25
|
+
const rejection = expect(waiting).rejects.toBe(reason)
|
|
26
|
+
|
|
27
|
+
controller.abort(reason)
|
|
28
|
+
|
|
29
|
+
await rejection
|
|
30
|
+
expect(vi.getTimerCount()).toBe(0)
|
|
31
|
+
} finally {
|
|
32
|
+
vi.useRealTimers()
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
})
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Default maximum duration for API dependency work. */
|
|
2
|
+
export const duration = 15_000
|
|
3
|
+
|
|
4
|
+
/** Returns a caller signal or a signal carrying the default deadline. */
|
|
5
|
+
export function signal(options: signal.Options = {}): AbortSignal {
|
|
6
|
+
return options.signal ?? AbortSignal.timeout(options.timeout ?? duration)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export declare namespace signal {
|
|
10
|
+
/** Options for {@link signal}. */
|
|
11
|
+
type Options = {
|
|
12
|
+
/** Existing caller signal. */
|
|
13
|
+
signal?: AbortSignal | null | undefined
|
|
14
|
+
/** Default maximum duration in milliseconds. */
|
|
15
|
+
timeout?: number | undefined
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Waits for a duration, rejecting immediately when `signal` aborts. */
|
|
20
|
+
export function wait(options: wait.Options): Promise<void> {
|
|
21
|
+
options.signal.throwIfAborted()
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const abort = () => {
|
|
24
|
+
clearTimeout(timer)
|
|
25
|
+
reject(options.signal.reason)
|
|
26
|
+
}
|
|
27
|
+
const timer = setTimeout(() => {
|
|
28
|
+
options.signal.removeEventListener('abort', abort)
|
|
29
|
+
resolve()
|
|
30
|
+
}, options.milliseconds)
|
|
31
|
+
options.signal.addEventListener('abort', abort, { once: true })
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export declare namespace wait {
|
|
36
|
+
/** Options for {@link wait}. */
|
|
37
|
+
type Options = {
|
|
38
|
+
/** Duration to wait in milliseconds. */
|
|
39
|
+
milliseconds: number
|
|
40
|
+
/** Signal that cancels the wait. */
|
|
41
|
+
signal: AbortSignal
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Runs asynchronous work under a hard deadline and aborts cooperative work. */
|
|
46
|
+
export function run<value>(
|
|
47
|
+
work: (signal: AbortSignal) => Promise<value>,
|
|
48
|
+
options: run.Options = {},
|
|
49
|
+
): Promise<value> {
|
|
50
|
+
const timeout = options.timeout ?? duration
|
|
51
|
+
const controller = new AbortController()
|
|
52
|
+
const timeoutError = new DOMException(`Timed out after ${timeout}ms.`, 'TimeoutError')
|
|
53
|
+
const error = options.error ?? timeoutError
|
|
54
|
+
const timer = setTimeout(() => controller.abort(timeoutError), timeout)
|
|
55
|
+
const operation = Promise.resolve().then(() => work(controller.signal))
|
|
56
|
+
|
|
57
|
+
return Promise.race([
|
|
58
|
+
operation,
|
|
59
|
+
new Promise<never>((_, reject) => {
|
|
60
|
+
controller.signal.addEventListener('abort', () => reject(error), { once: true })
|
|
61
|
+
}),
|
|
62
|
+
]).finally(() => clearTimeout(timer))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export declare namespace run {
|
|
66
|
+
/** Options for {@link run}. */
|
|
67
|
+
type Options = {
|
|
68
|
+
/** Error returned to the caller when the deadline expires. */
|
|
69
|
+
error?: Error | undefined
|
|
70
|
+
/** Maximum duration in milliseconds. */
|
|
71
|
+
timeout?: number | undefined
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/internal/Timing.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { Context, MiddlewareHandler } from 'hono'
|
|
|
2
2
|
|
|
3
3
|
/** Hono variables used to collect Server-Timing metrics. */
|
|
4
4
|
export type Variables = {
|
|
5
|
+
/** Operations that have started but not finished. */
|
|
6
|
+
activeTimings?: Active[] | undefined
|
|
5
7
|
/** Metrics emitted in the `Server-Timing` response header. */
|
|
6
8
|
serverTiming?: Metric[] | undefined
|
|
7
9
|
}
|
|
@@ -19,12 +21,22 @@ export type Metric = {
|
|
|
19
21
|
name: string
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
/** One operation that has started but not finished. */
|
|
25
|
+
export type Active = {
|
|
26
|
+
/** Metric name. */
|
|
27
|
+
name: string
|
|
28
|
+
/** Monotonic start time. */
|
|
29
|
+
start: number
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
/** Adds a `Server-Timing` header with total request duration. */
|
|
23
33
|
export function middleware<
|
|
24
34
|
environment extends Environment = Environment,
|
|
25
35
|
>(): MiddlewareHandler<environment> {
|
|
26
36
|
return async (c, next) => {
|
|
37
|
+
const active: Active[] = []
|
|
27
38
|
const metrics: Metric[] = []
|
|
39
|
+
c.set('activeTimings', active)
|
|
28
40
|
c.set('serverTiming', metrics)
|
|
29
41
|
|
|
30
42
|
const start = performance.now()
|
|
@@ -44,9 +56,13 @@ export async function time<environment extends Environment, value>(
|
|
|
44
56
|
fn: () => Promise<value> | value,
|
|
45
57
|
) {
|
|
46
58
|
const start = performance.now()
|
|
59
|
+
const active = { name, start }
|
|
60
|
+
c.get('activeTimings')?.push(active)
|
|
47
61
|
try {
|
|
48
62
|
return await fn()
|
|
49
63
|
} finally {
|
|
64
|
+
const activeTimings = c.get('activeTimings')
|
|
65
|
+
if (activeTimings) activeTimings.splice(activeTimings.indexOf(active), 1)
|
|
50
66
|
c.get('serverTiming')?.push({ duration: performance.now() - start, name })
|
|
51
67
|
}
|
|
52
68
|
}
|
|
@@ -176,6 +176,9 @@ export async function send(options: send.Options): Promise<Result> {
|
|
|
176
176
|
signal: controller.signal,
|
|
177
177
|
})
|
|
178
178
|
const durationMs = clock() - start
|
|
179
|
+
// The body is never read; an unreleased stream holds its buffer and
|
|
180
|
+
// connection in the isolate until GC, which stacks up during drains.
|
|
181
|
+
response.body?.cancel().catch(() => {})
|
|
179
182
|
if (
|
|
180
183
|
options.rejectRedirects &&
|
|
181
184
|
(response.status === 0 || (response.status >= 300 && response.status < 400))
|