tapimo 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -16
- package/dist/ApiKey.d.ts +4 -1
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +6 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +98 -3
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +150 -1
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +7917 -2315
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +141 -329
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +20 -4
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +23 -4
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +2 -2
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +2 -2
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +203 -120
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +111 -6
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +67 -0
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +12 -1
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/scopes.js +3 -0
- package/dist/admin/apps/scopes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +116 -116
- package/dist/admin/apps/verified-tokens.js +1 -1
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +13 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +151 -0
- package/dist/analytics/Analytics.d.ts.map +1 -0
- package/dist/analytics/Analytics.js +212 -0
- package/dist/analytics/Analytics.js.map +1 -0
- package/dist/analytics/tables/requestEvents.d.ts +215 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -0
- package/dist/analytics/tables/requestEvents.js +264 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -0
- package/dist/apps/data/App.d.ts +19576 -0
- package/dist/apps/data/App.d.ts.map +1 -0
- package/dist/apps/data/App.js +272 -0
- package/dist/apps/data/App.js.map +1 -0
- package/dist/apps/data/index.d.ts +3 -0
- package/dist/apps/data/index.d.ts.map +1 -0
- package/dist/apps/data/index.js +3 -0
- package/dist/apps/data/index.js.map +1 -0
- package/dist/apps/{activities.d.ts → data/routes/activities.d.ts} +32 -32
- package/dist/apps/{activities.d.ts.map → data/routes/activities.d.ts.map} +1 -1
- package/dist/apps/{activities.js → data/routes/activities.js} +13 -13
- package/dist/apps/data/routes/activities.js.map +1 -0
- package/dist/apps/{addresses.d.ts → data/routes/addresses.d.ts} +22 -22
- package/dist/apps/{addresses.d.ts.map → data/routes/addresses.d.ts.map} +1 -1
- package/dist/apps/{addresses.js → data/routes/addresses.js} +5 -5
- package/dist/apps/data/routes/addresses.js.map +1 -0
- package/dist/apps/{balances.d.ts → data/routes/balances.d.ts} +4 -4
- package/dist/apps/data/routes/balances.d.ts.map +1 -0
- package/dist/apps/{balances.js → data/routes/balances.js} +42 -11
- package/dist/apps/data/routes/balances.js.map +1 -0
- package/dist/apps/{blocks.d.ts → data/routes/blocks.d.ts} +47 -47
- package/dist/apps/data/routes/blocks.d.ts.map +1 -0
- package/dist/apps/{blocks.js → data/routes/blocks.js} +13 -13
- package/dist/apps/data/routes/blocks.js.map +1 -0
- package/dist/apps/{coingecko.d.ts → data/routes/coingecko.d.ts} +8 -8
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -0
- package/dist/apps/{coingecko.js → data/routes/coingecko.js} +13 -13
- package/dist/apps/data/routes/coingecko.js.map +1 -0
- package/dist/apps/{exchanges.d.ts → data/routes/exchanges.d.ts} +108 -108
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -0
- package/dist/apps/{exchanges.js → data/routes/exchanges.js} +19 -19
- package/dist/apps/data/routes/exchanges.js.map +1 -0
- package/dist/apps/{fee-amm.d.ts → data/routes/fee-amm.d.ts} +39 -39
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -0
- package/dist/apps/{fee-amm.js → data/routes/fee-amm.js} +17 -17
- package/dist/apps/data/routes/fee-amm.js.map +1 -0
- package/dist/apps/data/routes/funding.d.ts +765 -0
- package/dist/apps/data/routes/funding.d.ts.map +1 -0
- package/dist/apps/data/routes/funding.js +383 -0
- package/dist/apps/data/routes/funding.js.map +1 -0
- package/dist/apps/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
- package/dist/apps/data/routes/indexer.d.ts.map +1 -0
- package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
- package/dist/apps/data/routes/indexer.js.map +1 -0
- package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +49 -49
- package/dist/apps/data/routes/receipts.d.ts.map +1 -0
- package/dist/apps/{receipts.js → data/routes/receipts.js} +14 -20
- package/dist/apps/data/routes/receipts.js.map +1 -0
- package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +33 -40
- package/dist/apps/data/routes/rpc.d.ts.map +1 -0
- package/dist/apps/{rpc.js → data/routes/rpc.js} +35 -7
- package/dist/apps/data/routes/rpc.js.map +1 -0
- package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +40 -40
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
- package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
- package/dist/apps/data/routes/tokenlist.js.map +1 -0
- package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +468 -468
- package/dist/apps/data/routes/tokens.d.ts.map +1 -0
- package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
- package/dist/apps/data/routes/tokens.js.map +1 -0
- package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +304 -304
- package/dist/apps/data/routes/transactions.d.ts.map +1 -0
- package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
- package/dist/apps/data/routes/transactions.js.map +1 -0
- package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +62 -62
- package/dist/apps/data/routes/transfers.d.ts.map +1 -0
- package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
- package/dist/apps/data/routes/transfers.js.map +1 -0
- package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +6 -6
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
- package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
- package/dist/apps/data/routes/verified-tokens.js.map +1 -0
- package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +17 -17
- package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
- package/dist/apps/{webhooks.js → data/routes/webhooks.js} +38 -34
- package/dist/apps/data/routes/webhooks.js.map +1 -0
- package/dist/apps/docs/App.d.ts +29 -0
- package/dist/apps/docs/App.d.ts.map +1 -0
- package/dist/apps/docs/App.js +54 -0
- package/dist/apps/docs/App.js.map +1 -0
- package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
- package/dist/apps/docs/fonts.d.ts.map +1 -0
- package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
- package/dist/apps/docs/fonts.js.map +1 -0
- package/dist/apps/docs/index.d.ts +2 -0
- package/dist/apps/docs/index.d.ts.map +1 -0
- package/dist/apps/docs/index.js +2 -0
- package/dist/apps/docs/index.js.map +1 -0
- package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
- package/dist/apps/docs/logo.d.ts.map +1 -0
- package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
- package/dist/apps/docs/logo.js.map +1 -0
- package/dist/apps/docs/reference.d.ts +21 -0
- package/dist/apps/docs/reference.d.ts.map +1 -0
- package/dist/apps/docs/reference.js +112 -0
- package/dist/apps/docs/reference.js.map +1 -0
- package/dist/apps/index.d.ts +5 -0
- package/dist/apps/index.d.ts.map +1 -0
- package/dist/apps/index.js +5 -0
- package/dist/apps/index.js.map +1 -0
- package/dist/apps/mcp.d.ts +76 -0
- package/dist/apps/mcp.d.ts.map +1 -0
- package/dist/apps/mcp.js +188 -0
- package/dist/apps/mcp.js.map +1 -0
- package/dist/apps/metadata.d.ts +7 -0
- package/dist/apps/metadata.d.ts.map +1 -0
- package/dist/apps/metadata.js +15 -0
- package/dist/apps/metadata.js.map +1 -0
- package/dist/apps/platform/App.d.ts +5262 -0
- package/dist/apps/platform/App.d.ts.map +1 -0
- package/dist/apps/platform/App.js +84 -0
- package/dist/apps/platform/App.js.map +1 -0
- package/dist/apps/platform/Billing.d.ts +279 -0
- package/dist/apps/platform/Billing.d.ts.map +1 -0
- package/dist/apps/platform/Billing.js +477 -0
- package/dist/apps/platform/Billing.js.map +1 -0
- package/dist/apps/platform/index.d.ts +3 -0
- package/dist/apps/platform/index.d.ts.map +1 -0
- package/dist/apps/platform/index.js +3 -0
- package/dist/apps/platform/index.js.map +1 -0
- package/dist/apps/platform/routes/api-keys.d.ts +973 -0
- package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/platform/routes/api-keys.js +430 -0
- package/dist/apps/platform/routes/api-keys.js.map +1 -0
- package/dist/apps/platform/routes/billing.d.ts +1520 -0
- package/dist/apps/platform/routes/billing.d.ts.map +1 -0
- package/dist/apps/platform/routes/billing.js +795 -0
- package/dist/apps/platform/routes/billing.js.map +1 -0
- package/dist/apps/platform/routes/invitations.d.ts +851 -0
- package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
- package/dist/apps/platform/routes/invitations.js +471 -0
- package/dist/apps/platform/routes/invitations.js.map +1 -0
- package/dist/apps/platform/routes/me.d.ts +95 -0
- package/dist/apps/platform/routes/me.d.ts.map +1 -0
- package/dist/apps/platform/routes/me.js +81 -0
- package/dist/apps/platform/routes/me.js.map +1 -0
- package/dist/apps/platform/routes/members.d.ts +554 -0
- package/dist/apps/platform/routes/members.d.ts.map +1 -0
- package/dist/apps/platform/routes/members.js +251 -0
- package/dist/apps/platform/routes/members.js.map +1 -0
- package/dist/apps/platform/routes/orgs.d.ts +596 -0
- package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
- package/dist/apps/platform/routes/orgs.js +276 -0
- package/dist/apps/platform/routes/orgs.js.map +1 -0
- package/dist/apps/platform/routes/projects.d.ts +740 -0
- package/dist/apps/platform/routes/projects.d.ts.map +1 -0
- package/dist/apps/platform/routes/projects.js +286 -0
- package/dist/apps/platform/routes/projects.js.map +1 -0
- package/dist/apps/platform/routes/scopes.d.ts +107 -0
- package/dist/apps/platform/routes/scopes.d.ts.map +1 -0
- package/dist/apps/platform/routes/scopes.js +66 -0
- package/dist/apps/platform/routes/scopes.js.map +1 -0
- package/dist/apps/platform/routes/usage.d.ts +588 -0
- package/dist/apps/platform/routes/usage.d.ts.map +1 -0
- package/dist/apps/platform/routes/usage.js +391 -0
- package/dist/apps/platform/routes/usage.js.map +1 -0
- package/dist/apps/relay/App.d.ts +44 -0
- package/dist/apps/relay/App.d.ts.map +1 -0
- package/dist/apps/relay/App.js +211 -0
- package/dist/apps/relay/App.js.map +1 -0
- package/dist/apps/relay/Sponsorships.d.ts +107 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
- package/dist/apps/relay/Sponsorships.js +194 -0
- package/dist/apps/relay/Sponsorships.js.map +1 -0
- package/dist/apps/relay/index.d.ts +3 -0
- package/dist/apps/relay/index.d.ts.map +1 -0
- package/dist/apps/relay/index.js +3 -0
- package/dist/apps/relay/index.js.map +1 -0
- package/dist/cli/Cli.d.ts +9 -2
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +12 -4
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +5 -1
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +82 -3
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/db/Db.d.ts +17 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +254 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +159 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +187 -2
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/billingSettings.d.ts +55 -0
- package/dist/db/tables/billingSettings.d.ts.map +1 -0
- package/dist/db/tables/billingSettings.js +70 -0
- package/dist/db/tables/billingSettings.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +84 -0
- package/dist/db/tables/invitations.d.ts.map +1 -0
- package/dist/db/tables/invitations.js +165 -0
- package/dist/db/tables/invitations.js.map +1 -0
- package/dist/db/tables/memberships.d.ts +108 -0
- package/dist/db/tables/memberships.d.ts.map +1 -0
- package/dist/db/tables/memberships.js +153 -0
- package/dist/db/tables/memberships.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +48 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +97 -2
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +65 -0
- package/dist/db/tables/projects.d.ts.map +1 -0
- package/dist/db/tables/projects.js +75 -0
- package/dist/db/tables/projects.js.map +1 -0
- package/dist/db/tables/requestUsage.d.ts +121 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -0
- package/dist/db/tables/requestUsage.js +150 -0
- package/dist/db/tables/requestUsage.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +239 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
- package/dist/db/tables/sponsoredTransactions.js +314 -0
- package/dist/db/tables/sponsoredTransactions.js.map +1 -0
- package/dist/db/tables/stripeCustomers.d.ts +81 -0
- package/dist/db/tables/stripeCustomers.d.ts.map +1 -0
- package/dist/db/tables/stripeCustomers.js +120 -0
- package/dist/db/tables/stripeCustomers.js.map +1 -0
- package/dist/db/tables/users.d.ts +48 -0
- package/dist/db/tables/users.d.ts.map +1 -0
- package/dist/db/tables/users.js +65 -0
- package/dist/db/tables/users.js.map +1 -0
- package/dist/handlers/internal/executionError.d.ts.map +1 -1
- package/dist/handlers/internal/executionError.js +2 -0
- package/dist/handlers/internal/executionError.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +2 -6
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +11 -36
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +35 -2
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +53 -14
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts +10 -3
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +14 -6
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/handlers/relay.d.ts +6 -2
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +16 -2
- package/dist/handlers/relay.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +222 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +625 -74
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +4 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts +10 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +39 -8
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Fees.d.ts +27 -0
- package/dist/internal/Fees.d.ts.map +1 -0
- package/dist/internal/Fees.js +48 -0
- package/dist/internal/Fees.js.map +1 -0
- package/dist/internal/FundingRoutes.d.ts +183 -0
- package/dist/internal/FundingRoutes.d.ts.map +1 -0
- package/dist/internal/FundingRoutes.js +490 -0
- package/dist/internal/FundingRoutes.js.map +1 -0
- package/dist/internal/Id.d.ts +15 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +22 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/Log.d.ts +9 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +7 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +10 -20
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +8 -58
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +25 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +51 -0
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Schema.d.ts +8 -0
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +7 -0
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +7 -1
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +16 -2
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Viem.d.ts +84 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Webhooks.d.ts +1 -1
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +3 -3
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +33 -6
- package/src/ApiKey.ts +10 -2
- package/src/ApiKeys.test.ts +155 -1
- package/src/ApiKeys.ts +203 -1
- package/src/App.test.ts +64 -75741
- package/src/App.ts +218 -420
- package/src/Client.test-d.ts +657 -15
- package/src/Scope.ts +26 -4
- package/src/Webhooks.ts +2 -2
- package/src/admin/apps/api-keys.test.ts +51 -0
- package/src/admin/apps/api-keys.ts +84 -0
- package/src/admin/apps/scopes.test.ts +11 -1
- package/src/admin/apps/scopes.ts +3 -0
- package/src/admin/apps/verified-tokens.ts +1 -1
- package/src/admin/ui/src/components/Page.tsx +2 -3
- package/src/admin/ui/src/routes/__root.tsx +2 -2
- package/src/admin/ui/src/routes/api-keys.tsx +2 -2
- package/src/admin/ui.generated.ts +13 -13
- package/src/analytics/Analytics.test.ts +527 -0
- package/src/analytics/Analytics.ts +318 -0
- package/src/analytics/tables/requestEvents.ts +523 -0
- package/src/apps/composition.test.ts +66 -0
- package/src/apps/data/App.test.ts +72 -0
- package/src/apps/data/App.ts +330 -0
- package/src/apps/data/index.ts +2 -0
- package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
- package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
- package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
- package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +2 -2
- package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
- package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +3 -3
- package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
- package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
- package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
- package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +1 -1
- package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
- package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
- package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
- package/src/apps/data/routes/funding.test.ts +214 -0
- package/src/apps/data/routes/funding.ts +584 -0
- package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +26 -5
- package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
- package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +3 -3
- package/src/apps/{receipts.ts → data/routes/receipts.ts} +15 -22
- package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +122 -7
- package/src/apps/{rpc.ts → data/routes/rpc.ts} +38 -8
- package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +3 -3
- package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
- package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +2 -2
- package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
- package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +3 -3
- package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
- package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +2 -2
- package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
- package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +3 -3
- package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
- package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +7 -7
- package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +50 -43
- package/src/apps/docs/App.ts +65 -0
- package/src/apps/docs/index.ts +1 -0
- package/src/apps/docs/reference.ts +132 -0
- package/src/apps/index.ts +4 -0
- package/src/apps/mcp.test.ts +206 -0
- package/src/apps/mcp.ts +250 -0
- package/src/apps/metadata.ts +23 -0
- package/src/apps/platform/App.ts +169 -0
- package/src/apps/platform/Billing.test.ts +530 -0
- package/src/apps/platform/Billing.ts +682 -0
- package/src/apps/platform/index.ts +2 -0
- package/src/apps/platform/routes/api-keys.test.ts +493 -0
- package/src/apps/platform/routes/api-keys.ts +543 -0
- package/src/apps/platform/routes/billing.test.ts +1100 -0
- package/src/apps/platform/routes/billing.ts +966 -0
- package/src/apps/platform/routes/invitations.test.ts +409 -0
- package/src/apps/platform/routes/invitations.ts +587 -0
- package/src/apps/platform/routes/me.test.ts +351 -0
- package/src/apps/platform/routes/me.ts +106 -0
- package/src/apps/platform/routes/members.test.ts +195 -0
- package/src/apps/platform/routes/members.ts +313 -0
- package/src/apps/platform/routes/orgs.test.ts +313 -0
- package/src/apps/platform/routes/orgs.ts +365 -0
- package/src/apps/platform/routes/projects.test.ts +181 -0
- package/src/apps/platform/routes/projects.ts +367 -0
- package/src/apps/platform/routes/scopes.test.ts +29 -0
- package/src/apps/platform/routes/scopes.ts +85 -0
- package/src/apps/platform/routes/usage.test.ts +422 -0
- package/src/apps/platform/routes/usage.ts +527 -0
- package/src/apps/relay/App.test.ts +933 -0
- package/src/apps/relay/App.ts +236 -0
- package/src/apps/relay/Sponsorships.test.ts +375 -0
- package/src/apps/relay/Sponsorships.ts +306 -0
- package/src/apps/relay/index.ts +2 -0
- package/src/cli/Cli.test.ts +25 -2
- package/src/cli/Cli.ts +18 -3
- package/src/cli/commands/admin.test.ts +83 -0
- package/src/cli/commands/admin.ts +91 -3
- package/src/db/Db.ts +296 -0
- package/src/db/Schema.ts +241 -2
- package/src/db/tables/billingSettings.test.ts +87 -0
- package/src/db/tables/billingSettings.ts +108 -0
- package/src/db/tables/invitations.ts +198 -0
- package/src/db/tables/memberships.ts +208 -0
- package/src/db/tables/organizations.test.ts +38 -2
- package/src/db/tables/organizations.ts +117 -2
- package/src/db/tables/projects.ts +107 -0
- package/src/db/tables/requestUsage.ts +231 -0
- package/src/db/tables/sponsoredTransactions.test.ts +325 -0
- package/src/db/tables/sponsoredTransactions.ts +464 -0
- package/src/db/tables/stripeCustomers.test.ts +109 -0
- package/src/db/tables/stripeCustomers.ts +162 -0
- package/src/db/tables/users.ts +85 -0
- package/src/handlers/internal/executionError.ts +2 -0
- package/src/handlers/internal/multisig.test.ts +84 -10
- package/src/handlers/internal/multisig.ts +15 -50
- package/src/handlers/internal/sponsorship.ts +106 -20
- package/src/handlers/internal/utils.ts +19 -7
- package/src/handlers/{internal/relay.localnet.test.ts → relay.test.ts} +2 -2
- package/src/handlers/relay.ts +23 -5
- package/src/index.ts +1 -0
- package/src/internal/Auth.test.ts +491 -25
- package/src/internal/Auth.ts +839 -84
- package/src/internal/Cache.ts +5 -1
- package/src/internal/Cursor.test.ts +3 -2
- package/src/internal/EdgeCache.test.ts +27 -4
- package/src/internal/EdgeCache.ts +47 -9
- package/src/internal/Fees.test.ts +32 -0
- package/src/internal/Fees.ts +51 -0
- package/src/internal/FundingRoutes.ts +583 -0
- package/src/internal/Id.test.ts +17 -0
- package/src/internal/Id.ts +24 -0
- package/src/internal/Log.test.ts +2 -1
- package/src/internal/Log.ts +16 -3
- package/src/internal/MetricSink.ts +1 -1
- package/src/internal/OpenApi.ts +12 -60
- package/src/internal/RateLimit.test.ts +84 -0
- package/src/internal/RateLimit.ts +70 -0
- package/src/internal/Response.ts +1 -1
- package/src/internal/Schema.ts +8 -0
- package/src/internal/Store.test.ts +52 -0
- package/src/internal/Store.ts +24 -5
- package/src/internal/Tidx.local.test.ts +1 -1
- package/src/internal/VerifiedTokens.test.ts +1 -1
- package/src/internal/WebhookDestination.test.ts +1 -1
- package/src/internal/Webhooks.test.ts +7 -7
- package/src/internal/Webhooks.ts +4 -4
- package/dist/apps/activities.js.map +0 -1
- package/dist/apps/addresses.js.map +0 -1
- package/dist/apps/balances.d.ts.map +0 -1
- package/dist/apps/balances.js.map +0 -1
- package/dist/apps/blocks.d.ts.map +0 -1
- package/dist/apps/blocks.js.map +0 -1
- package/dist/apps/coingecko.d.ts.map +0 -1
- package/dist/apps/coingecko.js.map +0 -1
- package/dist/apps/exchanges.d.ts.map +0 -1
- package/dist/apps/exchanges.js.map +0 -1
- package/dist/apps/fee-amm.d.ts.map +0 -1
- package/dist/apps/fee-amm.js.map +0 -1
- package/dist/apps/indexer.d.ts.map +0 -1
- package/dist/apps/indexer.js.map +0 -1
- package/dist/apps/receipts.d.ts.map +0 -1
- package/dist/apps/receipts.js.map +0 -1
- package/dist/apps/rpc.d.ts.map +0 -1
- package/dist/apps/rpc.js.map +0 -1
- package/dist/apps/tokenlist.d.ts.map +0 -1
- package/dist/apps/tokenlist.js.map +0 -1
- package/dist/apps/tokens.d.ts.map +0 -1
- package/dist/apps/tokens.js.map +0 -1
- package/dist/apps/transactions.d.ts.map +0 -1
- package/dist/apps/transactions.js.map +0 -1
- package/dist/apps/transfers.d.ts.map +0 -1
- package/dist/apps/transfers.js.map +0 -1
- package/dist/apps/verified-tokens.d.ts.map +0 -1
- package/dist/apps/verified-tokens.js.map +0 -1
- package/dist/apps/webhooks.js.map +0 -1
- package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
- package/dist/internal/OpenApi.fonts.js.map +0 -1
- package/dist/internal/OpenApi.logo.d.ts.map +0 -1
- package/dist/internal/OpenApi.logo.js.map +0 -1
- package/src/handlers/internal/multisig.localnet.test.ts +0 -146
- /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
- /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
package/src/ApiKeys.test.ts
CHANGED
|
@@ -168,8 +168,162 @@ describe('revoke', () => {
|
|
|
168
168
|
|
|
169
169
|
// The id index entry maps id -> record key; revoke uses it directly.
|
|
170
170
|
expect(await ApiKeys.revoke(state, record.id)).toBe(true)
|
|
171
|
-
//
|
|
171
|
+
// The record and both index entries are gone.
|
|
172
172
|
const { keys } = await state.list({ prefix: 'apikey' })
|
|
173
173
|
expect(keys).toMatchInlineSnapshot(`[]`)
|
|
174
174
|
})
|
|
175
175
|
})
|
|
176
|
+
|
|
177
|
+
describe('get', () => {
|
|
178
|
+
test('reads a record by id, null when absent', async () => {
|
|
179
|
+
const state = Store.memory()
|
|
180
|
+
const { record } = await ApiKeys.mint(state, {
|
|
181
|
+
orgId: 'org_a',
|
|
182
|
+
projectId: 'prj_a',
|
|
183
|
+
scopes: ['data:read'],
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
expect((await ApiKeys.get(state, record.id))?.projectId).toBe('prj_a')
|
|
187
|
+
expect(await ApiKeys.get(state, 'key_missing')).toBeNull()
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
describe('listByOrg', () => {
|
|
192
|
+
beforeEach(() => vi.useFakeTimers({ now: new Date('2026-01-01T00:00:00.000Z') }))
|
|
193
|
+
afterEach(() => vi.useRealTimers())
|
|
194
|
+
|
|
195
|
+
test('lists through the org index, newest first, filtered by project', async () => {
|
|
196
|
+
const state = Store.memory()
|
|
197
|
+
|
|
198
|
+
await ApiKeys.mint(state, { name: 'a', orgId: 'org_a', projectId: 'prj_a', scopes: ['data:read'] }) // prettier-ignore
|
|
199
|
+
vi.setSystemTime(new Date('2026-01-01T00:00:01.000Z'))
|
|
200
|
+
await ApiKeys.mint(state, { name: 'b', orgId: 'org_a', projectId: 'prj_b', scopes: ['data:read'] }) // prettier-ignore
|
|
201
|
+
await ApiKeys.mint(state, { name: 'c', orgId: 'org_b', scopes: ['data:read'] })
|
|
202
|
+
|
|
203
|
+
expect((await ApiKeys.listByOrg(state, 'org_a')).map((record) => record.name))
|
|
204
|
+
.toMatchInlineSnapshot(`
|
|
205
|
+
[
|
|
206
|
+
"b",
|
|
207
|
+
"a",
|
|
208
|
+
]
|
|
209
|
+
`)
|
|
210
|
+
expect(
|
|
211
|
+
(await ApiKeys.listByOrg(state, 'org_a', { projectId: 'prj_b' })).map(
|
|
212
|
+
(record) => record.name,
|
|
213
|
+
),
|
|
214
|
+
).toMatchInlineSnapshot(`
|
|
215
|
+
[
|
|
216
|
+
"b",
|
|
217
|
+
]
|
|
218
|
+
`)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test('skips and lazily cleans dangling index entries', async () => {
|
|
222
|
+
const state = Store.memory()
|
|
223
|
+
await ApiKeys.mint(state, { orgId: 'org_a', scopes: ['data:read'] })
|
|
224
|
+
|
|
225
|
+
// Simulate a record evicted out-of-band (e.g. native TTL), leaving the
|
|
226
|
+
// index entry behind.
|
|
227
|
+
const recordKey = (await state.list({ prefix: 'apikey:' })).keys[0]!.name
|
|
228
|
+
await state.delete(recordKey)
|
|
229
|
+
|
|
230
|
+
expect(await ApiKeys.listByOrg(state, 'org_a')).toEqual([])
|
|
231
|
+
expect((await state.list({ prefix: 'apikey_org:' })).keys).toMatchInlineSnapshot(`[]`)
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
describe('attribute', () => {
|
|
236
|
+
test('re-attributes org and project, moving the org index', async () => {
|
|
237
|
+
const state = Store.memory()
|
|
238
|
+
const { record, token } = await ApiKeys.mint(state, { orgId: 'org_a', scopes: ['data:read'] })
|
|
239
|
+
|
|
240
|
+
const updated = await ApiKeys.attribute(state, record.id, {
|
|
241
|
+
orgId: 'org_b',
|
|
242
|
+
projectId: 'prj_b',
|
|
243
|
+
})
|
|
244
|
+
expect(updated?.orgId).toBe('org_b')
|
|
245
|
+
expect(updated?.projectId).toBe('prj_b')
|
|
246
|
+
|
|
247
|
+
// The original token keeps resolving, now carrying the attribution.
|
|
248
|
+
const resolved = await ApiKeys.resolve(state, token)
|
|
249
|
+
expect(resolved?.orgId).toBe('org_b')
|
|
250
|
+
expect(resolved?.projectId).toBe('prj_b')
|
|
251
|
+
|
|
252
|
+
expect(await ApiKeys.listByOrg(state, 'org_a')).toEqual([])
|
|
253
|
+
expect((await ApiKeys.listByOrg(state, 'org_b')).map(({ id }) => id)).toEqual([record.id])
|
|
254
|
+
|
|
255
|
+
expect(await ApiKeys.attribute(state, 'key_missing', { projectId: 'prj_x' })).toBeNull()
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
describe('setBillingActive', () => {
|
|
260
|
+
test('stamps billingActive onto the org keys in the target environment only', async () => {
|
|
261
|
+
const state = Store.memory()
|
|
262
|
+
const { token: sandboxToken } = await ApiKeys.mint(state, {
|
|
263
|
+
environment: 'sandbox',
|
|
264
|
+
orgId: 'org_a',
|
|
265
|
+
scopes: ['data:read'],
|
|
266
|
+
})
|
|
267
|
+
const { token: prodToken } = await ApiKeys.mint(state, {
|
|
268
|
+
environment: 'production',
|
|
269
|
+
orgId: 'org_a',
|
|
270
|
+
scopes: ['data:read'],
|
|
271
|
+
})
|
|
272
|
+
const { token: otherToken } = await ApiKeys.mint(state, {
|
|
273
|
+
environment: 'sandbox',
|
|
274
|
+
orgId: 'org_b',
|
|
275
|
+
scopes: ['data:read'],
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
const updated = await ApiKeys.setBillingActive(state, {
|
|
279
|
+
active: true,
|
|
280
|
+
environment: 'sandbox',
|
|
281
|
+
orgId: 'org_a',
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
expect(updated).toBe(1)
|
|
285
|
+
expect((await ApiKeys.resolve(state, sandboxToken))?.billingActive).toBe(true)
|
|
286
|
+
// The production key and another org's sandbox key are untouched.
|
|
287
|
+
expect((await ApiKeys.resolve(state, prodToken))?.billingActive).toBeUndefined()
|
|
288
|
+
expect((await ApiKeys.resolve(state, otherToken))?.billingActive).toBeUndefined()
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
test('skips records already carrying the target value', async () => {
|
|
292
|
+
const state = Store.memory()
|
|
293
|
+
await ApiKeys.mint(state, {
|
|
294
|
+
billingActive: true,
|
|
295
|
+
environment: 'sandbox',
|
|
296
|
+
orgId: 'org_a',
|
|
297
|
+
scopes: ['data:read'],
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
expect(
|
|
301
|
+
await ApiKeys.setBillingActive(state, {
|
|
302
|
+
active: true,
|
|
303
|
+
environment: 'sandbox',
|
|
304
|
+
orgId: 'org_a',
|
|
305
|
+
}),
|
|
306
|
+
).toBe(0)
|
|
307
|
+
})
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
describe('backfill', () => {
|
|
311
|
+
test('rebuilds index entries for legacy records', async () => {
|
|
312
|
+
const state = Store.memory()
|
|
313
|
+
const { record, token } = await ApiKeys.mint(state, { orgId: 'org_a', scopes: ['data:read'] })
|
|
314
|
+
|
|
315
|
+
// Legacy state: records exist, index entries do not.
|
|
316
|
+
for (const { name } of (await state.list({ prefix: 'apikey_id:' })).keys)
|
|
317
|
+
await state.delete(name)
|
|
318
|
+
for (const { name } of (await state.list({ prefix: 'apikey_org:' })).keys)
|
|
319
|
+
await state.delete(name)
|
|
320
|
+
expect(await ApiKeys.listByOrg(state, 'org_a')).toEqual([])
|
|
321
|
+
|
|
322
|
+
expect(await ApiKeys.backfill(state)).toEqual({ indexed: 1, scanned: 1 })
|
|
323
|
+
|
|
324
|
+
expect((await ApiKeys.listByOrg(state, 'org_a')).map(({ id }) => id)).toEqual([record.id])
|
|
325
|
+
expect(await ApiKeys.resolve(state, token)).not.toBeNull()
|
|
326
|
+
// The id index is restored, so revoke-by-id works again.
|
|
327
|
+
expect(await ApiKeys.revoke(state, record.id)).toBe(true)
|
|
328
|
+
})
|
|
329
|
+
})
|
package/src/ApiKeys.ts
CHANGED
|
@@ -97,9 +97,11 @@ export async function mint(state: Store.State, input: MintInput): Promise<MintRe
|
|
|
97
97
|
orgId: data.orgId ?? id,
|
|
98
98
|
scopes: data.scopes,
|
|
99
99
|
tokenLast4: token.slice(-4),
|
|
100
|
+
...(data.billingActive === undefined ? {} : { billingActive: data.billingActive }),
|
|
100
101
|
...(data.createdBy === undefined ? {} : { createdBy: data.createdBy }),
|
|
101
102
|
...(data.expiresAt === undefined ? {} : { expiresAt: data.expiresAt }),
|
|
102
103
|
...(data.name === undefined ? {} : { name: data.name }),
|
|
104
|
+
...(data.projectId === undefined ? {} : { projectId: data.projectId }),
|
|
103
105
|
...(data.rateLimits === undefined ? {} : { rateLimits: data.rateLimits }),
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -113,6 +115,9 @@ export async function mint(state: Store.State, input: MintInput): Promise<MintRe
|
|
|
113
115
|
// token hash, unrecoverable from the id alone). Shares the record's TTL so
|
|
114
116
|
// both entries expire together.
|
|
115
117
|
await state.put(idKeyFor(record.id), recordKey, { ttl })
|
|
118
|
+
// Index `org → recordKey` (one entry per key, so concurrent mints never
|
|
119
|
+
// race a shared value) backing org-scoped listing without a full scan.
|
|
120
|
+
await state.put(orgKeyFor(record.orgId, record.id), recordKey, { ttl })
|
|
116
121
|
return { record, token }
|
|
117
122
|
}
|
|
118
123
|
|
|
@@ -129,6 +134,19 @@ export async function resolve(state: Store.State, token: string): Promise<ApiKey
|
|
|
129
134
|
return read(state, ApiKey.keyFor(token), Date.now())
|
|
130
135
|
}
|
|
131
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Reads a key record by id (metadata only — never the token), or `null`.
|
|
139
|
+
*
|
|
140
|
+
* @param state - The KV state store holding key records.
|
|
141
|
+
* @param id - The key id (`key_…`).
|
|
142
|
+
* @returns The record, or `null`.
|
|
143
|
+
*/
|
|
144
|
+
export async function get(state: Store.State, id: string): Promise<Record | null> {
|
|
145
|
+
const recordKey = await state.get(idKeyFor(id))
|
|
146
|
+
if (!recordKey) return null
|
|
147
|
+
return read(state, recordKey, Date.now())
|
|
148
|
+
}
|
|
149
|
+
|
|
132
150
|
/**
|
|
133
151
|
* Lists key records (metadata only — never tokens), newest first. Expired or
|
|
134
152
|
* catalog-invalid records are skipped.
|
|
@@ -160,7 +178,47 @@ export declare namespace list {
|
|
|
160
178
|
}
|
|
161
179
|
|
|
162
180
|
/**
|
|
163
|
-
*
|
|
181
|
+
* Lists an organization's key records through the org index (no full scan),
|
|
182
|
+
* newest first. Dangling index entries (revoked or expired records) are
|
|
183
|
+
* skipped and lazily deleted.
|
|
184
|
+
*
|
|
185
|
+
* @param state - The KV state store holding key records.
|
|
186
|
+
* @param orgId - The owning organization id (`org_…`).
|
|
187
|
+
* @param options - Optional environment/project filters.
|
|
188
|
+
* @returns The records.
|
|
189
|
+
*/
|
|
190
|
+
export async function listByOrg(
|
|
191
|
+
state: Store.State,
|
|
192
|
+
orgId: string,
|
|
193
|
+
options: listByOrg.Options = {},
|
|
194
|
+
): Promise<readonly Record[]> {
|
|
195
|
+
const { keys } = await state.list({ prefix: `${orgPrefix}${orgId}:` })
|
|
196
|
+
const records: Record[] = []
|
|
197
|
+
for (const { name } of keys) {
|
|
198
|
+
const recordKey = await state.get(name)
|
|
199
|
+
const record = recordKey ? await read(state, recordKey, Date.now()) : null
|
|
200
|
+
if (!record) {
|
|
201
|
+
await state.delete(name)
|
|
202
|
+
continue
|
|
203
|
+
}
|
|
204
|
+
if (options.environment && record.environment !== options.environment) continue
|
|
205
|
+
if (!options.projectId || record.projectId === options.projectId) records.push(record)
|
|
206
|
+
}
|
|
207
|
+
return records.sort((a, b) => b.createdAt.localeCompare(a.createdAt))
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export declare namespace listByOrg {
|
|
211
|
+
/** Options for {@link listByOrg}. */
|
|
212
|
+
type Options = {
|
|
213
|
+
/** Restrict results to keys in this environment. */
|
|
214
|
+
environment?: 'production' | 'sandbox' | undefined
|
|
215
|
+
/** Restrict results to keys attributed to this project. */
|
|
216
|
+
projectId?: string | undefined
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Revokes a key by id, deleting its record and index entries.
|
|
164
222
|
*
|
|
165
223
|
* @param state - The KV state store holding key records.
|
|
166
224
|
* @param id - The key id (`key_…`).
|
|
@@ -169,11 +227,147 @@ export declare namespace list {
|
|
|
169
227
|
export async function revoke(state: Store.State, id: string): Promise<boolean> {
|
|
170
228
|
const recordKey = await state.get(idKeyFor(id))
|
|
171
229
|
if (!recordKey) return false
|
|
230
|
+
// Parse loosely for the org index entry: even a record the catalog no
|
|
231
|
+
// longer validates must clean up its index on revoke.
|
|
232
|
+
const raw = await state.get(recordKey)
|
|
233
|
+
const orgId = (() => {
|
|
234
|
+
try {
|
|
235
|
+
return raw ? (JSON.parse(raw) as { orgId?: string }).orgId : undefined
|
|
236
|
+
} catch {
|
|
237
|
+
return undefined
|
|
238
|
+
}
|
|
239
|
+
})()
|
|
172
240
|
await state.delete(recordKey)
|
|
173
241
|
await state.delete(idKeyFor(id))
|
|
242
|
+
if (orgId) await state.delete(orgKeyFor(orgId, id))
|
|
174
243
|
return true
|
|
175
244
|
}
|
|
176
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Re-attributes a key to an organization and/or project, rewriting its record
|
|
248
|
+
* in place (same token hash) and moving the org index entry when the org
|
|
249
|
+
* changes. The backfill path for legacy keys.
|
|
250
|
+
*
|
|
251
|
+
* @param state - The KV state store holding key records.
|
|
252
|
+
* @param id - The key id (`key_…`).
|
|
253
|
+
* @param input - The attribution to apply.
|
|
254
|
+
* @returns The updated record, or `null` when the key is absent.
|
|
255
|
+
*/
|
|
256
|
+
export async function attribute(
|
|
257
|
+
state: Store.State,
|
|
258
|
+
id: string,
|
|
259
|
+
input: attribute.Input,
|
|
260
|
+
): Promise<Record | null> {
|
|
261
|
+
const recordKey = await state.get(idKeyFor(id))
|
|
262
|
+
if (!recordKey) return null
|
|
263
|
+
const record = await read(state, recordKey, Date.now())
|
|
264
|
+
if (!record) return null
|
|
265
|
+
|
|
266
|
+
const updated: Record = {
|
|
267
|
+
...record,
|
|
268
|
+
...(input.orgId === undefined ? {} : { orgId: input.orgId }),
|
|
269
|
+
...(input.projectId === undefined ? {} : { projectId: input.projectId }),
|
|
270
|
+
}
|
|
271
|
+
const ttl =
|
|
272
|
+
updated.expiresAt === undefined
|
|
273
|
+
? undefined
|
|
274
|
+
: Math.max(1, Date.parse(updated.expiresAt) - Date.now())
|
|
275
|
+
await state.put(recordKey, JSON.stringify(updated), { ttl })
|
|
276
|
+
if (updated.orgId !== record.orgId) await state.delete(orgKeyFor(record.orgId, id))
|
|
277
|
+
await state.put(orgKeyFor(updated.orgId, id), recordKey, { ttl })
|
|
278
|
+
return updated
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export declare namespace attribute {
|
|
282
|
+
/** Attribution applied by {@link attribute}; omitted fields keep their current value. */
|
|
283
|
+
type Input = {
|
|
284
|
+
/** New owning organization id (`org_…`). */
|
|
285
|
+
orgId?: string | undefined
|
|
286
|
+
/** New owning project id (`prj_…`). */
|
|
287
|
+
projectId?: string | undefined
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Stamps `billingActive` onto every key an organization owns in an environment,
|
|
293
|
+
* re-syncing the snapshot the auth path reads when billing flips (activation or
|
|
294
|
+
* lapse). Called off the request path from the billing writer, so the hot path
|
|
295
|
+
* never reads billing state. Records already carrying the target value are left
|
|
296
|
+
* untouched.
|
|
297
|
+
*
|
|
298
|
+
* @param state - The KV state store holding key records.
|
|
299
|
+
* @param options - Owner, environment, and the new billing-active value.
|
|
300
|
+
* @returns The number of records updated.
|
|
301
|
+
*/
|
|
302
|
+
export async function setBillingActive(
|
|
303
|
+
state: Store.State,
|
|
304
|
+
options: setBillingActive.Options,
|
|
305
|
+
): Promise<number> {
|
|
306
|
+
const { active, environment, orgId } = options
|
|
307
|
+
const records = await listByOrg(state, orgId, { environment })
|
|
308
|
+
let updated = 0
|
|
309
|
+
for (const record of records) {
|
|
310
|
+
if (record.billingActive === active) continue
|
|
311
|
+
const recordKey = await state.get(idKeyFor(record.id))
|
|
312
|
+
if (!recordKey) continue
|
|
313
|
+
const next: Record = { ...record, billingActive: active }
|
|
314
|
+
const ttl =
|
|
315
|
+
next.expiresAt === undefined
|
|
316
|
+
? undefined
|
|
317
|
+
: Math.max(1, Date.parse(next.expiresAt) - Date.now())
|
|
318
|
+
await state.put(recordKey, JSON.stringify(next), { ttl })
|
|
319
|
+
updated += 1
|
|
320
|
+
}
|
|
321
|
+
return updated
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export declare namespace setBillingActive {
|
|
325
|
+
/** Options for {@link setBillingActive}. */
|
|
326
|
+
type Options = {
|
|
327
|
+
/** The new billing-active value to stamp. */
|
|
328
|
+
active: boolean
|
|
329
|
+
/** Environment whose keys are re-stamped. */
|
|
330
|
+
environment: 'production' | 'sandbox'
|
|
331
|
+
/** Owning organization id (`org_…`). */
|
|
332
|
+
orgId: string
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Rebuilds the `id` and `org` index entries for every stored record — the
|
|
338
|
+
* run-once backfill making legacy keys visible to org-scoped listing. Records
|
|
339
|
+
* themselves are never modified, so existing tokens keep resolving.
|
|
340
|
+
*
|
|
341
|
+
* @param state - The KV state store holding key records.
|
|
342
|
+
* @returns Scanned and indexed record counts.
|
|
343
|
+
*/
|
|
344
|
+
export async function backfill(state: Store.State): Promise<backfill.Result> {
|
|
345
|
+
const { keys } = await state.list({ prefix: ApiKey.recordPrefix })
|
|
346
|
+
let indexed = 0
|
|
347
|
+
for (const { name } of keys) {
|
|
348
|
+
const record = await read(state, name, Date.now())
|
|
349
|
+
if (!record) continue
|
|
350
|
+
const ttl =
|
|
351
|
+
record.expiresAt === undefined
|
|
352
|
+
? undefined
|
|
353
|
+
: Math.max(1, Date.parse(record.expiresAt) - Date.now())
|
|
354
|
+
await state.put(idKeyFor(record.id), name, { ttl })
|
|
355
|
+
await state.put(orgKeyFor(record.orgId, record.id), name, { ttl })
|
|
356
|
+
indexed += 1
|
|
357
|
+
}
|
|
358
|
+
return { indexed, scanned: keys.length }
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export declare namespace backfill {
|
|
362
|
+
/** Result of {@link backfill}. */
|
|
363
|
+
type Result = {
|
|
364
|
+
/** Records whose index entries were written. */
|
|
365
|
+
indexed: number
|
|
366
|
+
/** Stored records scanned (including invalid or expired ones, skipped). */
|
|
367
|
+
scanned: number
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
177
371
|
/**
|
|
178
372
|
* Reads and validates a stored record by storage key. Invalid, corrupt, or
|
|
179
373
|
* expired records (`expiresAt <= now`) resolve to `null`.
|
|
@@ -203,3 +397,11 @@ const idPrefix = 'apikey_id:'
|
|
|
203
397
|
function idKeyFor(id: string): string {
|
|
204
398
|
return `${idPrefix}${id}`
|
|
205
399
|
}
|
|
400
|
+
|
|
401
|
+
/** Storage-key prefix for the per-key `org → recordKey` listing index. */
|
|
402
|
+
const orgPrefix = 'apikey_org:'
|
|
403
|
+
|
|
404
|
+
/** Storage key under which a key's org index entry is persisted. */
|
|
405
|
+
function orgKeyFor(orgId: string, id: string): string {
|
|
406
|
+
return `${orgPrefix}${orgId}:${id}`
|
|
407
|
+
}
|