tapimo 0.2.0 → 0.4.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 +36 -8
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +5 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +28 -1
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +34 -1
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +7532 -4850
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +11 -3
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +11 -2
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +14 -3
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +63 -53
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +7 -0
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/scopes.d.ts +8 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/scopes.js +3 -0
- package/dist/admin/apps/scopes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +57 -57
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +13 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +151 -0
- package/dist/analytics/Analytics.d.ts.map +1 -0
- package/dist/analytics/Analytics.js +212 -0
- package/dist/analytics/Analytics.js.map +1 -0
- package/dist/analytics/tables/requestEvents.d.ts +215 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -0
- package/dist/analytics/tables/requestEvents.js +264 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -0
- package/dist/apps/data/App.d.ts +1049 -624
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +36 -0
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingRouteProviders.d.ts +54 -0
- package/dist/apps/data/FundingRouteProviders.d.ts.map +1 -0
- package/dist/apps/data/FundingRouteProviders.js +355 -0
- package/dist/apps/data/FundingRouteProviders.js.map +1 -0
- package/dist/apps/data/index.d.ts +1 -0
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +1 -0
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +45 -45
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/exchanges.d.ts +455 -455
- package/dist/apps/data/routes/fee-amm.d.ts +101 -101
- package/dist/apps/data/routes/funding.d.ts +843 -0
- package/dist/apps/data/routes/funding.d.ts.map +1 -0
- package/dist/apps/data/routes/funding.js +443 -0
- package/dist/apps/data/routes/funding.js.map +1 -0
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +2 -8
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +29 -36
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +29 -1
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +36 -36
- package/dist/apps/data/routes/transfers.d.ts +56 -56
- package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
- package/dist/apps/data/routes/webhooks.d.ts +45 -45
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +8 -8
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/docs/App.d.ts +5 -3
- package/dist/apps/docs/App.d.ts.map +1 -1
- package/dist/apps/docs/App.js +28 -96
- package/dist/apps/docs/App.js.map +1 -1
- package/dist/apps/docs/reference.d.ts +21 -0
- package/dist/apps/docs/reference.d.ts.map +1 -0
- package/dist/apps/docs/reference.js +112 -0
- package/dist/apps/docs/reference.js.map +1 -0
- package/dist/apps/index.d.ts +3 -2
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +3 -2
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/{platform → management}/App.d.ts +3015 -738
- package/dist/apps/management/App.d.ts.map +1 -0
- package/dist/apps/{platform → management}/App.js +20 -10
- package/dist/apps/management/App.js.map +1 -0
- package/dist/apps/management/Billing.d.ts +279 -0
- package/dist/apps/management/Billing.d.ts.map +1 -0
- package/dist/apps/management/Billing.js +477 -0
- package/dist/apps/management/Billing.js.map +1 -0
- package/dist/apps/management/index.d.ts +3 -0
- package/dist/apps/management/index.d.ts.map +1 -0
- package/dist/apps/management/index.js +3 -0
- package/dist/apps/management/index.js.map +1 -0
- package/dist/apps/{platform → management}/routes/api-keys.d.ts +341 -49
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/api-keys.js +116 -14
- package/dist/apps/management/routes/api-keys.js.map +1 -0
- package/dist/apps/management/routes/billing.d.ts +1520 -0
- package/dist/apps/management/routes/billing.d.ts.map +1 -0
- package/dist/apps/management/routes/billing.js +795 -0
- package/dist/apps/management/routes/billing.js.map +1 -0
- package/dist/apps/{platform → management}/routes/invitations.d.ts +202 -84
- package/dist/apps/management/routes/invitations.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/invitations.js +59 -1
- package/dist/apps/management/routes/invitations.js.map +1 -0
- package/dist/apps/{platform → management}/routes/me.d.ts +17 -17
- package/dist/apps/management/routes/me.d.ts.map +1 -0
- package/dist/apps/management/routes/me.js.map +1 -0
- package/dist/apps/management/routes/members.d.ts.map +1 -0
- package/dist/apps/management/routes/members.js.map +1 -0
- package/dist/apps/{platform → management}/routes/orgs.d.ts +50 -36
- package/dist/apps/management/routes/orgs.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/orgs.js +14 -3
- package/dist/apps/management/routes/orgs.js.map +1 -0
- package/dist/apps/{platform → management}/routes/projects.d.ts +97 -97
- package/dist/apps/{platform → management}/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js.map +1 -0
- package/dist/apps/management/routes/scopes.d.ts +107 -0
- package/dist/apps/management/routes/scopes.d.ts.map +1 -0
- package/dist/apps/management/routes/scopes.js +66 -0
- package/dist/apps/management/routes/scopes.js.map +1 -0
- package/dist/apps/management/routes/usage.d.ts +588 -0
- package/dist/apps/management/routes/usage.d.ts.map +1 -0
- package/dist/apps/management/routes/usage.js +391 -0
- package/dist/apps/management/routes/usage.js.map +1 -0
- package/dist/apps/mcp.d.ts +76 -0
- package/dist/apps/mcp.d.ts.map +1 -0
- package/dist/apps/mcp.js +188 -0
- package/dist/apps/mcp.js.map +1 -0
- package/dist/apps/relay/App.d.ts +4 -1
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +118 -10
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +2 -1
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/cli/Cli.d.ts +8 -1
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +11 -3
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +4 -0
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +80 -1
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/db/Db.d.ts +7 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +126 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +79 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +88 -2
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/billingSettings.d.ts +55 -0
- package/dist/db/tables/billingSettings.d.ts.map +1 -0
- package/dist/db/tables/billingSettings.js +70 -0
- package/dist/db/tables/billingSettings.js.map +1 -0
- package/dist/db/tables/invitations.js +2 -2
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +6 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +10 -4
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.js +2 -2
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +121 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -0
- package/dist/db/tables/requestUsage.js +150 -0
- package/dist/db/tables/requestUsage.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +119 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +155 -2
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/stripeCustomers.d.ts +81 -0
- package/dist/db/tables/stripeCustomers.d.ts.map +1 -0
- package/dist/db/tables/stripeCustomers.js +120 -0
- package/dist/db/tables/stripeCustomers.js.map +1 -0
- package/dist/db/tables/users.js +2 -2
- package/dist/db/tables/users.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +5 -2
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +19 -5
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts +10 -3
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +14 -6
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +18 -4
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +149 -77
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +4 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts +10 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +39 -8
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Fees.d.ts +27 -0
- package/dist/internal/Fees.d.ts.map +1 -0
- package/dist/internal/Fees.js +48 -0
- package/dist/internal/Fees.js.map +1 -0
- package/dist/internal/FundingRoutes.d.ts +915 -0
- package/dist/internal/FundingRoutes.d.ts.map +1 -0
- package/dist/internal/FundingRoutes.js +625 -0
- package/dist/internal/FundingRoutes.js.map +1 -0
- package/dist/internal/Id.d.ts +15 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +22 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/Log.d.ts +2 -0
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +3 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +10 -1
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +8 -1
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +25 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +51 -0
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Schema.d.ts +8 -0
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +7 -0
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +3 -3
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +8 -7
- package/src/ApiKey.ts +9 -2
- package/src/ApiKeys.test.ts +51 -0
- package/src/ApiKeys.ts +50 -1
- package/src/App.test.ts +33 -86718
- package/src/App.ts +26 -8
- package/src/Client.test-d.ts +353 -2
- package/src/Scope.ts +16 -3
- package/src/admin/apps/scopes.test.ts +6 -0
- package/src/admin/apps/scopes.ts +3 -0
- package/src/admin/ui/src/components/Page.tsx +2 -3
- package/src/admin/ui/src/routes/__root.tsx +2 -2
- package/src/admin/ui/src/routes/api-keys.tsx +2 -2
- package/src/admin/ui.generated.ts +13 -13
- package/src/analytics/Analytics.test.ts +527 -0
- package/src/analytics/Analytics.ts +318 -0
- package/src/analytics/tables/requestEvents.ts +523 -0
- package/src/apps/composition.test.ts +26 -13
- package/src/apps/data/App.test.ts +72 -0
- package/src/apps/data/App.ts +37 -0
- package/src/apps/data/FundingRouteProviders.test.ts +281 -0
- package/src/apps/data/FundingRouteProviders.ts +459 -0
- package/src/apps/data/index.ts +1 -0
- package/src/apps/data/routes/funding.test.ts +314 -0
- package/src/apps/data/routes/funding.ts +698 -0
- package/src/apps/data/routes/receipts.ts +2 -9
- package/src/apps/data/routes/rpc.test.ts +78 -2
- package/src/apps/data/routes/rpc.ts +31 -1
- package/src/apps/data/routes/webhooks.test.ts +1 -1
- package/src/apps/data/routes/webhooks.ts +11 -8
- package/src/apps/docs/App.ts +30 -101
- package/src/apps/docs/reference.ts +132 -0
- package/src/apps/index.ts +3 -2
- package/src/apps/{platform → management}/App.ts +56 -17
- package/src/apps/management/Billing.test.ts +530 -0
- package/src/apps/management/Billing.ts +682 -0
- package/src/apps/management/index.ts +2 -0
- package/src/apps/{platform → management}/routes/api-keys.test.ts +172 -9
- package/src/apps/{platform → management}/routes/api-keys.ts +137 -21
- package/src/apps/management/routes/billing.test.ts +1100 -0
- package/src/apps/management/routes/billing.ts +966 -0
- package/src/apps/{platform → management}/routes/invitations.test.ts +55 -7
- package/src/apps/{platform → management}/routes/invitations.ts +69 -1
- package/src/apps/management/routes/me.test.ts +351 -0
- package/src/apps/{platform → management}/routes/orgs.ts +26 -4
- package/src/apps/management/routes/scopes.test.ts +29 -0
- package/src/apps/management/routes/scopes.ts +85 -0
- package/src/apps/management/routes/usage.test.ts +422 -0
- package/src/apps/management/routes/usage.ts +527 -0
- package/src/apps/mcp.test.ts +206 -0
- package/src/apps/mcp.ts +250 -0
- package/src/apps/relay/App.test.ts +457 -8
- package/src/apps/relay/App.ts +120 -12
- package/src/apps/relay/Sponsorships.test.ts +1 -1
- package/src/apps/relay/Sponsorships.ts +2 -1
- package/src/cli/Cli.test.ts +25 -2
- package/src/cli/Cli.ts +17 -2
- package/src/cli/commands/admin.test.ts +83 -0
- package/src/cli/commands/admin.ts +89 -1
- package/src/db/Db.ts +137 -0
- package/src/db/Schema.ts +104 -2
- package/src/db/tables/billingSettings.test.ts +87 -0
- package/src/db/tables/billingSettings.ts +108 -0
- package/src/db/tables/invitations.ts +2 -2
- package/src/db/tables/organizations.test.ts +1 -1
- package/src/db/tables/organizations.ts +15 -5
- package/src/db/tables/projects.ts +2 -2
- package/src/db/tables/requestUsage.ts +231 -0
- package/src/db/tables/sponsoredTransactions.test.ts +108 -1
- package/src/db/tables/sponsoredTransactions.ts +230 -2
- package/src/db/tables/stripeCustomers.test.ts +109 -0
- package/src/db/tables/stripeCustomers.ts +162 -0
- package/src/db/tables/users.ts +2 -2
- package/src/handlers/internal/sponsorship.ts +34 -7
- package/src/handlers/internal/utils.ts +19 -7
- package/src/index.ts +1 -0
- package/src/internal/Auth.test.ts +175 -25
- package/src/internal/Auth.ts +176 -87
- package/src/internal/Cache.ts +5 -1
- package/src/internal/EdgeCache.test.ts +27 -4
- package/src/internal/EdgeCache.ts +47 -9
- package/src/internal/Fees.test.ts +32 -0
- package/src/internal/Fees.ts +51 -0
- package/src/internal/FundingRoutes.test.ts +213 -0
- package/src/internal/FundingRoutes.ts +898 -0
- package/src/internal/Id.test.ts +17 -0
- package/src/internal/Id.ts +24 -0
- package/src/internal/Log.test.ts +1 -0
- package/src/internal/Log.ts +5 -0
- package/src/internal/OpenApi.ts +12 -1
- package/src/internal/RateLimit.test.ts +84 -0
- package/src/internal/RateLimit.ts +70 -0
- package/src/internal/Response.ts +1 -1
- package/src/internal/Schema.ts +8 -0
- package/src/internal/Webhooks.test.ts +3 -3
- package/src/internal/Webhooks.ts +3 -3
- package/dist/apps/platform/App.d.ts.map +0 -1
- package/dist/apps/platform/App.js.map +0 -1
- package/dist/apps/platform/index.d.ts +0 -2
- package/dist/apps/platform/index.d.ts.map +0 -1
- package/dist/apps/platform/index.js +0 -2
- package/dist/apps/platform/index.js.map +0 -1
- package/dist/apps/platform/routes/api-keys.d.ts.map +0 -1
- package/dist/apps/platform/routes/api-keys.js.map +0 -1
- package/dist/apps/platform/routes/invitations.d.ts.map +0 -1
- package/dist/apps/platform/routes/invitations.js.map +0 -1
- package/dist/apps/platform/routes/me.d.ts.map +0 -1
- package/dist/apps/platform/routes/me.js.map +0 -1
- package/dist/apps/platform/routes/members.d.ts.map +0 -1
- package/dist/apps/platform/routes/members.js.map +0 -1
- package/dist/apps/platform/routes/orgs.d.ts.map +0 -1
- package/dist/apps/platform/routes/orgs.js.map +0 -1
- package/dist/apps/platform/routes/projects.js.map +0 -1
- package/src/apps/platform/index.ts +0 -1
- package/src/apps/platform/routes/me.test.ts +0 -121
- /package/dist/apps/{platform → management}/routes/me.js +0 -0
- /package/dist/apps/{platform → management}/routes/members.d.ts +0 -0
- /package/dist/apps/{platform → management}/routes/members.js +0 -0
- /package/dist/apps/{platform → management}/routes/projects.js +0 -0
- /package/src/apps/{platform → management}/routes/me.ts +0 -0
- /package/src/apps/{platform → management}/routes/members.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/members.ts +0 -0
- /package/src/apps/{platform → management}/routes/orgs.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/projects.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/projects.ts +0 -0
|
@@ -6,6 +6,7 @@ import type * as App from '../../../App.js'
|
|
|
6
6
|
import * as Auth from '../../../internal/Auth.js'
|
|
7
7
|
import * as Cache from '../../../internal/Cache.js'
|
|
8
8
|
import * as Cursor from '../../../internal/Cursor.js'
|
|
9
|
+
import * as Fees from '../../../internal/Fees.js'
|
|
9
10
|
import * as OpenApi from '../../../internal/OpenApi.js'
|
|
10
11
|
import * as Response from '../../../internal/Response.js'
|
|
11
12
|
import * as Schema from '../../../internal/Schema.js'
|
|
@@ -25,13 +26,6 @@ import { decodeTransactionType, embedFeeTokens, schema as txSchema } from './tra
|
|
|
25
26
|
/** Example transaction hash surfaced in OpenAPI docs. */
|
|
26
27
|
const exampleHash = '0x515801d7f9a5ac705e793e85904c9c69b3f1694b465cc8fb6ba3f0298dc82665'
|
|
27
28
|
|
|
28
|
-
// Tempo gas prices are denominated in attodollars (10^-18 USD) while fee-token
|
|
29
|
-
// balances use 6 decimals (microdollars, 10^-6 USD), so the fee charged to the
|
|
30
|
-
// fee payer — in the fee token's base units — is
|
|
31
|
-
// `ceil(gasUsed * effectiveGasPrice / 10^12)` (ceiling division). Mirrors
|
|
32
|
-
// `calc_gas_balance_spending` in tempoxyz/tempo.
|
|
33
|
-
const feeScalingFactor = 10n ** 12n
|
|
34
|
-
|
|
35
29
|
/**
|
|
36
30
|
* Computes the fee charged to the fee payer, in the fee token's base units, from
|
|
37
31
|
* the receipt's `gasUsed` and decimal `effectiveGasPrice`. Returns undefined
|
|
@@ -39,8 +33,7 @@ const feeScalingFactor = 10n ** 12n
|
|
|
39
33
|
*/
|
|
40
34
|
function computeFeeAmount(gasUsed: number | undefined, effectiveGasPrice: string | undefined) {
|
|
41
35
|
if (gasUsed === undefined || effectiveGasPrice === undefined) return undefined
|
|
42
|
-
|
|
43
|
-
return ((product + feeScalingFactor - 1n) / feeScalingFactor).toString()
|
|
36
|
+
return Fees.fromGas(BigInt(gasUsed), BigInt(effectiveGasPrice)).toString()
|
|
44
37
|
}
|
|
45
38
|
|
|
46
39
|
/** Zod schemas owned by the receipt handlers. */
|
|
@@ -96,7 +96,7 @@ describe('POST /rpc', () => {
|
|
|
96
96
|
}
|
|
97
97
|
})
|
|
98
98
|
|
|
99
|
-
test('
|
|
99
|
+
test('allows eth-prefixed methods anonymously', async () => {
|
|
100
100
|
const fetch = mockRpc()
|
|
101
101
|
|
|
102
102
|
try {
|
|
@@ -109,7 +109,7 @@ describe('POST /rpc', () => {
|
|
|
109
109
|
|
|
110
110
|
const response = await app.fetch(
|
|
111
111
|
new Request('http://tempo-api.test/rpc/testnet', {
|
|
112
|
-
body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: '
|
|
112
|
+
body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'eth_fillTransaction' }),
|
|
113
113
|
method: 'POST',
|
|
114
114
|
}),
|
|
115
115
|
)
|
|
@@ -122,6 +122,82 @@ describe('POST /rpc', () => {
|
|
|
122
122
|
}
|
|
123
123
|
})
|
|
124
124
|
|
|
125
|
+
test('requires an API key for non-eth methods', async () => {
|
|
126
|
+
const fetch = mockRpc()
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const app = TestApp.create()
|
|
130
|
+
const response = await app.fetch(
|
|
131
|
+
new Request('http://tempo-api.test/rpc', {
|
|
132
|
+
body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'tempo_fundAddress' }),
|
|
133
|
+
method: 'POST',
|
|
134
|
+
}),
|
|
135
|
+
)
|
|
136
|
+
const body = (await response.json()) as Record<string, unknown>
|
|
137
|
+
const { requestId, ...stable } = body
|
|
138
|
+
|
|
139
|
+
expect(response.status).toMatchInlineSnapshot(`401`)
|
|
140
|
+
expect(typeof requestId).toMatchInlineSnapshot(`"string"`)
|
|
141
|
+
expect(stable).toMatchInlineSnapshot(`
|
|
142
|
+
{
|
|
143
|
+
"error": {
|
|
144
|
+
"code": "api_key_missing",
|
|
145
|
+
"message": "Missing API key",
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
`)
|
|
149
|
+
expect(fetch.calls).toMatchInlineSnapshot(`[]`)
|
|
150
|
+
} finally {
|
|
151
|
+
fetch.restore()
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
test('requires an API key when a batch includes a private method', async () => {
|
|
156
|
+
const fetch = mockRpc()
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
const app = TestApp.create()
|
|
160
|
+
const response = await app.fetch(
|
|
161
|
+
new Request('http://tempo-api.test/rpc', {
|
|
162
|
+
body: JSON.stringify([
|
|
163
|
+
{ id: 1, jsonrpc: '2.0', method: 'eth_chainId' },
|
|
164
|
+
{ id: 2, jsonrpc: '2.0', method: 'tempo_fundAddress' },
|
|
165
|
+
]),
|
|
166
|
+
method: 'POST',
|
|
167
|
+
}),
|
|
168
|
+
)
|
|
169
|
+
const body = (await response.json()) as { error?: { code?: unknown } }
|
|
170
|
+
|
|
171
|
+
expect(response.status).toMatchInlineSnapshot(`401`)
|
|
172
|
+
expect(body.error?.code).toMatchInlineSnapshot(`"api_key_missing"`)
|
|
173
|
+
expect(fetch.calls).toMatchInlineSnapshot(`[]`)
|
|
174
|
+
} finally {
|
|
175
|
+
fetch.restore()
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
test('allows API keys to call private methods', async () => {
|
|
180
|
+
const fetch = mockRpc()
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const app = TestApp.create()
|
|
184
|
+
const response = await app.fetch(
|
|
185
|
+
new Request('http://tempo-api.test/rpc', {
|
|
186
|
+
body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'tempo_fundAddress' }),
|
|
187
|
+
headers: { 'tempo-api-key': TestApp.key.token },
|
|
188
|
+
method: 'POST',
|
|
189
|
+
}),
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
expect(response.status).toMatchInlineSnapshot(`200`)
|
|
193
|
+
expect(fetch.calls[0]?.body).toMatchInlineSnapshot(
|
|
194
|
+
`"{"id":1,"jsonrpc":"2.0","method":"tempo_fundAddress"}"`,
|
|
195
|
+
)
|
|
196
|
+
} finally {
|
|
197
|
+
fetch.restore()
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
|
|
125
201
|
test('uses the requested chain id for upstream URL resolution', async () => {
|
|
126
202
|
const fetch = mockRpc()
|
|
127
203
|
|
|
@@ -143,9 +143,22 @@ export function rpc() {
|
|
|
143
143
|
summary: 'Call JSON-RPC',
|
|
144
144
|
tags: ['RPC'],
|
|
145
145
|
}),
|
|
146
|
-
(c) => {
|
|
146
|
+
async (c) => {
|
|
147
147
|
if (Auth.narrowAccess) return Auth.accessError(c)
|
|
148
148
|
|
|
149
|
+
if (requiresApiKey(c)) {
|
|
150
|
+
const body = await c.req.raw
|
|
151
|
+
.clone()
|
|
152
|
+
.json()
|
|
153
|
+
.catch(() => undefined)
|
|
154
|
+
if (!isPublicRequest(body))
|
|
155
|
+
return Response.error(c, {
|
|
156
|
+
code: 'api_key_missing',
|
|
157
|
+
message: 'Missing API key',
|
|
158
|
+
status: 401,
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
149
162
|
const chainId = resolveChainId(c)
|
|
150
163
|
if (!chainId)
|
|
151
164
|
return Response.error(c, {
|
|
@@ -161,6 +174,23 @@ export function rpc() {
|
|
|
161
174
|
)
|
|
162
175
|
}
|
|
163
176
|
|
|
177
|
+
function requiresApiKey(c: Context<App.Environment>) {
|
|
178
|
+
if (!c.get('auth')) return false
|
|
179
|
+
const principal = Auth.getPrincipal(c)
|
|
180
|
+
return principal?.type !== 'api_key' && principal?.type !== 'super_admin'
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function isPublicRequest(body: unknown): boolean {
|
|
184
|
+
const requests = Array.isArray(body) ? body : [body]
|
|
185
|
+
return requests.length > 0 && requests.every((request) => isPublicMethod(request))
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isPublicMethod(request: unknown): boolean {
|
|
189
|
+
if (!request || typeof request !== 'object') return false
|
|
190
|
+
const method = (request as Record<string, unknown>)['method']
|
|
191
|
+
return typeof method === 'string' && method.startsWith('eth_')
|
|
192
|
+
}
|
|
193
|
+
|
|
164
194
|
async function passthrough(
|
|
165
195
|
c: Context<App.Environment>,
|
|
166
196
|
chainId: z.output<typeof Schema.ChainId>,
|
|
@@ -1151,7 +1151,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
1151
1151
|
// the real keyset/`toBlock` SQL and decode path end to end — no fabricated rows.
|
|
1152
1152
|
const realTidx = Tidx.getClient({
|
|
1153
1153
|
chainId: 42431,
|
|
1154
|
-
tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.
|
|
1154
|
+
tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.TIDX_BASIC_AUTH },
|
|
1155
1155
|
})
|
|
1156
1156
|
// The monitoring scanners (`log:emitted`/`block:created`/`transaction:included`)
|
|
1157
1157
|
// read the same immutable historical window over real RPC (chain 42431 →
|
|
@@ -533,7 +533,7 @@ export namespace schema {
|
|
|
533
533
|
.string()
|
|
534
534
|
.check(
|
|
535
535
|
z.describe('Webhook subscription ID (`wh_…`).'),
|
|
536
|
-
z.meta({ examples: ['
|
|
536
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
537
537
|
),
|
|
538
538
|
lastDeliveryAt: z
|
|
539
539
|
.optional(z.iso.datetime())
|
|
@@ -594,7 +594,10 @@ export namespace schema {
|
|
|
594
594
|
),
|
|
595
595
|
id: z
|
|
596
596
|
.string()
|
|
597
|
-
.check(
|
|
597
|
+
.check(
|
|
598
|
+
z.describe('Webhook delivery ID (`whd_…`).'),
|
|
599
|
+
z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
|
|
600
|
+
),
|
|
598
601
|
requestUrl: z
|
|
599
602
|
.string()
|
|
600
603
|
.check(
|
|
@@ -620,7 +623,7 @@ export namespace schema {
|
|
|
620
623
|
.string()
|
|
621
624
|
.check(
|
|
622
625
|
z.describe('Subscription ID (`wh_…`) this delivery belongs to.'),
|
|
623
|
-
z.meta({ examples: ['
|
|
626
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
624
627
|
),
|
|
625
628
|
})
|
|
626
629
|
.check(z.describe('One attempt by Tempo to deliver an event to your webhook URL.'))
|
|
@@ -901,7 +904,7 @@ export namespace schema {
|
|
|
901
904
|
.string()
|
|
902
905
|
.check(
|
|
903
906
|
z.describe('Subscription ID (`wh_…`) that produced this delivery.'),
|
|
904
|
-
z.meta({ examples: ['
|
|
907
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
905
908
|
),
|
|
906
909
|
}
|
|
907
910
|
|
|
@@ -1075,7 +1078,7 @@ export namespace schema {
|
|
|
1075
1078
|
.string()
|
|
1076
1079
|
.check(
|
|
1077
1080
|
z.describe('Webhook subscription ID (`wh_…`).'),
|
|
1078
|
-
z.meta({ examples: ['
|
|
1081
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
1079
1082
|
),
|
|
1080
1083
|
})
|
|
1081
1084
|
.check(z.describe('Path parameters for a webhook subscription request.'))
|
|
@@ -1158,13 +1161,13 @@ export namespace schema {
|
|
|
1158
1161
|
.string()
|
|
1159
1162
|
.check(
|
|
1160
1163
|
z.describe('Delivery ID (`whd_…`) you want Tempo to replay.'),
|
|
1161
|
-
z.meta({ examples: ['
|
|
1164
|
+
z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
|
|
1162
1165
|
),
|
|
1163
1166
|
id: z
|
|
1164
1167
|
.string()
|
|
1165
1168
|
.check(
|
|
1166
1169
|
z.describe('Webhook subscription ID (`wh_…`).'),
|
|
1167
|
-
z.meta({ examples: ['
|
|
1170
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
1168
1171
|
),
|
|
1169
1172
|
})
|
|
1170
1173
|
.check(z.describe('Path parameters for retrying a webhook delivery.'))
|
|
@@ -1209,7 +1212,7 @@ export namespace schema {
|
|
|
1209
1212
|
.string()
|
|
1210
1213
|
.check(
|
|
1211
1214
|
z.describe('ID of the webhook subscription that was deleted.'),
|
|
1212
|
-
z.meta({ examples: ['
|
|
1215
|
+
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
1213
1216
|
),
|
|
1214
1217
|
})
|
|
1215
1218
|
.check(z.describe('Confirmation that the webhook subscription was deleted.'))
|
package/src/apps/docs/App.ts
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
+
import type { Context } from 'hono'
|
|
1
2
|
import { Hono } from 'hono'
|
|
2
|
-
import { Handler as vocs_Handler } from 'vocs/server'
|
|
3
|
+
import type { Handler as vocs_Handler } from 'vocs/server'
|
|
3
4
|
|
|
4
5
|
import type * as App from '../../App.js'
|
|
5
6
|
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
7
|
|
|
10
8
|
/**
|
|
11
9
|
* The docs route group: the Vocs API reference served at the app root.
|
|
12
10
|
*
|
|
13
11
|
* ```ts
|
|
14
12
|
* import { docs } from 'tapimo/docs'
|
|
15
|
-
* App.create(options).route('/', data()).route('/',
|
|
13
|
+
* App.create(options).route('/', data()).route('/', management()).route('/', docs())
|
|
16
14
|
* ```
|
|
17
15
|
*
|
|
18
16
|
* The group registers no routes itself: it carries a reference factory (via
|
|
@@ -23,21 +21,26 @@ import { logoUrl } from './logo.js'
|
|
|
23
21
|
*
|
|
24
22
|
* Lives in the `tapimo/docs` subpath (never re-exported from `tapimo/apps`) so
|
|
25
23
|
* the Vocs renderer and its multi-MB icon/font data are bundled only by
|
|
26
|
-
* deployments that actually serve docs.
|
|
24
|
+
* deployments that actually serve docs. Even then the renderer loads lazily on
|
|
25
|
+
* the first docs request (see `reference.ts`), so API traffic and isolate
|
|
26
|
+
* startup never pay for it.
|
|
27
27
|
*/
|
|
28
28
|
export function docs(options: docs.Options = {}) {
|
|
29
29
|
return Metadata.attach(new Hono<App.Environment>(), {
|
|
30
|
-
docs: ({ spec }) =>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
docs: ({ spec }) => {
|
|
31
|
+
// Memoized across requests: all docs traffic shares one handler.
|
|
32
|
+
let handler: Promise<Hono> | undefined
|
|
33
|
+
return new Hono<App.Environment>().get('*', async (c, next) => {
|
|
34
|
+
handler ??= import('./reference.js').then((m) =>
|
|
35
|
+
m.create({ mount: mountFromRoutePath(c.req.routePath), spec, vocs: options }),
|
|
36
|
+
)
|
|
37
|
+
const response = await (await handler).fetch(c.req.raw, c.env, executionCtx(c))
|
|
38
|
+
// Inner 404 means "not a docs route" (`fallback: 'next'` semantics):
|
|
39
|
+
// defer to the host app's later routes / JSON `notFound`.
|
|
40
|
+
if (response.status === 404) return next()
|
|
41
|
+
return response
|
|
42
|
+
})
|
|
43
|
+
},
|
|
41
44
|
})
|
|
42
45
|
}
|
|
43
46
|
|
|
@@ -46,91 +49,17 @@ export declare namespace docs {
|
|
|
46
49
|
type Options = NonNullable<Parameters<typeof vocs_Handler.openApi>[0]['vocs']>
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
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;
|
|
52
|
+
/** Derives the host mount prefix from Hono's matched `routePath` (`/api/*` → `/api`, `/*` → ``). */
|
|
53
|
+
function mountFromRoutePath(routePath: string) {
|
|
54
|
+
return routePath.replace(/\*+$/, '').replace(/\/+$/, '')
|
|
88
55
|
}
|
|
89
56
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
|
57
|
+
// `c.executionCtx` throws outside Workers (tests, Node); docs rendering never
|
|
58
|
+
// uses `waitUntil`, so absence is fine.
|
|
59
|
+
function executionCtx(c: Context) {
|
|
60
|
+
try {
|
|
61
|
+
return c.executionCtx
|
|
62
|
+
} catch {
|
|
63
|
+
return undefined
|
|
124
64
|
}
|
|
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
65
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Hono } from 'hono'
|
|
2
|
+
import { Handler as vocs_Handler } from 'vocs/server'
|
|
3
|
+
|
|
4
|
+
import type * as App from '../../App.js'
|
|
5
|
+
import openrpcSpec from '../../openrpc.json' with { type: 'json' }
|
|
6
|
+
import type { docs } from './App.js'
|
|
7
|
+
import { pilatFontFaces } from './fonts.js'
|
|
8
|
+
import { logoUrl } from './logo.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Builds the Vocs reference handler. Loaded via dynamic import on the first
|
|
12
|
+
* docs request (see `docs()` in `App.ts`), keeping the multi-MB renderer off
|
|
13
|
+
* isolate startup.
|
|
14
|
+
*/
|
|
15
|
+
export function create(options: create.Options): Hono {
|
|
16
|
+
const { mount, spec, vocs } = options
|
|
17
|
+
const handler = vocs_Handler.openApi(
|
|
18
|
+
{
|
|
19
|
+
// Inline the OpenRPC doc so vocs expands it without a self-subrequest
|
|
20
|
+
// (see `inlineOpenrpc`); the public `/openapi.json` keeps the URL ref.
|
|
21
|
+
spec: () => spec().then(inlineOpenrpc),
|
|
22
|
+
sidebar: { collapsed: true },
|
|
23
|
+
vocs: { logoUrl, title: 'Tempo API Reference', ...vocs },
|
|
24
|
+
},
|
|
25
|
+
{ css, fallback: 'next' },
|
|
26
|
+
)
|
|
27
|
+
if (!mount) return handler
|
|
28
|
+
// Re-mount under the host prefix so the handler's `routePath`-derived mount
|
|
29
|
+
// (asset link bases, known-route checks) matches a direct `.route()` mount.
|
|
30
|
+
return new Hono().route(mount, handler)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export declare namespace create {
|
|
34
|
+
/** Options for building the reference handler. */
|
|
35
|
+
type Options = {
|
|
36
|
+
/** Host mount prefix derived from the wrapper's matched `routePath` (`''` at root). */
|
|
37
|
+
mount: string
|
|
38
|
+
/** Memoized OpenAPI document builder — the same document served at `/openapi.json`. */
|
|
39
|
+
spec: App.create.DocsContext['spec']
|
|
40
|
+
/** Vocs reference options (theme, top navigation, logo, socials, …). */
|
|
41
|
+
vocs: docs.Options
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Custom CSS injected into the standalone reference's shell `<head>` (via
|
|
47
|
+
* `Handler.openApi(_, { css })`), after the Vocs design-system styles so it
|
|
48
|
+
* overrides them:
|
|
49
|
+
*
|
|
50
|
+
* - Page/surface backgrounds use Tempo's near-black dark palette and pure-white
|
|
51
|
+
* light palette via `light-dark(<light>, <dark>)`.
|
|
52
|
+
* - The dark border color is darkened (the light theme keeps its default).
|
|
53
|
+
* - Every corner is squared. The universal `!important` rule beats hard-coded
|
|
54
|
+
* `border-radius` values and inline styles (e.g. the Scalar playground), which
|
|
55
|
+
* overriding the radius scale variables alone would miss.
|
|
56
|
+
* - The default sans/body font is Pilat (Vocs reads `--vocs-font-family`); the
|
|
57
|
+
* webfont is embedded via {@link pilatFontFaces}. Body stays at the default
|
|
58
|
+
* weight (400); headings are pinned to 500, which renders Pilat Demi (the
|
|
59
|
+
* family has no 500 cut, so Demi covers the 500-600 range — see
|
|
60
|
+
* {@link pilatFontFaces}).
|
|
61
|
+
*/
|
|
62
|
+
const css = `${pilatFontFaces}
|
|
63
|
+
|
|
64
|
+
:root {
|
|
65
|
+
--vocs-font-family: "Pilat", Arial, Helvetica, sans-serif;
|
|
66
|
+
--vocs-background-color-primary: light-dark(#fafafa, #0a0a0a);
|
|
67
|
+
--vocs-background-color-surface: light-dark(#fff, #121212);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:is(h1, h2, h3, h4, h5, h6)[data-v] {
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Nudge the header logo a touch larger than the default max-h-7 (1.75rem). */
|
|
75
|
+
[data-v-logo-image] {
|
|
76
|
+
max-height: 2rem;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Sidebar leaf items render Regular (the nav's 450 default otherwise resolves to
|
|
80
|
+
* Demi via the 500-600 range). Group labels ([data-v-sidebar-section-header])
|
|
81
|
+
* keep their heavier weight. */
|
|
82
|
+
[data-v-sidebar-item] {
|
|
83
|
+
font-weight: 400;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
[data-vocs-theme='dark'] {
|
|
87
|
+
--vocs-color-gray4: oklch(20% 0 0);
|
|
88
|
+
--vocs-color-gray5: oklch(0.23 0 0);
|
|
89
|
+
--vocs-border-color-primary: oklch(0.25 0 0);
|
|
90
|
+
--vocs-border-color-secondary: oklch(0.25 0 0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
*,
|
|
94
|
+
*::before,
|
|
95
|
+
*::after {
|
|
96
|
+
border-radius: 0 !important;
|
|
97
|
+
}`
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Returns a shallow copy of `spec` with the JSON-RPC passthrough operation's
|
|
101
|
+
* `x-openrpc` replaced by the inline OpenRPC document, for the docs handler.
|
|
102
|
+
*
|
|
103
|
+
* Vocs expands `x-openrpc` at request time. A URL reference (as kept in the
|
|
104
|
+
* public `/openapi.json` by `App.create`'s `applyOpenrpcLink`) would make the
|
|
105
|
+
* docs worker fetch its own `/openrpc.json` — a self-subrequest that is
|
|
106
|
+
* unreliable on Cloudflare Workers and silently falls back to a single,
|
|
107
|
+
* unexpanded operation. Inlining the committed artifact keeps expansion
|
|
108
|
+
* deterministic across local and deployed environments, without bloating the
|
|
109
|
+
* public spec. Only the affected path/op are cloned; the rest of the (large)
|
|
110
|
+
* document is shared by reference.
|
|
111
|
+
*/
|
|
112
|
+
function inlineOpenrpc<spec extends { paths: Record<string, unknown> }>(spec: spec): spec {
|
|
113
|
+
const paths: Record<string, unknown> = {}
|
|
114
|
+
for (const [pathname, item] of Object.entries(spec.paths)) {
|
|
115
|
+
let next = item
|
|
116
|
+
if (isRecord(item))
|
|
117
|
+
for (const [method, op] of Object.entries(item))
|
|
118
|
+
if (isRpcOperation(op)) next = { ...item, [method]: { ...op, 'x-openrpc': openrpcSpec } }
|
|
119
|
+
paths[pathname] = next
|
|
120
|
+
}
|
|
121
|
+
return { ...spec, paths }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// The JSON-RPC passthrough's operation id, set by its route definition and
|
|
125
|
+
// targeted by `App.create`'s `applyOpenrpcLink`.
|
|
126
|
+
function isRpcOperation(op: unknown): op is Record<string, unknown> {
|
|
127
|
+
return isRecord(op) && op['operationId'] === 'rpcRequest'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
131
|
+
return !!value && typeof value === 'object' && !Array.isArray(value)
|
|
132
|
+
}
|
package/src/apps/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { data } from './data/index.js'
|
|
2
|
-
export {
|
|
1
|
+
export { data, FundingRouteProviders } from './data/index.js'
|
|
2
|
+
export { management } from './management/index.js'
|
|
3
|
+
export { mcp } from './mcp.js'
|
|
3
4
|
export { relay } from './relay/index.js'
|