tapimo 0.1.0 → 0.3.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 +57 -16
- package/dist/ApiKey.d.ts +4 -1
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +6 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +98 -3
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +150 -1
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +7917 -2315
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +141 -329
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +20 -4
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +23 -4
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +2 -2
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +2 -2
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +203 -120
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +111 -6
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +67 -0
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +12 -1
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/scopes.js +3 -0
- package/dist/admin/apps/scopes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +116 -116
- package/dist/admin/apps/verified-tokens.js +1 -1
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +13 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +151 -0
- package/dist/analytics/Analytics.d.ts.map +1 -0
- package/dist/analytics/Analytics.js +212 -0
- package/dist/analytics/Analytics.js.map +1 -0
- package/dist/analytics/tables/requestEvents.d.ts +215 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -0
- package/dist/analytics/tables/requestEvents.js +264 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -0
- package/dist/apps/data/App.d.ts +19576 -0
- package/dist/apps/data/App.d.ts.map +1 -0
- package/dist/apps/data/App.js +272 -0
- package/dist/apps/data/App.js.map +1 -0
- package/dist/apps/data/index.d.ts +3 -0
- package/dist/apps/data/index.d.ts.map +1 -0
- package/dist/apps/data/index.js +3 -0
- package/dist/apps/data/index.js.map +1 -0
- package/dist/apps/{activities.d.ts → data/routes/activities.d.ts} +32 -32
- package/dist/apps/{activities.d.ts.map → data/routes/activities.d.ts.map} +1 -1
- package/dist/apps/{activities.js → data/routes/activities.js} +13 -13
- package/dist/apps/data/routes/activities.js.map +1 -0
- package/dist/apps/{addresses.d.ts → data/routes/addresses.d.ts} +22 -22
- package/dist/apps/{addresses.d.ts.map → data/routes/addresses.d.ts.map} +1 -1
- package/dist/apps/{addresses.js → data/routes/addresses.js} +5 -5
- package/dist/apps/data/routes/addresses.js.map +1 -0
- package/dist/apps/{balances.d.ts → data/routes/balances.d.ts} +4 -4
- package/dist/apps/data/routes/balances.d.ts.map +1 -0
- package/dist/apps/{balances.js → data/routes/balances.js} +42 -11
- package/dist/apps/data/routes/balances.js.map +1 -0
- package/dist/apps/{blocks.d.ts → data/routes/blocks.d.ts} +47 -47
- package/dist/apps/data/routes/blocks.d.ts.map +1 -0
- package/dist/apps/{blocks.js → data/routes/blocks.js} +13 -13
- package/dist/apps/data/routes/blocks.js.map +1 -0
- package/dist/apps/{coingecko.d.ts → data/routes/coingecko.d.ts} +8 -8
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -0
- package/dist/apps/{coingecko.js → data/routes/coingecko.js} +13 -13
- package/dist/apps/data/routes/coingecko.js.map +1 -0
- package/dist/apps/{exchanges.d.ts → data/routes/exchanges.d.ts} +108 -108
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -0
- package/dist/apps/{exchanges.js → data/routes/exchanges.js} +19 -19
- package/dist/apps/data/routes/exchanges.js.map +1 -0
- package/dist/apps/{fee-amm.d.ts → data/routes/fee-amm.d.ts} +39 -39
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -0
- package/dist/apps/{fee-amm.js → data/routes/fee-amm.js} +17 -17
- package/dist/apps/data/routes/fee-amm.js.map +1 -0
- package/dist/apps/data/routes/funding.d.ts +765 -0
- package/dist/apps/data/routes/funding.d.ts.map +1 -0
- package/dist/apps/data/routes/funding.js +383 -0
- package/dist/apps/data/routes/funding.js.map +1 -0
- package/dist/apps/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
- package/dist/apps/data/routes/indexer.d.ts.map +1 -0
- package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
- package/dist/apps/data/routes/indexer.js.map +1 -0
- package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +49 -49
- package/dist/apps/data/routes/receipts.d.ts.map +1 -0
- package/dist/apps/{receipts.js → data/routes/receipts.js} +14 -20
- package/dist/apps/data/routes/receipts.js.map +1 -0
- package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +33 -40
- package/dist/apps/data/routes/rpc.d.ts.map +1 -0
- package/dist/apps/{rpc.js → data/routes/rpc.js} +35 -7
- package/dist/apps/data/routes/rpc.js.map +1 -0
- package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +40 -40
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
- package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
- package/dist/apps/data/routes/tokenlist.js.map +1 -0
- package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +468 -468
- package/dist/apps/data/routes/tokens.d.ts.map +1 -0
- package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
- package/dist/apps/data/routes/tokens.js.map +1 -0
- package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +304 -304
- package/dist/apps/data/routes/transactions.d.ts.map +1 -0
- package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
- package/dist/apps/data/routes/transactions.js.map +1 -0
- package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +62 -62
- package/dist/apps/data/routes/transfers.d.ts.map +1 -0
- package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
- package/dist/apps/data/routes/transfers.js.map +1 -0
- package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +6 -6
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
- package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
- package/dist/apps/data/routes/verified-tokens.js.map +1 -0
- package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +17 -17
- package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
- package/dist/apps/{webhooks.js → data/routes/webhooks.js} +38 -34
- package/dist/apps/data/routes/webhooks.js.map +1 -0
- package/dist/apps/docs/App.d.ts +29 -0
- package/dist/apps/docs/App.d.ts.map +1 -0
- package/dist/apps/docs/App.js +54 -0
- package/dist/apps/docs/App.js.map +1 -0
- package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
- package/dist/apps/docs/fonts.d.ts.map +1 -0
- package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
- package/dist/apps/docs/fonts.js.map +1 -0
- package/dist/apps/docs/index.d.ts +2 -0
- package/dist/apps/docs/index.d.ts.map +1 -0
- package/dist/apps/docs/index.js +2 -0
- package/dist/apps/docs/index.js.map +1 -0
- package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
- package/dist/apps/docs/logo.d.ts.map +1 -0
- package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
- package/dist/apps/docs/logo.js.map +1 -0
- package/dist/apps/docs/reference.d.ts +21 -0
- package/dist/apps/docs/reference.d.ts.map +1 -0
- package/dist/apps/docs/reference.js +112 -0
- package/dist/apps/docs/reference.js.map +1 -0
- package/dist/apps/index.d.ts +5 -0
- package/dist/apps/index.d.ts.map +1 -0
- package/dist/apps/index.js +5 -0
- package/dist/apps/index.js.map +1 -0
- package/dist/apps/mcp.d.ts +76 -0
- package/dist/apps/mcp.d.ts.map +1 -0
- package/dist/apps/mcp.js +188 -0
- package/dist/apps/mcp.js.map +1 -0
- package/dist/apps/metadata.d.ts +7 -0
- package/dist/apps/metadata.d.ts.map +1 -0
- package/dist/apps/metadata.js +15 -0
- package/dist/apps/metadata.js.map +1 -0
- package/dist/apps/platform/App.d.ts +5262 -0
- package/dist/apps/platform/App.d.ts.map +1 -0
- package/dist/apps/platform/App.js +84 -0
- package/dist/apps/platform/App.js.map +1 -0
- package/dist/apps/platform/Billing.d.ts +279 -0
- package/dist/apps/platform/Billing.d.ts.map +1 -0
- package/dist/apps/platform/Billing.js +477 -0
- package/dist/apps/platform/Billing.js.map +1 -0
- package/dist/apps/platform/index.d.ts +3 -0
- package/dist/apps/platform/index.d.ts.map +1 -0
- package/dist/apps/platform/index.js +3 -0
- package/dist/apps/platform/index.js.map +1 -0
- package/dist/apps/platform/routes/api-keys.d.ts +973 -0
- package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/platform/routes/api-keys.js +430 -0
- package/dist/apps/platform/routes/api-keys.js.map +1 -0
- package/dist/apps/platform/routes/billing.d.ts +1520 -0
- package/dist/apps/platform/routes/billing.d.ts.map +1 -0
- package/dist/apps/platform/routes/billing.js +795 -0
- package/dist/apps/platform/routes/billing.js.map +1 -0
- package/dist/apps/platform/routes/invitations.d.ts +851 -0
- package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
- package/dist/apps/platform/routes/invitations.js +471 -0
- package/dist/apps/platform/routes/invitations.js.map +1 -0
- package/dist/apps/platform/routes/me.d.ts +95 -0
- package/dist/apps/platform/routes/me.d.ts.map +1 -0
- package/dist/apps/platform/routes/me.js +81 -0
- package/dist/apps/platform/routes/me.js.map +1 -0
- package/dist/apps/platform/routes/members.d.ts +554 -0
- package/dist/apps/platform/routes/members.d.ts.map +1 -0
- package/dist/apps/platform/routes/members.js +251 -0
- package/dist/apps/platform/routes/members.js.map +1 -0
- package/dist/apps/platform/routes/orgs.d.ts +596 -0
- package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
- package/dist/apps/platform/routes/orgs.js +276 -0
- package/dist/apps/platform/routes/orgs.js.map +1 -0
- package/dist/apps/platform/routes/projects.d.ts +740 -0
- package/dist/apps/platform/routes/projects.d.ts.map +1 -0
- package/dist/apps/platform/routes/projects.js +286 -0
- package/dist/apps/platform/routes/projects.js.map +1 -0
- package/dist/apps/platform/routes/scopes.d.ts +107 -0
- package/dist/apps/platform/routes/scopes.d.ts.map +1 -0
- package/dist/apps/platform/routes/scopes.js +66 -0
- package/dist/apps/platform/routes/scopes.js.map +1 -0
- package/dist/apps/platform/routes/usage.d.ts +588 -0
- package/dist/apps/platform/routes/usage.d.ts.map +1 -0
- package/dist/apps/platform/routes/usage.js +391 -0
- package/dist/apps/platform/routes/usage.js.map +1 -0
- package/dist/apps/relay/App.d.ts +44 -0
- package/dist/apps/relay/App.d.ts.map +1 -0
- package/dist/apps/relay/App.js +211 -0
- package/dist/apps/relay/App.js.map +1 -0
- package/dist/apps/relay/Sponsorships.d.ts +107 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
- package/dist/apps/relay/Sponsorships.js +194 -0
- package/dist/apps/relay/Sponsorships.js.map +1 -0
- package/dist/apps/relay/index.d.ts +3 -0
- package/dist/apps/relay/index.d.ts.map +1 -0
- package/dist/apps/relay/index.js +3 -0
- package/dist/apps/relay/index.js.map +1 -0
- package/dist/cli/Cli.d.ts +9 -2
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +12 -4
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +5 -1
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +82 -3
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/db/Db.d.ts +17 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +254 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +159 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +187 -2
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/billingSettings.d.ts +55 -0
- package/dist/db/tables/billingSettings.d.ts.map +1 -0
- package/dist/db/tables/billingSettings.js +70 -0
- package/dist/db/tables/billingSettings.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +84 -0
- package/dist/db/tables/invitations.d.ts.map +1 -0
- package/dist/db/tables/invitations.js +165 -0
- package/dist/db/tables/invitations.js.map +1 -0
- package/dist/db/tables/memberships.d.ts +108 -0
- package/dist/db/tables/memberships.d.ts.map +1 -0
- package/dist/db/tables/memberships.js +153 -0
- package/dist/db/tables/memberships.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +48 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +97 -2
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +65 -0
- package/dist/db/tables/projects.d.ts.map +1 -0
- package/dist/db/tables/projects.js +75 -0
- package/dist/db/tables/projects.js.map +1 -0
- package/dist/db/tables/requestUsage.d.ts +121 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -0
- package/dist/db/tables/requestUsage.js +150 -0
- package/dist/db/tables/requestUsage.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +239 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
- package/dist/db/tables/sponsoredTransactions.js +314 -0
- package/dist/db/tables/sponsoredTransactions.js.map +1 -0
- package/dist/db/tables/stripeCustomers.d.ts +81 -0
- package/dist/db/tables/stripeCustomers.d.ts.map +1 -0
- package/dist/db/tables/stripeCustomers.js +120 -0
- package/dist/db/tables/stripeCustomers.js.map +1 -0
- package/dist/db/tables/users.d.ts +48 -0
- package/dist/db/tables/users.d.ts.map +1 -0
- package/dist/db/tables/users.js +65 -0
- package/dist/db/tables/users.js.map +1 -0
- package/dist/handlers/internal/executionError.d.ts.map +1 -1
- package/dist/handlers/internal/executionError.js +2 -0
- package/dist/handlers/internal/executionError.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +2 -6
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +11 -36
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +35 -2
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +53 -14
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts +10 -3
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +14 -6
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/handlers/relay.d.ts +6 -2
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +16 -2
- package/dist/handlers/relay.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +222 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +625 -74
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +4 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts +10 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +39 -8
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Fees.d.ts +27 -0
- package/dist/internal/Fees.d.ts.map +1 -0
- package/dist/internal/Fees.js +48 -0
- package/dist/internal/Fees.js.map +1 -0
- package/dist/internal/FundingRoutes.d.ts +183 -0
- package/dist/internal/FundingRoutes.d.ts.map +1 -0
- package/dist/internal/FundingRoutes.js +490 -0
- package/dist/internal/FundingRoutes.js.map +1 -0
- package/dist/internal/Id.d.ts +15 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +22 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/Log.d.ts +9 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +7 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +10 -20
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +8 -58
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +25 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +51 -0
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Schema.d.ts +8 -0
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +7 -0
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +7 -1
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +16 -2
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Viem.d.ts +84 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Webhooks.d.ts +1 -1
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +3 -3
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +33 -6
- package/src/ApiKey.ts +10 -2
- package/src/ApiKeys.test.ts +155 -1
- package/src/ApiKeys.ts +203 -1
- package/src/App.test.ts +64 -75741
- package/src/App.ts +218 -420
- package/src/Client.test-d.ts +657 -15
- package/src/Scope.ts +26 -4
- package/src/Webhooks.ts +2 -2
- package/src/admin/apps/api-keys.test.ts +51 -0
- package/src/admin/apps/api-keys.ts +84 -0
- package/src/admin/apps/scopes.test.ts +11 -1
- package/src/admin/apps/scopes.ts +3 -0
- package/src/admin/apps/verified-tokens.ts +1 -1
- package/src/admin/ui/src/components/Page.tsx +2 -3
- package/src/admin/ui/src/routes/__root.tsx +2 -2
- package/src/admin/ui/src/routes/api-keys.tsx +2 -2
- package/src/admin/ui.generated.ts +13 -13
- package/src/analytics/Analytics.test.ts +527 -0
- package/src/analytics/Analytics.ts +318 -0
- package/src/analytics/tables/requestEvents.ts +523 -0
- package/src/apps/composition.test.ts +66 -0
- package/src/apps/data/App.test.ts +72 -0
- package/src/apps/data/App.ts +330 -0
- package/src/apps/data/index.ts +2 -0
- package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
- package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
- package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
- package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +2 -2
- package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
- package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +3 -3
- package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
- package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
- package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
- package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +1 -1
- package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
- package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
- package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
- package/src/apps/data/routes/funding.test.ts +214 -0
- package/src/apps/data/routes/funding.ts +584 -0
- package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +26 -5
- package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
- package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +3 -3
- package/src/apps/{receipts.ts → data/routes/receipts.ts} +15 -22
- package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +122 -7
- package/src/apps/{rpc.ts → data/routes/rpc.ts} +38 -8
- package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +3 -3
- package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
- package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +2 -2
- package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
- package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +3 -3
- package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
- package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +2 -2
- package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
- package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +3 -3
- package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
- package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +7 -7
- package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +50 -43
- package/src/apps/docs/App.ts +65 -0
- package/src/apps/docs/index.ts +1 -0
- package/src/apps/docs/reference.ts +132 -0
- package/src/apps/index.ts +4 -0
- package/src/apps/mcp.test.ts +206 -0
- package/src/apps/mcp.ts +250 -0
- package/src/apps/metadata.ts +23 -0
- package/src/apps/platform/App.ts +169 -0
- package/src/apps/platform/Billing.test.ts +530 -0
- package/src/apps/platform/Billing.ts +682 -0
- package/src/apps/platform/index.ts +2 -0
- package/src/apps/platform/routes/api-keys.test.ts +493 -0
- package/src/apps/platform/routes/api-keys.ts +543 -0
- package/src/apps/platform/routes/billing.test.ts +1100 -0
- package/src/apps/platform/routes/billing.ts +966 -0
- package/src/apps/platform/routes/invitations.test.ts +409 -0
- package/src/apps/platform/routes/invitations.ts +587 -0
- package/src/apps/platform/routes/me.test.ts +351 -0
- package/src/apps/platform/routes/me.ts +106 -0
- package/src/apps/platform/routes/members.test.ts +195 -0
- package/src/apps/platform/routes/members.ts +313 -0
- package/src/apps/platform/routes/orgs.test.ts +313 -0
- package/src/apps/platform/routes/orgs.ts +365 -0
- package/src/apps/platform/routes/projects.test.ts +181 -0
- package/src/apps/platform/routes/projects.ts +367 -0
- package/src/apps/platform/routes/scopes.test.ts +29 -0
- package/src/apps/platform/routes/scopes.ts +85 -0
- package/src/apps/platform/routes/usage.test.ts +422 -0
- package/src/apps/platform/routes/usage.ts +527 -0
- package/src/apps/relay/App.test.ts +933 -0
- package/src/apps/relay/App.ts +236 -0
- package/src/apps/relay/Sponsorships.test.ts +375 -0
- package/src/apps/relay/Sponsorships.ts +306 -0
- package/src/apps/relay/index.ts +2 -0
- package/src/cli/Cli.test.ts +25 -2
- package/src/cli/Cli.ts +18 -3
- package/src/cli/commands/admin.test.ts +83 -0
- package/src/cli/commands/admin.ts +91 -3
- package/src/db/Db.ts +296 -0
- package/src/db/Schema.ts +241 -2
- package/src/db/tables/billingSettings.test.ts +87 -0
- package/src/db/tables/billingSettings.ts +108 -0
- package/src/db/tables/invitations.ts +198 -0
- package/src/db/tables/memberships.ts +208 -0
- package/src/db/tables/organizations.test.ts +38 -2
- package/src/db/tables/organizations.ts +117 -2
- package/src/db/tables/projects.ts +107 -0
- package/src/db/tables/requestUsage.ts +231 -0
- package/src/db/tables/sponsoredTransactions.test.ts +325 -0
- package/src/db/tables/sponsoredTransactions.ts +464 -0
- package/src/db/tables/stripeCustomers.test.ts +109 -0
- package/src/db/tables/stripeCustomers.ts +162 -0
- package/src/db/tables/users.ts +85 -0
- package/src/handlers/internal/executionError.ts +2 -0
- package/src/handlers/internal/multisig.test.ts +84 -10
- package/src/handlers/internal/multisig.ts +15 -50
- package/src/handlers/internal/sponsorship.ts +106 -20
- package/src/handlers/internal/utils.ts +19 -7
- package/src/handlers/{internal/relay.localnet.test.ts → relay.test.ts} +2 -2
- package/src/handlers/relay.ts +23 -5
- package/src/index.ts +1 -0
- package/src/internal/Auth.test.ts +491 -25
- package/src/internal/Auth.ts +839 -84
- package/src/internal/Cache.ts +5 -1
- package/src/internal/Cursor.test.ts +3 -2
- package/src/internal/EdgeCache.test.ts +27 -4
- package/src/internal/EdgeCache.ts +47 -9
- package/src/internal/Fees.test.ts +32 -0
- package/src/internal/Fees.ts +51 -0
- package/src/internal/FundingRoutes.ts +583 -0
- package/src/internal/Id.test.ts +17 -0
- package/src/internal/Id.ts +24 -0
- package/src/internal/Log.test.ts +2 -1
- package/src/internal/Log.ts +16 -3
- package/src/internal/MetricSink.ts +1 -1
- package/src/internal/OpenApi.ts +12 -60
- package/src/internal/RateLimit.test.ts +84 -0
- package/src/internal/RateLimit.ts +70 -0
- package/src/internal/Response.ts +1 -1
- package/src/internal/Schema.ts +8 -0
- package/src/internal/Store.test.ts +52 -0
- package/src/internal/Store.ts +24 -5
- package/src/internal/Tidx.local.test.ts +1 -1
- package/src/internal/VerifiedTokens.test.ts +1 -1
- package/src/internal/WebhookDestination.test.ts +1 -1
- package/src/internal/Webhooks.test.ts +7 -7
- package/src/internal/Webhooks.ts +4 -4
- package/dist/apps/activities.js.map +0 -1
- package/dist/apps/addresses.js.map +0 -1
- package/dist/apps/balances.d.ts.map +0 -1
- package/dist/apps/balances.js.map +0 -1
- package/dist/apps/blocks.d.ts.map +0 -1
- package/dist/apps/blocks.js.map +0 -1
- package/dist/apps/coingecko.d.ts.map +0 -1
- package/dist/apps/coingecko.js.map +0 -1
- package/dist/apps/exchanges.d.ts.map +0 -1
- package/dist/apps/exchanges.js.map +0 -1
- package/dist/apps/fee-amm.d.ts.map +0 -1
- package/dist/apps/fee-amm.js.map +0 -1
- package/dist/apps/indexer.d.ts.map +0 -1
- package/dist/apps/indexer.js.map +0 -1
- package/dist/apps/receipts.d.ts.map +0 -1
- package/dist/apps/receipts.js.map +0 -1
- package/dist/apps/rpc.d.ts.map +0 -1
- package/dist/apps/rpc.js.map +0 -1
- package/dist/apps/tokenlist.d.ts.map +0 -1
- package/dist/apps/tokenlist.js.map +0 -1
- package/dist/apps/tokens.d.ts.map +0 -1
- package/dist/apps/tokens.js.map +0 -1
- package/dist/apps/transactions.d.ts.map +0 -1
- package/dist/apps/transactions.js.map +0 -1
- package/dist/apps/transfers.d.ts.map +0 -1
- package/dist/apps/transfers.js.map +0 -1
- package/dist/apps/verified-tokens.d.ts.map +0 -1
- package/dist/apps/verified-tokens.js.map +0 -1
- package/dist/apps/webhooks.js.map +0 -1
- package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
- package/dist/internal/OpenApi.fonts.js.map +0 -1
- package/dist/internal/OpenApi.logo.d.ts.map +0 -1
- package/dist/internal/OpenApi.logo.js.map +0 -1
- package/src/handlers/internal/multisig.localnet.test.ts +0 -146
- /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
- /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type Db, Webhooks as Core } from 'tapimo'
|
|
2
2
|
|
|
3
|
-
import * as Tidx from '
|
|
4
|
-
import * as Viem from '
|
|
5
|
-
import * as TestApp from '
|
|
6
|
-
import * as Mppx from '
|
|
7
|
-
import * as Runtime from '
|
|
8
|
-
import * as Tempo from '
|
|
3
|
+
import * as Tidx from '../../../internal/Tidx.js'
|
|
4
|
+
import * as Viem from '../../../internal/Viem.js'
|
|
5
|
+
import * as TestApp from '../../../../test/App.js'
|
|
6
|
+
import * as Mppx from '../../../../test/Mppx.js'
|
|
7
|
+
import * as Runtime from '../../../../test/runtime.js'
|
|
8
|
+
import * as Tempo from '../../../../test/Tempo.js'
|
|
9
9
|
import * as Webhooks from './webhooks.js'
|
|
10
10
|
|
|
11
11
|
/** API key with both webhook scopes, owned by `org_test`. */
|
|
@@ -1151,7 +1151,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
1151
1151
|
// the real keyset/`toBlock` SQL and decode path end to end — no fabricated rows.
|
|
1152
1152
|
const realTidx = Tidx.getClient({
|
|
1153
1153
|
chainId: 42431,
|
|
1154
|
-
tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.
|
|
1154
|
+
tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.TIDX_BASIC_AUTH },
|
|
1155
1155
|
})
|
|
1156
1156
|
// The monitoring scanners (`log:emitted`/`block:created`/`transaction:included`)
|
|
1157
1157
|
// read the same immutable historical window over real RPC (chain 42431 →
|
|
@@ -2,20 +2,20 @@ import { type Context, Hono } from 'hono'
|
|
|
2
2
|
import { type AbiEvent, parseAbiItem } from 'viem'
|
|
3
3
|
import * as z from 'zod/mini'
|
|
4
4
|
|
|
5
|
-
import type * as App from '
|
|
6
|
-
import * as Auth from '
|
|
7
|
-
import * as Cache from '
|
|
8
|
-
import * as Cursor from '
|
|
9
|
-
import * as Db from '
|
|
10
|
-
import * as OpenApi from '
|
|
11
|
-
import * as Response from '
|
|
12
|
-
import * as Schema from '
|
|
13
|
-
import * as Store from '
|
|
14
|
-
import type * as Tidx from '
|
|
15
|
-
import * as Ttl from '
|
|
16
|
-
import * as Value from '
|
|
17
|
-
import type * as Viem from '
|
|
18
|
-
import * as Webhooks from '
|
|
5
|
+
import type * as App from '../../../App.js'
|
|
6
|
+
import * as Auth from '../../../internal/Auth.js'
|
|
7
|
+
import * as Cache from '../../../internal/Cache.js'
|
|
8
|
+
import * as Cursor from '../../../internal/Cursor.js'
|
|
9
|
+
import * as Db from '../../../db/Db.js'
|
|
10
|
+
import * as OpenApi from '../../../internal/OpenApi.js'
|
|
11
|
+
import * as Response from '../../../internal/Response.js'
|
|
12
|
+
import * as Schema from '../../../internal/Schema.js'
|
|
13
|
+
import * as Store from '../../../internal/Store.js'
|
|
14
|
+
import type * as Tidx from '../../../internal/Tidx.js'
|
|
15
|
+
import * as Ttl from '../../../internal/Ttl.js'
|
|
16
|
+
import * as Value from '../../../internal/Value.js'
|
|
17
|
+
import type * as Viem from '../../../internal/Viem.js'
|
|
18
|
+
import * as Webhooks from '../../../internal/Webhooks.js'
|
|
19
19
|
import * as Receipts from './receipts.js'
|
|
20
20
|
import * as Transactions from './transactions.js'
|
|
21
21
|
import * as Transfers from './transfers.js'
|
|
@@ -378,7 +378,7 @@ export namespace schema {
|
|
|
378
378
|
.record(z.string(), z.unknown())
|
|
379
379
|
.check(
|
|
380
380
|
z.describe(
|
|
381
|
-
'Match decoded event arguments by name (indexed or non-indexed). Requires `signature`. Each value is an exact value or
|
|
381
|
+
'Match decoded event arguments by name (indexed or non-indexed). Requires `signature`. Each value is an exact value or a super admin object.',
|
|
382
382
|
),
|
|
383
383
|
z.meta({ examples: [{ to: '0x9e39034aae71fb89f66061a2602eb6efec271754' }] }),
|
|
384
384
|
),
|
|
@@ -533,7 +533,7 @@ export namespace schema {
|
|
|
533
533
|
.string()
|
|
534
534
|
.check(
|
|
535
535
|
z.describe('Webhook subscription ID (`wh_…`).'),
|
|
536
|
-
z.meta({ examples: ['
|
|
536
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
537
537
|
),
|
|
538
538
|
lastDeliveryAt: z
|
|
539
539
|
.optional(z.iso.datetime())
|
|
@@ -594,7 +594,10 @@ export namespace schema {
|
|
|
594
594
|
),
|
|
595
595
|
id: z
|
|
596
596
|
.string()
|
|
597
|
-
.check(
|
|
597
|
+
.check(
|
|
598
|
+
z.describe('Webhook delivery ID (`whd_…`).'),
|
|
599
|
+
z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
|
|
600
|
+
),
|
|
598
601
|
requestUrl: z
|
|
599
602
|
.string()
|
|
600
603
|
.check(
|
|
@@ -620,7 +623,7 @@ export namespace schema {
|
|
|
620
623
|
.string()
|
|
621
624
|
.check(
|
|
622
625
|
z.describe('Subscription ID (`wh_…`) this delivery belongs to.'),
|
|
623
|
-
z.meta({ examples: ['
|
|
626
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
624
627
|
),
|
|
625
628
|
})
|
|
626
629
|
.check(z.describe('One attempt by Tempo to deliver an event to your webhook URL.'))
|
|
@@ -901,7 +904,7 @@ export namespace schema {
|
|
|
901
904
|
.string()
|
|
902
905
|
.check(
|
|
903
906
|
z.describe('Subscription ID (`wh_…`) that produced this delivery.'),
|
|
904
|
-
z.meta({ examples: ['
|
|
907
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
905
908
|
),
|
|
906
909
|
}
|
|
907
910
|
|
|
@@ -1075,7 +1078,7 @@ export namespace schema {
|
|
|
1075
1078
|
.string()
|
|
1076
1079
|
.check(
|
|
1077
1080
|
z.describe('Webhook subscription ID (`wh_…`).'),
|
|
1078
|
-
z.meta({ examples: ['
|
|
1081
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
1079
1082
|
),
|
|
1080
1083
|
})
|
|
1081
1084
|
.check(z.describe('Path parameters for a webhook subscription request.'))
|
|
@@ -1158,13 +1161,13 @@ export namespace schema {
|
|
|
1158
1161
|
.string()
|
|
1159
1162
|
.check(
|
|
1160
1163
|
z.describe('Delivery ID (`whd_…`) you want Tempo to replay.'),
|
|
1161
|
-
z.meta({ examples: ['
|
|
1164
|
+
z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
|
|
1162
1165
|
),
|
|
1163
1166
|
id: z
|
|
1164
1167
|
.string()
|
|
1165
1168
|
.check(
|
|
1166
1169
|
z.describe('Webhook subscription ID (`wh_…`).'),
|
|
1167
|
-
z.meta({ examples: ['
|
|
1170
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
1168
1171
|
),
|
|
1169
1172
|
})
|
|
1170
1173
|
.check(z.describe('Path parameters for retrying a webhook delivery.'))
|
|
@@ -1209,7 +1212,7 @@ export namespace schema {
|
|
|
1209
1212
|
.string()
|
|
1210
1213
|
.check(
|
|
1211
1214
|
z.describe('ID of the webhook subscription that was deleted.'),
|
|
1212
|
-
z.meta({ examples: ['
|
|
1215
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
1213
1216
|
),
|
|
1214
1217
|
})
|
|
1215
1218
|
.check(z.describe('Confirmation that the webhook subscription was deleted.'))
|
|
@@ -1225,21 +1228,25 @@ export namespace schema {
|
|
|
1225
1228
|
*/
|
|
1226
1229
|
export function webhooks(options: webhooks.Options = {}) {
|
|
1227
1230
|
const hidden = !options.enabled
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
// outbound-HTTP surface is disabled (read-only deployment).
|
|
1233
|
-
if (!c.get('webhook')) return notEnabled(c) as never
|
|
1231
|
+
// Gate the whole resource on a configured state store. Without it the
|
|
1232
|
+
// outbound-HTTP surface is disabled (read-only deployment).
|
|
1233
|
+
const gate = async (c: Context<App.Environment>, next: () => Promise<void>) => {
|
|
1234
|
+
if (!c.get('webhook')) return notEnabled(c) as never
|
|
1234
1235
|
|
|
1235
|
-
|
|
1236
|
+
await next()
|
|
1236
1237
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1238
|
+
// Subscriptions are principal-scoped, mutating, and stateful: never cache.
|
|
1239
|
+
if (!c.res.headers.has('Cache-Control')) c.res.headers.set('Cache-Control', 'no-store')
|
|
1240
|
+
return
|
|
1241
|
+
}
|
|
1242
|
+
return (
|
|
1243
|
+
new Hono<App.Environment>()
|
|
1244
|
+
// `/v1/webhooks/*` does not match the collection root, so it gets its
|
|
1245
|
+
// own registration.
|
|
1246
|
+
.use('/v1/webhooks', gate)
|
|
1247
|
+
.use('/v1/webhooks/*', gate)
|
|
1241
1248
|
.get(
|
|
1242
|
-
'/event-types',
|
|
1249
|
+
'/v1/webhooks/event-types',
|
|
1243
1250
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
1244
1251
|
OpenApi.describeRoute({
|
|
1245
1252
|
description: 'See which onchain event types Tempo can POST to your webhook URL.',
|
|
@@ -1275,7 +1282,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1275
1282
|
},
|
|
1276
1283
|
)
|
|
1277
1284
|
.post(
|
|
1278
|
-
'/',
|
|
1285
|
+
'/v1/webhooks',
|
|
1279
1286
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1280
1287
|
OpenApi.validate('json', schema.createWebhook.Body, {
|
|
1281
1288
|
code: 'body_invalid',
|
|
@@ -1338,7 +1345,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1338
1345
|
},
|
|
1339
1346
|
)
|
|
1340
1347
|
.get(
|
|
1341
|
-
'/',
|
|
1348
|
+
'/v1/webhooks',
|
|
1342
1349
|
Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
|
|
1343
1350
|
OpenApi.validate('query', schema.listWebhooks.Query, {
|
|
1344
1351
|
code: 'query_invalid',
|
|
@@ -1412,7 +1419,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1412
1419
|
// constraint, this API-key-only route's policy would be collected for the
|
|
1413
1420
|
// event-types request and override its (intentionally public) access.
|
|
1414
1421
|
.get(
|
|
1415
|
-
'/:id{wh_[A-Za-z0-9_-]+}',
|
|
1422
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
|
|
1416
1423
|
Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
|
|
1417
1424
|
OpenApi.validate('param', schema.getWebhook.Params, {
|
|
1418
1425
|
code: 'param_invalid',
|
|
@@ -1464,7 +1471,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1464
1471
|
},
|
|
1465
1472
|
)
|
|
1466
1473
|
.get(
|
|
1467
|
-
'/:id{wh_[A-Za-z0-9_-]+}/deliveries',
|
|
1474
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/deliveries',
|
|
1468
1475
|
Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
|
|
1469
1476
|
OpenApi.validate('param', schema.listWebhookDeliveries.Params, {
|
|
1470
1477
|
code: 'param_invalid',
|
|
@@ -1555,7 +1562,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1555
1562
|
},
|
|
1556
1563
|
)
|
|
1557
1564
|
.post(
|
|
1558
|
-
'/:id{wh_[A-Za-z0-9_-]+}/ping',
|
|
1565
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/ping',
|
|
1559
1566
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1560
1567
|
OpenApi.validate('param', schema.pingWebhook.Params, {
|
|
1561
1568
|
code: 'param_invalid',
|
|
@@ -1620,7 +1627,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1620
1627
|
},
|
|
1621
1628
|
)
|
|
1622
1629
|
.post(
|
|
1623
|
-
'/:id{wh_[A-Za-z0-9_-]+}/deliveries/:deliveryId/retry',
|
|
1630
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/deliveries/:deliveryId/retry',
|
|
1624
1631
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1625
1632
|
OpenApi.validate('param', schema.retryWebhookDelivery.Params, {
|
|
1626
1633
|
code: 'param_invalid',
|
|
@@ -1691,7 +1698,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1691
1698
|
},
|
|
1692
1699
|
)
|
|
1693
1700
|
.patch(
|
|
1694
|
-
'/:id{wh_[A-Za-z0-9_-]+}',
|
|
1701
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
|
|
1695
1702
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1696
1703
|
OpenApi.validate('param', schema.updateWebhook.Params, {
|
|
1697
1704
|
code: 'param_invalid',
|
|
@@ -1763,7 +1770,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1763
1770
|
},
|
|
1764
1771
|
)
|
|
1765
1772
|
.delete(
|
|
1766
|
-
'/:id{wh_[A-Za-z0-9_-]+}',
|
|
1773
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
|
|
1767
1774
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1768
1775
|
OpenApi.validate('param', schema.deleteWebhook.Params, {
|
|
1769
1776
|
code: 'param_invalid',
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Context } from 'hono'
|
|
2
|
+
import { Hono } from 'hono'
|
|
3
|
+
import type { Handler as vocs_Handler } from 'vocs/server'
|
|
4
|
+
|
|
5
|
+
import type * as App from '../../App.js'
|
|
6
|
+
import * as Metadata from '../metadata.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The docs route group: the Vocs API reference served at the app root.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { docs } from 'tapimo/docs'
|
|
13
|
+
* App.create(options).route('/', data()).route('/', platform()).route('/', docs())
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* The group registers no routes itself: it carries a reference factory (via
|
|
17
|
+
* {@link Metadata}) that `App.create` mounts on finalize, after every group and
|
|
18
|
+
* the OpenAPI/OpenRPC documents — so the reference always renders the full
|
|
19
|
+
* composed surface and its catch-all stays behind API routes, wherever the
|
|
20
|
+
* group sits in the composition chain.
|
|
21
|
+
*
|
|
22
|
+
* Lives in the `tapimo/docs` subpath (never re-exported from `tapimo/apps`) so
|
|
23
|
+
* the Vocs renderer and its multi-MB icon/font data are bundled only by
|
|
24
|
+
* deployments that actually serve docs. Even then the renderer loads lazily on
|
|
25
|
+
* the first docs request (see `reference.ts`), so API traffic and isolate
|
|
26
|
+
* startup never pay for it.
|
|
27
|
+
*/
|
|
28
|
+
export function docs(options: docs.Options = {}) {
|
|
29
|
+
return Metadata.attach(new Hono<App.Environment>(), {
|
|
30
|
+
docs: ({ spec }) => {
|
|
31
|
+
// Memoized across requests: all docs traffic shares one handler.
|
|
32
|
+
let handler: Promise<Hono> | undefined
|
|
33
|
+
return new Hono<App.Environment>().get('*', async (c, next) => {
|
|
34
|
+
handler ??= import('./reference.js').then((m) =>
|
|
35
|
+
m.create({ mount: mountFromRoutePath(c.req.routePath), spec, vocs: options }),
|
|
36
|
+
)
|
|
37
|
+
const response = await (await handler).fetch(c.req.raw, c.env, executionCtx(c))
|
|
38
|
+
// Inner 404 means "not a docs route" (`fallback: 'next'` semantics):
|
|
39
|
+
// defer to the host app's later routes / JSON `notFound`.
|
|
40
|
+
if (response.status === 404) return next()
|
|
41
|
+
return response
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export declare namespace docs {
|
|
48
|
+
/** Vocs API reference options (theme, top navigation, logo, socials, …). */
|
|
49
|
+
type Options = NonNullable<Parameters<typeof vocs_Handler.openApi>[0]['vocs']>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Derives the host mount prefix from Hono's matched `routePath` (`/api/*` → `/api`, `/*` → ``). */
|
|
53
|
+
function mountFromRoutePath(routePath: string) {
|
|
54
|
+
return routePath.replace(/\*+$/, '').replace(/\/+$/, '')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// `c.executionCtx` throws outside Workers (tests, Node); docs rendering never
|
|
58
|
+
// uses `waitUntil`, so absence is fine.
|
|
59
|
+
function executionCtx(c: Context) {
|
|
60
|
+
try {
|
|
61
|
+
return c.executionCtx
|
|
62
|
+
} catch {
|
|
63
|
+
return undefined
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { docs } from './App.js'
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Hono } from 'hono'
|
|
2
|
+
import { Handler as vocs_Handler } from 'vocs/server'
|
|
3
|
+
|
|
4
|
+
import type * as App from '../../App.js'
|
|
5
|
+
import openrpcSpec from '../../openrpc.json' with { type: 'json' }
|
|
6
|
+
import type { docs } from './App.js'
|
|
7
|
+
import { pilatFontFaces } from './fonts.js'
|
|
8
|
+
import { logoUrl } from './logo.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Builds the Vocs reference handler. Loaded via dynamic import on the first
|
|
12
|
+
* docs request (see `docs()` in `App.ts`), keeping the multi-MB renderer off
|
|
13
|
+
* isolate startup.
|
|
14
|
+
*/
|
|
15
|
+
export function create(options: create.Options): Hono {
|
|
16
|
+
const { mount, spec, vocs } = options
|
|
17
|
+
const handler = vocs_Handler.openApi(
|
|
18
|
+
{
|
|
19
|
+
// Inline the OpenRPC doc so vocs expands it without a self-subrequest
|
|
20
|
+
// (see `inlineOpenrpc`); the public `/openapi.json` keeps the URL ref.
|
|
21
|
+
spec: () => spec().then(inlineOpenrpc),
|
|
22
|
+
sidebar: { collapsed: true },
|
|
23
|
+
vocs: { logoUrl, title: 'Tempo API Reference', ...vocs },
|
|
24
|
+
},
|
|
25
|
+
{ css, fallback: 'next' },
|
|
26
|
+
)
|
|
27
|
+
if (!mount) return handler
|
|
28
|
+
// Re-mount under the host prefix so the handler's `routePath`-derived mount
|
|
29
|
+
// (asset link bases, known-route checks) matches a direct `.route()` mount.
|
|
30
|
+
return new Hono().route(mount, handler)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export declare namespace create {
|
|
34
|
+
/** Options for building the reference handler. */
|
|
35
|
+
type Options = {
|
|
36
|
+
/** Host mount prefix derived from the wrapper's matched `routePath` (`''` at root). */
|
|
37
|
+
mount: string
|
|
38
|
+
/** Memoized OpenAPI document builder — the same document served at `/openapi.json`. */
|
|
39
|
+
spec: App.create.DocsContext['spec']
|
|
40
|
+
/** Vocs reference options (theme, top navigation, logo, socials, …). */
|
|
41
|
+
vocs: docs.Options
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Custom CSS injected into the standalone reference's shell `<head>` (via
|
|
47
|
+
* `Handler.openApi(_, { css })`), after the Vocs design-system styles so it
|
|
48
|
+
* overrides them:
|
|
49
|
+
*
|
|
50
|
+
* - Page/surface backgrounds use Tempo's near-black dark palette and pure-white
|
|
51
|
+
* light palette via `light-dark(<light>, <dark>)`.
|
|
52
|
+
* - The dark border color is darkened (the light theme keeps its default).
|
|
53
|
+
* - Every corner is squared. The universal `!important` rule beats hard-coded
|
|
54
|
+
* `border-radius` values and inline styles (e.g. the Scalar playground), which
|
|
55
|
+
* overriding the radius scale variables alone would miss.
|
|
56
|
+
* - The default sans/body font is Pilat (Vocs reads `--vocs-font-family`); the
|
|
57
|
+
* webfont is embedded via {@link pilatFontFaces}. Body stays at the default
|
|
58
|
+
* weight (400); headings are pinned to 500, which renders Pilat Demi (the
|
|
59
|
+
* family has no 500 cut, so Demi covers the 500-600 range — see
|
|
60
|
+
* {@link pilatFontFaces}).
|
|
61
|
+
*/
|
|
62
|
+
const css = `${pilatFontFaces}
|
|
63
|
+
|
|
64
|
+
:root {
|
|
65
|
+
--vocs-font-family: "Pilat", Arial, Helvetica, sans-serif;
|
|
66
|
+
--vocs-background-color-primary: light-dark(#fafafa, #0a0a0a);
|
|
67
|
+
--vocs-background-color-surface: light-dark(#fff, #121212);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:is(h1, h2, h3, h4, h5, h6)[data-v] {
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Nudge the header logo a touch larger than the default max-h-7 (1.75rem). */
|
|
75
|
+
[data-v-logo-image] {
|
|
76
|
+
max-height: 2rem;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Sidebar leaf items render Regular (the nav's 450 default otherwise resolves to
|
|
80
|
+
* Demi via the 500-600 range). Group labels ([data-v-sidebar-section-header])
|
|
81
|
+
* keep their heavier weight. */
|
|
82
|
+
[data-v-sidebar-item] {
|
|
83
|
+
font-weight: 400;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
[data-vocs-theme='dark'] {
|
|
87
|
+
--vocs-color-gray4: oklch(20% 0 0);
|
|
88
|
+
--vocs-color-gray5: oklch(0.23 0 0);
|
|
89
|
+
--vocs-border-color-primary: oklch(0.25 0 0);
|
|
90
|
+
--vocs-border-color-secondary: oklch(0.25 0 0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
*,
|
|
94
|
+
*::before,
|
|
95
|
+
*::after {
|
|
96
|
+
border-radius: 0 !important;
|
|
97
|
+
}`
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Returns a shallow copy of `spec` with the JSON-RPC passthrough operation's
|
|
101
|
+
* `x-openrpc` replaced by the inline OpenRPC document, for the docs handler.
|
|
102
|
+
*
|
|
103
|
+
* Vocs expands `x-openrpc` at request time. A URL reference (as kept in the
|
|
104
|
+
* public `/openapi.json` by `App.create`'s `applyOpenrpcLink`) would make the
|
|
105
|
+
* docs worker fetch its own `/openrpc.json` — a self-subrequest that is
|
|
106
|
+
* unreliable on Cloudflare Workers and silently falls back to a single,
|
|
107
|
+
* unexpanded operation. Inlining the committed artifact keeps expansion
|
|
108
|
+
* deterministic across local and deployed environments, without bloating the
|
|
109
|
+
* public spec. Only the affected path/op are cloned; the rest of the (large)
|
|
110
|
+
* document is shared by reference.
|
|
111
|
+
*/
|
|
112
|
+
function inlineOpenrpc<spec extends { paths: Record<string, unknown> }>(spec: spec): spec {
|
|
113
|
+
const paths: Record<string, unknown> = {}
|
|
114
|
+
for (const [pathname, item] of Object.entries(spec.paths)) {
|
|
115
|
+
let next = item
|
|
116
|
+
if (isRecord(item))
|
|
117
|
+
for (const [method, op] of Object.entries(item))
|
|
118
|
+
if (isRpcOperation(op)) next = { ...item, [method]: { ...op, 'x-openrpc': openrpcSpec } }
|
|
119
|
+
paths[pathname] = next
|
|
120
|
+
}
|
|
121
|
+
return { ...spec, paths }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// The JSON-RPC passthrough's operation id, set by its route definition and
|
|
125
|
+
// targeted by `App.create`'s `applyOpenrpcLink`.
|
|
126
|
+
function isRpcOperation(op: unknown): op is Record<string, unknown> {
|
|
127
|
+
return isRecord(op) && op['operationId'] === 'rpcRequest'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
131
|
+
return !!value && typeof value === 'object' && !Array.isArray(value)
|
|
132
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { Cli as incur_Cli, z } from 'incur'
|
|
2
|
+
|
|
3
|
+
import * as TestApp from '../../test/App.js'
|
|
4
|
+
import * as Runtime from '../../test/runtime.js'
|
|
5
|
+
import { mcp } from './mcp.js'
|
|
6
|
+
|
|
7
|
+
const origin = 'https://api.tempo-api.test'
|
|
8
|
+
|
|
9
|
+
/** API key with read-only webhook scope, used to prove header forwarding. */
|
|
10
|
+
const reader = {
|
|
11
|
+
id: 'key_reader',
|
|
12
|
+
orgId: 'org_test',
|
|
13
|
+
scopes: ['webhooks:read'],
|
|
14
|
+
token: 'secret_reader',
|
|
15
|
+
} satisfies TestApp.kvStore.Key
|
|
16
|
+
|
|
17
|
+
/** Composes a test app with the MCP group mounted, dispatching in-process. */
|
|
18
|
+
function createHost(
|
|
19
|
+
options: {
|
|
20
|
+
app?: ReturnType<typeof TestApp.create> | undefined
|
|
21
|
+
docs?: mcp.Options['docs'] | undefined
|
|
22
|
+
} = {},
|
|
23
|
+
) {
|
|
24
|
+
const app = options.app ?? TestApp.create()
|
|
25
|
+
const host = mcp({ docs: options.docs ?? false, fetch: (request) => app.fetch(request) })
|
|
26
|
+
return { app, host }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Stub remote docs MCP server: an in-process incur CLI serving `/mcp`. */
|
|
30
|
+
function docsStub() {
|
|
31
|
+
const remote = incur_Cli.create('docs-remote', { version: '1.0.0' }).command('search', {
|
|
32
|
+
description: 'Search docs',
|
|
33
|
+
options: z.object({ query: z.string().describe('Search query') }),
|
|
34
|
+
run: (context) => ({ hits: [context.options.query] }),
|
|
35
|
+
})
|
|
36
|
+
return { fetch: (request: Request) => remote.fetch(request), url: 'http://docs.local/mcp' }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Anything serving `/mcp`: the group host, or a composed app it is mounted into. */
|
|
40
|
+
type Host = { fetch: (request: Request) => Response | Promise<Response> }
|
|
41
|
+
|
|
42
|
+
async function request(host: Host, body: unknown, headers: Record<string, string> = {}) {
|
|
43
|
+
const response = await host.fetch(
|
|
44
|
+
new Request(new URL('/mcp', origin), {
|
|
45
|
+
body: JSON.stringify(body),
|
|
46
|
+
headers: {
|
|
47
|
+
accept: 'application/json, text/event-stream',
|
|
48
|
+
'content-type': 'application/json',
|
|
49
|
+
...headers,
|
|
50
|
+
},
|
|
51
|
+
method: 'POST',
|
|
52
|
+
}),
|
|
53
|
+
)
|
|
54
|
+
expect(response.status).toBe(200)
|
|
55
|
+
return (await response.json()) as { result: any }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function initialize(host: Host) {
|
|
59
|
+
return request(host, {
|
|
60
|
+
id: 1,
|
|
61
|
+
jsonrpc: '2.0',
|
|
62
|
+
method: 'initialize',
|
|
63
|
+
params: {
|
|
64
|
+
capabilities: {},
|
|
65
|
+
clientInfo: { name: 'test-client', version: '1.0.0' },
|
|
66
|
+
protocolVersion: '2025-03-26',
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function toolsList(host: Host) {
|
|
72
|
+
const body = await request(host, { id: 2, jsonrpc: '2.0', method: 'tools/list', params: {} })
|
|
73
|
+
return (body.result.tools as { name: string }[]).map((tool) => tool.name)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function toolsCall(
|
|
77
|
+
host: Host,
|
|
78
|
+
name: string,
|
|
79
|
+
args: Record<string, unknown>,
|
|
80
|
+
headers: Record<string, string> = {},
|
|
81
|
+
) {
|
|
82
|
+
const body = await request(
|
|
83
|
+
host,
|
|
84
|
+
{ id: 3, jsonrpc: '2.0', method: 'tools/call', params: { arguments: args, name } },
|
|
85
|
+
headers,
|
|
86
|
+
)
|
|
87
|
+
return body.result as {
|
|
88
|
+
content: { text: string; type: string }[]
|
|
89
|
+
isError?: boolean
|
|
90
|
+
structuredContent?: Record<string, unknown>
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Parses a tool result: structured content when present, else the JSON text item. */
|
|
95
|
+
function resultJson(result: Awaited<ReturnType<typeof toolsCall>>) {
|
|
96
|
+
return result.structuredContent ?? JSON.parse(result.content[0]!.text)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
test('scopes tools to the data domain', async () => {
|
|
100
|
+
const { app, host } = createHost({ docs: docsStub() })
|
|
101
|
+
|
|
102
|
+
// The domain filter must drop paths that actually exist in the spec.
|
|
103
|
+
const spec = (await (await app.fetch(new Request(new URL('/openapi.json', origin)))).json()) as {
|
|
104
|
+
paths: Record<string, unknown>
|
|
105
|
+
}
|
|
106
|
+
expect(Object.keys(spec.paths).some((path) => path.startsWith('/gecko/'))).toBe(true)
|
|
107
|
+
expect(Object.keys(spec.paths).some((path) => path.startsWith('/v1/auth/'))).toBe(true)
|
|
108
|
+
expect(Object.keys(spec.paths).some((path) => path.startsWith('/v1/orgs'))).toBe(true)
|
|
109
|
+
|
|
110
|
+
await initialize(host)
|
|
111
|
+
const tools = await toolsList(host)
|
|
112
|
+
|
|
113
|
+
expect(tools).toContain('v1_tokens_get')
|
|
114
|
+
expect(tools).toContain('docs_search')
|
|
115
|
+
// RPC is part of the data domain tag group.
|
|
116
|
+
expect(tools.some((name) => name.startsWith('rpc'))).toBe(true)
|
|
117
|
+
// Out of domain: CoinGecko mirrors, session auth, platform, relay.
|
|
118
|
+
expect(tools.some((name) => name.startsWith('gecko_'))).toBe(false)
|
|
119
|
+
expect(tools.some((name) => name.startsWith('v1_auth_'))).toBe(false)
|
|
120
|
+
expect(tools.some((name) => name.startsWith('v1_orgs'))).toBe(false)
|
|
121
|
+
expect(tools.some((name) => name.startsWith('v1_me'))).toBe(false)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('executes generated tools against the composed app', async () => {
|
|
125
|
+
// Verified tokens are database-backed, so seed the default chain.
|
|
126
|
+
const db = TestApp.database()
|
|
127
|
+
await TestApp.verifiedSeed(db, Runtime.get().chainId)
|
|
128
|
+
const { host } = createHost({ app: TestApp.create({ db }) })
|
|
129
|
+
|
|
130
|
+
await initialize(host)
|
|
131
|
+
const result = await toolsCall(host, 'v1_tokens_get', { verified: true })
|
|
132
|
+
|
|
133
|
+
expect(result.isError).toBeFalsy()
|
|
134
|
+
const body = resultJson(result) as { data: { verified: boolean }[]; nextCursor: unknown }
|
|
135
|
+
expect(body.data.length).toBeGreaterThan(0)
|
|
136
|
+
expect(body.data.every((token) => token.verified === true)).toBe(true)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('forwards the caller Authorization header to authenticated tools', async () => {
|
|
140
|
+
const { host } = createHost({ app: TestApp.create({ auth: { keys: [reader] } }) })
|
|
141
|
+
await initialize(host)
|
|
142
|
+
|
|
143
|
+
const denied = await toolsCall(host, 'v1_webhooks_get', {})
|
|
144
|
+
expect(denied.isError).toBe(true)
|
|
145
|
+
|
|
146
|
+
const allowed = await toolsCall(
|
|
147
|
+
host,
|
|
148
|
+
'v1_webhooks_get',
|
|
149
|
+
{},
|
|
150
|
+
{ authorization: `Bearer ${reader.token}` },
|
|
151
|
+
)
|
|
152
|
+
expect(allowed.isError).toBeFalsy()
|
|
153
|
+
expect(resultJson(allowed)).toMatchObject({ data: [] })
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('proxies docs tool calls to the remote MCP source', async () => {
|
|
157
|
+
const { host } = createHost({ docs: docsStub() })
|
|
158
|
+
await initialize(host)
|
|
159
|
+
|
|
160
|
+
const result = await toolsCall(host, 'docs_search', { query: 'fees' })
|
|
161
|
+
|
|
162
|
+
expect(result.isError).toBeFalsy()
|
|
163
|
+
expect(resultJson(result)).toMatchObject({ hits: ['fees'] })
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
test('documents POST /mcp and keeps it open under auth enforcement', async () => {
|
|
167
|
+
// Worker-style composition: the group mounted into the app it dispatches to.
|
|
168
|
+
const app = TestApp.create()
|
|
169
|
+
app.route('/', mcp({ docs: false, fetch: (request) => app.fetch(request) }))
|
|
170
|
+
|
|
171
|
+
const spec = (await (await app.fetch(new Request(new URL('/openapi.json', origin)))).json()) as {
|
|
172
|
+
paths: Record<string, { post?: { operationId?: string; security?: unknown; tags?: string[] } }>
|
|
173
|
+
'x-tagGroups': { name: string; tags: string[] }[]
|
|
174
|
+
}
|
|
175
|
+
const operation = spec.paths['/mcp']?.post
|
|
176
|
+
expect(operation?.operationId).toBe('mcpRequest')
|
|
177
|
+
expect(operation?.tags).toEqual(['MCP'])
|
|
178
|
+
// Anonymous and any-valid-key access; no required scopes.
|
|
179
|
+
expect(operation?.security).toEqual([{ apiKey: [] }, { bearerAuth: [] }, {}])
|
|
180
|
+
|
|
181
|
+
// Surfaces under `Data API` in the reference, but the tool filter excludes the `MCP` tag.
|
|
182
|
+
const groups = Object.fromEntries(spec['x-tagGroups'].map((group) => [group.name, group.tags]))
|
|
183
|
+
expect(groups['MCP']).toBeUndefined()
|
|
184
|
+
expect(groups['Data API']).toContain('MCP')
|
|
185
|
+
|
|
186
|
+
// Documenting the route makes it auth-enforced; the public lane keeps it
|
|
187
|
+
// anonymously reachable, and the endpoint never surfaces itself as a tool.
|
|
188
|
+
await initialize(app)
|
|
189
|
+
const tools = await toolsList(app)
|
|
190
|
+
expect(tools.length).toBeGreaterThan(0)
|
|
191
|
+
expect(tools.some((name) => name.startsWith('mcp'))).toBe(false)
|
|
192
|
+
|
|
193
|
+
// A presented-but-invalid key is rejected at the transport.
|
|
194
|
+
const rejected = await app.fetch(
|
|
195
|
+
new Request(new URL('/mcp', origin), {
|
|
196
|
+
body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'tools/list', params: {} }),
|
|
197
|
+
headers: {
|
|
198
|
+
accept: 'application/json, text/event-stream',
|
|
199
|
+
authorization: 'Bearer not-a-key',
|
|
200
|
+
'content-type': 'application/json',
|
|
201
|
+
},
|
|
202
|
+
method: 'POST',
|
|
203
|
+
}),
|
|
204
|
+
)
|
|
205
|
+
expect(rejected.status).toBe(401)
|
|
206
|
+
})
|