tapimo 0.0.2 → 0.2.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 +38 -16
- package/dist/ApiKey.d.ts +14 -11
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +11 -12
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +207 -0
- package/dist/ApiKeys.d.ts.map +1 -0
- package/dist/ApiKeys.js +282 -0
- package/dist/ApiKeys.js.map +1 -0
- package/dist/App.d.ts +6771 -3819
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +145 -317
- package/dist/App.js.map +1 -1
- package/dist/Handler.d.ts +86 -0
- package/dist/Handler.d.ts.map +1 -0
- package/dist/Handler.js +83 -0
- package/dist/Handler.js.map +1 -0
- package/dist/Scope.d.ts +14 -4
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +16 -4
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +5 -7
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +11 -4
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/Access.d.ts +1 -3
- package/dist/admin/Access.d.ts.map +1 -1
- package/dist/admin/Access.js +1 -3
- package/dist/admin/Access.js.map +1 -1
- package/dist/admin/App.d.ts +167 -205
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +2 -4
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +105 -5
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +75 -9
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +6 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +35 -149
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +18 -39
- 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 +1 -1
- package/dist/apps/data/App.d.ts +19176 -0
- package/dist/apps/data/App.d.ts.map +1 -0
- package/dist/apps/data/App.js +236 -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} +49 -49
- 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} +183 -183
- 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} +460 -460
- 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} +94 -94
- 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/{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} +6 -6
- package/dist/apps/data/routes/receipts.d.ts.map +1 -0
- package/dist/apps/{receipts.js → data/routes/receipts.js} +12 -12
- package/dist/apps/data/routes/receipts.js.map +1 -0
- package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +4 -4
- package/dist/apps/data/routes/rpc.d.ts.map +1 -0
- package/dist/apps/{rpc.js → data/routes/rpc.js} +6 -6
- package/dist/apps/data/routes/rpc.js.map +1 -0
- package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +4 -4
- 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} +11 -11
- 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} +288 -288
- 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} +35 -35
- 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} +42 -42
- 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} +66 -63
- package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
- package/dist/apps/{webhooks.js → data/routes/webhooks.js} +67 -59
- package/dist/apps/data/routes/webhooks.js.map +1 -0
- package/dist/apps/docs/App.d.ts +27 -0
- package/dist/apps/docs/App.d.ts.map +1 -0
- package/dist/apps/docs/App.js +122 -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/index.d.ts +4 -0
- package/dist/apps/index.d.ts.map +1 -0
- package/dist/apps/index.js +4 -0
- package/dist/apps/index.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 +2985 -0
- package/dist/apps/platform/App.d.ts.map +1 -0
- package/dist/apps/platform/App.js +74 -0
- package/dist/apps/platform/App.js.map +1 -0
- package/dist/apps/platform/index.d.ts +2 -0
- package/dist/apps/platform/index.d.ts.map +1 -0
- package/dist/apps/platform/index.js +2 -0
- package/dist/apps/platform/index.js.map +1 -0
- package/dist/apps/platform/routes/api-keys.d.ts +681 -0
- package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/platform/routes/api-keys.js +328 -0
- package/dist/apps/platform/routes/api-keys.js.map +1 -0
- package/dist/apps/platform/routes/invitations.d.ts +733 -0
- package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
- package/dist/apps/platform/routes/invitations.js +413 -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 +582 -0
- package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
- package/dist/apps/platform/routes/orgs.js +265 -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/relay/App.d.ts +41 -0
- package/dist/apps/relay/App.d.ts.map +1 -0
- package/dist/apps/relay/App.js +103 -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 +193 -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.d.ts → cli/Cli.d.ts} +13 -2
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +19 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +15 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +60 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cloudflare.d.ts +7 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +9 -0
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +113 -0
- package/dist/db/Db.d.ts.map +1 -0
- package/dist/db/Db.js +402 -0
- package/dist/db/Db.js.map +1 -0
- package/dist/db/Schema.d.ts +168 -0
- package/dist/db/Schema.d.ts.map +1 -0
- package/dist/db/Schema.js +229 -0
- package/dist/db/Schema.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 +123 -0
- package/dist/db/tables/organizations.d.ts.map +1 -0
- package/dist/db/tables/organizations.js +170 -0
- package/dist/db/tables/organizations.js.map +1 -0
- 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/sponsoredTransactions.d.ts +120 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
- package/dist/db/tables/sponsoredTransactions.js +161 -0
- package/dist/db/tables/sponsoredTransactions.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/db/tables/verifiedTokens.d.ts +53 -0
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokens.js +74 -0
- package/dist/db/tables/verifiedTokens.js.map +1 -0
- package/dist/db/tables/webhookDeliveries.d.ts +71 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -0
- package/dist/db/tables/webhookDeliveries.js +119 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +158 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -0
- package/dist/db/tables/webhookSubscriptions.js +272 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -0
- package/dist/handlers/internal/executionError.d.ts +25 -0
- package/dist/handlers/internal/executionError.d.ts.map +1 -0
- package/dist/handlers/internal/executionError.js +186 -0
- package/dist/handlers/internal/executionError.js.map +1 -0
- package/dist/handlers/internal/multisig.d.ts +233 -0
- package/dist/handlers/internal/multisig.d.ts.map +1 -0
- package/dist/handlers/internal/multisig.js +542 -0
- package/dist/handlers/internal/multisig.js.map +1 -0
- package/dist/handlers/internal/requestListener.d.ts +124 -0
- package/dist/handlers/internal/requestListener.d.ts.map +1 -0
- package/dist/handlers/internal/requestListener.js +173 -0
- package/dist/handlers/internal/requestListener.js.map +1 -0
- package/dist/handlers/internal/sponsorship.d.ts +113 -0
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -0
- package/dist/handlers/internal/sponsorship.js +128 -0
- package/dist/handlers/internal/sponsorship.js.map +1 -0
- package/dist/handlers/internal/types.d.ts +284 -0
- package/dist/handlers/internal/types.d.ts.map +1 -0
- package/dist/handlers/internal/types.js +2 -0
- package/dist/handlers/internal/types.js.map +1 -0
- package/dist/handlers/internal/utils.d.ts +34 -0
- package/dist/handlers/internal/utils.d.ts.map +1 -0
- package/dist/handlers/internal/utils.js +131 -0
- package/dist/handlers/internal/utils.js.map +1 -0
- package/dist/handlers/relay.d.ts +123 -0
- package/dist/handlers/relay.d.ts.map +1 -0
- package/dist/handlers/relay.js +1278 -0
- package/dist/handlers/relay.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +224 -16
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +572 -33
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +4 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +0 -19
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +0 -57
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RpcSchema.d.ts +10 -0
- package/dist/internal/RpcSchema.d.ts.map +1 -0
- package/dist/internal/RpcSchema.js +2 -0
- package/dist/internal/RpcSchema.js.map +1 -0
- package/dist/internal/Store.d.ts +49 -4
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +81 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts +15 -34
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +115 -159
- package/dist/internal/VerifiedTokens.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 +50 -36
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +92 -205
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +37 -6
- package/src/ApiKey.test.ts +3 -3
- package/src/ApiKey.ts +11 -12
- package/src/ApiKeys.test.ts +278 -0
- package/src/ApiKeys.ts +358 -0
- package/src/App.test-d.ts +1 -1
- package/src/App.test.ts +40508 -19083
- package/src/App.ts +239 -416
- package/src/Client.test-d.ts +307 -16
- package/src/Handler.ts +154 -0
- package/src/Scope.ts +17 -4
- package/src/Webhooks.test.ts +8 -7
- package/src/Webhooks.ts +13 -7
- package/src/admin/Access.ts +1 -3
- package/src/admin/App.ts +19 -24
- package/src/admin/apps/api-keys.test.ts +70 -18
- package/src/admin/apps/api-keys.ts +92 -9
- package/src/admin/apps/scopes.test.ts +8 -0
- package/src/admin/apps/verified-tokens.test.ts +3 -30
- package/src/admin/apps/verified-tokens.ts +18 -37
- package/src/admin/ui.generated.ts +1 -1
- package/src/apps/composition.test.ts +66 -0
- package/src/apps/data/App.ts +295 -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} +6 -5
- package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
- package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +4 -4
- 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} +2 -2
- 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/{indexer.test.ts → data/routes/indexer.test.ts} +27 -6
- package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
- package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +4 -4
- package/src/apps/{receipts.ts → data/routes/receipts.ts} +13 -13
- package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +142 -13
- package/src/apps/{rpc.ts → data/routes/rpc.ts} +7 -7
- package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +8 -10
- package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
- package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +6 -5
- package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
- package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +4 -4
- package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
- package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +3 -3
- package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
- package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +27 -15
- package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
- package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +137 -150
- package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +83 -81
- package/src/apps/docs/App.ts +136 -0
- package/src/apps/docs/index.ts +1 -0
- package/src/apps/index.ts +3 -0
- package/src/apps/metadata.ts +23 -0
- package/src/apps/platform/App.ts +130 -0
- package/src/apps/platform/index.ts +1 -0
- package/src/apps/platform/routes/api-keys.test.ts +330 -0
- package/src/apps/platform/routes/api-keys.ts +427 -0
- package/src/apps/platform/routes/invitations.test.ts +361 -0
- package/src/apps/platform/routes/invitations.ts +519 -0
- package/src/apps/platform/routes/me.test.ts +121 -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 +343 -0
- package/src/apps/platform/routes/projects.test.ts +181 -0
- package/src/apps/platform/routes/projects.ts +367 -0
- package/src/apps/relay/App.test.ts +484 -0
- package/src/apps/relay/App.ts +128 -0
- package/src/apps/relay/Sponsorships.test.ts +375 -0
- package/src/apps/relay/Sponsorships.ts +305 -0
- package/src/apps/relay/index.ts +2 -0
- package/src/{Cli.test.ts → cli/Cli.test.ts} +10 -9
- package/src/{Cli.ts → cli/Cli.ts} +16 -9
- package/src/cli/bin.ts +4 -0
- package/src/cli/commands/admin.test.ts +71 -0
- package/src/cli/commands/admin.ts +60 -0
- package/src/cloudflare.ts +10 -0
- package/src/db/Db.test.ts +84 -0
- package/src/db/Db.ts +542 -0
- package/src/db/Schema.ts +301 -0
- package/src/db/tables/invitations.ts +198 -0
- package/src/db/tables/memberships.ts +208 -0
- package/src/db/tables/organizations.test.ts +160 -0
- package/src/db/tables/organizations.ts +232 -0
- package/src/db/tables/projects.ts +107 -0
- package/src/db/tables/sponsoredTransactions.test.ts +218 -0
- package/src/db/tables/sponsoredTransactions.ts +236 -0
- package/src/db/tables/users.ts +85 -0
- package/src/db/tables/verifiedTokens.ts +111 -0
- package/src/db/tables/webhookDeliveries.ts +159 -0
- package/src/db/tables/webhookSubscriptions.ts +358 -0
- package/src/handlers/internal/executionError.ts +207 -0
- package/src/handlers/internal/multisig.test.ts +818 -0
- package/src/handlers/internal/multisig.ts +823 -0
- package/src/handlers/internal/requestListener.ts +273 -0
- package/src/handlers/internal/sponsorship.ts +245 -0
- package/src/handlers/internal/types.ts +378 -0
- package/src/handlers/internal/utils.ts +153 -0
- package/src/handlers/relay.test.ts +2035 -0
- package/src/handlers/relay.ts +1623 -0
- package/src/index.ts +4 -2
- package/src/internal/Auth.test.ts +337 -21
- package/src/internal/Auth.ts +783 -44
- package/src/internal/Cursor.test.ts +3 -2
- package/src/internal/Log.test.ts +1 -1
- package/src/internal/Log.ts +11 -3
- package/src/internal/MetricSink.ts +1 -1
- package/src/internal/OpenApi.ts +0 -59
- package/src/internal/RateLimit.test.ts +1 -1
- package/src/internal/RpcSchema.ts +10 -0
- package/src/internal/Store.test.ts +150 -10
- package/src/internal/Store.ts +136 -11
- package/src/internal/Tidx.local.test.ts +1 -1
- package/src/internal/VerifiedTokens.test.ts +99 -115
- package/src/internal/VerifiedTokens.ts +123 -175
- package/src/internal/WebhookDestination.test.ts +1 -1
- package/src/internal/Webhooks.test.ts +111 -111
- package/src/internal/Webhooks.ts +103 -221
- package/dist/ApiKeySource.d.ts +0 -166
- package/dist/ApiKeySource.d.ts.map +0 -1
- package/dist/ApiKeySource.js +0 -234
- package/dist/ApiKeySource.js.map +0 -1
- package/dist/Cli.d.ts.map +0 -1
- package/dist/Cli.js +0 -13
- package/dist/Cli.js.map +0 -1
- 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/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/31318/verified-tokens.json +0 -30
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +0 -4
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +0 -30
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +0 -11
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +0 -1
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +0 -5
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +0 -177
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +0 -1
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +0 -1
- package/seeds/42431/verified-tokens.json +0 -44
- package/seeds/openrpc/README.md +0 -27
- package/seeds/openrpc/execution-apis.json +0 -8989
- package/src/ApiKeySource.test-d.ts +0 -11
- package/src/ApiKeySource.test.ts +0 -295
- package/src/ApiKeySource.ts +0 -303
- /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
- /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
|
@@ -2,19 +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
|
|
10
|
-
import * as
|
|
11
|
-
import * as
|
|
12
|
-
import * as
|
|
13
|
-
import
|
|
14
|
-
import * as
|
|
15
|
-
import * as
|
|
16
|
-
import
|
|
17
|
-
import * as
|
|
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'
|
|
18
19
|
import * as Receipts from './receipts.js'
|
|
19
20
|
import * as Transactions from './transactions.js'
|
|
20
21
|
import * as Transfers from './transfers.js'
|
|
@@ -377,7 +378,7 @@ export namespace schema {
|
|
|
377
378
|
.record(z.string(), z.unknown())
|
|
378
379
|
.check(
|
|
379
380
|
z.describe(
|
|
380
|
-
'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.',
|
|
381
382
|
),
|
|
382
383
|
z.meta({ examples: [{ to: '0x9e39034aae71fb89f66061a2602eb6efec271754' }] }),
|
|
383
384
|
),
|
|
@@ -1224,21 +1225,25 @@ export namespace schema {
|
|
|
1224
1225
|
*/
|
|
1225
1226
|
export function webhooks(options: webhooks.Options = {}) {
|
|
1226
1227
|
const hidden = !options.enabled
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
// outbound-HTTP surface is disabled (read-only deployment).
|
|
1232
|
-
if (!c.get('webhook')) return notEnabled(c) as never
|
|
1228
|
+
// Gate the whole resource on a configured state store. Without it the
|
|
1229
|
+
// outbound-HTTP surface is disabled (read-only deployment).
|
|
1230
|
+
const gate = async (c: Context<App.Environment>, next: () => Promise<void>) => {
|
|
1231
|
+
if (!c.get('webhook')) return notEnabled(c) as never
|
|
1233
1232
|
|
|
1234
|
-
|
|
1233
|
+
await next()
|
|
1235
1234
|
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1235
|
+
// Subscriptions are principal-scoped, mutating, and stateful: never cache.
|
|
1236
|
+
if (!c.res.headers.has('Cache-Control')) c.res.headers.set('Cache-Control', 'no-store')
|
|
1237
|
+
return
|
|
1238
|
+
}
|
|
1239
|
+
return (
|
|
1240
|
+
new Hono<App.Environment>()
|
|
1241
|
+
// `/v1/webhooks/*` does not match the collection root, so it gets its
|
|
1242
|
+
// own registration.
|
|
1243
|
+
.use('/v1/webhooks', gate)
|
|
1244
|
+
.use('/v1/webhooks/*', gate)
|
|
1240
1245
|
.get(
|
|
1241
|
-
'/event-types',
|
|
1246
|
+
'/v1/webhooks/event-types',
|
|
1242
1247
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
1243
1248
|
OpenApi.describeRoute({
|
|
1244
1249
|
description: 'See which onchain event types Tempo can POST to your webhook URL.',
|
|
@@ -1274,7 +1279,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1274
1279
|
},
|
|
1275
1280
|
)
|
|
1276
1281
|
.post(
|
|
1277
|
-
'/',
|
|
1282
|
+
'/v1/webhooks',
|
|
1278
1283
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1279
1284
|
OpenApi.validate('json', schema.createWebhook.Body, {
|
|
1280
1285
|
code: 'body_invalid',
|
|
@@ -1306,7 +1311,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1306
1311
|
})
|
|
1307
1312
|
|
|
1308
1313
|
const webhook = c.get('webhook')!
|
|
1309
|
-
const
|
|
1314
|
+
const db = Db.get(c.get('db'))
|
|
1310
1315
|
const owner = ownerFor(c)
|
|
1311
1316
|
if (!owner) return unauthorized(c)
|
|
1312
1317
|
|
|
@@ -1315,7 +1320,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1315
1320
|
|
|
1316
1321
|
try {
|
|
1317
1322
|
const subscription = await Webhooks.createSubscription(
|
|
1318
|
-
|
|
1323
|
+
db,
|
|
1319
1324
|
{
|
|
1320
1325
|
chainId,
|
|
1321
1326
|
...(body.context === undefined ? {} : { context: body.context }),
|
|
@@ -1337,7 +1342,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1337
1342
|
},
|
|
1338
1343
|
)
|
|
1339
1344
|
.get(
|
|
1340
|
-
'/',
|
|
1345
|
+
'/v1/webhooks',
|
|
1341
1346
|
Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
|
|
1342
1347
|
OpenApi.validate('query', schema.listWebhooks.Query, {
|
|
1343
1348
|
code: 'query_invalid',
|
|
@@ -1365,7 +1370,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1365
1370
|
message: 'Check the query parameters and try again.',
|
|
1366
1371
|
})
|
|
1367
1372
|
|
|
1368
|
-
const
|
|
1373
|
+
const db = Db.get(c.get('db'))
|
|
1369
1374
|
const owner = ownerFor(c)
|
|
1370
1375
|
if (!owner) return unauthorized(c)
|
|
1371
1376
|
|
|
@@ -1375,12 +1380,12 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1375
1380
|
// run it concurrently with the page list. Best-effort: a failure
|
|
1376
1381
|
// omits `meta` rather than failing the page.
|
|
1377
1382
|
const countPromise = include.includes('totalCount')
|
|
1378
|
-
? Webhooks.countSubscriptions(
|
|
1383
|
+
? Webhooks.countSubscriptions(db, owner).catch(() => undefined)
|
|
1379
1384
|
: undefined
|
|
1380
1385
|
|
|
1381
1386
|
// Fetch one extra to detect a further page without a second round-trip.
|
|
1382
1387
|
// `page` translates to a positional slice of `(page - 1) * limit` rows.
|
|
1383
|
-
const rows = await Webhooks.listSubscriptions(
|
|
1388
|
+
const rows = await Webhooks.listSubscriptions(db, owner, {
|
|
1384
1389
|
cursor,
|
|
1385
1390
|
limit: limit + 1,
|
|
1386
1391
|
offset: page !== undefined && page > 1 ? (page - 1) * limit : undefined,
|
|
@@ -1411,7 +1416,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1411
1416
|
// constraint, this API-key-only route's policy would be collected for the
|
|
1412
1417
|
// event-types request and override its (intentionally public) access.
|
|
1413
1418
|
.get(
|
|
1414
|
-
'/:id{wh_[A-Za-z0-9_-]+}',
|
|
1419
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
|
|
1415
1420
|
Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
|
|
1416
1421
|
OpenApi.validate('param', schema.getWebhook.Params, {
|
|
1417
1422
|
code: 'param_invalid',
|
|
@@ -1445,13 +1450,13 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1445
1450
|
message: 'Check the path parameters and try again.',
|
|
1446
1451
|
})
|
|
1447
1452
|
|
|
1448
|
-
const
|
|
1453
|
+
const db = Db.get(c.get('db'))
|
|
1449
1454
|
const owner = ownerFor(c)
|
|
1450
1455
|
if (!owner) return unauthorized(c)
|
|
1451
1456
|
|
|
1452
1457
|
const { id } = c.req.valid('param')
|
|
1453
1458
|
try {
|
|
1454
|
-
const subscription = await Webhooks.getSubscription(
|
|
1459
|
+
const subscription = await Webhooks.getSubscription(db, owner, id)
|
|
1455
1460
|
if (!subscription) return notFound(c)
|
|
1456
1461
|
return c.json(
|
|
1457
1462
|
Response.validated(schema.getWebhook.Response, toPublic(subscription)),
|
|
@@ -1463,7 +1468,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1463
1468
|
},
|
|
1464
1469
|
)
|
|
1465
1470
|
.get(
|
|
1466
|
-
'/:id{wh_[A-Za-z0-9_-]+}/deliveries',
|
|
1471
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/deliveries',
|
|
1467
1472
|
Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
|
|
1468
1473
|
OpenApi.validate('param', schema.listWebhookDeliveries.Params, {
|
|
1469
1474
|
code: 'param_invalid',
|
|
@@ -1506,7 +1511,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1506
1511
|
message: 'Check the query parameters and try again.',
|
|
1507
1512
|
})
|
|
1508
1513
|
|
|
1509
|
-
const
|
|
1514
|
+
const db = Db.get(c.get('db'))
|
|
1510
1515
|
const owner = ownerFor(c)
|
|
1511
1516
|
if (!owner) return unauthorized(c)
|
|
1512
1517
|
|
|
@@ -1515,19 +1520,19 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1515
1520
|
try {
|
|
1516
1521
|
// Owner-scope first: resolving the subscription under the caller's owner
|
|
1517
1522
|
// key 404s ids they don't own (indistinguishable from "doesn't exist").
|
|
1518
|
-
const subscription = await Webhooks.getSubscription(
|
|
1523
|
+
const subscription = await Webhooks.getSubscription(db, owner, id)
|
|
1519
1524
|
if (!subscription) return notFound(c)
|
|
1520
1525
|
|
|
1521
1526
|
// `totalCount` is opt-in and exact (the delivery log is TTL-bounded);
|
|
1522
1527
|
// run it concurrently with the page list. Best-effort: a failure
|
|
1523
1528
|
// omits `meta` rather than failing the page.
|
|
1524
1529
|
const countPromise = include.includes('totalCount')
|
|
1525
|
-
? Webhooks.countDeliveries(
|
|
1530
|
+
? Webhooks.countDeliveries(db, id).catch(() => undefined)
|
|
1526
1531
|
: undefined
|
|
1527
1532
|
|
|
1528
1533
|
// Fetch one extra to detect a further page without a second round-trip.
|
|
1529
1534
|
// `page` translates to a positional slice of `(page - 1) * limit` rows.
|
|
1530
|
-
const rows = await Webhooks.listDeliveries(
|
|
1535
|
+
const rows = await Webhooks.listDeliveries(db, id, {
|
|
1531
1536
|
cursor,
|
|
1532
1537
|
limit: limit + 1,
|
|
1533
1538
|
offset: page !== undefined && page > 1 ? (page - 1) * limit : undefined,
|
|
@@ -1554,7 +1559,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1554
1559
|
},
|
|
1555
1560
|
)
|
|
1556
1561
|
.post(
|
|
1557
|
-
'/:id{wh_[A-Za-z0-9_-]+}/ping',
|
|
1562
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/ping',
|
|
1558
1563
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1559
1564
|
OpenApi.validate('param', schema.pingWebhook.Params, {
|
|
1560
1565
|
code: 'param_invalid',
|
|
@@ -1589,20 +1594,20 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1589
1594
|
message: 'Check the path parameters and try again.',
|
|
1590
1595
|
})
|
|
1591
1596
|
|
|
1592
|
-
const
|
|
1597
|
+
const db = Db.get(c.get('db'))
|
|
1593
1598
|
const owner = ownerFor(c)
|
|
1594
1599
|
if (!owner) return unauthorized(c)
|
|
1595
1600
|
|
|
1596
1601
|
const { id } = c.req.valid('param')
|
|
1597
1602
|
try {
|
|
1598
1603
|
// Owner-scope first so unowned/unknown ids are indistinguishable (404).
|
|
1599
|
-
const subscription = await Webhooks.getSubscription(
|
|
1604
|
+
const subscription = await Webhooks.getSubscription(db, owner, id)
|
|
1600
1605
|
if (!subscription) return notFound(c)
|
|
1601
1606
|
|
|
1602
1607
|
// Inline delivery (not the queue) so the caller gets an immediate
|
|
1603
1608
|
// result. `ping` never mutates the subscription's failure/lifecycle
|
|
1604
1609
|
// state — a test must not disable a healthy endpoint.
|
|
1605
|
-
const { envelope, result } = await Webhooks.ping(
|
|
1610
|
+
const { envelope, result } = await Webhooks.ping(db, subscription)
|
|
1606
1611
|
return c.json(
|
|
1607
1612
|
Response.validated(schema.pingWebhook.Response, {
|
|
1608
1613
|
delivered: result.ok,
|
|
@@ -1619,7 +1624,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1619
1624
|
},
|
|
1620
1625
|
)
|
|
1621
1626
|
.post(
|
|
1622
|
-
'/:id{wh_[A-Za-z0-9_-]+}/deliveries/:deliveryId/retry',
|
|
1627
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/deliveries/:deliveryId/retry',
|
|
1623
1628
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1624
1629
|
OpenApi.validate('param', schema.retryWebhookDelivery.Params, {
|
|
1625
1630
|
code: 'param_invalid',
|
|
@@ -1653,17 +1658,17 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1653
1658
|
message: 'Check the path parameters and try again.',
|
|
1654
1659
|
})
|
|
1655
1660
|
|
|
1656
|
-
const
|
|
1661
|
+
const db = Db.get(c.get('db'))
|
|
1657
1662
|
const owner = ownerFor(c)
|
|
1658
1663
|
if (!owner) return unauthorized(c)
|
|
1659
1664
|
|
|
1660
1665
|
const { deliveryId, id } = c.req.valid('param')
|
|
1661
1666
|
try {
|
|
1662
1667
|
// Owner-scope the subscription first so unowned ids 404 like elsewhere.
|
|
1663
|
-
const subscription = await Webhooks.getSubscription(
|
|
1668
|
+
const subscription = await Webhooks.getSubscription(db, owner, id)
|
|
1664
1669
|
if (!subscription) return notFound(c)
|
|
1665
1670
|
|
|
1666
|
-
const delivery = await Webhooks.getDelivery(
|
|
1671
|
+
const delivery = await Webhooks.getDelivery(db, id, deliveryId)
|
|
1667
1672
|
if (!delivery)
|
|
1668
1673
|
return Response.error(c, {
|
|
1669
1674
|
code: 'delivery_not_found',
|
|
@@ -1673,7 +1678,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1673
1678
|
|
|
1674
1679
|
// Replay the exact persisted envelope inline. Unlike `ping`, this is a
|
|
1675
1680
|
// real event, so the outcome updates the subscription's failure state.
|
|
1676
|
-
const result = await Webhooks.deliverAndRecord(
|
|
1681
|
+
const result = await Webhooks.deliverAndRecord(db, subscription, delivery.envelope)
|
|
1677
1682
|
return c.json(
|
|
1678
1683
|
Response.validated(schema.retryWebhookDelivery.Response, {
|
|
1679
1684
|
delivered: result.ok,
|
|
@@ -1690,7 +1695,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1690
1695
|
},
|
|
1691
1696
|
)
|
|
1692
1697
|
.patch(
|
|
1693
|
-
'/:id{wh_[A-Za-z0-9_-]+}',
|
|
1698
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
|
|
1694
1699
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1695
1700
|
OpenApi.validate('param', schema.updateWebhook.Params, {
|
|
1696
1701
|
code: 'param_invalid',
|
|
@@ -1733,7 +1738,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1733
1738
|
message: 'Check the request body and try again.',
|
|
1734
1739
|
})
|
|
1735
1740
|
|
|
1736
|
-
const
|
|
1741
|
+
const db = Db.get(c.get('db'))
|
|
1737
1742
|
const owner = ownerFor(c)
|
|
1738
1743
|
if (!owner) return unauthorized(c)
|
|
1739
1744
|
|
|
@@ -1746,11 +1751,11 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1746
1751
|
// persisting — otherwise a bad filter would silently widen the match
|
|
1747
1752
|
// set at scan time.
|
|
1748
1753
|
if (patch.filters !== undefined) {
|
|
1749
|
-
const existing = await Webhooks.getSubscription(
|
|
1754
|
+
const existing = await Webhooks.getSubscription(db, owner, id)
|
|
1750
1755
|
if (!existing) return notFound(c)
|
|
1751
1756
|
parseFilters(existing.eventType, patch.filters)
|
|
1752
1757
|
}
|
|
1753
|
-
const subscription = await Webhooks.updateSubscription(
|
|
1758
|
+
const subscription = await Webhooks.updateSubscription(db, owner, id, patch)
|
|
1754
1759
|
if (!subscription) return notFound(c)
|
|
1755
1760
|
return c.json(
|
|
1756
1761
|
Response.validated(schema.updateWebhook.Response, toPublic(subscription)),
|
|
@@ -1762,7 +1767,7 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1762
1767
|
},
|
|
1763
1768
|
)
|
|
1764
1769
|
.delete(
|
|
1765
|
-
'/:id{wh_[A-Za-z0-9_-]+}',
|
|
1770
|
+
'/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
|
|
1766
1771
|
Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
|
|
1767
1772
|
OpenApi.validate('param', schema.deleteWebhook.Params, {
|
|
1768
1773
|
code: 'param_invalid',
|
|
@@ -1796,13 +1801,13 @@ export function webhooks(options: webhooks.Options = {}) {
|
|
|
1796
1801
|
message: 'Check the path parameters and try again.',
|
|
1797
1802
|
})
|
|
1798
1803
|
|
|
1799
|
-
const
|
|
1804
|
+
const db = Db.get(c.get('db'))
|
|
1800
1805
|
const owner = ownerFor(c)
|
|
1801
1806
|
if (!owner) return unauthorized(c)
|
|
1802
1807
|
|
|
1803
1808
|
const { id } = c.req.valid('param')
|
|
1804
1809
|
try {
|
|
1805
|
-
const deleted = await Webhooks.deleteSubscription(
|
|
1810
|
+
const deleted = await Webhooks.deleteSubscription(db, owner, id)
|
|
1806
1811
|
if (!deleted) return notFound(c)
|
|
1807
1812
|
return c.json(Response.validated(schema.deleteWebhook.Response, { id }), 200)
|
|
1808
1813
|
} catch (cause) {
|
|
@@ -1874,12 +1879,13 @@ type ScanPage = {
|
|
|
1874
1879
|
export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
1875
1880
|
const {
|
|
1876
1881
|
batchSize = 100,
|
|
1882
|
+
cache: cache_metadata = Store.memory(),
|
|
1877
1883
|
chainId,
|
|
1878
1884
|
client,
|
|
1879
1885
|
confirmations = 2,
|
|
1886
|
+
db,
|
|
1880
1887
|
eventTypes = ['token:transfer', 'transaction:included', 'log:emitted', 'block:created'],
|
|
1881
1888
|
maxBlocks = 1_000,
|
|
1882
|
-
store,
|
|
1883
1889
|
tidx,
|
|
1884
1890
|
} = options
|
|
1885
1891
|
const now = options.now ?? (() => new Date())
|
|
@@ -1888,7 +1894,7 @@ export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
|
1888
1894
|
// Queue producer instead and the consumer runs `deliverAndRecord`.
|
|
1889
1895
|
const dispatch =
|
|
1890
1896
|
options.dispatch ??
|
|
1891
|
-
(({ envelope, subscription }) => Webhooks.deliverAndRecord(
|
|
1897
|
+
(({ envelope, subscription }) => Webhooks.deliverAndRecord(db, subscription, envelope))
|
|
1892
1898
|
|
|
1893
1899
|
// Head resolution is lazy and per-source. RPC types work back from the live
|
|
1894
1900
|
// RPC head; the legacy TIDX types from the indexed head (never ahead of the
|
|
@@ -1901,6 +1907,9 @@ export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
|
1901
1907
|
(tidxHead ??= tidx ? await getIndexedHead(tidx, chainId) : await resolveRpcHead())
|
|
1902
1908
|
|
|
1903
1909
|
const rpcSafeBlock = Math.max(0, (await resolveRpcHead()) - confirmations)
|
|
1910
|
+
// Reclaim expired rows (MPP-owned subscriptions, aged delivery logs) once
|
|
1911
|
+
// per tick; reads filter expiry at query time, so this is hygiene only.
|
|
1912
|
+
await Webhooks.pruneExpired(db, { now }).catch(() => {})
|
|
1904
1913
|
// Per-tick lazy cache so multiple subscriptions of the same/related types
|
|
1905
1914
|
// share fetched blocks and receipts instead of refetching the same window.
|
|
1906
1915
|
const cache = createChainCache(client)
|
|
@@ -1916,19 +1925,15 @@ export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
|
1916
1925
|
for (const eventType of eventTypes) {
|
|
1917
1926
|
const legacy = eventType === 'token:transfer'
|
|
1918
1927
|
const safeBlock = legacy ? Math.max(0, (await resolveTidxHead()) - confirmations) : rpcSafeBlock
|
|
1919
|
-
const subscriptions = await Webhooks.listActive(
|
|
1928
|
+
const subscriptions = await Webhooks.listActive(db, chainId, eventType)
|
|
1920
1929
|
for (const subscription of subscriptions) {
|
|
1921
1930
|
result.subscriptions++
|
|
1922
|
-
const cursor = await Webhooks.getCursor(
|
|
1931
|
+
const cursor = await Webhooks.getCursor(db, subscription.id)
|
|
1923
1932
|
if (cursor === null) {
|
|
1924
1933
|
// First time we've seen this subscription: anchor it at the head of the
|
|
1925
1934
|
// confirmed window so we never backfill from genesis. Events start
|
|
1926
1935
|
// flowing from the next tick onward.
|
|
1927
|
-
await Webhooks.setCursor(
|
|
1928
|
-
store,
|
|
1929
|
-
subscription.id,
|
|
1930
|
-
Cursor.encode([safeBlock, endOfBlockIndex]),
|
|
1931
|
-
)
|
|
1936
|
+
await Webhooks.setCursor(db, subscription.id, Cursor.encode([safeBlock, endOfBlockIndex]))
|
|
1932
1937
|
continue
|
|
1933
1938
|
}
|
|
1934
1939
|
const page = await scanSubscription({
|
|
@@ -1951,7 +1956,7 @@ export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
|
1951
1956
|
// payloads) can render `amount` in token units. Non-fatal on failure.
|
|
1952
1957
|
const data =
|
|
1953
1958
|
eventType === 'token:transfer'
|
|
1954
|
-
? await withTokenMetadata(item.data, { chainId, client
|
|
1959
|
+
? await withTokenMetadata(item.data, { cache: cache_metadata, chainId, client })
|
|
1955
1960
|
: item.data
|
|
1956
1961
|
const envelope = Webhooks.buildEnvelope({
|
|
1957
1962
|
blockNumber: item.cursor[0],
|
|
@@ -1976,21 +1981,16 @@ export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
|
1976
1981
|
// matches); keyset scanners advance past the last dispatched row, or — on
|
|
1977
1982
|
// a complete empty page — to the end of the confirmed window.
|
|
1978
1983
|
if (failed) {
|
|
1979
|
-
if (accepted) await Webhooks.setCursor(
|
|
1984
|
+
if (accepted) await Webhooks.setCursor(db, subscription.id, Cursor.encode([...accepted]))
|
|
1980
1985
|
} else if (page.scannedThrough !== undefined)
|
|
1981
1986
|
await Webhooks.setCursor(
|
|
1982
|
-
|
|
1987
|
+
db,
|
|
1983
1988
|
subscription.id,
|
|
1984
1989
|
Cursor.encode([page.scannedThrough, endOfBlockIndex]),
|
|
1985
1990
|
)
|
|
1986
|
-
else if (accepted)
|
|
1987
|
-
await Webhooks.setCursor(store, subscription.id, Cursor.encode([...accepted]))
|
|
1991
|
+
else if (accepted) await Webhooks.setCursor(db, subscription.id, Cursor.encode([...accepted]))
|
|
1988
1992
|
else if (!page.hasMore)
|
|
1989
|
-
await Webhooks.setCursor(
|
|
1990
|
-
store,
|
|
1991
|
-
subscription.id,
|
|
1992
|
-
Cursor.encode([safeBlock, endOfBlockIndex]),
|
|
1993
|
-
)
|
|
1993
|
+
await Webhooks.setCursor(db, subscription.id, Cursor.encode([safeBlock, endOfBlockIndex]))
|
|
1994
1994
|
}
|
|
1995
1995
|
}
|
|
1996
1996
|
|
|
@@ -2009,12 +2009,16 @@ export declare namespace poll {
|
|
|
2009
2009
|
type Options = {
|
|
2010
2010
|
/** Max matching rows scanned per subscription per tick (default 100). */
|
|
2011
2011
|
batchSize?: number | undefined
|
|
2012
|
+
/** Cache store for the token-metadata memoize (defaults to a fresh in-memory store; pass a persistent one to share lookups across ticks). */
|
|
2013
|
+
cache?: Store.Store | undefined
|
|
2012
2014
|
/** Chain to poll. Callers loop over chains. */
|
|
2013
2015
|
chainId: number
|
|
2014
2016
|
/** viem RPC client for the chain (used by the RPC monitoring scanners). */
|
|
2015
2017
|
client: Viem.getClient.ReturnType
|
|
2016
2018
|
/** Reorg-safety window: only emit blocks this far behind head (default 2). */
|
|
2017
2019
|
confirmations?: number | undefined
|
|
2020
|
+
/** Database holding subscriptions + cursors. */
|
|
2021
|
+
db: Db.Db
|
|
2018
2022
|
/**
|
|
2019
2023
|
* Delivery transport. Defaults to inline {@link Webhooks.deliverAndRecord} (self-host);
|
|
2020
2024
|
* on Cloudflare pass a Queue producer so retry/backoff/DLQ are native.
|
|
@@ -2028,8 +2032,6 @@ export declare namespace poll {
|
|
|
2028
2032
|
maxBlocks?: number | undefined
|
|
2029
2033
|
/** Clock for envelope timestamps; injectable for tests. */
|
|
2030
2034
|
now?: (() => Date) | undefined
|
|
2031
|
-
/** Webhook state store (subscriptions + cursors). */
|
|
2032
|
-
store: Store.State
|
|
2033
2035
|
/** TIDX query client for the legacy `token:transfer` type. */
|
|
2034
2036
|
tidx?: Tidx.Client | undefined
|
|
2035
2037
|
}
|
|
@@ -2059,9 +2061,9 @@ export declare namespace poll {
|
|
|
2059
2061
|
async function withTokenMetadata(
|
|
2060
2062
|
data: unknown,
|
|
2061
2063
|
deps: {
|
|
2064
|
+
cache: Store.Store
|
|
2062
2065
|
chainId: number
|
|
2063
2066
|
client: Viem.getClient.ReturnType
|
|
2064
|
-
store: Store.State
|
|
2065
2067
|
},
|
|
2066
2068
|
): Promise<unknown> {
|
|
2067
2069
|
if (typeof data !== 'object' || data === null) return data
|
|
@@ -2079,7 +2081,7 @@ async function withTokenMetadata(
|
|
|
2079
2081
|
*/
|
|
2080
2082
|
async function resolveTokenMetadata(
|
|
2081
2083
|
address: string,
|
|
2082
|
-
deps: { chainId: number; client: Viem.getClient.ReturnType
|
|
2084
|
+
deps: { cache: Store.Store; chainId: number; client: Viem.getClient.ReturnType },
|
|
2083
2085
|
): Promise<{ decimals: number; symbol: string } | undefined> {
|
|
2084
2086
|
try {
|
|
2085
2087
|
return await Store.memoize(
|
|
@@ -2089,7 +2091,7 @@ async function resolveTokenMetadata(
|
|
|
2089
2091
|
},
|
|
2090
2092
|
{
|
|
2091
2093
|
key: `webhook:token-meta:v1:${deps.chainId}:${address}`,
|
|
2092
|
-
store: deps.
|
|
2094
|
+
store: deps.cache,
|
|
2093
2095
|
ttl: Ttl.minutes(5),
|
|
2094
2096
|
},
|
|
2095
2097
|
)
|
|
@@ -0,0 +1,136 @@
|
|
|
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 * as Metadata from '../metadata.js'
|
|
6
|
+
import openrpcSpec from '../../openrpc.json' with { type: 'json' }
|
|
7
|
+
import { pilatFontFaces } from './fonts.js'
|
|
8
|
+
import { logoUrl } from './logo.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The docs route group: the Vocs API reference served at the app root.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { docs } from 'tapimo/docs'
|
|
15
|
+
* App.create(options).route('/', data()).route('/', platform()).route('/', docs())
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* The group registers no routes itself: it carries a reference factory (via
|
|
19
|
+
* {@link Metadata}) that `App.create` mounts on finalize, after every group and
|
|
20
|
+
* the OpenAPI/OpenRPC documents — so the reference always renders the full
|
|
21
|
+
* composed surface and its catch-all stays behind API routes, wherever the
|
|
22
|
+
* group sits in the composition chain.
|
|
23
|
+
*
|
|
24
|
+
* Lives in the `tapimo/docs` subpath (never re-exported from `tapimo/apps`) so
|
|
25
|
+
* the Vocs renderer and its multi-MB icon/font data are bundled only by
|
|
26
|
+
* deployments that actually serve docs.
|
|
27
|
+
*/
|
|
28
|
+
export function docs(options: docs.Options = {}) {
|
|
29
|
+
return Metadata.attach(new Hono<App.Environment>(), {
|
|
30
|
+
docs: ({ spec }) =>
|
|
31
|
+
vocs_Handler.openApi(
|
|
32
|
+
{
|
|
33
|
+
// Inline the OpenRPC doc so vocs expands it without a self-subrequest
|
|
34
|
+
// (see `inlineOpenrpc`); the public `/openapi.json` keeps the URL ref.
|
|
35
|
+
spec: () => spec().then(inlineOpenrpc),
|
|
36
|
+
sidebar: { collapsed: true },
|
|
37
|
+
vocs: { logoUrl, title: 'Tempo API Reference', ...options },
|
|
38
|
+
},
|
|
39
|
+
{ css, fallback: 'next' },
|
|
40
|
+
),
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare namespace docs {
|
|
45
|
+
/** Vocs API reference options (theme, top navigation, logo, socials, …). */
|
|
46
|
+
type Options = NonNullable<Parameters<typeof vocs_Handler.openApi>[0]['vocs']>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Custom CSS injected into the standalone reference's shell `<head>` (via
|
|
51
|
+
* `Handler.openApi(_, { css })`), after the Vocs design-system styles so it
|
|
52
|
+
* overrides them:
|
|
53
|
+
*
|
|
54
|
+
* - Page/surface backgrounds use Tempo's near-black dark palette and pure-white
|
|
55
|
+
* light palette via `light-dark(<light>, <dark>)`.
|
|
56
|
+
* - The dark border color is darkened (the light theme keeps its default).
|
|
57
|
+
* - Every corner is squared. The universal `!important` rule beats hard-coded
|
|
58
|
+
* `border-radius` values and inline styles (e.g. the Scalar playground), which
|
|
59
|
+
* overriding the radius scale variables alone would miss.
|
|
60
|
+
* - The default sans/body font is Pilat (Vocs reads `--vocs-font-family`); the
|
|
61
|
+
* webfont is embedded via {@link pilatFontFaces}. Body stays at the default
|
|
62
|
+
* weight (400); headings are pinned to 500, which renders Pilat Demi (the
|
|
63
|
+
* family has no 500 cut, so Demi covers the 500-600 range — see
|
|
64
|
+
* {@link pilatFontFaces}).
|
|
65
|
+
*/
|
|
66
|
+
const css = `${pilatFontFaces}
|
|
67
|
+
|
|
68
|
+
:root {
|
|
69
|
+
--vocs-font-family: "Pilat", Arial, Helvetica, sans-serif;
|
|
70
|
+
--vocs-background-color-primary: light-dark(#fafafa, #0a0a0a);
|
|
71
|
+
--vocs-background-color-surface: light-dark(#fff, #121212);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
:is(h1, h2, h3, h4, h5, h6)[data-v] {
|
|
75
|
+
font-weight: 500;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Nudge the header logo a touch larger than the default max-h-7 (1.75rem). */
|
|
79
|
+
[data-v-logo-image] {
|
|
80
|
+
max-height: 2rem;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Sidebar leaf items render Regular (the nav's 450 default otherwise resolves to
|
|
84
|
+
* Demi via the 500-600 range). Group labels ([data-v-sidebar-section-header])
|
|
85
|
+
* keep their heavier weight. */
|
|
86
|
+
[data-v-sidebar-item] {
|
|
87
|
+
font-weight: 400;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
[data-vocs-theme='dark'] {
|
|
91
|
+
--vocs-color-gray4: oklch(20% 0 0);
|
|
92
|
+
--vocs-color-gray5: oklch(0.23 0 0);
|
|
93
|
+
--vocs-border-color-primary: oklch(0.25 0 0);
|
|
94
|
+
--vocs-border-color-secondary: oklch(0.25 0 0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
*,
|
|
98
|
+
*::before,
|
|
99
|
+
*::after {
|
|
100
|
+
border-radius: 0 !important;
|
|
101
|
+
}`
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Returns a shallow copy of `spec` with the JSON-RPC passthrough operation's
|
|
105
|
+
* `x-openrpc` replaced by the inline OpenRPC document, for the docs handler.
|
|
106
|
+
*
|
|
107
|
+
* Vocs expands `x-openrpc` at request time. A URL reference (as kept in the
|
|
108
|
+
* public `/openapi.json` by `App.create`'s `applyOpenrpcLink`) would make the
|
|
109
|
+
* docs worker fetch its own `/openrpc.json` — a self-subrequest that is
|
|
110
|
+
* unreliable on Cloudflare Workers and silently falls back to a single,
|
|
111
|
+
* unexpanded operation. Inlining the committed artifact keeps expansion
|
|
112
|
+
* deterministic across local and deployed environments, without bloating the
|
|
113
|
+
* public spec. Only the affected path/op are cloned; the rest of the (large)
|
|
114
|
+
* document is shared by reference.
|
|
115
|
+
*/
|
|
116
|
+
function inlineOpenrpc<spec extends { paths: Record<string, unknown> }>(spec: spec): spec {
|
|
117
|
+
const paths: Record<string, unknown> = {}
|
|
118
|
+
for (const [pathname, item] of Object.entries(spec.paths)) {
|
|
119
|
+
let next = item
|
|
120
|
+
if (isRecord(item))
|
|
121
|
+
for (const [method, op] of Object.entries(item))
|
|
122
|
+
if (isRpcOperation(op)) next = { ...item, [method]: { ...op, 'x-openrpc': openrpcSpec } }
|
|
123
|
+
paths[pathname] = next
|
|
124
|
+
}
|
|
125
|
+
return { ...spec, paths }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// The JSON-RPC passthrough's operation id, set by its route definition and
|
|
129
|
+
// targeted by `App.create`'s `applyOpenrpcLink`.
|
|
130
|
+
function isRpcOperation(op: unknown): op is Record<string, unknown> {
|
|
131
|
+
return isRecord(op) && op['operationId'] === 'rpcRequest'
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
135
|
+
return !!value && typeof value === 'object' && !Array.isArray(value)
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { docs } from './App.js'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Hono } from 'hono'
|
|
2
|
+
|
|
3
|
+
import type * as App from '../App.js'
|
|
4
|
+
|
|
5
|
+
// Hono's `.route()` drops sub-app metadata, so a group's OpenAPI metadata can't
|
|
6
|
+
// ride the instance through it. Each group attaches its metadata here and
|
|
7
|
+
// `App.create` reads it back on mount. The `WeakMap` keeps the association off
|
|
8
|
+
// the app's type, so `testClient`/`hc` inference is untouched.
|
|
9
|
+
const registry = new WeakMap<Hono<any, any>, App.create.Metadata>()
|
|
10
|
+
|
|
11
|
+
/** Attaches a group's OpenAPI metadata to its app instance for `create` to collect on mount. */
|
|
12
|
+
export function attach<const app extends Hono<any, any>>(
|
|
13
|
+
app: app,
|
|
14
|
+
metadata: App.create.Metadata,
|
|
15
|
+
): app {
|
|
16
|
+
registry.set(app, metadata)
|
|
17
|
+
return app
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Reads the OpenAPI metadata attached to an app instance, if any. */
|
|
21
|
+
export function read(app: Hono<any, any>): App.create.Metadata | undefined {
|
|
22
|
+
return registry.get(app)
|
|
23
|
+
}
|