tapimo 0.0.0 → 0.0.2
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/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/ApiKey.d.ts +65 -0
- package/dist/ApiKey.d.ts.map +1 -0
- package/dist/ApiKey.js +105 -0
- package/dist/ApiKey.js.map +1 -0
- package/dist/ApiKeySource.d.ts +166 -0
- package/dist/ApiKeySource.d.ts.map +1 -0
- package/dist/ApiKeySource.js +234 -0
- package/dist/ApiKeySource.js.map +1 -0
- package/dist/App.d.ts +19317 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +612 -0
- package/dist/App.js.map +1 -0
- package/dist/Assets.d.ts +44 -0
- package/dist/Assets.d.ts.map +1 -0
- package/dist/Assets.js +23 -0
- package/dist/Assets.js.map +1 -0
- package/dist/Auth.d.ts +2 -0
- package/dist/Auth.d.ts.map +1 -0
- package/dist/Auth.js +2 -0
- package/dist/Auth.js.map +1 -0
- package/dist/Cli.d.ts +21 -0
- package/dist/Cli.d.ts.map +1 -0
- package/dist/Cli.js +13 -0
- package/dist/Cli.js.map +1 -0
- package/dist/Client.d.ts +20 -0
- package/dist/Client.d.ts.map +1 -0
- package/dist/Client.js +24 -0
- package/dist/Client.js.map +1 -0
- package/dist/Metrics.d.ts +70 -0
- package/dist/Metrics.d.ts.map +1 -0
- package/dist/Metrics.js +91 -0
- package/dist/Metrics.js.map +1 -0
- package/dist/Scope.d.ts +35 -0
- package/dist/Scope.d.ts.map +1 -0
- package/dist/Scope.js +38 -0
- package/dist/Scope.js.map +1 -0
- package/dist/Webhooks.d.ts +79 -0
- package/dist/Webhooks.d.ts.map +1 -0
- package/dist/Webhooks.js +107 -0
- package/dist/Webhooks.js.map +1 -0
- package/dist/admin/Access.d.ts +41 -0
- package/dist/admin/Access.d.ts.map +1 -0
- package/dist/admin/Access.js +75 -0
- package/dist/admin/Access.js.map +1 -0
- package/dist/admin/App.d.ts +1221 -0
- package/dist/admin/App.d.ts.map +1 -0
- package/dist/admin/App.js +113 -0
- package/dist/admin/App.js.map +1 -0
- package/dist/admin/apps/api-keys.d.ts +209 -0
- package/dist/admin/apps/api-keys.d.ts.map +1 -0
- package/dist/admin/apps/api-keys.js +129 -0
- package/dist/admin/apps/api-keys.js.map +1 -0
- package/dist/admin/apps/scopes.d.ts +46 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -0
- package/dist/admin/apps/scopes.js +41 -0
- package/dist/admin/apps/scopes.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +1206 -0
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -0
- package/dist/admin/apps/verified-tokens.js +485 -0
- package/dist/admin/apps/verified-tokens.js.map +1 -0
- package/dist/admin/index.d.ts +3 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/ui.generated.d.ts +11 -0
- package/dist/admin/ui.generated.d.ts.map +1 -0
- package/dist/admin/ui.generated.js +43 -0
- package/dist/admin/ui.generated.js.map +1 -0
- package/dist/apps/activities.d.ts +18725 -0
- package/dist/apps/activities.d.ts.map +1 -0
- package/dist/apps/activities.js +3138 -0
- package/dist/apps/activities.js.map +1 -0
- package/dist/apps/addresses.d.ts +3662 -0
- package/dist/apps/addresses.d.ts.map +1 -0
- package/dist/apps/addresses.js +22 -0
- package/dist/apps/addresses.js.map +1 -0
- package/dist/apps/balances.d.ts +342 -0
- package/dist/apps/balances.d.ts.map +1 -0
- package/dist/apps/balances.js +393 -0
- package/dist/apps/balances.js.map +1 -0
- package/dist/apps/blocks.d.ts +931 -0
- package/dist/apps/blocks.d.ts.map +1 -0
- package/dist/apps/blocks.js +689 -0
- package/dist/apps/blocks.js.map +1 -0
- package/dist/apps/coingecko.d.ts +1053 -0
- package/dist/apps/coingecko.d.ts.map +1 -0
- package/dist/apps/coingecko.js +1015 -0
- package/dist/apps/coingecko.js.map +1 -0
- package/dist/apps/exchanges.d.ts +3000 -0
- package/dist/apps/exchanges.d.ts.map +1 -0
- package/dist/apps/exchanges.js +3570 -0
- package/dist/apps/exchanges.js.map +1 -0
- package/dist/apps/fee-amm.d.ts +640 -0
- package/dist/apps/fee-amm.d.ts.map +1 -0
- package/dist/apps/fee-amm.js +815 -0
- package/dist/apps/fee-amm.js.map +1 -0
- package/dist/apps/indexer.d.ts +116 -0
- package/dist/apps/indexer.d.ts.map +1 -0
- package/dist/apps/indexer.js +270 -0
- package/dist/apps/indexer.js.map +1 -0
- package/dist/apps/receipts.d.ts +1438 -0
- package/dist/apps/receipts.d.ts.map +1 -0
- package/dist/apps/receipts.js +874 -0
- package/dist/apps/receipts.js.map +1 -0
- package/dist/apps/rpc.d.ts +173 -0
- package/dist/apps/rpc.d.ts.map +1 -0
- package/dist/apps/rpc.js +191 -0
- package/dist/apps/rpc.js.map +1 -0
- package/dist/apps/tokenlist.d.ts +192 -0
- package/dist/apps/tokenlist.d.ts.map +1 -0
- package/dist/apps/tokenlist.js +153 -0
- package/dist/apps/tokenlist.js.map +1 -0
- package/dist/apps/tokens.d.ts +2246 -0
- package/dist/apps/tokens.d.ts.map +1 -0
- package/dist/apps/tokens.js +1789 -0
- package/dist/apps/tokens.js.map +1 -0
- package/dist/apps/transactions.d.ts +2327 -0
- package/dist/apps/transactions.d.ts.map +1 -0
- package/dist/apps/transactions.js +975 -0
- package/dist/apps/transactions.js.map +1 -0
- package/dist/apps/transfers.d.ts +589 -0
- package/dist/apps/transfers.d.ts.map +1 -0
- package/dist/apps/transfers.js +769 -0
- package/dist/apps/transfers.js.map +1 -0
- package/dist/apps/verified-tokens.d.ts +544 -0
- package/dist/apps/verified-tokens.d.ts.map +1 -0
- package/dist/apps/verified-tokens.js +234 -0
- package/dist/apps/verified-tokens.js.map +1 -0
- package/dist/apps/webhooks.d.ts +7684 -0
- package/dist/apps/webhooks.d.ts.map +1 -0
- package/dist/apps/webhooks.js +2112 -0
- package/dist/apps/webhooks.js.map +1 -0
- package/dist/cloudflare.d.ts +32 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +45 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/Auth.d.ts +298 -0
- package/dist/internal/Auth.d.ts.map +1 -0
- package/dist/internal/Auth.js +618 -0
- package/dist/internal/Auth.js.map +1 -0
- package/dist/internal/Cache.d.ts +74 -0
- package/dist/internal/Cache.d.ts.map +1 -0
- package/dist/internal/Cache.js +215 -0
- package/dist/internal/Cache.js.map +1 -0
- package/dist/internal/Cursor.d.ts +79 -0
- package/dist/internal/Cursor.d.ts.map +1 -0
- package/dist/internal/Cursor.js +116 -0
- package/dist/internal/Cursor.js.map +1 -0
- package/dist/internal/EdgeCache.d.ts +59 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -0
- package/dist/internal/EdgeCache.js +174 -0
- package/dist/internal/EdgeCache.js.map +1 -0
- package/dist/internal/Log.d.ts +104 -0
- package/dist/internal/Log.d.ts.map +1 -0
- package/dist/internal/Log.js +118 -0
- package/dist/internal/Log.js.map +1 -0
- package/dist/internal/MetricSink.d.ts +65 -0
- package/dist/internal/MetricSink.d.ts.map +1 -0
- package/dist/internal/MetricSink.js +146 -0
- package/dist/internal/MetricSink.js.map +1 -0
- package/dist/internal/Mpp.d.ts +71 -0
- package/dist/internal/Mpp.d.ts.map +1 -0
- package/dist/internal/Mpp.js +105 -0
- package/dist/internal/Mpp.js.map +1 -0
- package/dist/internal/OpenApi.d.ts +313 -0
- package/dist/internal/OpenApi.d.ts.map +1 -0
- package/dist/internal/OpenApi.fonts.d.ts +2 -0
- package/dist/internal/OpenApi.fonts.d.ts.map +1 -0
- package/dist/internal/OpenApi.fonts.js +39 -0
- package/dist/internal/OpenApi.fonts.js.map +1 -0
- package/dist/internal/OpenApi.js +335 -0
- package/dist/internal/OpenApi.js.map +1 -0
- package/dist/internal/OpenApi.logo.d.ts +6 -0
- package/dist/internal/OpenApi.logo.d.ts.map +1 -0
- package/dist/internal/OpenApi.logo.js +19 -0
- package/dist/internal/OpenApi.logo.js.map +1 -0
- package/dist/internal/Path.d.ts +5 -0
- package/dist/internal/Path.d.ts.map +1 -0
- package/dist/internal/Path.js +16 -0
- package/dist/internal/Path.js.map +1 -0
- package/dist/internal/RateLimit.d.ts +60 -0
- package/dist/internal/RateLimit.d.ts.map +1 -0
- package/dist/internal/RateLimit.js +48 -0
- package/dist/internal/RateLimit.js.map +1 -0
- package/dist/internal/Response.d.ts +132 -0
- package/dist/internal/Response.d.ts.map +1 -0
- package/dist/internal/Response.js +72 -0
- package/dist/internal/Response.js.map +1 -0
- package/dist/internal/Schema.d.ts +257 -0
- package/dist/internal/Schema.d.ts.map +1 -0
- package/dist/internal/Schema.js +360 -0
- package/dist/internal/Schema.js.map +1 -0
- package/dist/internal/Store.d.ts +204 -0
- package/dist/internal/Store.d.ts.map +1 -0
- package/dist/internal/Store.js +291 -0
- package/dist/internal/Store.js.map +1 -0
- package/dist/internal/Tidx.d.ts +120 -0
- package/dist/internal/Tidx.d.ts.map +1 -0
- package/dist/internal/Tidx.js +156 -0
- package/dist/internal/Tidx.js.map +1 -0
- package/dist/internal/Timing.d.ts +22 -0
- package/dist/internal/Timing.d.ts.map +1 -0
- package/dist/internal/Timing.js +32 -0
- package/dist/internal/Timing.js.map +1 -0
- package/dist/internal/Ttl.d.ts +25 -0
- package/dist/internal/Ttl.d.ts.map +1 -0
- package/dist/internal/Ttl.js +49 -0
- package/dist/internal/Ttl.js.map +1 -0
- package/dist/internal/Value.d.ts +47 -0
- package/dist/internal/Value.d.ts.map +1 -0
- package/dist/internal/Value.js +122 -0
- package/dist/internal/Value.js.map +1 -0
- package/dist/internal/VerifiedTokens.d.ts +228 -0
- package/dist/internal/VerifiedTokens.d.ts.map +1 -0
- package/dist/internal/VerifiedTokens.js +450 -0
- package/dist/internal/VerifiedTokens.js.map +1 -0
- package/dist/internal/Viem.d.ts +2082 -0
- package/dist/internal/Viem.d.ts.map +1 -0
- package/dist/internal/Viem.js +63 -0
- package/dist/internal/Viem.js.map +1 -0
- package/dist/internal/WebhookDestination.d.ts +198 -0
- package/dist/internal/WebhookDestination.d.ts.map +1 -0
- package/dist/internal/WebhookDestination.js +170 -0
- package/dist/internal/WebhookDestination.js.map +1 -0
- package/dist/internal/Webhooks.d.ts +433 -0
- package/dist/internal/Webhooks.d.ts.map +1 -0
- package/dist/internal/Webhooks.js +489 -0
- package/dist/internal/Webhooks.js.map +1 -0
- package/dist/internal/webhookDestinations/betterStack.d.ts +26 -0
- package/dist/internal/webhookDestinations/betterStack.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/betterStack.js +76 -0
- package/dist/internal/webhookDestinations/betterStack.js.map +1 -0
- package/dist/internal/webhookDestinations/slack.d.ts +59 -0
- package/dist/internal/webhookDestinations/slack.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/slack.js +422 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -0
- package/dist/internal/webhookDestinations/url.d.ts +17 -0
- package/dist/internal/webhookDestinations/url.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/url.js +130 -0
- package/dist/internal/webhookDestinations/url.js.map +1 -0
- package/dist/openrpc.json +5302 -0
- package/package.json +46 -4
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
- package/seeds/31318/verified-tokens.json +30 -0
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +4 -0
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +30 -0
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +11 -0
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +1 -0
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +5 -0
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +177 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +1 -0
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +1 -0
- package/seeds/42431/verified-tokens.json +44 -0
- package/seeds/openrpc/README.md +27 -0
- package/seeds/openrpc/execution-apis.json +8989 -0
- package/src/ApiKey.test.ts +91 -0
- package/src/ApiKey.ts +122 -0
- package/src/ApiKeySource.test-d.ts +11 -0
- package/src/ApiKeySource.test.ts +295 -0
- package/src/ApiKeySource.ts +303 -0
- package/src/App.test-d.ts +38 -0
- package/src/App.test.ts +65927 -0
- package/src/App.ts +855 -0
- package/src/Assets.ts +58 -0
- package/src/Auth.ts +1 -0
- package/src/Cli.test.ts +81 -0
- package/src/Cli.ts +38 -0
- package/src/Client.test-d.ts +1438 -0
- package/src/Client.test.ts +134 -0
- package/src/Client.ts +45 -0
- package/src/Metrics.ts +154 -0
- package/src/Scope.ts +50 -0
- package/src/Webhooks.test.ts +49 -0
- package/src/Webhooks.ts +172 -0
- package/src/admin/Access.test.ts +130 -0
- package/src/admin/Access.ts +87 -0
- package/src/admin/App.test.ts +225 -0
- package/src/admin/App.ts +216 -0
- package/src/admin/apps/api-keys.test.ts +156 -0
- package/src/admin/apps/api-keys.ts +157 -0
- package/src/admin/apps/scopes.test.ts +52 -0
- package/src/admin/apps/scopes.ts +47 -0
- package/src/admin/apps/verified-tokens.test.ts +415 -0
- package/src/admin/apps/verified-tokens.ts +566 -0
- package/src/admin/index.ts +2 -0
- package/src/admin/ui/plugin.ts +135 -0
- package/src/admin/ui/src/components/Checkbox.tsx +22 -0
- package/src/admin/ui/src/components/Dialog.tsx +32 -0
- package/src/admin/ui/src/components/MobileProfile.tsx +31 -0
- package/src/admin/ui/src/components/Page.tsx +53 -0
- package/src/admin/ui/src/components/TempoLogo.tsx +37 -0
- package/src/admin/ui/src/fonts/Pilat-Demi.woff2 +0 -0
- package/src/admin/ui/src/fonts/Pilat-Regular.woff2 +0 -0
- package/src/admin/ui/src/lib/api-keys.ts +63 -0
- package/src/admin/ui/src/lib/client.ts +15 -0
- package/src/admin/ui/src/lib/config.ts +57 -0
- package/src/admin/ui/src/lib/query-client.ts +26 -0
- package/src/admin/ui/src/lib/scopes.ts +25 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +89 -0
- package/src/admin/ui/src/lib/wagmi.ts +18 -0
- package/src/admin/ui/src/routeTree.gen.ts +104 -0
- package/src/admin/ui/src/router.tsx +25 -0
- package/src/admin/ui/src/routes/__root.tsx +219 -0
- package/src/admin/ui/src/routes/api-keys.tsx +329 -0
- package/src/admin/ui/src/routes/index.tsx +7 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +331 -0
- package/src/admin/ui/src/styles.css +20 -0
- package/src/admin/ui/tsconfig.json +16 -0
- package/src/admin/ui/vite.config.ts +29 -0
- package/src/admin/ui.generated.ts +60 -0
- package/src/apps/activities.test.ts +1020 -0
- package/src/apps/activities.ts +3934 -0
- package/src/apps/addresses.ts +24 -0
- package/src/apps/balances.test.ts +274 -0
- package/src/apps/balances.ts +533 -0
- package/src/apps/blocks.test.ts +385 -0
- package/src/apps/blocks.ts +896 -0
- package/src/apps/coingecko.test.ts +218 -0
- package/src/apps/coingecko.ts +1383 -0
- package/src/apps/exchanges.test.ts +958 -0
- package/src/apps/exchanges.ts +4773 -0
- package/src/apps/fee-amm.test.ts +321 -0
- package/src/apps/fee-amm.ts +1121 -0
- package/src/apps/indexer.test.ts +153 -0
- package/src/apps/indexer.ts +330 -0
- package/src/apps/receipts.test.ts +285 -0
- package/src/apps/receipts.ts +1193 -0
- package/src/apps/rpc.test.ts +302 -0
- package/src/apps/rpc.ts +222 -0
- package/src/apps/tokenlist.test.ts +80 -0
- package/src/apps/tokenlist.ts +207 -0
- package/src/apps/tokens.test.ts +1062 -0
- package/src/apps/tokens.ts +2292 -0
- package/src/apps/transactions.test.ts +408 -0
- package/src/apps/transactions.ts +1363 -0
- package/src/apps/transfers.test.ts +371 -0
- package/src/apps/transfers.ts +1116 -0
- package/src/apps/verified-tokens.test.ts +114 -0
- package/src/apps/verified-tokens.ts +295 -0
- package/src/apps/webhooks.test.ts +1937 -0
- package/src/apps/webhooks.ts +2926 -0
- package/src/cloudflare.ts +55 -0
- package/src/index.ts +15 -0
- package/src/internal/Auth.test.ts +980 -0
- package/src/internal/Auth.ts +1012 -0
- package/src/internal/Cache.test.ts +240 -0
- package/src/internal/Cache.ts +262 -0
- package/src/internal/Cursor.test.ts +100 -0
- package/src/internal/Cursor.ts +149 -0
- package/src/internal/EdgeCache.test.ts +234 -0
- package/src/internal/EdgeCache.ts +224 -0
- package/src/internal/Errors.ts +14 -0
- package/src/internal/Log.test.ts +244 -0
- package/src/internal/Log.ts +216 -0
- package/src/internal/MetricSink.ts +220 -0
- package/src/internal/Mpp.test.ts +64 -0
- package/src/internal/Mpp.ts +141 -0
- package/src/internal/OpenApi.fonts.ts +38 -0
- package/src/internal/OpenApi.logo.ts +18 -0
- package/src/internal/OpenApi.ts +488 -0
- package/src/internal/Path.test.ts +14 -0
- package/src/internal/Path.ts +15 -0
- package/src/internal/RateLimit.test.ts +93 -0
- package/src/internal/RateLimit.ts +93 -0
- package/src/internal/Response.ts +131 -0
- package/src/internal/Schema.test.ts +34 -0
- package/src/internal/Schema.ts +523 -0
- package/src/internal/Store.test.ts +545 -0
- package/src/internal/Store.ts +526 -0
- package/src/internal/Tidx.local.test.ts +33 -0
- package/src/internal/Tidx.test.ts +294 -0
- package/src/internal/Tidx.ts +238 -0
- package/src/internal/Timing.test.ts +22 -0
- package/src/internal/Timing.ts +62 -0
- package/src/internal/Ttl.test.ts +18 -0
- package/src/internal/Ttl.ts +59 -0
- package/src/internal/Value.ts +114 -0
- package/src/internal/VerifiedTokens.test.ts +333 -0
- package/src/internal/VerifiedTokens.ts +645 -0
- package/src/internal/Viem.test.ts +115 -0
- package/src/internal/Viem.ts +165 -0
- package/src/internal/WebhookDestination.test.ts +648 -0
- package/src/internal/WebhookDestination.ts +331 -0
- package/src/internal/Webhooks.test.ts +668 -0
- package/src/internal/Webhooks.ts +940 -0
- package/src/internal/webhookDestinations/betterStack.ts +91 -0
- package/src/internal/webhookDestinations/slack.ts +496 -0
- package/src/internal/webhookDestinations/url.ts +128 -0
- package/src/openrpc.json +5302 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Context, Env, MiddlewareHandler } from 'hono';
|
|
2
|
+
import type * as z from 'zod/mini';
|
|
3
|
+
/**
|
|
4
|
+
* Named `Cache-Control` policies, tiered by how volatile each resource is. The
|
|
5
|
+
* `max-age` bounds how stale a shared (edge) hit can be; `stale-while-revalidate`
|
|
6
|
+
* lets clients/CDNs serve a slightly older copy while refreshing in the
|
|
7
|
+
* background. Handlers may override per response via `Cache.setPolicy` (e.g. a
|
|
8
|
+
* mined transaction is `immutable`, a pending one is `noStore`).
|
|
9
|
+
*/
|
|
10
|
+
export declare const policies: {
|
|
11
|
+
/**
|
|
12
|
+
* Publicly shareable binary assets (token logos). `public` because the bytes
|
|
13
|
+
* carry no per-principal data and the edge layer strips per-request headers.
|
|
14
|
+
* Deliberately NOT `immutable`: these live at a stable URL
|
|
15
|
+
* (`/tokens/:token/logo`) whose underlying R2 icon can be replaced in place
|
|
16
|
+
* (admin upload), so a long `max-age` is paired with `stale-while-revalidate`
|
|
17
|
+
* to revalidate rather than pin a replaced logo for a year. Use a versioned/
|
|
18
|
+
* content-addressed URL if true `immutable` forever-caching is needed.
|
|
19
|
+
*/
|
|
20
|
+
readonly asset: 'public, max-age=86400, stale-while-revalidate=604800';
|
|
21
|
+
/** Fallback for routes that do not specify a policy. */
|
|
22
|
+
readonly default: 'private, max-age=30, stale-while-revalidate=300';
|
|
23
|
+
/** Newest-first feeds (transactions, receipts, transfers): refresh quickly. */
|
|
24
|
+
readonly feed: 'private, max-age=10, stale-while-revalidate=30';
|
|
25
|
+
/** Immutable resources (mined transactions and receipts): cache aggressively. */
|
|
26
|
+
readonly immutable: 'private, max-age=86400, stale-while-revalidate=604800';
|
|
27
|
+
/** Token metadata and indexed listings: change slowly. */
|
|
28
|
+
readonly metadata: 'private, max-age=60, stale-while-revalidate=300';
|
|
29
|
+
/** Transient or uncacheable responses (pending transactions). */
|
|
30
|
+
readonly noStore: 'no-store';
|
|
31
|
+
/** Slow-changing curated data (verified tokens). */
|
|
32
|
+
readonly stable: 'private, max-age=300, stale-while-revalidate=3600';
|
|
33
|
+
/** Current-state pages (holders, balances): moderately volatile. */
|
|
34
|
+
readonly state: 'private, max-age=30, stale-while-revalidate=120';
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Overrides the cache policy for the current response, taking precedence over
|
|
38
|
+
* the route's default `Cache.response` policy. Lets a handler vary caching by
|
|
39
|
+
* outcome — e.g. cache a mined transaction as `immutable` but a pending one as
|
|
40
|
+
* `noStore`. Must be called before the handler returns.
|
|
41
|
+
*/
|
|
42
|
+
export declare function setPolicy<environment extends Env>(c: Context<environment>, cacheControl: string): void;
|
|
43
|
+
/** Hono response-cache helpers. */
|
|
44
|
+
export declare function response<environment extends Env>(options: response.Options<environment>): MiddlewareHandler<environment>;
|
|
45
|
+
export declare namespace response {
|
|
46
|
+
/** Options for response caching. */
|
|
47
|
+
type Options<environment extends Env> = {
|
|
48
|
+
/** Cache-control value returned to clients. */
|
|
49
|
+
cacheControl?: string | undefined;
|
|
50
|
+
/** Cache name passed to Hono's cache middleware. */
|
|
51
|
+
name: string;
|
|
52
|
+
/** Cache key generator. */
|
|
53
|
+
key: (c: Context<environment>) => Promise<string> | string;
|
|
54
|
+
/** Vary headers used for the response and cache key. */
|
|
55
|
+
vary?: readonly string[] | undefined;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export declare namespace response {
|
|
59
|
+
/** Per-request headers that must not be stored in shared response caches. */
|
|
60
|
+
const preservedHeaders: string[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Builds a cache key from the request URL after parsing query params through
|
|
64
|
+
* the given Zod schema. Defaults from the schema are baked into the key so
|
|
65
|
+
* cached entries collide regardless of param ordering, casing, or omitted
|
|
66
|
+
* defaults. Resolves an optional `chainId` query parameter against the app's
|
|
67
|
+
* default chain id when the caller did not provide one.
|
|
68
|
+
*/
|
|
69
|
+
export declare function urlKey<environment extends {
|
|
70
|
+
Variables: {
|
|
71
|
+
chainId: number;
|
|
72
|
+
};
|
|
73
|
+
}, schema extends z.ZodMiniType>(c: Context<environment>, schema: schema): string;
|
|
74
|
+
//# sourceMappingURL=Cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cache.d.ts","sourceRoot":"","sources":["../../src/internal/Cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAG3D,OAAO,KAAK,KAAK,CAAC,MAAM,UAAU,CAAA;AAIlC;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ;IACnB;;;;;;;;OAQG;aACH,KAAK,EAAE,sDAAsD;IAC7D,wDAAwD;aACxD,OAAO,EAAE,iDAAiD;IAC1D,+EAA+E;aAC/E,IAAI,EAAE,gDAAgD;IACtD,iFAAiF;aACjF,SAAS,EAAE,uDAAuD;IAClE,0DAA0D;aAC1D,QAAQ,EAAE,iDAAiD;IAC3D,iEAAiE;aACjE,OAAO,EAAE,UAAU;IACnB,oDAAoD;aACpD,MAAM,EAAE,mDAAmD;IAC3D,oEAAoE;aACpE,KAAK,EAAE,iDAAiD;CAChD,CAAA;AAEV;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,WAAW,SAAS,GAAG,EAC/C,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EACvB,YAAY,EAAE,MAAM,GACnB,IAAI,CAEN;AAED,mCAAmC;AACnC,wBAAgB,QAAQ,CAAC,WAAW,SAAS,GAAG,EAC9C,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,GACrC,iBAAiB,CAAC,WAAW,CAAC,CAoGhC;AAED,MAAM,CAAC,OAAO,WAAW,QAAQ,CAAC;IAChC,oCAAoC;IACpC,KAAK,OAAO,CAAC,WAAW,SAAS,GAAG,IAAI;QACtC,+CAA+C;QAC/C,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACjC,oDAAoD;QACpD,IAAI,EAAE,MAAM,CAAA;QACZ,2BAA2B;QAC3B,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAA;QAC1D,wDAAwD;QACxD,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;KACrC,CAAA;CACF;AAED,yBAAiB,QAAQ,CAAC;IACxB,6EAA6E;IACtE,MAAM,gBAAgB,UAAgE,CAAA;CAC9F;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CACpB,WAAW,SAAS;IAAE,SAAS,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACtD,MAAM,SAAS,CAAC,CAAC,WAAW,EAC5B,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAUjD"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { cache as hono_cache } from 'hono/cache';
|
|
2
|
+
import { etag as hono_etag, RETAINED_304_HEADERS } from 'hono/etag';
|
|
3
|
+
import * as EdgeCache from './EdgeCache.js';
|
|
4
|
+
/**
|
|
5
|
+
* Named `Cache-Control` policies, tiered by how volatile each resource is. The
|
|
6
|
+
* `max-age` bounds how stale a shared (edge) hit can be; `stale-while-revalidate`
|
|
7
|
+
* lets clients/CDNs serve a slightly older copy while refreshing in the
|
|
8
|
+
* background. Handlers may override per response via `Cache.setPolicy` (e.g. a
|
|
9
|
+
* mined transaction is `immutable`, a pending one is `noStore`).
|
|
10
|
+
*/
|
|
11
|
+
export const policies = {
|
|
12
|
+
/**
|
|
13
|
+
* Publicly shareable binary assets (token logos). `public` because the bytes
|
|
14
|
+
* carry no per-principal data and the edge layer strips per-request headers.
|
|
15
|
+
* Deliberately NOT `immutable`: these live at a stable URL
|
|
16
|
+
* (`/tokens/:token/logo`) whose underlying R2 icon can be replaced in place
|
|
17
|
+
* (admin upload), so a long `max-age` is paired with `stale-while-revalidate`
|
|
18
|
+
* to revalidate rather than pin a replaced logo for a year. Use a versioned/
|
|
19
|
+
* content-addressed URL if true `immutable` forever-caching is needed.
|
|
20
|
+
*/
|
|
21
|
+
asset: 'public, max-age=86400, stale-while-revalidate=604800',
|
|
22
|
+
/** Fallback for routes that do not specify a policy. */
|
|
23
|
+
default: 'private, max-age=30, stale-while-revalidate=300',
|
|
24
|
+
/** Newest-first feeds (transactions, receipts, transfers): refresh quickly. */
|
|
25
|
+
feed: 'private, max-age=10, stale-while-revalidate=30',
|
|
26
|
+
/** Immutable resources (mined transactions and receipts): cache aggressively. */
|
|
27
|
+
immutable: 'private, max-age=86400, stale-while-revalidate=604800',
|
|
28
|
+
/** Token metadata and indexed listings: change slowly. */
|
|
29
|
+
metadata: 'private, max-age=60, stale-while-revalidate=300',
|
|
30
|
+
/** Transient or uncacheable responses (pending transactions). */
|
|
31
|
+
noStore: 'no-store',
|
|
32
|
+
/** Slow-changing curated data (verified tokens). */
|
|
33
|
+
stable: 'private, max-age=300, stale-while-revalidate=3600',
|
|
34
|
+
/** Current-state pages (holders, balances): moderately volatile. */
|
|
35
|
+
state: 'private, max-age=30, stale-while-revalidate=120',
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Overrides the cache policy for the current response, taking precedence over
|
|
39
|
+
* the route's default `Cache.response` policy. Lets a handler vary caching by
|
|
40
|
+
* outcome — e.g. cache a mined transaction as `immutable` but a pending one as
|
|
41
|
+
* `noStore`. Must be called before the handler returns.
|
|
42
|
+
*/
|
|
43
|
+
export function setPolicy(c, cacheControl) {
|
|
44
|
+
c.set('cacheControl', cacheControl);
|
|
45
|
+
}
|
|
46
|
+
/** Hono response-cache helpers. */
|
|
47
|
+
export function response(options) {
|
|
48
|
+
const defaultCacheControl = options.cacheControl ?? policies.default;
|
|
49
|
+
const vary = options.vary ?? ['Accept-Encoding', 'Authorization', 'Tempo-API-Key'];
|
|
50
|
+
// hono/cache suffixes its key with `::<directive>=<value>` for every
|
|
51
|
+
// configured vary directive (trimmed, lowercased, deduped). Mirror that
|
|
52
|
+
// normalization so the `no-cache` purge below deletes exactly the entry the
|
|
53
|
+
// wrapped middleware reads — drift here would make refreshes silently miss.
|
|
54
|
+
const varyKeyDirectives = [
|
|
55
|
+
...new Set(vary.map((name) => name.trim().toLowerCase()).filter(Boolean)),
|
|
56
|
+
];
|
|
57
|
+
const cache = hono_cache({
|
|
58
|
+
cacheName: options.name,
|
|
59
|
+
keyGenerator: options.key,
|
|
60
|
+
onCacheNotAvailable: false,
|
|
61
|
+
vary: [...vary],
|
|
62
|
+
wait: true,
|
|
63
|
+
});
|
|
64
|
+
const etag = hono_etag();
|
|
65
|
+
return async (c, next) => {
|
|
66
|
+
const values = response.preservedHeaders.map((name) => [name, c.res.headers.get(name)]);
|
|
67
|
+
// Honor the standard request `Cache-Control` directives (plus the HTTP/1.0
|
|
68
|
+
// `Pragma: no-cache` fallback, used only when `Cache-Control` is absent),
|
|
69
|
+
// mirroring `EdgeCache.middleware`: a refresh that bypasses the edge layer
|
|
70
|
+
// must also bypass this inner response cache, or the caller is served the
|
|
71
|
+
// inner stored copy and the "refresh" never reaches the handler.
|
|
72
|
+
// `no-cache` purges the stored entry so the wrapped hono/cache misses and
|
|
73
|
+
// re-stores the fresh response; `no-store` skips reads and writes entirely
|
|
74
|
+
// while leaving the stored entry untouched.
|
|
75
|
+
const directives = (c.req.header('Cache-Control') ?? c.req.header('Pragma') ?? '').toLowerCase();
|
|
76
|
+
const noStore = directives.includes('no-store');
|
|
77
|
+
const noCache = noStore || directives.includes('no-cache');
|
|
78
|
+
const caches = globalThis.caches;
|
|
79
|
+
if (noCache && !noStore && caches) {
|
|
80
|
+
let key = await options.key(c);
|
|
81
|
+
for (const name of varyKeyDirectives)
|
|
82
|
+
key += `::${name}=${encodeURIComponent(c.req.raw.headers.get(name) ?? '')}`;
|
|
83
|
+
await (await caches.open(options.name)).delete(key);
|
|
84
|
+
}
|
|
85
|
+
// Run ETag inside Hono's cache miss path so fresh responses are hashed
|
|
86
|
+
// once before storage. Cached hits bypass Hono's ETag middleware, so this
|
|
87
|
+
// wrapper handles conditional requests from the stored ETag below.
|
|
88
|
+
const handler = async () => {
|
|
89
|
+
await etag(c, async () => {
|
|
90
|
+
await next();
|
|
91
|
+
// Rate-limit headers are per request and would be stale if stored with
|
|
92
|
+
// the shared cached body.
|
|
93
|
+
for (const name of response.preservedHeaders)
|
|
94
|
+
c.res.headers.delete(name);
|
|
95
|
+
});
|
|
96
|
+
// Stamp the resolved policy's shared form onto 2xx responses BEFORE
|
|
97
|
+
// hono/cache stores them: the explicit `s-maxage` bounds the stored
|
|
98
|
+
// entry's lifetime to the policy (instead of the platform cache's
|
|
99
|
+
// default TTL), and a policy resolved to `noStore` (e.g. a pending
|
|
100
|
+
// transaction via `setPolicy`) becomes `no-store`, which hono/cache
|
|
101
|
+
// refuses to store. Client-facing headers are applied after storage
|
|
102
|
+
// below; non-2xx responses keep their own headers (`Response.error`
|
|
103
|
+
// marks envelopes `no-store`).
|
|
104
|
+
if (c.res.status >= 200 && c.res.status < 300) {
|
|
105
|
+
const policy = edgeCachePolicy(c.get('cacheControl') ?? defaultCacheControl);
|
|
106
|
+
c.res.headers.set('Cache-Control', policy ? EdgeCache.cacheControl(policy) : 'no-store');
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const result = noStore ? await handler() : await cache(c, handler);
|
|
110
|
+
// A handler may override the policy per response (see `setPolicy`); fall back
|
|
111
|
+
// to the route default. Publishing the derived policy is what marks the
|
|
112
|
+
// response as eligible for the shared edge cache (see `EdgeCache.middleware`),
|
|
113
|
+
// so `noStore` responses are never persisted there. The edge layer reads this
|
|
114
|
+
// after the whole chain runs, so setting it here (post-handler) is in time.
|
|
115
|
+
const cacheControl = c.get('cacheControl') ?? defaultCacheControl;
|
|
116
|
+
c.set('edgeCache', edgeCachePolicy(cacheControl));
|
|
117
|
+
let res = result instanceof Response ? new Response(result.body, result) : c.res;
|
|
118
|
+
if (result instanceof Response &&
|
|
119
|
+
etagMatches(res.headers.get('ETag'), c.req.header('If-None-Match')))
|
|
120
|
+
res = notModified(res);
|
|
121
|
+
// Apply private client cache headers after Hono cache storage; the stored
|
|
122
|
+
// copy carries the shared `public, s-maxage` form stamped above, while the
|
|
123
|
+
// client receives the policy's private form. Error responses keep their
|
|
124
|
+
// own `Cache-Control` (`no-store` from `Response.error` or the app-level
|
|
125
|
+
// safety net) instead of inheriting the route policy.
|
|
126
|
+
if ((res.status >= 200 && res.status < 300) || res.status === 304)
|
|
127
|
+
setCacheHeaders(res.headers, { cacheControl, vary });
|
|
128
|
+
for (const [name, value] of values)
|
|
129
|
+
if (value)
|
|
130
|
+
res.headers.set(name, value);
|
|
131
|
+
if (result instanceof Response)
|
|
132
|
+
return res;
|
|
133
|
+
return undefined;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
(function (response) {
|
|
137
|
+
/** Per-request headers that must not be stored in shared response caches. */
|
|
138
|
+
response.preservedHeaders = ['RateLimit-Limit', 'RateLimit-Remaining', 'RateLimit-Reset'];
|
|
139
|
+
})(response || (response = {}));
|
|
140
|
+
/**
|
|
141
|
+
* Builds a cache key from the request URL after parsing query params through
|
|
142
|
+
* the given Zod schema. Defaults from the schema are baked into the key so
|
|
143
|
+
* cached entries collide regardless of param ordering, casing, or omitted
|
|
144
|
+
* defaults. Resolves an optional `chainId` query parameter against the app's
|
|
145
|
+
* default chain id when the caller did not provide one.
|
|
146
|
+
*/
|
|
147
|
+
export function urlKey(c, schema) {
|
|
148
|
+
const url = new URL(c.req.url);
|
|
149
|
+
const query = schema.parse(Object.fromEntries(url.searchParams));
|
|
150
|
+
url.search = '';
|
|
151
|
+
if (query['chainId'] === undefined)
|
|
152
|
+
url.searchParams.set('chainId', String(c.get('chainId')));
|
|
153
|
+
for (const [key, value] of Object.entries(query)) {
|
|
154
|
+
if (value === undefined)
|
|
155
|
+
continue;
|
|
156
|
+
url.searchParams.set(key, String(value));
|
|
157
|
+
}
|
|
158
|
+
return url.toString();
|
|
159
|
+
}
|
|
160
|
+
function etagMatches(etag, ifNoneMatch) {
|
|
161
|
+
if (!etag || !ifNoneMatch)
|
|
162
|
+
return false;
|
|
163
|
+
return ifNoneMatch.split(/,\s*/).some((tag) => stripWeak(tag) === stripWeak(etag));
|
|
164
|
+
}
|
|
165
|
+
function notModified(response) {
|
|
166
|
+
const headers = new Headers();
|
|
167
|
+
for (const name of RETAINED_304_HEADERS) {
|
|
168
|
+
const value = response.headers.get(name);
|
|
169
|
+
if (value)
|
|
170
|
+
headers.set(name, value);
|
|
171
|
+
}
|
|
172
|
+
return new Response(null, {
|
|
173
|
+
headers,
|
|
174
|
+
status: 304,
|
|
175
|
+
statusText: 'Not Modified',
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function setCacheHeaders(headers, options) {
|
|
179
|
+
headers.set('Cache-Control', options.cacheControl);
|
|
180
|
+
const vary = new Map((headers.get('Vary') ?? '')
|
|
181
|
+
.split(',')
|
|
182
|
+
.map((value) => value.trim())
|
|
183
|
+
.filter(Boolean)
|
|
184
|
+
.map((value) => [value.toLowerCase(), value]));
|
|
185
|
+
for (const value of options.vary)
|
|
186
|
+
vary.set(value.toLowerCase(), value);
|
|
187
|
+
headers.set('Vary', Array.from(vary.values()).join(', '));
|
|
188
|
+
}
|
|
189
|
+
function stripWeak(etag) {
|
|
190
|
+
return etag.replace(/^W\//, '');
|
|
191
|
+
}
|
|
192
|
+
// Derive the shared-cache policy from a route's client `Cache-Control`. A
|
|
193
|
+
// positive `s-maxage`/`max-age` (and no `no-store`/`no-cache`) is what makes a
|
|
194
|
+
// route eligible for the anonymous edge cache; the `private` directive only
|
|
195
|
+
// scopes the client copy and is intentionally ignored here.
|
|
196
|
+
function edgeCachePolicy(cacheControl) {
|
|
197
|
+
const directives = new Map(cacheControl
|
|
198
|
+
.split(',')
|
|
199
|
+
.map((part) => part.trim().toLowerCase())
|
|
200
|
+
.filter(Boolean)
|
|
201
|
+
.map((part) => part.split('=')));
|
|
202
|
+
if (directives.has('no-store') || directives.has('no-cache'))
|
|
203
|
+
return undefined;
|
|
204
|
+
const maxAge = Number(directives.get('s-maxage') ?? directives.get('max-age'));
|
|
205
|
+
if (!Number.isFinite(maxAge) || maxAge <= 0)
|
|
206
|
+
return undefined;
|
|
207
|
+
const staleWhileRevalidate = Number(directives.get('stale-while-revalidate'));
|
|
208
|
+
return {
|
|
209
|
+
maxAge,
|
|
210
|
+
staleWhileRevalidate: Number.isFinite(staleWhileRevalidate) && staleWhileRevalidate > 0
|
|
211
|
+
? staleWhileRevalidate
|
|
212
|
+
: undefined,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=Cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cache.js","sourceRoot":"","sources":["../../src/internal/Cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAGnE,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB;;;;;;;;OAQG;IACH,KAAK,EAAE,sDAAsD;IAC7D,wDAAwD;IACxD,OAAO,EAAE,iDAAiD;IAC1D,+EAA+E;IAC/E,IAAI,EAAE,gDAAgD;IACtD,iFAAiF;IACjF,SAAS,EAAE,uDAAuD;IAClE,0DAA0D;IAC1D,QAAQ,EAAE,iDAAiD;IAC3D,iEAAiE;IACjE,OAAO,EAAE,UAAU;IACnB,oDAAoD;IACpD,MAAM,EAAE,mDAAmD;IAC3D,oEAAoE;IACpE,KAAK,EAAE,iDAAiD;CAChD,CAAA;AAEV;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,CAAuB,EACvB,YAAoB;IAEpB,CAAC,CAAC,GAAG,CAAC,cAAuB,EAAE,YAAqB,CAAC,CAAA;AACvD,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,QAAQ,CACtB,OAAsC;IAEtC,MAAM,mBAAmB,GAAG,OAAO,CAAC,YAAY,IAAI,QAAQ,CAAC,OAAO,CAAA;IACpE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,iBAAiB,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;IAClF,qEAAqE;IACrE,wEAAwE;IACxE,4EAA4E;IAC5E,4EAA4E;IAC5E,MAAM,iBAAiB,GAAG;QACxB,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;KAC1E,CAAA;IACD,MAAM,KAAK,GAAG,UAAU,CAAC;QACvB,SAAS,EAAE,OAAO,CAAC,IAAI;QACvB,YAAY,EAAE,OAAO,CAAC,GAAG;QACzB,mBAAmB,EAAE,KAAK;QAC1B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACf,IAAI,EAAE,IAAI;KACX,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,SAAS,EAAE,CAAA;IAExB,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAU,CAAC,CAAA;QAEhG,2EAA2E;QAC3E,0EAA0E;QAC1E,2EAA2E;QAC3E,0EAA0E;QAC1E,iEAAiE;QACjE,0EAA0E;QAC1E,2EAA2E;QAC3E,4CAA4C;QAC5C,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;QAChG,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;QAC/C,MAAM,OAAO,GAAG,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;QAM1D,MAAM,MAAM,GAAI,UAAkC,CAAC,MAAM,CAAA;QACzD,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,MAAM,EAAE,CAAC;YAClC,IAAI,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC9B,KAAK,MAAM,IAAI,IAAI,iBAAiB;gBAClC,GAAG,IAAI,KAAK,IAAI,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAA;YAC7E,MAAM,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACrD,CAAC;QAED,uEAAuE;QACvE,0EAA0E;QAC1E,mEAAmE;QACnE,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;YACzB,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;gBACvB,MAAM,IAAI,EAAE,CAAA;gBACZ,uEAAuE;gBACvE,0BAA0B;gBAC1B,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,gBAAgB;oBAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAC1E,CAAC,CAAC,CAAA;YACF,oEAAoE;YACpE,oEAAoE;YACpE,kEAAkE;YAClE,mEAAmE;YACnE,oEAAoE;YACpE,oEAAoE;YACpE,oEAAoE;YACpE,+BAA+B;YAC/B,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBAC9C,MAAM,MAAM,GAAG,eAAe,CAC3B,CAAC,CAAC,GAAG,CAAC,cAAuB,CAAwB,IAAI,mBAAmB,CAC9E,CAAA;gBACD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;YAC1F,CAAC;QACH,CAAC,CAAA;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;QAElE,8EAA8E;QAC9E,wEAAwE;QACxE,+EAA+E;QAC/E,8EAA8E;QAC9E,4EAA4E;QAC5E,MAAM,YAAY,GACf,CAAC,CAAC,GAAG,CAAC,cAAuB,CAAwB,IAAI,mBAAmB,CAAA;QAC/E,CAAC,CAAC,GAAG,CAAC,WAAoB,EAAE,eAAe,CAAC,YAAY,CAAU,CAAC,CAAA;QAEnE,IAAI,GAAG,GAAG,MAAM,YAAY,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QAChF,IACE,MAAM,YAAY,QAAQ;YAC1B,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAEnE,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;QAExB,0EAA0E;QAC1E,2EAA2E;QAC3E,wEAAwE;QACxE,yEAAyE;QACzE,sDAAsD;QACtD,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAC/D,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;QACtD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM;YAAE,IAAI,KAAK;gBAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC3E,IAAI,MAAM,YAAY,QAAQ;YAAE,OAAO,GAAG,CAAA;QAC1C,OAAO,SAAS,CAAA;IAClB,CAAC,CAAA;AACH,CAAC;AAgBD,WAAiB,QAAQ;IACvB,6EAA6E;IAChE,yBAAgB,GAAG,CAAC,iBAAiB,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,CAAA;AAC/F,CAAC,EAHgB,QAAQ,KAAR,QAAQ,QAGxB;AAED;;;;;;GAMG;AACH,MAAM,UAAU,MAAM,CAGpB,CAAuB,EAAE,MAAc;IACvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAA4B,CAAA;IAC3F,GAAG,CAAC,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS;QAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;IAC7F,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAQ;QACjC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAkC,CAAC,CAAC,CAAA;IACvE,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC;AAED,SAAS,WAAW,CAAC,IAAmB,EAAE,WAA+B;IACvE,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW;QAAE,OAAO,KAAK,CAAA;IACvC,OAAO,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;AACpF,CAAC;AAED,SAAS,WAAW,CAAC,QAAkB;IACrC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;IAC7B,KAAK,MAAM,IAAI,IAAI,oBAAoB,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACxC,IAAI,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC;IACD,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,OAAO;QACP,MAAM,EAAE,GAAG;QACX,UAAU,EAAE,cAAc;KAC3B,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,eAAe,CACtB,OAAgB,EAChB,OAA0D;IAE1D,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,CAClB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;SACxB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,KAAK,CAAU,CAAC,CACzD,CAAA;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI;QAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAA;IACtE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AACjC,CAAC;AAED,0EAA0E;AAC1E,+EAA+E;AAC/E,4EAA4E;AAC5E,4DAA4D;AAC5D,SAAS,eAAe,CAAC,YAAoB;IAC3C,MAAM,UAAU,GAAG,IAAI,GAAG,CACxB,YAAY;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;SACxC,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiC,CAAC,CAClE,CAAA;IACD,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAA;IAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAA;IAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,SAAS,CAAA;IAC7D,MAAM,oBAAoB,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAA;IAC7E,OAAO;QACL,MAAM;QACN,oBAAoB,EAClB,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,oBAAoB,GAAG,CAAC;YAC/D,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,SAAS;KAChB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque keyset-pagination cursor: a positional tuple encoding the sort-key of
|
|
3
|
+
* the last returned row (e.g. `[block, index]` for an append-only feed, or
|
|
4
|
+
* `[balance, address]` for a balance ranking). Pages are anchored to this
|
|
5
|
+
* position rather than a numeric offset, so rows arriving at the head of a feed
|
|
6
|
+
* cannot shift items across page boundaries (the duplicate/skip hazard of offset
|
|
7
|
+
* pagination over a live feed).
|
|
8
|
+
*
|
|
9
|
+
* The token is opaque on purpose: callers must treat it as a blob and pass back
|
|
10
|
+
* the `nextCursor` from the previous page verbatim. Because cursor values are
|
|
11
|
+
* inlined into upstream SQL, every field is validated on decode against its
|
|
12
|
+
* declared `Field` kind and re-serialized into a safe SQL literal via `literal`,
|
|
13
|
+
* so a malformed or forged cursor degrades to "start from the head" rather than
|
|
14
|
+
* reaching the query.
|
|
15
|
+
*/
|
|
16
|
+
export type Cursor = (string | number)[];
|
|
17
|
+
/** The kind of a cursor field, determining its validation and SQL literal form. */
|
|
18
|
+
export type Field = 'int' | 'uint' | 'address' | 'timestamp';
|
|
19
|
+
/** Encodes a positional tuple as an opaque, URL-safe token. */
|
|
20
|
+
export declare function encode(values: Cursor): string;
|
|
21
|
+
/**
|
|
22
|
+
* Splits a keyset query result (fetched with one extra row, `LIMIT n + 1`) into
|
|
23
|
+
* a page. Returns the page `rows` (capped at `limit`), whether `hasMore` rows
|
|
24
|
+
* follow, and the `nextCursor` anchoring the next page below the last row.
|
|
25
|
+
*
|
|
26
|
+
* `key` derives the next-page cursor tuple from the last row of the page,
|
|
27
|
+
* returning `undefined` when the row's sort-key can't be extracted (then
|
|
28
|
+
* `nextCursor` is `null`). Callers build their typed `data` from `rows`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function paginate<row>(options: {
|
|
31
|
+
/** The raw query result, fetched with one extra row (`LIMIT limit + 1`). */
|
|
32
|
+
rows: readonly row[];
|
|
33
|
+
/** The requested page size. */
|
|
34
|
+
limit: number;
|
|
35
|
+
/** Derives the next-page cursor tuple from the last row of the page. */
|
|
36
|
+
key: (row: row) => Cursor | undefined;
|
|
37
|
+
}): {
|
|
38
|
+
hasMore: boolean;
|
|
39
|
+
nextCursor: string | null;
|
|
40
|
+
rows: row[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Decodes a cursor token, validating arity and each field against `fields`.
|
|
44
|
+
* Returns `undefined` for anything malformed/forged so a bad cursor falls back
|
|
45
|
+
* to the head page instead of erroring (or reaching SQL).
|
|
46
|
+
*/
|
|
47
|
+
export declare function decode(token: string, fields: readonly Field[]): Cursor | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Renders a (decode-validated) cursor value as a safe SQL literal: integers and
|
|
50
|
+
* uint256 decimals are inlined bare; addresses are lowercased and quoted;
|
|
51
|
+
* timestamps are quoted. Only ever call with values returned from `decode`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function literal(value: string | number, field: Field): string;
|
|
54
|
+
/**
|
|
55
|
+
* Builds a strict lexicographic keyset predicate for the given ORDER BY columns
|
|
56
|
+
* and direction. Columns carry pre-rendered `literal`s.
|
|
57
|
+
*
|
|
58
|
+
* When every column sorts the same way, this emits a row-value (tuple)
|
|
59
|
+
* comparison, e.g. for `ORDER BY a DESC, b DESC` after `(va, vb)`:
|
|
60
|
+
* `((a, b) < (va, vb))`. This single-predicate form is the only one the
|
|
61
|
+
* indexer's signature-decoded queries accept (they reject the equivalent
|
|
62
|
+
* `OR`-expansion), and standard Postgres / ClickHouse support it too.
|
|
63
|
+
*
|
|
64
|
+
* When directions are mixed (e.g. a ranking `ORDER BY balance DESC, addr ASC`),
|
|
65
|
+
* a tuple comparison can't express it, so it falls back to the `OR` expansion:
|
|
66
|
+
* `((a < va) OR (a = va AND b > vb))`. Mixed-direction keysets only run against
|
|
67
|
+
* ClickHouse, which accepts the `OR` form.
|
|
68
|
+
*
|
|
69
|
+
* Multi-column keysets additionally AND a redundant non-strict bound on the
|
|
70
|
+
* first column (`a <= va`): neither the tuple nor the `OR` form alone lets the
|
|
71
|
+
* ClickHouse planner prune the primary-key range, so without the bare bound a
|
|
72
|
+
* deep cursor page scans from the tip (see the Q1 notes in `activities.ts`).
|
|
73
|
+
*/
|
|
74
|
+
export declare function keyset(columns: readonly {
|
|
75
|
+
name: string;
|
|
76
|
+
literal: string;
|
|
77
|
+
order: 'asc' | 'desc';
|
|
78
|
+
}[]): string;
|
|
79
|
+
//# sourceMappingURL=Cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cursor.d.ts","sourceRoot":"","sources":["../../src/internal/Cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;AAExC,mFAAmF;AACnF,MAAM,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,CAAA;AAE5D,+DAA+D;AAC/D,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE;IACrC,4EAA4E;IAC5E,IAAI,EAAE,SAAS,GAAG,EAAE,CAAA;IACpB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,wEAAwE;IACxE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAA;CACtC,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,GAAG,EAAE,CAAA;CAAE,CAO/D;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,GAAG,SAAS,CASlF;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAUpE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CACpB,OAAO,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,EAAE,GAC3E,MAAM,CAsBR"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** Encodes a positional tuple as an opaque, URL-safe token. */
|
|
2
|
+
export function encode(values) {
|
|
3
|
+
return base64UrlEncode(JSON.stringify(values));
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Splits a keyset query result (fetched with one extra row, `LIMIT n + 1`) into
|
|
7
|
+
* a page. Returns the page `rows` (capped at `limit`), whether `hasMore` rows
|
|
8
|
+
* follow, and the `nextCursor` anchoring the next page below the last row.
|
|
9
|
+
*
|
|
10
|
+
* `key` derives the next-page cursor tuple from the last row of the page,
|
|
11
|
+
* returning `undefined` when the row's sort-key can't be extracted (then
|
|
12
|
+
* `nextCursor` is `null`). Callers build their typed `data` from `rows`.
|
|
13
|
+
*/
|
|
14
|
+
export function paginate(options) {
|
|
15
|
+
const { rows, limit, key } = options;
|
|
16
|
+
const pageRows = rows.slice(0, limit);
|
|
17
|
+
const hasMore = rows.length > limit;
|
|
18
|
+
const last = pageRows.at(-1);
|
|
19
|
+
const tuple = hasMore && last !== undefined ? key(last) : undefined;
|
|
20
|
+
return { hasMore, nextCursor: tuple ? encode(tuple) : null, rows: pageRows };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Decodes a cursor token, validating arity and each field against `fields`.
|
|
24
|
+
* Returns `undefined` for anything malformed/forged so a bad cursor falls back
|
|
25
|
+
* to the head page instead of erroring (or reaching SQL).
|
|
26
|
+
*/
|
|
27
|
+
export function decode(token, fields) {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(base64UrlDecode(token));
|
|
30
|
+
if (!Array.isArray(parsed) || parsed.length !== fields.length)
|
|
31
|
+
return undefined;
|
|
32
|
+
for (let i = 0; i < fields.length; i++)
|
|
33
|
+
if (!isValid(parsed[i], fields[i]))
|
|
34
|
+
return undefined;
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Renders a (decode-validated) cursor value as a safe SQL literal: integers and
|
|
43
|
+
* uint256 decimals are inlined bare; addresses are lowercased and quoted;
|
|
44
|
+
* timestamps are quoted. Only ever call with values returned from `decode`.
|
|
45
|
+
*/
|
|
46
|
+
export function literal(value, field) {
|
|
47
|
+
switch (field) {
|
|
48
|
+
case 'int':
|
|
49
|
+
case 'uint':
|
|
50
|
+
return String(value);
|
|
51
|
+
case 'address':
|
|
52
|
+
return `'${String(value).toLowerCase()}'`;
|
|
53
|
+
case 'timestamp':
|
|
54
|
+
return `'${String(value)}'`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Builds a strict lexicographic keyset predicate for the given ORDER BY columns
|
|
59
|
+
* and direction. Columns carry pre-rendered `literal`s.
|
|
60
|
+
*
|
|
61
|
+
* When every column sorts the same way, this emits a row-value (tuple)
|
|
62
|
+
* comparison, e.g. for `ORDER BY a DESC, b DESC` after `(va, vb)`:
|
|
63
|
+
* `((a, b) < (va, vb))`. This single-predicate form is the only one the
|
|
64
|
+
* indexer's signature-decoded queries accept (they reject the equivalent
|
|
65
|
+
* `OR`-expansion), and standard Postgres / ClickHouse support it too.
|
|
66
|
+
*
|
|
67
|
+
* When directions are mixed (e.g. a ranking `ORDER BY balance DESC, addr ASC`),
|
|
68
|
+
* a tuple comparison can't express it, so it falls back to the `OR` expansion:
|
|
69
|
+
* `((a < va) OR (a = va AND b > vb))`. Mixed-direction keysets only run against
|
|
70
|
+
* ClickHouse, which accepts the `OR` form.
|
|
71
|
+
*
|
|
72
|
+
* Multi-column keysets additionally AND a redundant non-strict bound on the
|
|
73
|
+
* first column (`a <= va`): neither the tuple nor the `OR` form alone lets the
|
|
74
|
+
* ClickHouse planner prune the primary-key range, so without the bare bound a
|
|
75
|
+
* deep cursor page scans from the tip (see the Q1 notes in `activities.ts`).
|
|
76
|
+
*/
|
|
77
|
+
export function keyset(columns) {
|
|
78
|
+
const first = columns[0];
|
|
79
|
+
const bound = columns.length > 1
|
|
80
|
+
? `${first.name} ${first.order === 'asc' ? '>=' : '<='} ${first.literal} AND `
|
|
81
|
+
: '';
|
|
82
|
+
const uniform = columns.every((column) => column.order === first.order);
|
|
83
|
+
if (uniform) {
|
|
84
|
+
const op = first.order === 'asc' ? '>' : '<';
|
|
85
|
+
const names = columns.map((column) => column.name).join(', ');
|
|
86
|
+
const literals = columns.map((column) => column.literal).join(', ');
|
|
87
|
+
return `(${bound}(${names}) ${op} (${literals}))`;
|
|
88
|
+
}
|
|
89
|
+
const clauses = [];
|
|
90
|
+
for (let i = 0; i < columns.length; i++) {
|
|
91
|
+
const parts = columns.slice(0, i).map((column) => `${column.name} = ${column.literal}`);
|
|
92
|
+
const op = columns[i].order === 'asc' ? '>' : '<';
|
|
93
|
+
parts.push(`${columns[i].name} ${op} ${columns[i].literal}`);
|
|
94
|
+
clauses.push(`(${parts.join(' AND ')})`);
|
|
95
|
+
}
|
|
96
|
+
return `(${bound}(${clauses.join(' OR ')}))`;
|
|
97
|
+
}
|
|
98
|
+
function isValid(value, field) {
|
|
99
|
+
switch (field) {
|
|
100
|
+
case 'int':
|
|
101
|
+
return typeof value === 'number' && Number.isInteger(value) && value >= 0;
|
|
102
|
+
case 'uint':
|
|
103
|
+
return typeof value === 'string' && /^\d+$/.test(value);
|
|
104
|
+
case 'address':
|
|
105
|
+
return typeof value === 'string' && /^0x[0-9a-fA-F]{40}$/.test(value);
|
|
106
|
+
case 'timestamp':
|
|
107
|
+
return typeof value === 'string' && !Number.isNaN(Date.parse(value));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function base64UrlEncode(value) {
|
|
111
|
+
return btoa(value).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '');
|
|
112
|
+
}
|
|
113
|
+
function base64UrlDecode(value) {
|
|
114
|
+
return atob(value.replaceAll('-', '+').replaceAll('_', '/'));
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=Cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cursor.js","sourceRoot":"","sources":["../../src/internal/Cursor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Env, MiddlewareHandler } from 'hono';
|
|
2
|
+
import type * as Store from './Store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Per-request edge-cache policy published by `Cache.response` for routes that
|
|
5
|
+
* opted into response caching. Its presence is what marks a response as safe to
|
|
6
|
+
* persist in the shared edge cache.
|
|
7
|
+
*/
|
|
8
|
+
export type Policy = {
|
|
9
|
+
/** Shared max-age / s-maxage in seconds for the stored response. */
|
|
10
|
+
maxAge: number;
|
|
11
|
+
/** Stale-while-revalidate window in seconds, if any. */
|
|
12
|
+
staleWhileRevalidate?: number | undefined;
|
|
13
|
+
};
|
|
14
|
+
/** Hono variables published by the edge-cache layer. */
|
|
15
|
+
export type Variables = {
|
|
16
|
+
/** Edge-cache policy for the current route, set by `Cache.response`. */
|
|
17
|
+
edgeCache?: Policy | undefined;
|
|
18
|
+
/** `'hit'` when the edge cache served the response without reaching the origin handlers. */
|
|
19
|
+
edgeCacheStatus?: 'hit' | undefined;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Serves GET responses from the edge cache store BEFORE auth and rate-limiting
|
|
23
|
+
* run, so cache hits skip the per-request store round-trips that dominate
|
|
24
|
+
* latency — for every caller, authenticated or not. Place this ahead of the
|
|
25
|
+
* auth middleware.
|
|
26
|
+
*
|
|
27
|
+
* Only 2xx responses from routes that opted into caching (via `Cache.response`,
|
|
28
|
+
* which publishes the `edgeCache` policy) are stored, and the policy is only
|
|
29
|
+
* published for routes whose responses are public and URL-keyed (no per-principal
|
|
30
|
+
* data), so a single shared entry is safe to serve to all callers. The trade-off
|
|
31
|
+
* is that cache hits bypass origin metering: they are not counted against
|
|
32
|
+
* rate-limit quotas.
|
|
33
|
+
*
|
|
34
|
+
* The cache is a plain `Store.Store` — the same store the origin read cache uses
|
|
35
|
+
* — holding the response serialized to a string under a URL key. It is a no-op
|
|
36
|
+
* when no store is supplied.
|
|
37
|
+
*
|
|
38
|
+
* Standard request `Cache-Control` directives let a caller invalidate without an
|
|
39
|
+
* out-of-band purge: `no-cache` forces a refresh (skip the stored hit, re-fetch,
|
|
40
|
+
* overwrite the entry) and `no-store` bypasses the cache entirely. Both fall
|
|
41
|
+
* through to the origin and are metered normally. The store is colo-local, so a
|
|
42
|
+
* refresh only affects the data center serving that request.
|
|
43
|
+
*/
|
|
44
|
+
export declare function middleware<environment extends Env>(options?: middleware.Options): MiddlewareHandler<environment>;
|
|
45
|
+
export declare namespace middleware {
|
|
46
|
+
/** Options for the edge-cache middleware. */
|
|
47
|
+
type Options = {
|
|
48
|
+
/** Store backing the edge cache. The layer is a no-op when omitted. */
|
|
49
|
+
store?: Store.Store | undefined;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Builds the shared-cache `Cache-Control` value for a stored copy: `public`
|
|
54
|
+
* with `max-age`/`s-maxage` bound to the policy plus an optional
|
|
55
|
+
* `stale-while-revalidate` window. Used for this layer's stored copies and by
|
|
56
|
+
* `Cache.response` to bound the inner response cache's entry lifetime.
|
|
57
|
+
*/
|
|
58
|
+
export declare function cacheControl(policy: Policy): string;
|
|
59
|
+
//# sourceMappingURL=EdgeCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EdgeCache.d.ts","sourceRoot":"","sources":["../../src/internal/EdgeCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAGlD,OAAO,KAAK,KAAK,KAAK,MAAM,YAAY,CAAA;AAExC;;;;GAIG;AACH,MAAM,MAAM,MAAM,GAAG;IACnB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1C,CAAA;AAED,wDAAwD;AACxD,MAAM,MAAM,SAAS,GAAG;IACtB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,4FAA4F;IAC5F,eAAe,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;CACpC,CAAA;AAmBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,UAAU,CAAC,WAAW,SAAS,GAAG,EAChD,OAAO,GAAE,UAAU,CAAC,OAAY,GAC/B,iBAAiB,CAAC,WAAW,CAAC,CA+ChC;AAED,MAAM,CAAC,OAAO,WAAW,UAAU,CAAC;IAClC,6CAA6C;IAC7C,KAAK,OAAO,GAAG;QACb,uEAAuE;QACvE,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAA;KAChC,CAAA;CACF;AA0FD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,UAK1C"}
|