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
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as Timeout from './Timeout.js'
|
|
2
|
+
|
|
3
|
+
/** Installs the default outbound fetch timeout once for this runtime. */
|
|
4
|
+
export function install(): void {
|
|
5
|
+
if (isInstalled(globalThis.fetch)) return
|
|
6
|
+
|
|
7
|
+
const fetch = withTimeout(globalThis.fetch.bind(globalThis), { timeout: Timeout.duration })
|
|
8
|
+
Object.defineProperty(fetch, timeoutMarker, { value: true })
|
|
9
|
+
globalThis.fetch = fetch
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Adds a default maximum duration to fetch calls that do not carry a signal. */
|
|
13
|
+
export function withTimeout(
|
|
14
|
+
fetch: typeof globalThis.fetch,
|
|
15
|
+
options: withTimeout.Options,
|
|
16
|
+
): typeof globalThis.fetch {
|
|
17
|
+
return ((input, init) => {
|
|
18
|
+
const signal = resolveSignal(input, { init, timeout: options.timeout })
|
|
19
|
+
return fetch(input, { ...init, signal })
|
|
20
|
+
}) as typeof globalThis.fetch
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Resolves a caller signal or creates the default fetch deadline signal. */
|
|
24
|
+
export function resolveSignal(
|
|
25
|
+
input: Parameters<typeof globalThis.fetch>[0],
|
|
26
|
+
options: resolveSignal.Options,
|
|
27
|
+
): AbortSignal {
|
|
28
|
+
return (
|
|
29
|
+
options.init?.signal ??
|
|
30
|
+
(input instanceof Request ? input.signal : Timeout.signal({ timeout: options.timeout }))
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export declare namespace resolveSignal {
|
|
35
|
+
/** Options for {@link resolveSignal}. */
|
|
36
|
+
type Options = {
|
|
37
|
+
/** Optional fetch initialization carrying a caller signal. */
|
|
38
|
+
init?: Parameters<typeof globalThis.fetch>[1]
|
|
39
|
+
/** Default maximum duration in milliseconds. */
|
|
40
|
+
timeout: number
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare namespace withTimeout {
|
|
45
|
+
/** Options for {@link withTimeout}. */
|
|
46
|
+
type Options = {
|
|
47
|
+
/** Maximum fetch duration in milliseconds. */
|
|
48
|
+
timeout: number
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const timeoutMarker = Symbol.for('tempo.api.fetch.timeout')
|
|
53
|
+
|
|
54
|
+
function isInstalled(fetch: typeof globalThis.fetch): boolean {
|
|
55
|
+
return timeoutMarker in fetch
|
|
56
|
+
}
|
package/src/internal/Log.test.ts
CHANGED
|
@@ -457,6 +457,27 @@ describe('middleware', () => {
|
|
|
457
457
|
`)
|
|
458
458
|
})
|
|
459
459
|
|
|
460
|
+
test('preserves the request error and unfinished stages', async () => {
|
|
461
|
+
const entries: Log.Entry[] = []
|
|
462
|
+
const causes: Error[] = []
|
|
463
|
+
const api = app({
|
|
464
|
+
emit: (entry, cause) => {
|
|
465
|
+
entries.push(entry)
|
|
466
|
+
if (cause) causes.push(cause)
|
|
467
|
+
},
|
|
468
|
+
})
|
|
469
|
+
const cause = new Error('Memoized cache-miss flight timed out after 15000ms.')
|
|
470
|
+
api.get('/activities', (c) => {
|
|
471
|
+
void Timing.time(c, 'transaction_activity_mpp', () => new Promise(() => {}))
|
|
472
|
+
return Response.upstream(c, cause)
|
|
473
|
+
})
|
|
474
|
+
|
|
475
|
+
await api.request('/activities')
|
|
476
|
+
|
|
477
|
+
expect(causes[0]).toBe(cause)
|
|
478
|
+
expect(entries[0]?.pendingTimings?.['transaction_activity_mpp']).toBeGreaterThanOrEqual(0)
|
|
479
|
+
})
|
|
480
|
+
|
|
460
481
|
test('includes bounded funding provider attempts', async () => {
|
|
461
482
|
const entries: Log.Entry[] = []
|
|
462
483
|
const api = app({ emit: (entry) => void entries.push(entry) })
|
package/src/internal/Log.ts
CHANGED
|
@@ -151,6 +151,8 @@ export type Entry = {
|
|
|
151
151
|
path: string
|
|
152
152
|
/** MPP payment reason when the request was paid per call. */
|
|
153
153
|
payment?: Auth.Payment['reason'] | undefined
|
|
154
|
+
/** Operations still running when the response completed, with elapsed milliseconds. */
|
|
155
|
+
pendingTimings?: Record<string, number> | undefined
|
|
154
156
|
/** Bounded outcome for an MPP relay operation. */
|
|
155
157
|
mpp?: {
|
|
156
158
|
/** Resolved Tempo chain selected by the credential. */
|
|
@@ -228,7 +230,7 @@ export type Entry = {
|
|
|
228
230
|
}
|
|
229
231
|
|
|
230
232
|
/** Sink receiving one {@link Entry} per request. */
|
|
231
|
-
export type Emit = (entry: Entry) => Promise<void> | void
|
|
233
|
+
export type Emit = (entry: Entry, cause?: Error) => Promise<void> | void
|
|
232
234
|
|
|
233
235
|
/**
|
|
234
236
|
* Emits one canonical structured log entry per request, after the response is
|
|
@@ -258,7 +260,8 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
258
260
|
// Hono cannot resolve variable types through the generic `environment`,
|
|
259
261
|
// so shared-variable reads are cast from the environment contract above
|
|
260
262
|
// (the same pattern EdgeCache uses for its cross-layer reads).
|
|
261
|
-
const
|
|
263
|
+
const cause = c.error
|
|
264
|
+
const error = cause as (Error & ErrorMetadata) | undefined
|
|
262
265
|
const principal = c.get('principal' as never) as Auth.Principal | undefined
|
|
263
266
|
const errorCaptured = c.get('errorCaptured' as never) as boolean | undefined
|
|
264
267
|
const chainId = c.get('chainId' as never) as number | undefined
|
|
@@ -279,7 +282,6 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
279
282
|
error?.providerFailures ?? (c.get('providerFailures' as never) as Entry['providerFailures'])
|
|
280
283
|
const rpc = c.get('rpcResponse' as never) as Entry['rpc']
|
|
281
284
|
const sponsorship = c.get('sponsorship' as never) as Entry['sponsorship']
|
|
282
|
-
|
|
283
285
|
// The `request` total metric duplicates `duration` (measured here, one
|
|
284
286
|
// layer further out), so only operation timings are kept.
|
|
285
287
|
const metrics = (c.get('serverTiming' as never) as Timing.Metric[] | undefined)?.filter(
|
|
@@ -295,6 +297,17 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
295
297
|
}, new Map<string, number>()),
|
|
296
298
|
)
|
|
297
299
|
: undefined
|
|
300
|
+
const activeTimings = c.get('activeTimings' as never) as Timing.Active[] | undefined
|
|
301
|
+
const pendingTimings = activeTimings?.length
|
|
302
|
+
? Object.fromEntries(
|
|
303
|
+
activeTimings.reduce((result, timing) => {
|
|
304
|
+
const duration = round(performance.now() - timing.start)
|
|
305
|
+
const existing = result.get(timing.name)
|
|
306
|
+
if (existing === undefined || duration > existing) result.set(timing.name, duration)
|
|
307
|
+
return result
|
|
308
|
+
}, new Map<string, number>()),
|
|
309
|
+
)
|
|
310
|
+
: undefined
|
|
298
311
|
|
|
299
312
|
const rateLimit = (() => {
|
|
300
313
|
const limit = c.res.headers.get('RateLimit-Limit')
|
|
@@ -310,7 +323,7 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
310
323
|
}
|
|
311
324
|
})()
|
|
312
325
|
|
|
313
|
-
const
|
|
326
|
+
const entry = {
|
|
314
327
|
...(c.get('edgeCacheStatus' as never) === 'hit' ? { cache: 'hit' as const } : {}),
|
|
315
328
|
...(chainId === undefined ? {} : { chainId }),
|
|
316
329
|
duration: round(duration),
|
|
@@ -333,6 +346,7 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
333
346
|
...(mpp === undefined ? {} : { mpp }),
|
|
334
347
|
path: url.pathname,
|
|
335
348
|
...(principal?.payment === undefined ? {} : { payment: principal.payment.reason }),
|
|
349
|
+
...(pendingTimings === undefined ? {} : { pendingTimings }),
|
|
336
350
|
...(principal === undefined
|
|
337
351
|
? {}
|
|
338
352
|
: {
|
|
@@ -360,7 +374,8 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
360
374
|
...(sponsorship === undefined ? {} : { sponsorship }),
|
|
361
375
|
status,
|
|
362
376
|
...(timings === undefined ? {} : { timings }),
|
|
363
|
-
}
|
|
377
|
+
} satisfies Entry
|
|
378
|
+
const result = fn(entry, cause)
|
|
364
379
|
|
|
365
380
|
if (result instanceof Promise) {
|
|
366
381
|
const promise = result.catch((error) => console.error('request log sink failed', error))
|
package/src/internal/OpenApi.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { Context, Env, MiddlewareHandler, ValidationTargets } from 'hono'
|
|
2
2
|
import type { HasRequiredKeys } from 'hono/utils/types'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
describeRoute as core_describeRoute,
|
|
5
|
+
type DescribeRouteOptions,
|
|
6
|
+
resolver,
|
|
7
|
+
type ResponsesWithResolver,
|
|
8
|
+
uniqueSymbol,
|
|
9
|
+
validator,
|
|
10
|
+
} from 'hono-openapi'
|
|
4
11
|
import * as z from 'zod/mini'
|
|
5
12
|
import * as Response from './Response.js'
|
|
6
13
|
import * as Schema from './Schema.js'
|
|
@@ -41,7 +48,6 @@ const schemaOptions = { options: { override: recoverExamples, unrepresentable: '
|
|
|
41
48
|
// re-exports because `uniqueSymbol` is a `unique symbol` whose identity is
|
|
42
49
|
// lost when copied through a `const` declaration.
|
|
43
50
|
export {
|
|
44
|
-
describeRoute,
|
|
45
51
|
type HandlerUniqueProperty,
|
|
46
52
|
resolver,
|
|
47
53
|
type ResponsesWithResolver,
|
|
@@ -49,12 +55,53 @@ export {
|
|
|
49
55
|
validator,
|
|
50
56
|
} from 'hono-openapi'
|
|
51
57
|
|
|
58
|
+
function cloneResponseContainers(spec: DescribeRouteOptions): DescribeRouteOptions {
|
|
59
|
+
if (!spec.responses) return spec
|
|
60
|
+
return {
|
|
61
|
+
...spec,
|
|
62
|
+
responses: Object.fromEntries(
|
|
63
|
+
Object.entries(spec.responses).map(([status, response]) => [
|
|
64
|
+
status,
|
|
65
|
+
!response || !('content' in response)
|
|
66
|
+
? response
|
|
67
|
+
: {
|
|
68
|
+
...response,
|
|
69
|
+
content: Object.fromEntries(
|
|
70
|
+
Object.entries(response.content ?? {}).map(([mediaType, media]) => [
|
|
71
|
+
mediaType,
|
|
72
|
+
{ ...media },
|
|
73
|
+
]),
|
|
74
|
+
),
|
|
75
|
+
},
|
|
76
|
+
]),
|
|
77
|
+
),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Describes a route without allowing spec generation to mutate reusable response definitions. */
|
|
82
|
+
export function describeRoute(spec: DescribeRouteOptions): MiddlewareHandler {
|
|
83
|
+
const handler = core_describeRoute(spec)
|
|
84
|
+
Object.defineProperty(handler, uniqueSymbol, {
|
|
85
|
+
get: () => ({ spec: cloneResponseContainers(spec) }),
|
|
86
|
+
})
|
|
87
|
+
return handler
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Emits a named OpenAPI component and uses its `$ref` wherever the schema appears. */
|
|
91
|
+
export function component<const schema extends z.ZodMiniType>(
|
|
92
|
+
schema: schema,
|
|
93
|
+
name: string,
|
|
94
|
+
): schema {
|
|
95
|
+
const cloned = schema.clone()
|
|
96
|
+
z.globalRegistry.add(cloned, { ...z.globalRegistry.get(schema), ref: name })
|
|
97
|
+
return cloned as schema
|
|
98
|
+
}
|
|
99
|
+
|
|
52
100
|
/**
|
|
53
101
|
* Standard machine-readable `error.code` values per status, shared API-wide.
|
|
54
102
|
* The reference enumerates `error.code` to these so generated clients narrow it
|
|
55
|
-
* to a literal union instead of an open `string`.
|
|
56
|
-
*
|
|
57
|
-
* via the `codes` override in {@link responses.Options}.
|
|
103
|
+
* to a literal union instead of an open `string`. The values here are shared
|
|
104
|
+
* defaults; operation-specific codes are supplied through {@link responses.Options}.
|
|
58
105
|
*/
|
|
59
106
|
export const errorCodes = {
|
|
60
107
|
400: [
|
|
@@ -80,7 +127,7 @@ export const errorCodes = {
|
|
|
80
127
|
'api_key_malformed',
|
|
81
128
|
],
|
|
82
129
|
401: ['api_key_missing', 'api_key_invalid', 'unauthorized'],
|
|
83
|
-
403: ['api_key_forbidden', 'api_key_ip_forbidden', '
|
|
130
|
+
403: ['api_key_forbidden', 'api_key_ip_forbidden', 'forbidden'],
|
|
84
131
|
404: [
|
|
85
132
|
'not_found',
|
|
86
133
|
'token_not_found',
|
|
@@ -101,6 +148,7 @@ export const errorCodes = {
|
|
|
101
148
|
500: ['internal_error'],
|
|
102
149
|
501: ['billing_unconfigured'],
|
|
103
150
|
502: ['upstream_error'],
|
|
151
|
+
504: ['request_timeout'],
|
|
104
152
|
} as const satisfies Record<number, readonly [string, ...string[]]>
|
|
105
153
|
|
|
106
154
|
/**
|
|
@@ -164,11 +212,79 @@ export const rateLimitHeaders = {
|
|
|
164
212
|
/** Representative `requestId` used in error-body examples. */
|
|
165
213
|
const exampleRequestId = '0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9'
|
|
166
214
|
|
|
167
|
-
|
|
168
|
-
|
|
215
|
+
const standardErrorNames = {
|
|
216
|
+
400: 'InvalidRequestError',
|
|
217
|
+
401: 'AuthenticationError',
|
|
218
|
+
403: 'ForbiddenError',
|
|
219
|
+
404: 'ResourceNotFoundError',
|
|
220
|
+
429: 'RateLimitError',
|
|
221
|
+
500: 'InternalError',
|
|
222
|
+
501: 'NotImplementedError',
|
|
223
|
+
502: 'UpstreamError',
|
|
224
|
+
504: 'RequestTimeoutError',
|
|
225
|
+
} as const satisfies Record<keyof typeof errorCodes, string>
|
|
226
|
+
|
|
227
|
+
const reservedErrorNames = new Set<string>(Object.values(standardErrorNames))
|
|
228
|
+
const errorSchemas = new Map<string, z.ZodMiniType>()
|
|
229
|
+
|
|
230
|
+
function errorName(status: number, codes: readonly string[]) {
|
|
231
|
+
const standard = errorCodes[status as keyof typeof errorCodes]
|
|
232
|
+
if (
|
|
233
|
+
standard &&
|
|
234
|
+
standard.length === codes.length &&
|
|
235
|
+
[...standard].sort().every((code, index) => code === codes[index])
|
|
236
|
+
)
|
|
237
|
+
return standardErrorNames[status as keyof typeof standardErrorNames]
|
|
238
|
+
const name = `${codes
|
|
239
|
+
.map((code) =>
|
|
240
|
+
code
|
|
241
|
+
.split('_')
|
|
242
|
+
.map((part) => `${part[0]?.toUpperCase()}${part.slice(1)}`)
|
|
243
|
+
.join(''),
|
|
244
|
+
)
|
|
245
|
+
.join('Or')}Error`
|
|
246
|
+
if (reservedErrorNames.has(name)) return `${name.slice(0, -'Error'.length)}${status}Error`
|
|
247
|
+
return name
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function errorSchema(status: number, codes: readonly [string, ...string[]] | undefined) {
|
|
251
|
+
const defaults = errorCodes[status as keyof typeof errorCodes]
|
|
252
|
+
if (!codes && !defaults) {
|
|
253
|
+
const cached = errorSchemas.get('*')
|
|
254
|
+
if (cached) return cached
|
|
255
|
+
const schema = component(Schema.errorResponse(), 'ErrorResponse')
|
|
256
|
+
errorSchemas.set('*', schema)
|
|
257
|
+
return schema
|
|
258
|
+
}
|
|
259
|
+
const normalized = [...(codes ?? defaults ?? [])].sort() as [string, ...string[]]
|
|
260
|
+
const key = normalized.join('\0')
|
|
261
|
+
const cached = errorSchemas.get(key)
|
|
262
|
+
if (cached) return cached
|
|
263
|
+
const schema = component(Schema.errorResponse(normalized), errorName(status, normalized))
|
|
264
|
+
errorSchemas.set(key, schema)
|
|
265
|
+
return schema
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function mergeErrorCodes(
|
|
269
|
+
status: number,
|
|
270
|
+
codes: readonly string[] | undefined,
|
|
271
|
+
): readonly [string, ...string[]] | undefined {
|
|
272
|
+
if (!codes) return errorCodes[status as keyof typeof errorCodes]
|
|
273
|
+
if (status !== 400 && status !== 403)
|
|
274
|
+
return codes.length ? (codes as [string, ...string[]]) : undefined
|
|
275
|
+
const baseline = status === 400 ? (['api_key_malformed'] as const) : errorCodes[403]
|
|
276
|
+
return [...new Set([...baseline, ...codes])] as [string, ...string[]]
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Builds the `application/json` content for a standard error response: the named enumerated-code envelope plus an example body. */
|
|
280
|
+
function errorContent(
|
|
281
|
+
status: number,
|
|
282
|
+
codes: readonly [string, ...string[]] | undefined,
|
|
283
|
+
message: string,
|
|
284
|
+
) {
|
|
169
285
|
return {
|
|
170
286
|
'application/json': {
|
|
171
|
-
schema: resolver(
|
|
287
|
+
schema: resolver(errorSchema(status, codes), schemaOptions),
|
|
172
288
|
example: { error: { code: codes?.[0] ?? 'error', message }, requestId: exampleRequestId },
|
|
173
289
|
},
|
|
174
290
|
}
|
|
@@ -186,32 +302,35 @@ export const paymentChallenge = {
|
|
|
186
302
|
headers: { 'WWW-Authenticate': headerRef('WwwAuthenticate') },
|
|
187
303
|
} as const
|
|
188
304
|
|
|
189
|
-
|
|
190
|
-
const rateLimitedResponse = {
|
|
191
|
-
content: errorContent(errorCodes[429], 'Rate limit exceeded.'),
|
|
192
|
-
description:
|
|
193
|
-
'Rate limit exceeded. On endpoints that accept MPP, over-quota unpaid requests return `402 Payment Required` instead.',
|
|
194
|
-
headers: { ...rateLimitHeaders },
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/** Shared `500` internal-error response, registered as `components.responses.InternalError`. */
|
|
198
|
-
const serverErrorResponse = {
|
|
199
|
-
content: errorContent(errorCodes[500], 'Internal server error.'),
|
|
200
|
-
description: 'Internal server error.',
|
|
201
|
-
}
|
|
305
|
+
type ResponseComponentName = 'InternalError' | 'PaymentRequired' | 'RateLimited' | 'RequestTimeout'
|
|
202
306
|
|
|
203
307
|
/**
|
|
204
308
|
* Reusable responses registered under `components.responses` (see `App.create`)
|
|
205
|
-
* and `$ref`-erenced from operations, so the uniform `402`/`429`/`500`
|
|
206
|
-
* are defined once instead of inlined on every operation.
|
|
309
|
+
* and `$ref`-erenced from operations, so the uniform `402`/`429`/`500`/`504`
|
|
310
|
+
* responses are defined once instead of inlined on every operation.
|
|
207
311
|
*/
|
|
208
|
-
export
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
312
|
+
export function responseComponents(): ResponsesWithResolver {
|
|
313
|
+
return {
|
|
314
|
+
InternalError: {
|
|
315
|
+
content: errorContent(500, errorCodes[500], 'Internal server error.'),
|
|
316
|
+
description: 'Internal server error.',
|
|
317
|
+
},
|
|
318
|
+
PaymentRequired: paymentChallenge,
|
|
319
|
+
RateLimited: {
|
|
320
|
+
content: errorContent(429, errorCodes[429], 'Rate limit exceeded.'),
|
|
321
|
+
description:
|
|
322
|
+
'Rate limit exceeded. On endpoints that accept MPP, over-quota unpaid requests return `402 Payment Required` instead.',
|
|
323
|
+
headers: { ...rateLimitHeaders },
|
|
324
|
+
},
|
|
325
|
+
RequestTimeout: {
|
|
326
|
+
content: errorContent(504, errorCodes[504], 'Request timed out'),
|
|
327
|
+
description:
|
|
328
|
+
'Request timed out. The request did not complete within the 60-second deadline; retry it.',
|
|
329
|
+
},
|
|
330
|
+
}
|
|
212
331
|
}
|
|
213
332
|
|
|
214
|
-
const responseRef = (name:
|
|
333
|
+
const responseRef = (name: ResponseComponentName) => ({
|
|
215
334
|
$ref: `#/components/responses/${name}`,
|
|
216
335
|
})
|
|
217
336
|
|
|
@@ -232,22 +351,24 @@ export function standardError(
|
|
|
232
351
|
): ResponsesWithResolver[string] {
|
|
233
352
|
if (status === 429) return responseRef('RateLimited')
|
|
234
353
|
if (status === 500) return responseRef('InternalError')
|
|
235
|
-
|
|
354
|
+
if (status === 504) return responseRef('RequestTimeout')
|
|
355
|
+
return { content: errorContent(status, mergeErrorCodes(status, codes), description), description }
|
|
236
356
|
}
|
|
237
357
|
|
|
238
358
|
/**
|
|
239
359
|
* Builds an OpenAPI `responses` map with the API's standard error responses
|
|
240
360
|
* pre-filled, plus the success response (with rate-limit headers):
|
|
241
361
|
*
|
|
242
|
-
* - `400` invalid request, `401` missing/invalid key, `
|
|
243
|
-
* `500` internal error,
|
|
244
|
-
*
|
|
362
|
+
* - `400` invalid request, `401` missing/invalid key, `403` forbidden, `429`
|
|
363
|
+
* rate limited, `500` internal error, `502` upstream failure, and `504`
|
|
364
|
+
* request timeout on every operation;
|
|
365
|
+
* - `404`/`409`/`412`/`413`/`415` only when an `errors` entry is set.
|
|
245
366
|
*
|
|
246
|
-
* `error.code` is enumerated per status from {@link errorCodes}
|
|
247
|
-
*
|
|
248
|
-
* `429
|
|
249
|
-
*
|
|
250
|
-
*
|
|
367
|
+
* `error.code` is enumerated per status from {@link errorCodes}. Operation-level
|
|
368
|
+
* 400/403 codes merge with shared auth codes; other overrides replace defaults.
|
|
369
|
+
* The default `429` and `500` `$ref` shared {@link responseComponents}; an exact
|
|
370
|
+
* operation-level `429` override is emitted inline with the standard headers.
|
|
371
|
+
* `402` is injected per operation from the route's MPP policy in `App.ts`.
|
|
251
372
|
*/
|
|
252
373
|
export function responses<schema extends z.ZodMiniType>(
|
|
253
374
|
options: responses.Options<schema>,
|
|
@@ -257,10 +378,11 @@ export function responses<schema extends z.ZodMiniType>(
|
|
|
257
378
|
const override = errors?.[status as 400]
|
|
258
379
|
const description =
|
|
259
380
|
typeof override === 'string' ? override : (override?.description ?? fallback)
|
|
260
|
-
const codes =
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
381
|
+
const codes = mergeErrorCodes(status, typeof override === 'object' ? override.codes : undefined)
|
|
382
|
+
return {
|
|
383
|
+
content: errorContent(status, codes, description),
|
|
384
|
+
description,
|
|
385
|
+
}
|
|
264
386
|
}
|
|
265
387
|
return {
|
|
266
388
|
200: {
|
|
@@ -279,39 +401,41 @@ export function responses<schema extends z.ZodMiniType>(
|
|
|
279
401
|
},
|
|
280
402
|
400: error(400, 'Invalid request.'),
|
|
281
403
|
401: error(401, 'Missing or invalid API key.'),
|
|
282
|
-
|
|
404
|
+
403: error(403, 'Forbidden.'),
|
|
283
405
|
...(errors?.[404] && { 404: error(404, 'Not found.') }),
|
|
284
406
|
...(errors?.[409] && { 409: error(409, 'Conflict.') }),
|
|
285
407
|
...(errors?.[412] && { 412: error(412, 'Precondition failed.') }),
|
|
286
408
|
...(errors?.[413] && { 413: error(413, 'Payload too large.') }),
|
|
287
409
|
...(errors?.[415] && { 415: error(415, 'Unsupported media type.') }),
|
|
288
|
-
429:
|
|
410
|
+
429: errors?.[429]
|
|
411
|
+
? { ...error(429, 'Rate limit exceeded.'), headers: { ...rateLimitHeaders } }
|
|
412
|
+
: responseRef('RateLimited'),
|
|
289
413
|
500: responseRef('InternalError'),
|
|
290
414
|
...(errors?.[501] && { 501: error(501, 'Not implemented.') }),
|
|
291
415
|
502: error(502, 'Upstream data failure.'),
|
|
416
|
+
504: responseRef('RequestTimeout'),
|
|
292
417
|
}
|
|
293
418
|
}
|
|
294
419
|
|
|
295
420
|
export declare namespace responses {
|
|
296
421
|
/**
|
|
297
422
|
* Override for a standard error response: a description string, or an object
|
|
298
|
-
* adding
|
|
423
|
+
* adding operation codes. Codes replace defaults except shared 400/403 auth codes.
|
|
299
424
|
*/
|
|
300
425
|
type ErrorOverride =
|
|
301
426
|
| string
|
|
302
427
|
| {
|
|
303
428
|
/** Human-readable description of the error response. */
|
|
304
429
|
description?: string | undefined
|
|
305
|
-
/**
|
|
306
|
-
codes?: readonly
|
|
430
|
+
/** Operation-specific `error.code` values for this status. */
|
|
431
|
+
codes?: readonly string[] | undefined
|
|
307
432
|
}
|
|
308
433
|
|
|
309
434
|
/** Options for building a standard OpenAPI responses map. */
|
|
310
435
|
type Options<schema> = {
|
|
311
436
|
/**
|
|
312
|
-
* Optional overrides for standard error responses
|
|
313
|
-
* `
|
|
314
|
-
* includes that status in the map.
|
|
437
|
+
* Optional overrides for standard error responses. Setting
|
|
438
|
+
* `404`/`409`/`412`/`413`/`415` includes that status in the map.
|
|
315
439
|
*/
|
|
316
440
|
errors?:
|
|
317
441
|
| {
|
|
@@ -319,7 +443,7 @@ export declare namespace responses {
|
|
|
319
443
|
400?: ErrorOverride | undefined
|
|
320
444
|
/** Override for the 401 response. */
|
|
321
445
|
401?: ErrorOverride | undefined
|
|
322
|
-
/**
|
|
446
|
+
/** Add operation-specific 403 codes or override its description. */
|
|
323
447
|
403?: ErrorOverride | undefined
|
|
324
448
|
/** Override for the 404 response. Setting this includes 404 in the map. */
|
|
325
449
|
404?: ErrorOverride | undefined
|
|
@@ -331,6 +455,8 @@ export declare namespace responses {
|
|
|
331
455
|
413?: ErrorOverride | undefined
|
|
332
456
|
/** Override for the 415 response. Setting this includes 415 in the map. */
|
|
333
457
|
415?: ErrorOverride | undefined
|
|
458
|
+
/** Override the shared 429 response with operation-specific rate-limit codes. */
|
|
459
|
+
429?: ErrorOverride | undefined
|
|
334
460
|
/** Override for the 501 response. Setting this includes 501 in the map. */
|
|
335
461
|
501?: ErrorOverride | undefined
|
|
336
462
|
/** Override for the 502 response. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono'
|
|
2
|
+
import { Tidx } from 'tidx.ts'
|
|
2
3
|
|
|
3
4
|
import * as Response from './Response.js'
|
|
4
5
|
|
|
@@ -25,4 +26,98 @@ describe('upstream', () => {
|
|
|
25
26
|
`)
|
|
26
27
|
expect(captured).toBe(cause)
|
|
27
28
|
})
|
|
29
|
+
|
|
30
|
+
test('returns a query error when a positional page times out', async () => {
|
|
31
|
+
const app = new Hono()
|
|
32
|
+
const cause = new Tidx.FetchRequestError(
|
|
33
|
+
'Request timeout',
|
|
34
|
+
new globalThis.Response(null, { status: 408 }),
|
|
35
|
+
)
|
|
36
|
+
let captured: Error | undefined
|
|
37
|
+
|
|
38
|
+
app.use(async (c, next) => {
|
|
39
|
+
await next()
|
|
40
|
+
captured = c.error
|
|
41
|
+
})
|
|
42
|
+
app.get('/', (c) => Response.upstream(c, cause, { page: 2 }))
|
|
43
|
+
|
|
44
|
+
const response = await app.request('/')
|
|
45
|
+
expect(response.status).toMatchInlineSnapshot(`400`)
|
|
46
|
+
expect(await response.json()).toMatchInlineSnapshot(`
|
|
47
|
+
{
|
|
48
|
+
"error": {
|
|
49
|
+
"code": "query_invalid",
|
|
50
|
+
"message": "The requested page timed out. Use cursor pagination for deep traversal.",
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
`)
|
|
54
|
+
expect(captured).toBe(cause)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('returns a query error when a positional page is rejected', async () => {
|
|
58
|
+
const app = new Hono()
|
|
59
|
+
const cause = new Tidx.FetchRequestError(
|
|
60
|
+
'Query rejected',
|
|
61
|
+
new globalThis.Response(null, { status: 422 }),
|
|
62
|
+
)
|
|
63
|
+
let captured: Error | undefined
|
|
64
|
+
|
|
65
|
+
app.use(async (c, next) => {
|
|
66
|
+
await next()
|
|
67
|
+
captured = c.error
|
|
68
|
+
})
|
|
69
|
+
app.get('/', (c) => Response.upstream(c, cause, { page: 584 }))
|
|
70
|
+
|
|
71
|
+
const response = await app.request('/')
|
|
72
|
+
expect(response.status).toMatchInlineSnapshot(`400`)
|
|
73
|
+
expect(await response.json()).toMatchInlineSnapshot(`
|
|
74
|
+
{
|
|
75
|
+
"error": {
|
|
76
|
+
"code": "query_invalid",
|
|
77
|
+
"message": "The requested page was rejected. Use cursor pagination for deep traversal.",
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
`)
|
|
81
|
+
expect(captured).toBe(cause)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('keeps timeouts without a deep positional page as upstream errors', async () => {
|
|
85
|
+
const app = new Hono()
|
|
86
|
+
const cause = new Tidx.FetchRequestError(
|
|
87
|
+
'Request timeout',
|
|
88
|
+
new globalThis.Response(null, { status: 408 }),
|
|
89
|
+
)
|
|
90
|
+
app.get('/', (c) => Response.upstream(c, cause, { page: undefined }))
|
|
91
|
+
|
|
92
|
+
const response = await app.request('/')
|
|
93
|
+
expect(response.status).toMatchInlineSnapshot(`502`)
|
|
94
|
+
expect(await response.json()).toMatchInlineSnapshot(`
|
|
95
|
+
{
|
|
96
|
+
"error": {
|
|
97
|
+
"code": "upstream_error",
|
|
98
|
+
"message": "Upstream service could not complete the request",
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
`)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('keeps query rejections without a deep positional page as upstream errors', async () => {
|
|
105
|
+
const app = new Hono()
|
|
106
|
+
const cause = new Tidx.FetchRequestError(
|
|
107
|
+
'Query rejected',
|
|
108
|
+
new globalThis.Response(null, { status: 422 }),
|
|
109
|
+
)
|
|
110
|
+
app.get('/', (c) => Response.upstream(c, cause, { page: undefined }))
|
|
111
|
+
|
|
112
|
+
const response = await app.request('/')
|
|
113
|
+
expect(response.status).toMatchInlineSnapshot(`502`)
|
|
114
|
+
expect(await response.json()).toMatchInlineSnapshot(`
|
|
115
|
+
{
|
|
116
|
+
"error": {
|
|
117
|
+
"code": "upstream_error",
|
|
118
|
+
"message": "Upstream service could not complete the request",
|
|
119
|
+
},
|
|
120
|
+
}
|
|
121
|
+
`)
|
|
122
|
+
})
|
|
28
123
|
})
|