tapimo 0.15.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -0
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +4 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +37 -11
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +163 -10
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +13085 -11974
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +46 -15
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +1 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +1 -1
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +896 -191
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +5 -1
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +33 -33
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +8 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +66 -27
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +36 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +25 -25
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +5 -4
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/route-policies.d.ts +632 -0
- package/dist/admin/apps/route-policies.d.ts.map +1 -0
- package/dist/admin/apps/route-policies.js +257 -0
- package/dist/admin/apps/route-policies.js.map +1 -0
- package/dist/admin/apps/routes-support.js +39 -3
- package/dist/admin/apps/routes-support.js.map +1 -1
- package/dist/admin/apps/routes.d.ts +454 -1
- package/dist/admin/apps/routes.d.ts.map +1 -1
- package/dist/admin/apps/routes.js +82 -1
- package/dist/admin/apps/routes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +10 -4
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +24 -4
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/index.d.ts +0 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +0 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +99 -103
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +65 -1
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +1 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +58 -59
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +2709 -2670
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +5 -5
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +50 -0
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +248 -248
- package/dist/apps/data/routes/balances.d.ts +22 -22
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +5 -7
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +54 -54
- package/dist/apps/data/routes/earn.d.ts +103 -12
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +456 -220
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +267 -97
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +1 -19
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +93 -56
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +10 -10
- package/dist/apps/data/routes/rpc.d.ts +30 -30
- package/dist/apps/data/routes/rpc.js +45 -11
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +11 -6
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +2 -0
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +30 -22
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +12 -12
- package/dist/apps/data/routes/valuation.d.ts +30 -30
- package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +1 -1
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +18 -11
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +3 -3
- package/dist/apps/management/App.d.ts +3043 -2198
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -0
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/Billing.d.ts +2 -4
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +65 -26
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +16 -4
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +70 -11
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +84 -84
- package/dist/apps/management/routes/cli.d.ts +912 -0
- package/dist/apps/management/routes/cli.d.ts.map +1 -0
- package/dist/apps/management/routes/cli.js +416 -0
- package/dist/apps/management/routes/cli.js.map +1 -0
- package/dist/apps/management/routes/faucet.d.ts +8 -8
- package/dist/apps/management/routes/invitations.d.ts +24 -24
- package/dist/apps/management/routes/invite-links.d.ts +66 -66
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +20 -20
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +8 -2
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +76 -76
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +42 -42
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +7 -9
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +119 -119
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +16 -3
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +4 -2
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.js +6 -4
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
- package/dist/apps/relay/App.d.ts +8 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +16 -4
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -6
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +71 -60
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/apps/routes/Access.d.ts +53 -0
- package/dist/apps/routes/Access.d.ts.map +1 -1
- package/dist/apps/routes/Access.js +121 -0
- package/dist/apps/routes/Access.js.map +1 -1
- package/dist/apps/routes/App.d.ts +397 -158
- package/dist/apps/routes/App.d.ts.map +1 -1
- package/dist/apps/routes/App.js.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.d.ts +169 -61
- package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.js +217 -32
- package/dist/apps/routes/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/routes/routes/quotes.d.ts +90 -0
- package/dist/apps/routes/routes/quotes.d.ts.map +1 -1
- package/dist/apps/routes/routes/quotes.js +101 -27
- package/dist/apps/routes/routes/quotes.js.map +1 -1
- package/dist/apps/routes/routes/transfers.d.ts +187 -135
- package/dist/apps/routes/routes/transfers.d.ts.map +1 -1
- package/dist/apps/routes/routes/transfers.js +182 -37
- package/dist/apps/routes/routes/transfers.js.map +1 -1
- package/dist/cli/ApiKeys.d.ts +120 -0
- package/dist/cli/ApiKeys.d.ts.map +1 -0
- package/dist/cli/ApiKeys.js +138 -0
- package/dist/cli/ApiKeys.js.map +1 -0
- package/dist/cli/Cli.d.ts +92 -34
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +188 -11
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/Credentials.d.ts +95 -0
- package/dist/cli/Credentials.d.ts.map +1 -0
- package/dist/cli/Credentials.js +110 -0
- package/dist/cli/Credentials.js.map +1 -0
- package/dist/cli/Spec.d.ts +59 -0
- package/dist/cli/Spec.d.ts.map +1 -0
- package/dist/cli/Spec.js +77 -0
- package/dist/cli/Spec.js.map +1 -0
- package/dist/cli/bin.js +5 -1
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +5 -5
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/auth.d.ts +73 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +204 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/keys.d.ts +17 -0
- package/dist/cli/commands/keys.d.ts.map +1 -0
- package/dist/cli/commands/keys.js +109 -0
- package/dist/cli/commands/keys.js.map +1 -0
- package/dist/cloudflare.d.ts +27 -2
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +144 -17
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +23 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +418 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +44 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +56 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.d.ts +28 -2
- package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.js +65 -9
- package/dist/db/tables/apiKeyAdmissions.js.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts +2 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.js +2 -2
- package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -1
- package/dist/db/tables/authAccounts.d.ts.map +1 -1
- package/dist/db/tables/authAccounts.js +1 -0
- package/dist/db/tables/authAccounts.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 +12 -1
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +4 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +8 -34
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +5 -1
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +10 -2
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.d.ts +13 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.js +11 -0
- package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -1
- package/dist/db/tables/rewardRuns.d.ts.map +1 -1
- package/dist/db/tables/rewardRuns.js +4 -0
- package/dist/db/tables/rewardRuns.js.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.js +2 -0
- package/dist/db/tables/rewardTransactionAttempts.js.map +1 -1
- package/dist/db/tables/routesDepositAddresses.d.ts +29 -0
- package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -1
- package/dist/db/tables/routesDepositAddresses.js +84 -31
- package/dist/db/tables/routesDepositAddresses.js.map +1 -1
- package/dist/db/tables/routesDeposits.d.ts.map +1 -1
- package/dist/db/tables/routesDeposits.js +31 -21
- package/dist/db/tables/routesDeposits.js.map +1 -1
- package/dist/db/tables/routesIdempotency.d.ts.map +1 -1
- package/dist/db/tables/routesIdempotency.js +2 -0
- package/dist/db/tables/routesIdempotency.js.map +1 -1
- package/dist/db/tables/routesPolicies.d.ts +58 -0
- package/dist/db/tables/routesPolicies.d.ts.map +1 -0
- package/dist/db/tables/routesPolicies.js +198 -0
- package/dist/db/tables/routesPolicies.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts +22 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidies.js +41 -0
- package/dist/db/tables/routesTransferSubsidies.js.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.js +12 -4
- package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -1
- package/dist/db/tables/routesTransfers.d.ts +26 -1
- package/dist/db/tables/routesTransfers.d.ts.map +1 -1
- package/dist/db/tables/routesTransfers.js +36 -6
- package/dist/db/tables/routesTransfers.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +45 -13
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +144 -33
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +2 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +11 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.d.ts +21 -4
- package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.js +65 -44
- package/dist/db/tables/verifiedTokenRequests.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +1 -1
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +3 -2
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/relay.d.ts +2 -0
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +34 -15
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +73 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +212 -85
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/BetterAuth.d.ts +22 -0
- package/dist/internal/BetterAuth.d.ts.map +1 -1
- package/dist/internal/BetterAuth.js +17 -14
- package/dist/internal/BetterAuth.js.map +1 -1
- package/dist/internal/Cache.d.ts +5 -0
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +3 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/CliAuth.d.ts +243 -0
- package/dist/internal/CliAuth.d.ts.map +1 -0
- package/dist/internal/CliAuth.js +249 -0
- package/dist/internal/CliAuth.js.map +1 -0
- package/dist/internal/EarnSharePrices.d.ts +1 -1
- package/dist/internal/EarnSharePrices.d.ts.map +1 -1
- package/dist/internal/EarnSharePrices.js +7 -3
- package/dist/internal/EarnSharePrices.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +47 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +188 -4
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/EarnWithdrawals.d.ts +73 -0
- package/dist/internal/EarnWithdrawals.d.ts.map +1 -0
- package/dist/internal/EarnWithdrawals.js +189 -0
- package/dist/internal/EarnWithdrawals.js.map +1 -0
- package/dist/internal/ExecutionContext.d.ts +21 -0
- package/dist/internal/ExecutionContext.d.ts.map +1 -0
- package/dist/internal/ExecutionContext.js +16 -0
- package/dist/internal/ExecutionContext.js.map +1 -0
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +163 -130
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +26 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +67 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +174 -27
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Store.d.ts +6 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +4 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Timing.d.ts +6 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +21 -1
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/Tron.d.ts +124 -0
- package/dist/internal/Tron.d.ts.map +1 -0
- package/dist/internal/Tron.js +202 -0
- package/dist/internal/Tron.js.map +1 -0
- package/dist/internal/Viem.d.ts +4 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +25 -6
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/rewards/Read.d.ts +2 -2
- package/dist/internal/rewards/Read.d.ts.map +1 -1
- package/dist/internal/rewards/Read.js +11 -2
- package/dist/internal/rewards/Read.js.map +1 -1
- package/dist/internal/routes/Action.d.ts +27 -0
- package/dist/internal/routes/Action.d.ts.map +1 -1
- package/dist/internal/routes/Action.js +49 -1
- package/dist/internal/routes/Action.js.map +1 -1
- package/dist/internal/routes/Chain.d.ts +2 -0
- package/dist/internal/routes/Chain.d.ts.map +1 -1
- package/dist/internal/routes/Chain.js +4 -0
- package/dist/internal/routes/Chain.js.map +1 -1
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/DepositAddress.js +5 -0
- package/dist/internal/routes/DepositAddress.js.map +1 -1
- package/dist/internal/routes/Evidence.d.ts.map +1 -1
- package/dist/internal/routes/Evidence.js +6 -2
- package/dist/internal/routes/Evidence.js.map +1 -1
- package/dist/internal/routes/EvmTransferSettlement.d.ts +17 -0
- package/dist/internal/routes/EvmTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/EvmTransferSettlement.js +196 -0
- package/dist/internal/routes/EvmTransferSettlement.js.map +1 -0
- package/dist/internal/routes/Policy.d.ts +161 -0
- package/dist/internal/routes/Policy.d.ts.map +1 -0
- package/dist/internal/routes/Policy.js +249 -0
- package/dist/internal/routes/Policy.js.map +1 -0
- package/dist/internal/routes/Provider.d.ts +66 -3
- package/dist/internal/routes/Provider.d.ts.map +1 -1
- package/dist/internal/routes/Provider.js +106 -27
- package/dist/internal/routes/Provider.js.map +1 -1
- package/dist/internal/routes/Quota.d.ts +57 -0
- package/dist/internal/routes/Quota.d.ts.map +1 -0
- package/dist/internal/routes/Quota.js +144 -0
- package/dist/internal/routes/Quota.js.map +1 -0
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
- package/dist/internal/routes/Reconciliation.js +163 -47
- package/dist/internal/routes/Reconciliation.js.map +1 -1
- package/dist/internal/routes/SolanaTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/SolanaTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSettlement.js +220 -0
- package/dist/internal/routes/SolanaTransferSettlement.js.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts +172 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js +564 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/Subsidy.d.ts +2 -2
- package/dist/internal/routes/Subsidy.d.ts.map +1 -1
- package/dist/internal/routes/Subsidy.js +2 -2
- package/dist/internal/routes/Subsidy.js.map +1 -1
- package/dist/internal/routes/Transfer.d.ts +229 -1
- package/dist/internal/routes/Transfer.d.ts.map +1 -1
- package/dist/internal/routes/Transfer.js +644 -7
- package/dist/internal/routes/Transfer.js.map +1 -1
- package/dist/internal/routes/TransferReconciliation.d.ts +6 -0
- package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -1
- package/dist/internal/routes/TransferReconciliation.js +83 -159
- package/dist/internal/routes/TransferReconciliation.js.map +1 -1
- package/dist/internal/routes/TransferSettlement.d.ts +45 -0
- package/dist/internal/routes/TransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TransferSettlement.js +2 -0
- package/dist/internal/routes/TransferSettlement.js.map +1 -0
- package/dist/internal/routes/TransferSubsidy.d.ts +23 -8
- package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -1
- package/dist/internal/routes/TransferSubsidy.js +64 -5
- package/dist/internal/routes/TransferSubsidy.js.map +1 -1
- package/dist/internal/routes/TronTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/TronTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSettlement.js +201 -0
- package/dist/internal/routes/TronTransferSettlement.js.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts +174 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.js +439 -0
- package/dist/internal/routes/TronTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/index.d.ts +3 -0
- package/dist/internal/routes/index.d.ts.map +1 -1
- package/dist/internal/routes/index.js +3 -0
- package/dist/internal/routes/index.js.map +1 -1
- package/dist/internal/routes/providers/across.d.ts +3 -0
- package/dist/internal/routes/providers/across.d.ts.map +1 -1
- package/dist/internal/routes/providers/across.js +11 -0
- package/dist/internal/routes/providers/across.js.map +1 -1
- package/dist/internal/routes/providers/legacyMesh.d.ts +29 -0
- package/dist/internal/routes/providers/legacyMesh.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMesh.js +474 -0
- package/dist/internal/routes/providers/legacyMesh.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts +59 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js +229 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts +19 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js +457 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts +123 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js +333 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js.map +1 -0
- package/dist/internal/routes/providers/propAmm.d.ts +70 -0
- package/dist/internal/routes/providers/propAmm.d.ts.map +1 -0
- package/dist/internal/routes/providers/propAmm.js +524 -0
- package/dist/internal/routes/providers/propAmm.js.map +1 -0
- package/dist/internal/routes/providers/relay.d.ts +4 -1
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +353 -42
- package/dist/internal/routes/providers/relay.js.map +1 -1
- package/dist/internal/routes/providers/rhino.d.ts +3 -0
- package/dist/internal/routes/providers/rhino.d.ts.map +1 -1
- package/dist/internal/routes/providers/rhino.js +11 -0
- package/dist/internal/routes/providers/rhino.js.map +1 -1
- package/dist/internal/routes/providers/squid.d.ts +3 -0
- package/dist/internal/routes/providers/squid.d.ts.map +1 -1
- package/dist/internal/routes/providers/squid.js +19 -0
- package/dist/internal/routes/providers/squid.js.map +1 -1
- package/dist/internal/routes/providers/stargate.d.ts.map +1 -1
- package/dist/internal/routes/providers/stargate.js +22 -9
- package/dist/internal/routes/providers/stargate.js.map +1 -1
- package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -1
- package/dist/internal/routes/providers/symbiosis.js +13 -17
- package/dist/internal/routes/providers/symbiosis.js.map +1 -1
- package/dist/providers/index.d.ts +14 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +16 -6
- package/src/ApiKey.ts +7 -3
- package/src/ApiKeys.test.ts +652 -8
- package/src/ApiKeys.ts +191 -11
- package/src/App.test.ts +405 -18
- package/src/App.ts +51 -15
- package/src/Client.test-d.ts +157 -10
- package/src/Client.test.ts +4 -4
- package/src/Scope.ts +1 -2
- package/src/admin/App.ts +11 -5
- package/src/admin/apps/api-keys.test.ts +98 -2
- package/src/admin/apps/api-keys.ts +21 -12
- package/src/admin/apps/earn-vaults.test.ts +76 -7
- package/src/admin/apps/earn-vaults.ts +47 -8
- package/src/admin/apps/organizations.test.ts +147 -31
- package/src/admin/apps/organizations.ts +5 -4
- package/src/admin/apps/route-policies.test.ts +220 -0
- package/src/admin/apps/route-policies.ts +322 -0
- package/src/admin/apps/routes-support.test.ts +107 -2
- package/src/admin/apps/routes-support.ts +43 -3
- package/src/admin/apps/routes.test.ts +150 -0
- package/src/admin/apps/routes.ts +97 -1
- package/src/admin/apps/scopes.test.ts +1 -1
- package/src/admin/apps/verified-tokens.test.ts +32 -0
- package/src/admin/apps/verified-tokens.ts +30 -4
- package/src/admin/index.ts +0 -1
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/components/Dialog.tsx +1 -1
- package/src/admin/ui/src/components/EarnVaultForm.tsx +45 -0
- package/src/admin/ui/src/components/RoutePicker.tsx +79 -0
- package/src/admin/ui/src/lib/earn-vaults.ts +1 -1
- package/src/admin/ui/src/lib/route-policies.test.ts +452 -0
- package/src/admin/ui/src/lib/route-policies.ts +232 -0
- package/src/admin/ui/src/lib/routes.ts +34 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +24 -9
- package/src/admin/ui/src/routeTree.gen.ts +21 -0
- package/src/admin/ui/src/routes/__root.tsx +1 -1
- package/src/admin/ui/src/routes/api-keys.tsx +21 -2
- package/src/admin/ui/src/routes/early-access.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +22 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +10 -0
- package/src/admin/ui/src/routes/organizations.tsx +35 -4
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +18 -3
- package/src/admin/ui/src/routes/route-policies.tsx +678 -0
- package/src/admin/ui/src/routes/routes.tsx +85 -2
- package/src/admin/ui/src/routes/routes_.support.tsx +6 -22
- package/src/admin/ui/src/routes/subsidies.tsx +1 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +65 -20
- package/src/admin/ui.generated.ts +99 -104
- package/src/analytics/Analytics.test.ts +4 -50
- package/src/analytics/Analytics.ts +65 -1
- package/src/analytics/tables/requestEvents.test.ts +402 -1
- package/src/analytics/tables/requestEvents.ts +62 -93
- package/src/apps/data/App.test.ts +26 -0
- package/src/apps/data/routes/activities.test.ts +315 -14
- package/src/apps/data/routes/activities.ts +60 -0
- package/src/apps/data/routes/balances.ts +5 -7
- package/src/apps/data/routes/earn.bench.ts +18 -0
- package/src/apps/data/routes/earn.local.test.ts +507 -0
- package/src/apps/data/routes/earn.test.ts +405 -127
- package/src/apps/data/routes/earn.ts +660 -270
- package/src/apps/data/routes/exchanges.bench.ts +3 -1
- package/src/apps/data/routes/exchanges.test.ts +166 -2
- package/src/apps/data/routes/exchanges.ts +308 -101
- package/src/apps/data/routes/fee-amm.test.ts +153 -2
- package/src/apps/data/routes/fee-amm.ts +132 -62
- package/src/apps/data/routes/receipts.test.ts +21 -18
- package/src/apps/data/routes/rpc.test.ts +34 -2
- package/src/apps/data/routes/rpc.ts +47 -10
- package/src/apps/data/routes/tokens.provenance.test.ts +157 -0
- package/src/apps/data/routes/tokens.test.ts +4 -4
- package/src/apps/data/routes/tokens.ts +11 -6
- package/src/apps/data/routes/transactions.test.ts +29 -0
- package/src/apps/data/routes/transactions.ts +33 -22
- package/src/apps/data/routes/webhooks.scan.test.ts +29 -0
- package/src/apps/data/routes/webhooks.test.ts +18 -3
- package/src/apps/data/routes/webhooks.ts +27 -13
- package/src/apps/management/App.ts +4 -0
- package/src/apps/management/Billing.test.ts +253 -27
- package/src/apps/management/Billing.ts +83 -29
- package/src/apps/management/routes/api-keys.test.ts +1 -1
- package/src/apps/management/routes/api-keys.ts +85 -11
- package/src/apps/management/routes/billing.test.ts +68 -4
- package/src/apps/management/routes/cli.test.ts +370 -0
- package/src/apps/management/routes/cli.ts +533 -0
- package/src/apps/management/routes/me.test.ts +14 -4
- package/src/apps/management/routes/orgs.test.ts +108 -4
- package/src/apps/management/routes/orgs.ts +7 -2
- package/src/apps/management/routes/usage.test.ts +2 -2
- package/src/apps/management/routes/verified-token-requests.test.ts +16 -2
- package/src/apps/management/routes/verified-token-requests.ts +7 -10
- package/src/apps/mcp.test.ts +108 -25
- package/src/apps/mcp.ts +15 -3
- package/src/apps/mpp/internal/Policy.test.ts +51 -4
- package/src/apps/mpp/internal/Policy.ts +6 -2
- package/src/apps/mpp/internal/Sponsorship.test.ts +29 -0
- package/src/apps/mpp/internal/Sponsorship.ts +6 -4
- package/src/apps/relay/App.test.ts +85 -1
- package/src/apps/relay/App.ts +28 -4
- package/src/apps/relay/Sponsorships.test.ts +97 -1
- package/src/apps/relay/Sponsorships.ts +77 -66
- package/src/apps/routes/Access.test.ts +319 -0
- package/src/apps/routes/Access.ts +147 -0
- package/src/apps/routes/App.ts +10 -0
- package/src/apps/routes/routes/chains.test.ts +3 -2
- package/src/apps/routes/routes/deposit-addresses.test.ts +978 -34
- package/src/apps/routes/routes/deposit-addresses.ts +243 -32
- package/src/apps/routes/routes/propAmm.local.test.ts +951 -0
- package/src/apps/routes/routes/quotes.test.ts +81 -8
- package/src/apps/routes/routes/quotes.ts +109 -27
- package/src/apps/routes/routes/transfers.test.ts +252 -15
- package/src/apps/routes/routes/transfers.ts +212 -33
- package/src/cli/ApiKeys.test.ts +265 -0
- package/src/cli/ApiKeys.ts +189 -0
- package/src/cli/Cli.test.ts +188 -0
- package/src/cli/Cli.ts +280 -12
- package/src/cli/Credentials.test.ts +122 -0
- package/src/cli/Credentials.ts +144 -0
- package/src/cli/Spec.test.ts +133 -0
- package/src/cli/Spec.ts +132 -0
- package/src/cli/bin.test.ts +49 -0
- package/src/cli/bin.ts +5 -1
- package/src/cli/commands/auth.test.ts +138 -0
- package/src/cli/commands/auth.ts +254 -0
- package/src/cli/commands/keys.test.ts +68 -0
- package/src/cli/commands/keys.ts +125 -0
- package/src/cloudflare.ts +184 -36
- package/src/db/Db.test.ts +877 -0
- package/src/db/Db.ts +507 -1
- package/src/db/Schema.ts +75 -4
- package/src/db/tables/apiKeyAdmissions.test.ts +57 -0
- package/src/db/tables/apiKeyAdmissions.ts +101 -11
- package/src/db/tables/apiKeyOwnerTombstones.ts +2 -2
- package/src/db/tables/authAccounts.test.ts +30 -0
- package/src/db/tables/authAccounts.ts +1 -0
- package/src/db/tables/earnVaults.test.ts +34 -0
- package/src/db/tables/earnVaults.ts +17 -2
- package/src/db/tables/organizations.test.ts +148 -84
- package/src/db/tables/organizations.ts +11 -43
- package/src/db/tables/requestUsage.ts +13 -2
- package/src/db/tables/rewardCampaigns.test.ts +163 -0
- package/src/db/tables/rewardEligibilityAssociations.test.ts +14 -0
- package/src/db/tables/rewardEligibilityAssociations.ts +24 -0
- package/src/db/tables/rewardRuns.ts +4 -0
- package/src/db/tables/rewardTransactionAttempts.ts +2 -0
- package/src/db/tables/routesDepositAddresses.test.ts +263 -0
- package/src/db/tables/routesDepositAddresses.ts +118 -34
- package/src/db/tables/routesDeposits.test.ts +133 -0
- package/src/db/tables/routesDeposits.ts +47 -26
- package/src/db/tables/routesIdempotency.test.ts +80 -0
- package/src/db/tables/routesIdempotency.ts +2 -0
- package/src/db/tables/routesPolicies.test.ts +143 -0
- package/src/db/tables/routesPolicies.ts +251 -0
- package/src/db/tables/routesTransferSubsidies.ts +64 -0
- package/src/db/tables/routesTransferSubsidyNonces.ts +16 -4
- package/src/db/tables/routesTransfers.test.ts +183 -2
- package/src/db/tables/routesTransfers.ts +65 -6
- package/src/db/tables/sponsoredTransactions.test.ts +351 -76
- package/src/db/tables/sponsoredTransactions.ts +182 -38
- package/src/db/tables/users.test.ts +51 -0
- package/src/db/tables/users.ts +12 -0
- package/src/db/tables/verifiedTokenRequests.test.ts +39 -20
- package/src/db/tables/verifiedTokenRequests.ts +80 -44
- package/src/handlers/internal/multisig.store.test.ts +120 -0
- package/src/handlers/internal/multisig.test.ts +389 -0
- package/src/handlers/internal/multisig.ts +13 -10
- package/src/handlers/relay.test.ts +259 -83
- package/src/handlers/relay.ts +36 -17
- package/src/internal/Auth.test.ts +383 -8
- package/src/internal/Auth.ts +272 -99
- package/src/internal/BetterAuth.test.ts +58 -22
- package/src/internal/BetterAuth.ts +23 -17
- package/src/internal/Cache.ts +3 -1
- package/src/internal/CliAuth.test.ts +279 -0
- package/src/internal/CliAuth.ts +319 -0
- package/src/internal/EarnSharePrices.test.ts +25 -0
- package/src/internal/EarnSharePrices.ts +9 -2
- package/src/internal/EarnVaults.test.ts +67 -0
- package/src/internal/EarnVaults.ts +299 -4
- package/src/internal/EarnWithdrawals.test.ts +315 -0
- package/src/internal/EarnWithdrawals.ts +266 -0
- package/src/internal/ExecutionContext.ts +31 -0
- package/src/internal/Log.test.ts +210 -0
- package/src/internal/Log.ts +180 -142
- package/src/internal/MetricSink.test.ts +190 -15
- package/src/internal/MetricSink.ts +27 -1
- package/src/internal/RateLimit.test.ts +144 -8
- package/src/internal/RateLimit.ts +254 -26
- package/src/internal/Store.ts +4 -5
- package/src/internal/Timing.test.ts +32 -0
- package/src/internal/Timing.ts +20 -1
- package/src/internal/Tron.test-d.ts +22 -0
- package/src/internal/Tron.test.ts +94 -0
- package/src/internal/Tron.ts +289 -0
- package/src/internal/Viem.rpc.test.ts +76 -0
- package/src/internal/Viem.ts +29 -6
- package/src/internal/rewards/Read.test.ts +109 -0
- package/src/internal/rewards/Read.ts +13 -4
- package/src/internal/routes/Action.test.ts +70 -0
- package/src/internal/routes/Action.ts +76 -1
- package/src/internal/routes/Chain.test.ts +18 -0
- package/src/internal/routes/Chain.ts +5 -0
- package/src/internal/routes/DepositAddress.ts +5 -0
- package/src/internal/routes/Evidence.test.ts +64 -0
- package/src/internal/routes/Evidence.ts +11 -3
- package/src/internal/routes/EvmTransferSettlement.ts +213 -0
- package/src/internal/routes/Policy.test.ts +316 -0
- package/src/internal/routes/Policy.ts +399 -0
- package/src/internal/routes/Provider.test.ts +103 -2
- package/src/internal/routes/Provider.ts +149 -27
- package/src/internal/routes/Quota.test.ts +149 -0
- package/src/internal/routes/Quota.ts +226 -0
- package/src/internal/routes/Reconciliation.local.test.ts +285 -0
- package/src/internal/routes/Reconciliation.test.ts +371 -13
- package/src/internal/routes/Reconciliation.ts +193 -42
- package/src/internal/routes/SolanaTransferSettlement.ts +232 -0
- package/src/internal/routes/SolanaTransferSubsidy.test.ts +471 -0
- package/src/internal/routes/SolanaTransferSubsidy.ts +760 -0
- package/src/internal/routes/SourceObservation.test.ts +221 -0
- package/src/internal/routes/Subsidy.local.test.ts +46 -0
- package/src/internal/routes/Subsidy.ts +4 -2
- package/src/internal/routes/Transfer.solana.test.ts +389 -0
- package/src/internal/routes/Transfer.test.ts +130 -1
- package/src/internal/routes/Transfer.tron.test.ts +172 -0
- package/src/internal/routes/Transfer.ts +866 -8
- package/src/internal/routes/TransferReconciliation.test.ts +26 -4
- package/src/internal/routes/TransferReconciliation.ts +91 -166
- package/src/internal/routes/TransferSettlement.ts +48 -0
- package/src/internal/routes/TransferSubsidy.local.test.ts +143 -0
- package/src/internal/routes/TransferSubsidy.test.ts +34 -4
- package/src/internal/routes/TransferSubsidy.ts +87 -12
- package/src/internal/routes/TronTransferSettlement.ts +212 -0
- package/src/internal/routes/TronTransferSubsidy.test.ts +109 -0
- package/src/internal/routes/TronTransferSubsidy.ts +619 -0
- package/src/internal/routes/index.test.ts +3 -0
- package/src/internal/routes/index.ts +3 -0
- package/src/internal/routes/providers/across.ts +13 -0
- package/src/internal/routes/providers/index.test.ts +141 -0
- package/src/internal/routes/providers/legacyMesh.test.ts +484 -0
- package/src/internal/routes/providers/legacyMesh.ts +633 -0
- package/src/internal/routes/providers/legacyMeshDelivery.test.ts +306 -0
- package/src/internal/routes/providers/legacyMeshDelivery.ts +320 -0
- package/src/internal/routes/providers/legacyMeshOutbound.test.ts +401 -0
- package/src/internal/routes/providers/legacyMeshOutbound.ts +566 -0
- package/src/internal/routes/providers/legacyMeshOutboundDelivery.ts +473 -0
- package/src/internal/routes/providers/propAmm.ts +640 -0
- package/src/internal/routes/providers/relay.test.ts +1299 -18
- package/src/internal/routes/providers/relay.ts +424 -39
- package/src/internal/routes/providers/rhino.ts +14 -1
- package/src/internal/routes/providers/squid.ts +21 -0
- package/src/internal/routes/providers/stargate.test.ts +105 -1
- package/src/internal/routes/providers/stargate.ts +22 -9
- package/src/internal/routes/providers/symbiosis.ts +13 -47
- package/src/providers/index.test.ts +2 -0
- package/src/providers/index.ts +18 -0
- package/dist/admin/Access.d.ts +0 -39
- package/dist/admin/Access.d.ts.map +0 -1
- package/dist/admin/Access.js +0 -73
- package/dist/admin/Access.js.map +0 -1
- package/src/admin/Access.test.ts +0 -130
- package/src/admin/Access.ts +0 -85
package/src/App.test.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as http from 'node:http'
|
|
2
|
+
import { sql } from 'kysely'
|
|
2
3
|
import { Challenge } from 'mppx'
|
|
3
4
|
import * as Docs from 'tapimo/docs'
|
|
4
|
-
import { ApiKeys, App, Metrics, RateLimit, Store } from 'tapimo/server'
|
|
5
|
+
import { ApiKeys, App, Db, Metrics, RateLimit, Store } from 'tapimo/server'
|
|
5
6
|
import * as Tokenlist from './apps/data/routes/tokenlist.js'
|
|
6
7
|
import * as Tokens from './apps/data/routes/tokens.js'
|
|
7
8
|
import * as Organizations from './db/tables/organizations.js'
|
|
@@ -11,6 +12,82 @@ import * as Runtime from '../test/runtime.js'
|
|
|
11
12
|
import * as Tempo from '../test/Tempo.js'
|
|
12
13
|
|
|
13
14
|
describe('create', () => {
|
|
15
|
+
test('reuses a database factory within each concurrent request', async () => {
|
|
16
|
+
const databases: Db.Db[] = []
|
|
17
|
+
const source = () => {
|
|
18
|
+
const database = TestApp.database()
|
|
19
|
+
databases.push(database)
|
|
20
|
+
return database
|
|
21
|
+
}
|
|
22
|
+
type Row = { value: number }
|
|
23
|
+
const app = TestApp.create({ auth: false, db: { cached: source, source } }).get(
|
|
24
|
+
'/database-scope',
|
|
25
|
+
async (c) => {
|
|
26
|
+
const first = Db.get(c.get('db'))
|
|
27
|
+
const second = Db.get(c.get('db'))
|
|
28
|
+
const cached = Db.get(c.get('dbCached'))
|
|
29
|
+
const results = await Promise.all([
|
|
30
|
+
sql<Row>`SELECT pg_sleep(0.01), 1 AS value`.execute(first.kysely),
|
|
31
|
+
sql<Row>`SELECT 2 AS value`.execute(second.kysely),
|
|
32
|
+
sql<Row>`SELECT 3 AS value`.execute(cached.kysely),
|
|
33
|
+
])
|
|
34
|
+
return c.json(results.map((result) => result.rows.map((row) => row.value)))
|
|
35
|
+
},
|
|
36
|
+
)
|
|
37
|
+
try {
|
|
38
|
+
const responses = await Promise.all([
|
|
39
|
+
app.request('/database-scope'),
|
|
40
|
+
app.request('/database-scope'),
|
|
41
|
+
])
|
|
42
|
+
expect(await Promise.all(responses.map((response) => response.json())))
|
|
43
|
+
.toMatchInlineSnapshot(`
|
|
44
|
+
[
|
|
45
|
+
[
|
|
46
|
+
[
|
|
47
|
+
1,
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
2,
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
3,
|
|
54
|
+
],
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
[
|
|
58
|
+
1,
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
2,
|
|
62
|
+
],
|
|
63
|
+
[
|
|
64
|
+
3,
|
|
65
|
+
],
|
|
66
|
+
],
|
|
67
|
+
]
|
|
68
|
+
`)
|
|
69
|
+
expect(databases).toHaveLength(2)
|
|
70
|
+
expect(databases[0]).not.toBe(databases[1])
|
|
71
|
+
expect(
|
|
72
|
+
responses.every((response) => response.headers.get('server-timing')?.includes('db;')),
|
|
73
|
+
).toBe(true)
|
|
74
|
+
expect(
|
|
75
|
+
responses.every((response) =>
|
|
76
|
+
response.headers.get('server-timing')?.includes('db_cached;'),
|
|
77
|
+
),
|
|
78
|
+
).toBe(true)
|
|
79
|
+
expect(
|
|
80
|
+
responses.every((response) =>
|
|
81
|
+
['db_acquire', 'db_query', 'db_cached_acquire', 'db_cached_query'].every((stage) =>
|
|
82
|
+
response.headers.get('server-timing')?.includes(`${stage};`),
|
|
83
|
+
),
|
|
84
|
+
),
|
|
85
|
+
).toBe(true)
|
|
86
|
+
} finally {
|
|
87
|
+
await Promise.all(databases.map((database) => database.close()))
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
14
91
|
test('rejects duplicate provider ids', () => {
|
|
15
92
|
expect(() =>
|
|
16
93
|
TestApp.create({
|
|
@@ -144,11 +221,11 @@ describe('create', () => {
|
|
|
144
221
|
})
|
|
145
222
|
|
|
146
223
|
test('bypasses an exhausted edge limit for cached API keys on protected routes', async () => {
|
|
147
|
-
|
|
148
|
-
const rateLimit = RateLimit.memory()
|
|
224
|
+
let attempts = 0
|
|
149
225
|
const global = {
|
|
150
|
-
async limit(
|
|
151
|
-
|
|
226
|
+
async limit() {
|
|
227
|
+
attempts++
|
|
228
|
+
return { success: attempts === 1 }
|
|
152
229
|
},
|
|
153
230
|
} satisfies RateLimit.Binding
|
|
154
231
|
const app = TestApp.create({
|
|
@@ -184,11 +261,11 @@ describe('create', () => {
|
|
|
184
261
|
})
|
|
185
262
|
|
|
186
263
|
test('edge-limits repeated requests after a cached key becomes invalid', async () => {
|
|
187
|
-
|
|
188
|
-
const rateLimit = RateLimit.memory()
|
|
264
|
+
let attempts = 0
|
|
189
265
|
const global = {
|
|
190
|
-
async limit(
|
|
191
|
-
|
|
266
|
+
async limit() {
|
|
267
|
+
attempts++
|
|
268
|
+
return { success: attempts === 1 }
|
|
192
269
|
},
|
|
193
270
|
} satisfies RateLimit.Binding
|
|
194
271
|
const store = Store.memory()
|
|
@@ -208,7 +285,295 @@ describe('create', () => {
|
|
|
208
285
|
expect(throttled.headers.get('server-timing')).toContain('edge_rate_limit')
|
|
209
286
|
})
|
|
210
287
|
|
|
211
|
-
test('
|
|
288
|
+
test('isolates cold API keys from anonymous edge limits', async () => {
|
|
289
|
+
const limit = { limit: 1, period: 'minute' } satisfies RateLimit.Limit
|
|
290
|
+
const rateLimit = RateLimit.memory()
|
|
291
|
+
const ip = {
|
|
292
|
+
async limit({ key }) {
|
|
293
|
+
return { success: (await rateLimit.consume({ key, limit })).allowed }
|
|
294
|
+
},
|
|
295
|
+
} satisfies RateLimit.Binding
|
|
296
|
+
const app = TestApp.create({
|
|
297
|
+
auth: {
|
|
298
|
+
edgeRateLimit: (request, options) =>
|
|
299
|
+
RateLimit.edge(request, { ip, resolvePartition: options.resolvePartition }),
|
|
300
|
+
},
|
|
301
|
+
})
|
|
302
|
+
const headers = { 'cf-connecting-ip': '203.0.113.7' }
|
|
303
|
+
|
|
304
|
+
const allowed = await app.request('/health', { headers })
|
|
305
|
+
const anonymous = await app.request('/health', { headers })
|
|
306
|
+
const authenticated = await app.request('/v1/tokens/not-an-address', {
|
|
307
|
+
headers: { ...headers, 'tempo-api-key': TestApp.key.token },
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
expect(allowed.status).toBe(200)
|
|
311
|
+
expect(anonymous.status).toBe(429)
|
|
312
|
+
expect(authenticated.status).toBe(400)
|
|
313
|
+
expect(authenticated.headers.get('server-timing')).toContain('edge_rate_limit')
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
test('resolves cold and cached API keys without Postgres queries', async () => {
|
|
317
|
+
const queries: number[] = []
|
|
318
|
+
const db = Db.observe(TestApp.database(), { onQuery: (ms) => queries.push(ms) })
|
|
319
|
+
const app = TestApp.create({ cache: { store: Store.memory() }, db })
|
|
320
|
+
|
|
321
|
+
for (let request = 0; request < 2; request++) {
|
|
322
|
+
const response = await app.request('/v1/tokens/not-an-address', {
|
|
323
|
+
headers: { 'tempo-api-key': TestApp.key.token },
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
expect(response.status).toBe(400)
|
|
327
|
+
const stages = response.headers
|
|
328
|
+
.get('server-timing')!
|
|
329
|
+
.split(',')
|
|
330
|
+
.map((stage) => stage.trim().split(';')[0])
|
|
331
|
+
expect(stages.filter((stage) => ['auth_key', 'rate_limit', 'db'].includes(stage!)))
|
|
332
|
+
.toMatchInlineSnapshot(`
|
|
333
|
+
[
|
|
334
|
+
"auth_key",
|
|
335
|
+
"rate_limit",
|
|
336
|
+
]
|
|
337
|
+
`)
|
|
338
|
+
}
|
|
339
|
+
expect(queries).toMatchInlineSnapshot(`[]`)
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
test.each(['cold', 'cached', 'probe'])(
|
|
343
|
+
'rejects a KV-fenced key during %s resolution',
|
|
344
|
+
async (mode) => {
|
|
345
|
+
const queries: number[] = []
|
|
346
|
+
const db = Db.observe(TestApp.database(), { onQuery: (ms) => queries.push(ms) })
|
|
347
|
+
const store = Store.memory()
|
|
348
|
+
const { record, token } = await ApiKeys.mintBounded(db, store, {
|
|
349
|
+
orgId: 'org_revocation',
|
|
350
|
+
scopes: ['data:read'],
|
|
351
|
+
})
|
|
352
|
+
const limit = { limit: 1, period: 'minute' } satisfies RateLimit.Limit
|
|
353
|
+
const rateLimit = RateLimit.memory()
|
|
354
|
+
const ip = {
|
|
355
|
+
async limit({ key }) {
|
|
356
|
+
return { success: (await rateLimit.consume({ key, limit })).allowed }
|
|
357
|
+
},
|
|
358
|
+
} satisfies RateLimit.Binding
|
|
359
|
+
const app = TestApp.create({
|
|
360
|
+
auth:
|
|
361
|
+
mode === 'probe'
|
|
362
|
+
? {
|
|
363
|
+
edgeRateLimit: (request, options) =>
|
|
364
|
+
RateLimit.edge(request, { ip, resolvePartition: options.resolvePartition }),
|
|
365
|
+
}
|
|
366
|
+
: {},
|
|
367
|
+
db,
|
|
368
|
+
kv: { store },
|
|
369
|
+
})
|
|
370
|
+
const headers = { 'cf-connecting-ip': '203.0.113.7', 'tempo-api-key': token }
|
|
371
|
+
if (mode === 'cached')
|
|
372
|
+
expect((await app.request('/v1/tokens/not-an-address', { headers })).status).toBe(400)
|
|
373
|
+
if (mode === 'probe')
|
|
374
|
+
expect(
|
|
375
|
+
(await app.request('/health', { headers: { 'cf-connecting-ip': '203.0.113.7' } })).status,
|
|
376
|
+
).toBe(200)
|
|
377
|
+
await store.delete(`apikey_id:${record.id}`)
|
|
378
|
+
await ApiKeys.revokeBounded(db, store, record.id)
|
|
379
|
+
queries.length = 0
|
|
380
|
+
|
|
381
|
+
const response = await app.request('/v1/tokens/not-an-address', { headers })
|
|
382
|
+
|
|
383
|
+
expect(response.status).toBe(mode === 'probe' ? 429 : 401)
|
|
384
|
+
expect(queries).toMatchInlineSnapshot(`[]`)
|
|
385
|
+
},
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
test('keeps rotating invalid API keys in the anonymous edge limit', async () => {
|
|
389
|
+
const limit = { limit: 2, period: 'minute' } satisfies RateLimit.Limit
|
|
390
|
+
const rateLimit = RateLimit.memory()
|
|
391
|
+
const ip = {
|
|
392
|
+
async limit({ key }) {
|
|
393
|
+
return { success: (await rateLimit.consume({ key, limit })).allowed }
|
|
394
|
+
},
|
|
395
|
+
} satisfies RateLimit.Binding
|
|
396
|
+
const app = TestApp.create({
|
|
397
|
+
auth: {
|
|
398
|
+
edgeRateLimit: (request, options) =>
|
|
399
|
+
RateLimit.edge(request, { ip, resolvePartition: options.resolvePartition }),
|
|
400
|
+
},
|
|
401
|
+
})
|
|
402
|
+
const headers = { 'cf-connecting-ip': '203.0.113.7' }
|
|
403
|
+
|
|
404
|
+
const invalid = await app.request('/v1/tokens/not-an-address', {
|
|
405
|
+
headers: { ...headers, 'tempo-api-key': 'invalid-one' },
|
|
406
|
+
})
|
|
407
|
+
const rotated = await app.request('/v1/tokens/not-an-address', {
|
|
408
|
+
headers: { ...headers, 'tempo-api-key': 'invalid-two' },
|
|
409
|
+
})
|
|
410
|
+
const blocked = await app.request('/v1/tokens/not-an-address', {
|
|
411
|
+
headers: { ...headers, 'tempo-api-key': 'invalid-three' },
|
|
412
|
+
})
|
|
413
|
+
const authenticated = await app.request('/v1/tokens/not-an-address', {
|
|
414
|
+
headers: { ...headers, 'tempo-api-key': TestApp.key.token },
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
expect(invalid.status).toBe(401)
|
|
418
|
+
expect(rotated.status).toBe(401)
|
|
419
|
+
expect(blocked.status).toBe(429)
|
|
420
|
+
expect(authenticated.status).toBe(400)
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
test('does not cache a key whose isolated edge limit rejects', async () => {
|
|
424
|
+
let attempts = 0
|
|
425
|
+
const ip = {
|
|
426
|
+
async limit() {
|
|
427
|
+
attempts++
|
|
428
|
+
// Shared and partition buckets reject; the credential-probe admission
|
|
429
|
+
// bucket allows so each request exercises the uncached probe path.
|
|
430
|
+
return { success: attempts % 3 === 2 }
|
|
431
|
+
},
|
|
432
|
+
} satisfies RateLimit.Binding
|
|
433
|
+
const app = TestApp.create({
|
|
434
|
+
auth: {
|
|
435
|
+
edgeRateLimit: (request, options) =>
|
|
436
|
+
RateLimit.edge(request, { ip, resolvePartition: options.resolvePartition }),
|
|
437
|
+
},
|
|
438
|
+
})
|
|
439
|
+
const headers = {
|
|
440
|
+
'cf-connecting-ip': '203.0.113.7',
|
|
441
|
+
'tempo-api-key': TestApp.key.token,
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const first = await app.request('/v1/tokens/not-an-address', { headers })
|
|
445
|
+
const second = await app.request('/v1/tokens/not-an-address', { headers })
|
|
446
|
+
|
|
447
|
+
expect(first.status).toBe(429)
|
|
448
|
+
expect(second.status).toBe(429)
|
|
449
|
+
expect(attempts).toBe(6)
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
test('does not warm the resolution cache from concurrent credential probes', async () => {
|
|
453
|
+
const queries: number[] = []
|
|
454
|
+
const db = Db.observe(TestApp.database(), { onQuery: (ms) => queries.push(ms) })
|
|
455
|
+
const store = Store.memory()
|
|
456
|
+
const { record, token: apiKey } = await ApiKeys.mint(store, { scopes: ['data:read'] })
|
|
457
|
+
const release = Promise.withResolvers<void>()
|
|
458
|
+
const partitions: (string | undefined)[] = []
|
|
459
|
+
const app = TestApp.create({
|
|
460
|
+
auth: {
|
|
461
|
+
edgeRateLimit: async (_request, options) => {
|
|
462
|
+
partitions.push(await options.resolvePartition?.())
|
|
463
|
+
if (partitions.length === 2) {
|
|
464
|
+
// Revoke after both probes but before either request enters auth resolution.
|
|
465
|
+
await ApiKeys.revoke(store, record.id)
|
|
466
|
+
release.resolve()
|
|
467
|
+
}
|
|
468
|
+
await release.promise
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
db,
|
|
472
|
+
kv: { store },
|
|
473
|
+
})
|
|
474
|
+
const headers = { 'tempo-api-key': apiKey }
|
|
475
|
+
|
|
476
|
+
const responses = await Promise.all([
|
|
477
|
+
app.request('/v1/tokens/not-an-address', { headers }),
|
|
478
|
+
app.request('/v1/tokens/not-an-address', { headers }),
|
|
479
|
+
])
|
|
480
|
+
|
|
481
|
+
expect(partitions).toHaveLength(2)
|
|
482
|
+
expect(partitions[0]).toBeTypeOf('string')
|
|
483
|
+
expect(partitions[1]).toBe(partitions[0])
|
|
484
|
+
expect(responses.map((response) => response.status)).toMatchInlineSnapshot(`
|
|
485
|
+
[
|
|
486
|
+
401,
|
|
487
|
+
401,
|
|
488
|
+
]
|
|
489
|
+
`)
|
|
490
|
+
expect(queries).toMatchInlineSnapshot(`[]`)
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
test('keeps CLI session tokens out of API-key quota resolution', async () => {
|
|
494
|
+
const partitioned: boolean[] = []
|
|
495
|
+
const app = TestApp.create({
|
|
496
|
+
auth: {
|
|
497
|
+
edgeRateLimit: async (_request, options) => {
|
|
498
|
+
partitioned.push(options.resolvePartition !== undefined)
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
await app.request('/v1/orgs', { headers: { 'tempo-api-key': TestApp.key.token } })
|
|
504
|
+
const cli = await app.request('/v1/orgs', {
|
|
505
|
+
headers: { authorization: `Bearer tempo:cli:${'ab'.repeat(32)}` },
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
expect(partitioned).toEqual([true, false])
|
|
509
|
+
expect(cli.status).toBe(401)
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
test('records the presented credential without an edge limiter', async () => {
|
|
513
|
+
const entries: Log.Entry[] = []
|
|
514
|
+
const app = TestApp.create({ logger: (entry) => void entries.push(entry) })
|
|
515
|
+
|
|
516
|
+
const response = await app.request('/v1/not-a-route', {
|
|
517
|
+
headers: { 'tempo-api-key': TestApp.key.token },
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
expect({
|
|
521
|
+
credential: entries[0]?.credential,
|
|
522
|
+
status: response.status,
|
|
523
|
+
}).toMatchInlineSnapshot(`
|
|
524
|
+
{
|
|
525
|
+
"credential": "api_key",
|
|
526
|
+
"status": 404,
|
|
527
|
+
}
|
|
528
|
+
`)
|
|
529
|
+
})
|
|
530
|
+
|
|
531
|
+
test('attributes a request canceled during auth to its presented credential', async () => {
|
|
532
|
+
const entries: Log.Entry[] = []
|
|
533
|
+
const started = Promise.withResolvers<void>()
|
|
534
|
+
const release = Promise.withResolvers<void>()
|
|
535
|
+
const app = TestApp.create({
|
|
536
|
+
auth: {
|
|
537
|
+
edgeRateLimit: async () => {
|
|
538
|
+
started.resolve()
|
|
539
|
+
await release.promise
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
logger: (entry) => void entries.push(entry),
|
|
543
|
+
})
|
|
544
|
+
const controller = new AbortController()
|
|
545
|
+
|
|
546
|
+
const response = app.request('/v1/tokens/not-an-address', {
|
|
547
|
+
headers: { 'tempo-api-key': TestApp.key.token },
|
|
548
|
+
signal: controller.signal,
|
|
549
|
+
})
|
|
550
|
+
await started.promise
|
|
551
|
+
controller.abort()
|
|
552
|
+
const [canceled] = entries
|
|
553
|
+
release.resolve()
|
|
554
|
+
await response
|
|
555
|
+
|
|
556
|
+
expect(entries).toHaveLength(1)
|
|
557
|
+
expect({
|
|
558
|
+
credential: canceled?.credential,
|
|
559
|
+
errorCode: canceled?.errorCode,
|
|
560
|
+
pendingTimings: Object.keys(canceled?.pendingTimings ?? {}),
|
|
561
|
+
principal: canceled?.principal,
|
|
562
|
+
status: canceled?.status,
|
|
563
|
+
}).toMatchInlineSnapshot(`
|
|
564
|
+
{
|
|
565
|
+
"credential": "api_key",
|
|
566
|
+
"errorCode": "client_canceled",
|
|
567
|
+
"pendingTimings": [
|
|
568
|
+
"edge_rate_limit",
|
|
569
|
+
],
|
|
570
|
+
"principal": undefined,
|
|
571
|
+
"status": 499,
|
|
572
|
+
}
|
|
573
|
+
`)
|
|
574
|
+
})
|
|
575
|
+
|
|
576
|
+
test('applies the edge limit to invalid keys and before CORS', async () => {
|
|
212
577
|
const limit = { limit: 1, period: 'minute' } satisfies RateLimit.Limit
|
|
213
578
|
const rateLimit = RateLimit.memory()
|
|
214
579
|
const global = {
|
|
@@ -402,6 +767,27 @@ describe('create', () => {
|
|
|
402
767
|
])
|
|
403
768
|
})
|
|
404
769
|
|
|
770
|
+
test('tags openapi.json and answers a matching If-None-Match with 304', async () => {
|
|
771
|
+
const app = TestApp.create()
|
|
772
|
+
const first = await app.request('/openapi.json')
|
|
773
|
+
const etag = first.headers.get('etag')
|
|
774
|
+
expect(etag).toMatch(/^"[0-9a-f]{32}"$/)
|
|
775
|
+
expect(first.headers.get('cache-control')).toBe('no-cache')
|
|
776
|
+
expect((await app.request('/openapi.json')).headers.get('etag')).toBe(etag)
|
|
777
|
+
|
|
778
|
+
// CDNs weaken strong tags when they compress, so weak validators must match too.
|
|
779
|
+
const revalidated = await app.request('/openapi.json', {
|
|
780
|
+
headers: { 'if-none-match': `W/${etag}` },
|
|
781
|
+
})
|
|
782
|
+
expect(revalidated.status).toBe(304)
|
|
783
|
+
expect(revalidated.headers.get('etag')).toBe(etag)
|
|
784
|
+
expect(await revalidated.text()).toBe('')
|
|
785
|
+
|
|
786
|
+
const stale = await app.request('/openapi.json', { headers: { 'if-none-match': '"stale"' } })
|
|
787
|
+
expect(stale.status).toBe(200)
|
|
788
|
+
expect((await stale.json()).openapi).toBeDefined()
|
|
789
|
+
})
|
|
790
|
+
|
|
405
791
|
test('keeps standard and custom error component names distinct', async () => {
|
|
406
792
|
const spec = await (await TestApp.create().request('/openapi.json')).json()
|
|
407
793
|
const billing =
|
|
@@ -468,7 +854,7 @@ describe('create', () => {
|
|
|
468
854
|
expect((await app.request('/v1/tokens/not-an-address', { headers })).status).toBe(401)
|
|
469
855
|
})
|
|
470
856
|
|
|
471
|
-
test('rejects an attributed key after its
|
|
857
|
+
test('rejects an attributed key after its owner deletion publishes the KV fence', async () => {
|
|
472
858
|
const db = TestApp.database()
|
|
473
859
|
const store = Store.memory()
|
|
474
860
|
const organization = await Organizations.create(db, { name: 'Acme' })
|
|
@@ -480,7 +866,11 @@ describe('create', () => {
|
|
|
480
866
|
const headers = { authorization: `Bearer ${token}` }
|
|
481
867
|
|
|
482
868
|
expect((await app.request('/v1/tokens/not-an-address', { headers })).status).toBe(400)
|
|
483
|
-
expect(
|
|
869
|
+
expect(
|
|
870
|
+
await Organizations.deleteOrganization(db, organization.id, {
|
|
871
|
+
beforeCommit: () => ApiKeys.markOwnerDeleting(store, { orgId: organization.id }),
|
|
872
|
+
}),
|
|
873
|
+
).toBe(true)
|
|
484
874
|
expect((await app.request('/v1/tokens/not-an-address', { headers })).status).toBe(401)
|
|
485
875
|
})
|
|
486
876
|
|
|
@@ -510,7 +900,7 @@ describe('create', () => {
|
|
|
510
900
|
expect(rejected.status).toMatchInlineSnapshot(`401`)
|
|
511
901
|
})
|
|
512
902
|
|
|
513
|
-
test('
|
|
903
|
+
test('rejects a cached key after its KV revocation marker propagates', async () => {
|
|
514
904
|
const store = Store.memory()
|
|
515
905
|
const { record, token } = await ApiKeys.mint(store, {
|
|
516
906
|
scopes: ['data:read'],
|
|
@@ -522,12 +912,9 @@ describe('create', () => {
|
|
|
522
912
|
const authed = await app.request('/v1/tokens/not-an-address', { headers })
|
|
523
913
|
expect(authed.status).toMatchInlineSnapshot(`400`)
|
|
524
914
|
|
|
525
|
-
// The positive resolve is cached per isolate (60s by default), so the
|
|
526
|
-
// revoked key keeps authenticating until the entry expires — the
|
|
527
|
-
// documented trade-off for skipping a backend read per request.
|
|
528
915
|
expect(await ApiKeys.revoke(store, record.id)).toMatchInlineSnapshot(`true`)
|
|
529
916
|
const revoked = await app.request('/v1/tokens/not-an-address', { headers })
|
|
530
|
-
expect(revoked.status).toMatchInlineSnapshot(`
|
|
917
|
+
expect(revoked.status).toMatchInlineSnapshot(`401`)
|
|
531
918
|
})
|
|
532
919
|
|
|
533
920
|
test('applies endpoint auth overrides', async () => {
|
|
@@ -809,7 +1196,7 @@ describe('create', () => {
|
|
|
809
1196
|
{
|
|
810
1197
|
"cache": "hit",
|
|
811
1198
|
"chainId": 42431,
|
|
812
|
-
"route": "
|
|
1199
|
+
"route": "/v1/tokenlist",
|
|
813
1200
|
},
|
|
814
1201
|
]
|
|
815
1202
|
`)
|
package/src/App.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as asyncHooks from 'node:async_hooks'
|
|
1
2
|
import type { Context } from 'hono'
|
|
2
3
|
import { Hono } from 'hono'
|
|
3
4
|
import { matchedRoutes } from 'hono/route'
|
|
@@ -7,13 +8,16 @@ import { HTTPException } from 'hono/http-exception'
|
|
|
7
8
|
import { requestId, type RequestIdVariables } from 'hono/request-id'
|
|
8
9
|
import { timeout as hono_timeout } from 'hono/timeout'
|
|
9
10
|
import { generateSpecs } from 'hono-openapi'
|
|
11
|
+
import { Hash, Hex } from 'ox'
|
|
10
12
|
import type { Chain } from 'viem'
|
|
11
13
|
|
|
12
14
|
import type * as Analytics from './analytics/Analytics.js'
|
|
13
15
|
import * as ApiKey from './ApiKey.js'
|
|
14
16
|
import * as Assets from './Assets.js'
|
|
15
17
|
import * as Auth from './internal/Auth.js'
|
|
18
|
+
import * as Cache from './internal/Cache.js'
|
|
16
19
|
import * as Db from './db/Db.js'
|
|
20
|
+
import * as ExecutionContext from './internal/ExecutionContext.js'
|
|
17
21
|
import * as EdgeCache from './internal/EdgeCache.js'
|
|
18
22
|
import * as core_Email from './internal/Email.js'
|
|
19
23
|
import * as Log from './internal/Log.js'
|
|
@@ -41,6 +45,8 @@ import * as Management from './apps/management/App.js'
|
|
|
41
45
|
import * as Mpp from './apps/mpp/App.js'
|
|
42
46
|
import * as Relay from './apps/relay/App.js'
|
|
43
47
|
|
|
48
|
+
const databaseScopes = new asyncHooks.AsyncLocalStorage<Map<Db.Source, Db.Db>>()
|
|
49
|
+
|
|
44
50
|
export import data = Data.data
|
|
45
51
|
export import routes = Routes.routes
|
|
46
52
|
export import management = Management.management
|
|
@@ -328,6 +334,13 @@ export function create<const path extends string = '/'>(options: create.Options<
|
|
|
328
334
|
// Normalize the `db` option: the plain form is `{ source }` with no cached
|
|
329
335
|
// side; `cached` falls back to `source` so consumers never branch.
|
|
330
336
|
const db = 'source' in options.db ? options.db : { source: options.db }
|
|
337
|
+
// Postgres time, including Hyperdrive connect, lands in one stage per source.
|
|
338
|
+
// Wrapped once: snapshot caches key on source identity, so a per-request
|
|
339
|
+
// wrapper would defeat them. Built-in auth reads through the same source.
|
|
340
|
+
const db_observed = {
|
|
341
|
+
cached: observeSource(db.cached ?? db.source, 'db_cached'),
|
|
342
|
+
source: observeSource(db.source, 'db'),
|
|
343
|
+
}
|
|
331
344
|
|
|
332
345
|
const providers = (() => {
|
|
333
346
|
const values = options.providers ?? []
|
|
@@ -356,7 +369,7 @@ export function create<const path extends string = '/'>(options: create.Options<
|
|
|
356
369
|
const auth = Auth.install({
|
|
357
370
|
auth: options.auth,
|
|
358
371
|
basePath,
|
|
359
|
-
db:
|
|
372
|
+
db: db_observed.source,
|
|
360
373
|
email: () => email,
|
|
361
374
|
getClient,
|
|
362
375
|
kv: options.kv,
|
|
@@ -364,12 +377,13 @@ export function create<const path extends string = '/'>(options: create.Options<
|
|
|
364
377
|
})
|
|
365
378
|
|
|
366
379
|
base.use('*', Timing.middleware())
|
|
380
|
+
base.use('*', (_c, next) => databaseScopes.run(new Map(), next))
|
|
367
381
|
base.use('*', async (c, next) => {
|
|
368
382
|
c.set('analytics', analytics)
|
|
369
383
|
c.set('basePath', basePath)
|
|
370
384
|
c.set('chainId', defaultChainId)
|
|
371
|
-
c.set('db',
|
|
372
|
-
c.set('dbCached',
|
|
385
|
+
c.set('db', db_observed.source)
|
|
386
|
+
c.set('dbCached', db_observed.cached)
|
|
373
387
|
c.set('email', email)
|
|
374
388
|
c.set('getClient', (chainId) => getClient(chainId, Auth.getPrincipal(c)))
|
|
375
389
|
c.set('kv', options.kv)
|
|
@@ -377,7 +391,7 @@ export function create<const path extends string = '/'>(options: create.Options<
|
|
|
377
391
|
c.set('providers', providers)
|
|
378
392
|
c.set('rpc', options.rpc)
|
|
379
393
|
c.set('scopeCatalog', scopeCatalog)
|
|
380
|
-
c.set('store', Store.withRequest(store, c.req, { waitUntil:
|
|
394
|
+
c.set('store', Store.withRequest(store, c.req, { waitUntil: ExecutionContext.waitUntil(c) }))
|
|
381
395
|
c.set('supportedChainIds', supportedChainIds)
|
|
382
396
|
c.set('vercelOidc', options.vercelOidc)
|
|
383
397
|
c.set('zones', zones)
|
|
@@ -511,6 +525,15 @@ export function create<const path extends string = '/'>(options: create.Options<
|
|
|
511
525
|
// while `/openapi.json` and the Vocs handler start the memoized build.
|
|
512
526
|
let spec: ReturnType<typeof buildSpec> | undefined
|
|
513
527
|
const getSpec = () => (spec ??= buildSpec())
|
|
528
|
+
// The document is fixed per isolate, so serialize and tag it once; revalidating
|
|
529
|
+
// clients (the CLI loads it on every run) then cost a 304 instead of 1.5 MB.
|
|
530
|
+
type SpecDocument = { body: string; etag: string }
|
|
531
|
+
let specDocument: Promise<SpecDocument> | undefined
|
|
532
|
+
const getSpecDocument = () =>
|
|
533
|
+
(specDocument ??= getSpec().then((value) => {
|
|
534
|
+
const body = JSON.stringify(value)
|
|
535
|
+
return { body, etag: `"${Hash.sha256(Hex.fromString(body)).slice(2, 34)}"` }
|
|
536
|
+
}))
|
|
514
537
|
const buildSpec = async () => {
|
|
515
538
|
// Merge each mounted group's contributed OpenAPI metadata (tags, security
|
|
516
539
|
// schemes, webhooks block). Unused tags/schemes don't render, so a subset
|
|
@@ -634,7 +657,13 @@ export function create<const path extends string = '/'>(options: create.Options<
|
|
|
634
657
|
})
|
|
635
658
|
finalized = true
|
|
636
659
|
|
|
637
|
-
app.get('/openapi.json', async (c) =>
|
|
660
|
+
app.get('/openapi.json', async (c) => {
|
|
661
|
+
const { body, etag } = await getSpecDocument()
|
|
662
|
+
c.header('Cache-Control', 'no-cache')
|
|
663
|
+
c.header('ETag', etag)
|
|
664
|
+
if (Cache.Etag.matches(etag, c.req.header('If-None-Match'))) return c.body(null, 304)
|
|
665
|
+
return c.body(body, 200, { 'Content-Type': 'application/json' })
|
|
666
|
+
})
|
|
638
667
|
|
|
639
668
|
// The OpenRPC document is a committed build artifact (no runtime generator);
|
|
640
669
|
// see scripts/openrpc/build.ts and `pnpm openrpc:build`.
|
|
@@ -669,6 +698,23 @@ export function listener(app: { fetch: NodeServer.Fetch }): Listener {
|
|
|
669
698
|
return NodeServer.getRequestListener(app.fetch)
|
|
670
699
|
}
|
|
671
700
|
|
|
701
|
+
/** Wraps a source so each query's duration lands in the current request's `name` stage. */
|
|
702
|
+
function observeSource(source: Db.Source, name: string): Db.Source {
|
|
703
|
+
return () => {
|
|
704
|
+
// Authentication and handlers share one pool without retaining Worker connections across requests.
|
|
705
|
+
const scope = databaseScopes.getStore()
|
|
706
|
+
const database = scope?.get(source) ?? Db.get(source)
|
|
707
|
+
scope?.set(source, database)
|
|
708
|
+
return Db.observe(database, {
|
|
709
|
+
onQuery: (ms, timing) => {
|
|
710
|
+
Timing.record(name, ms)
|
|
711
|
+
Timing.record(`${name}_acquire`, timing.acquire)
|
|
712
|
+
Timing.record(`${name}_query`, timing.query)
|
|
713
|
+
},
|
|
714
|
+
})
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
672
718
|
export declare namespace create {
|
|
673
719
|
/**
|
|
674
720
|
* Options for creating the Tempo API Hono app: shared chain, RPC, database,
|
|
@@ -1228,16 +1274,6 @@ namespace ResponseBody {
|
|
|
1228
1274
|
}
|
|
1229
1275
|
}
|
|
1230
1276
|
|
|
1231
|
-
function getWaitUntil(c: { executionCtx?: { waitUntil(promise: Promise<unknown>): void } }) {
|
|
1232
|
-
// `c.executionCtx` throws in runtimes without one, so cache persistence falls back to an awaited write.
|
|
1233
|
-
try {
|
|
1234
|
-
const context = c.executionCtx
|
|
1235
|
-
return context ? context.waitUntil.bind(context) : undefined
|
|
1236
|
-
} catch {
|
|
1237
|
-
return undefined
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
1277
|
namespace NodeServer {
|
|
1242
1278
|
type GetRequestListener = (typeof import('@hono/node-server'))['getRequestListener']
|
|
1243
1279
|
export type Fetch = Parameters<GetRequestListener>[0]
|