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
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { type Context, Hono } from 'hono'
|
|
2
|
+
import * as z from 'zod/mini'
|
|
3
|
+
|
|
4
|
+
import * as ApiKeys from '../../../ApiKeys.js'
|
|
5
|
+
import type * as App from '../../../App.js'
|
|
6
|
+
import * as Auth from '../../../internal/Auth.js'
|
|
7
|
+
import * as Db from '../../../db/Db.js'
|
|
8
|
+
import * as Memberships from '../../../db/tables/memberships.js'
|
|
9
|
+
import * as OpenApi from '../../../internal/OpenApi.js'
|
|
10
|
+
import * as Organizations from '../../../db/tables/organizations.js'
|
|
11
|
+
import * as Response from '../../../internal/Response.js'
|
|
12
|
+
import * as Schema from '../../../internal/Schema.js'
|
|
13
|
+
|
|
14
|
+
/** Zod schemas owned by the organizations resource. */
|
|
15
|
+
export namespace schema {
|
|
16
|
+
const name = z
|
|
17
|
+
.string()
|
|
18
|
+
.check(
|
|
19
|
+
z.minLength(1),
|
|
20
|
+
z.maxLength(100),
|
|
21
|
+
z.describe('Human-readable name.'),
|
|
22
|
+
z.meta({ examples: ['Acme, Inc.'] }),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
/** One organization: the top-level tenant that owns API keys. */
|
|
26
|
+
export const Organization = Schema.describe(
|
|
27
|
+
z.object({
|
|
28
|
+
createdAt: z
|
|
29
|
+
.string()
|
|
30
|
+
.check(
|
|
31
|
+
z.describe('When the organization was created (ISO 8601).'),
|
|
32
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
33
|
+
),
|
|
34
|
+
id: z
|
|
35
|
+
.string()
|
|
36
|
+
.check(
|
|
37
|
+
z.describe('Opaque organization id (`org_…`).'),
|
|
38
|
+
z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
|
|
39
|
+
),
|
|
40
|
+
name: z
|
|
41
|
+
.string()
|
|
42
|
+
.check(
|
|
43
|
+
z.describe('Human-readable organization name.'),
|
|
44
|
+
z.meta({ examples: ['Acme, Inc.'] }),
|
|
45
|
+
),
|
|
46
|
+
role: z
|
|
47
|
+
.optional(z.enum(Memberships.roles))
|
|
48
|
+
.check(
|
|
49
|
+
z.describe("The caller's role in this organization; absent for the super admin."),
|
|
50
|
+
z.meta({ examples: ['owner'] }),
|
|
51
|
+
),
|
|
52
|
+
updatedAt: z
|
|
53
|
+
.string()
|
|
54
|
+
.check(
|
|
55
|
+
z.describe('When the organization was last updated (ISO 8601).'),
|
|
56
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
57
|
+
),
|
|
58
|
+
}),
|
|
59
|
+
'An organization: the top-level tenant that owns API keys.',
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
/** Path parameters addressing one organization. */
|
|
63
|
+
export const Params = z
|
|
64
|
+
.object({
|
|
65
|
+
orgId: z
|
|
66
|
+
.string()
|
|
67
|
+
.check(
|
|
68
|
+
z.describe('The organization id (`org_…`).'),
|
|
69
|
+
z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
|
|
70
|
+
),
|
|
71
|
+
})
|
|
72
|
+
.check(z.describe('Path parameters for one organization.'))
|
|
73
|
+
|
|
74
|
+
/** Request body creating or renaming an organization. */
|
|
75
|
+
export const OrganizationBody = z
|
|
76
|
+
.object({ name })
|
|
77
|
+
.check(z.describe('Fields for creating or renaming an organization.'))
|
|
78
|
+
|
|
79
|
+
/** Schemas for the deleteOrganization operation. */
|
|
80
|
+
export namespace deleteOrganization {
|
|
81
|
+
/** Confirmation that the organization was deleted. */
|
|
82
|
+
export const Response = z
|
|
83
|
+
.object({
|
|
84
|
+
id: z
|
|
85
|
+
.string()
|
|
86
|
+
.check(
|
|
87
|
+
z.describe('ID of the organization that was deleted.'),
|
|
88
|
+
z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
|
|
89
|
+
),
|
|
90
|
+
})
|
|
91
|
+
.check(z.describe('Confirmation that the organization was deleted.'))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Schemas for the listOrganizations operation. */
|
|
95
|
+
export namespace listOrganizations {
|
|
96
|
+
/** Non-paginated list of organizations. */
|
|
97
|
+
export const Response = Schema.describe(
|
|
98
|
+
z.object({
|
|
99
|
+
data: z.array(Organization).check(z.describe('The organizations, newest first.')),
|
|
100
|
+
}),
|
|
101
|
+
'A non-paginated list of organizations.',
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Mounts the `/orgs` resource: session-owned tenancy (each organization is
|
|
108
|
+
* owned by the user that created it). The super admin bypasses ownership;
|
|
109
|
+
* inaccessible or absent ids render `404` so foreign org ids are
|
|
110
|
+
* indistinguishable from missing ones. Projects nest under `/orgs/:orgId` in
|
|
111
|
+
* the projects app.
|
|
112
|
+
*/
|
|
113
|
+
export function orgs() {
|
|
114
|
+
return new Hono<App.Environment>()
|
|
115
|
+
.get(
|
|
116
|
+
'/v1/orgs',
|
|
117
|
+
Auth.policy({ session: true }),
|
|
118
|
+
OpenApi.describeRoute({
|
|
119
|
+
operationId: 'listOrganizations',
|
|
120
|
+
responses: OpenApi.responses({
|
|
121
|
+
success: {
|
|
122
|
+
description: 'The organizations, newest first.',
|
|
123
|
+
schema: schema.listOrganizations.Response,
|
|
124
|
+
},
|
|
125
|
+
}),
|
|
126
|
+
summary: 'List organizations',
|
|
127
|
+
tags: ['Organizations'],
|
|
128
|
+
}),
|
|
129
|
+
async (c) => {
|
|
130
|
+
if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
|
|
131
|
+
|
|
132
|
+
const principal = Auth.getPrincipal(c)
|
|
133
|
+
if (principal?.type !== 'session' && principal?.type !== 'super_admin')
|
|
134
|
+
return sessionRequired(c)
|
|
135
|
+
|
|
136
|
+
const db = Db.get(c.get('db'))
|
|
137
|
+
try {
|
|
138
|
+
const records =
|
|
139
|
+
principal.type === 'super_admin'
|
|
140
|
+
? await Organizations.list(db)
|
|
141
|
+
: await Organizations.listByMember(db, principal.id)
|
|
142
|
+
return c.json(
|
|
143
|
+
Response.validated(schema.listOrganizations.Response, {
|
|
144
|
+
data: records.map(serializeOrganization),
|
|
145
|
+
}),
|
|
146
|
+
200,
|
|
147
|
+
)
|
|
148
|
+
} catch (cause) {
|
|
149
|
+
return Response.upstream(c, cause)
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
)
|
|
153
|
+
.post(
|
|
154
|
+
'/v1/orgs',
|
|
155
|
+
Auth.policy({ session: true }),
|
|
156
|
+
OpenApi.validate('json', schema.OrganizationBody, {
|
|
157
|
+
code: 'body_invalid',
|
|
158
|
+
message: 'Check the request body and try again.',
|
|
159
|
+
}),
|
|
160
|
+
OpenApi.describeRoute({
|
|
161
|
+
operationId: 'createOrganization',
|
|
162
|
+
responses: OpenApi.responses({
|
|
163
|
+
success: {
|
|
164
|
+
description: 'The created organization.',
|
|
165
|
+
schema: schema.Organization,
|
|
166
|
+
},
|
|
167
|
+
}),
|
|
168
|
+
summary: 'Create organization',
|
|
169
|
+
tags: ['Organizations'],
|
|
170
|
+
}),
|
|
171
|
+
async (c) => {
|
|
172
|
+
if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
|
|
173
|
+
if (OpenApi.narrowValidation)
|
|
174
|
+
return OpenApi.validationError(c, {
|
|
175
|
+
code: 'body_invalid',
|
|
176
|
+
message: 'Check the request body and try again.',
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const principal = Auth.getPrincipal(c)
|
|
180
|
+
if (principal?.type !== 'session' && principal?.type !== 'super_admin')
|
|
181
|
+
return sessionRequired(c)
|
|
182
|
+
|
|
183
|
+
const body = c.req.valid('json')
|
|
184
|
+
const db = Db.get(c.get('db'))
|
|
185
|
+
try {
|
|
186
|
+
// Sessions own what they create; the super admin has no user row.
|
|
187
|
+
// Organizations provisioned by the super admin start memberless.
|
|
188
|
+
const record =
|
|
189
|
+
principal.type === 'super_admin'
|
|
190
|
+
? await Organizations.create(db, { createdBy: 'super_admin', name: body.name })
|
|
191
|
+
: {
|
|
192
|
+
...(await Organizations.createOwned(db, {
|
|
193
|
+
name: body.name,
|
|
194
|
+
userId: principal.id,
|
|
195
|
+
})),
|
|
196
|
+
role: 'owner' as const,
|
|
197
|
+
}
|
|
198
|
+
return c.json(Response.validated(schema.Organization, serializeOrganization(record)), 200)
|
|
199
|
+
} catch (cause) {
|
|
200
|
+
return Response.upstream(c, cause)
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
)
|
|
204
|
+
.get(
|
|
205
|
+
'/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}',
|
|
206
|
+
Auth.policy({ session: true }),
|
|
207
|
+
Auth.ensureOrg(),
|
|
208
|
+
OpenApi.validate('param', schema.Params, {
|
|
209
|
+
code: 'param_invalid',
|
|
210
|
+
message: 'Check the path parameters and try again.',
|
|
211
|
+
}),
|
|
212
|
+
OpenApi.describeRoute({
|
|
213
|
+
operationId: 'getOrganization',
|
|
214
|
+
responses: OpenApi.responses({
|
|
215
|
+
errors: { 404: 'No accessible organization was found for this id.' },
|
|
216
|
+
success: { description: 'One organization.', schema: schema.Organization },
|
|
217
|
+
}),
|
|
218
|
+
summary: 'Get organization',
|
|
219
|
+
tags: ['Organizations'],
|
|
220
|
+
}),
|
|
221
|
+
async (c) => {
|
|
222
|
+
if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
|
|
223
|
+
if (Auth.narrowScope) return Auth.ensureOrgError(c)
|
|
224
|
+
if (OpenApi.narrowValidation)
|
|
225
|
+
return OpenApi.validationError(c, {
|
|
226
|
+
code: 'param_invalid',
|
|
227
|
+
message: 'Check the path parameters and try again.',
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
return c.json(
|
|
231
|
+
Response.validated(
|
|
232
|
+
schema.Organization,
|
|
233
|
+
serializeOrganization({ ...Auth.org(c), role: Auth.membership(c)?.role }),
|
|
234
|
+
),
|
|
235
|
+
200,
|
|
236
|
+
)
|
|
237
|
+
},
|
|
238
|
+
)
|
|
239
|
+
.patch(
|
|
240
|
+
'/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}',
|
|
241
|
+
Auth.policy({ session: true }),
|
|
242
|
+
Auth.ensureOrg({ role: 'owner' }),
|
|
243
|
+
OpenApi.validate('param', schema.Params, {
|
|
244
|
+
code: 'param_invalid',
|
|
245
|
+
message: 'Check the path parameters and try again.',
|
|
246
|
+
}),
|
|
247
|
+
OpenApi.validate('json', schema.OrganizationBody, {
|
|
248
|
+
code: 'body_invalid',
|
|
249
|
+
message: 'Check the request body and try again.',
|
|
250
|
+
}),
|
|
251
|
+
OpenApi.describeRoute({
|
|
252
|
+
operationId: 'updateOrganization',
|
|
253
|
+
responses: OpenApi.responses({
|
|
254
|
+
errors: { 404: 'No accessible organization was found for this id.' },
|
|
255
|
+
success: { description: 'The updated organization.', schema: schema.Organization },
|
|
256
|
+
}),
|
|
257
|
+
summary: 'Update organization',
|
|
258
|
+
tags: ['Organizations'],
|
|
259
|
+
}),
|
|
260
|
+
async (c) => {
|
|
261
|
+
if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
|
|
262
|
+
if (OpenApi.narrowValidation)
|
|
263
|
+
return OpenApi.validationError(c, {
|
|
264
|
+
code: 'param_invalid',
|
|
265
|
+
message: 'Check the path parameters and try again.',
|
|
266
|
+
})
|
|
267
|
+
if (OpenApi.narrowValidation)
|
|
268
|
+
return OpenApi.validationError(c, {
|
|
269
|
+
code: 'body_invalid',
|
|
270
|
+
message: 'Check the request body and try again.',
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
const body = c.req.valid('json')
|
|
274
|
+
const db = Db.get(c.get('db'))
|
|
275
|
+
try {
|
|
276
|
+
const updated = await Organizations.update(db, Auth.org(c).id, { name: body.name })
|
|
277
|
+
if (!updated) return organizationNotFound(c)
|
|
278
|
+
return c.json(
|
|
279
|
+
Response.validated(
|
|
280
|
+
schema.Organization,
|
|
281
|
+
serializeOrganization({ ...updated, role: Auth.membership(c)?.role }),
|
|
282
|
+
),
|
|
283
|
+
200,
|
|
284
|
+
)
|
|
285
|
+
} catch (cause) {
|
|
286
|
+
return Response.upstream(c, cause)
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
)
|
|
290
|
+
.delete(
|
|
291
|
+
'/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}',
|
|
292
|
+
Auth.policy({ session: true }),
|
|
293
|
+
Auth.ensureOrg({ role: 'owner' }),
|
|
294
|
+
OpenApi.validate('param', schema.Params, {
|
|
295
|
+
code: 'param_invalid',
|
|
296
|
+
message: 'Check the path parameters and try again.',
|
|
297
|
+
}),
|
|
298
|
+
OpenApi.describeRoute({
|
|
299
|
+
description: 'Delete an organization and all of its projects.',
|
|
300
|
+
operationId: 'deleteOrganization',
|
|
301
|
+
responses: OpenApi.responses({
|
|
302
|
+
errors: { 404: 'No accessible organization was found for this id.' },
|
|
303
|
+
success: {
|
|
304
|
+
description: 'Confirmation that the organization was deleted.',
|
|
305
|
+
schema: schema.deleteOrganization.Response,
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
summary: 'Delete organization',
|
|
309
|
+
tags: ['Organizations'],
|
|
310
|
+
}),
|
|
311
|
+
async (c) => {
|
|
312
|
+
if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
|
|
313
|
+
if (Auth.narrowScope) return Auth.ensureOrgError(c)
|
|
314
|
+
if (OpenApi.narrowValidation)
|
|
315
|
+
return OpenApi.validationError(c, {
|
|
316
|
+
code: 'param_invalid',
|
|
317
|
+
message: 'Check the path parameters and try again.',
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
const db = Db.get(c.get('db'))
|
|
321
|
+
try {
|
|
322
|
+
const kv = c.get('kv')
|
|
323
|
+
if (kv)
|
|
324
|
+
for (const record of await ApiKeys.listByOrg(kv.store, Auth.org(c).id))
|
|
325
|
+
await ApiKeys.revoke(kv.store, record.id)
|
|
326
|
+
const deleted = await Organizations.deleteOrganization(db, Auth.org(c).id)
|
|
327
|
+
if (!deleted) return organizationNotFound(c)
|
|
328
|
+
return c.json(
|
|
329
|
+
Response.validated(schema.deleteOrganization.Response, { id: Auth.org(c).id }),
|
|
330
|
+
200,
|
|
331
|
+
)
|
|
332
|
+
} catch (cause) {
|
|
333
|
+
return Response.upstream(c, cause)
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function serializeOrganization(
|
|
340
|
+
record: Organizations.Record & { role?: Memberships.Role | undefined },
|
|
341
|
+
) {
|
|
342
|
+
return {
|
|
343
|
+
createdAt: record.createdAt,
|
|
344
|
+
id: record.id,
|
|
345
|
+
name: record.name,
|
|
346
|
+
...(record.role ? { role: record.role } : {}),
|
|
347
|
+
updatedAt: record.updatedAt,
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function organizationNotFound(c: Context<App.Environment>) {
|
|
352
|
+
return Response.error(c, {
|
|
353
|
+
code: 'organization_not_found',
|
|
354
|
+
message: 'Organization not found',
|
|
355
|
+
status: 404,
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function sessionRequired(c: Context<App.Environment>) {
|
|
360
|
+
return Response.error(c, {
|
|
361
|
+
code: 'forbidden',
|
|
362
|
+
message: 'Session required',
|
|
363
|
+
status: 403,
|
|
364
|
+
})
|
|
365
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
2
|
+
|
|
3
|
+
import * as TestApp from '../../../../test/App.js'
|
|
4
|
+
import * as Orgs from './orgs.js'
|
|
5
|
+
import * as Projects from './projects.js'
|
|
6
|
+
|
|
7
|
+
/** Origin pinned for SIWE domain binding; Hono test requests use this host. */
|
|
8
|
+
const origin = 'http://localhost'
|
|
9
|
+
|
|
10
|
+
/** RequestInit for a JSON mutation carrying the session cookie. */
|
|
11
|
+
function json(method: 'PATCH' | 'POST', cookie: string, body: unknown) {
|
|
12
|
+
return {
|
|
13
|
+
body: JSON.stringify(body),
|
|
14
|
+
headers: { 'content-type': 'application/json', cookie },
|
|
15
|
+
method,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function createApp() {
|
|
20
|
+
return TestApp.create({ session: { wallet: { origin } } })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Signs in a fresh scripted account; returns its session cookie. */
|
|
24
|
+
async function session(app: TestApp.signIn.App) {
|
|
25
|
+
const account = privateKeyToAccount(generatePrivateKey())
|
|
26
|
+
const { cookie } = await TestApp.signIn(app, account)
|
|
27
|
+
return cookie!
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe('projects', () => {
|
|
31
|
+
test('creates, lists, reads, and renames projects', async () => {
|
|
32
|
+
const app = createApp()
|
|
33
|
+
const cookie = await session(app)
|
|
34
|
+
const created = await app.request('/v1/orgs', json('POST', cookie, { name: 'Acme' }))
|
|
35
|
+
const org = await TestApp.json(created, Orgs.schema.Organization)
|
|
36
|
+
|
|
37
|
+
const createdProject = await app.request(
|
|
38
|
+
`/v1/orgs/${org.id}/projects`,
|
|
39
|
+
json('POST', cookie, { name: 'Checkout' }),
|
|
40
|
+
)
|
|
41
|
+
expect(createdProject.status).toBe(200)
|
|
42
|
+
const project = await TestApp.json(createdProject, Projects.schema.Project)
|
|
43
|
+
expect(project.id.startsWith('prj_')).toBe(true)
|
|
44
|
+
expect(project.orgId).toBe(org.id)
|
|
45
|
+
expect(project.environments).toMatchInlineSnapshot(`
|
|
46
|
+
[
|
|
47
|
+
"production",
|
|
48
|
+
"sandbox",
|
|
49
|
+
]
|
|
50
|
+
`)
|
|
51
|
+
|
|
52
|
+
const listed = await app.request(`/v1/orgs/${org.id}/projects`, { headers: { cookie } })
|
|
53
|
+
const list = await TestApp.json(listed, Projects.schema.listProjects.Response)
|
|
54
|
+
expect(list.data.map(({ name }) => name)).toEqual(['Checkout'])
|
|
55
|
+
|
|
56
|
+
const detail = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
57
|
+
headers: { cookie },
|
|
58
|
+
})
|
|
59
|
+
expect(detail.status).toBe(200)
|
|
60
|
+
|
|
61
|
+
const renamed = await app.request(
|
|
62
|
+
`/v1/orgs/${org.id}/projects/${project.id}`,
|
|
63
|
+
json('PATCH', cookie, { name: 'Checkout v2' }),
|
|
64
|
+
)
|
|
65
|
+
expect(renamed.status).toBe(200)
|
|
66
|
+
expect((await TestApp.json(renamed, Projects.schema.Project)).name).toBe('Checkout v2')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('deletes a project, leaving the organization and siblings intact', async () => {
|
|
70
|
+
const app = createApp()
|
|
71
|
+
const cookie = await session(app)
|
|
72
|
+
const created = await app.request('/v1/orgs', json('POST', cookie, { name: 'Acme' }))
|
|
73
|
+
const org = await TestApp.json(created, Orgs.schema.Organization)
|
|
74
|
+
const createdProject = await app.request(
|
|
75
|
+
`/v1/orgs/${org.id}/projects`,
|
|
76
|
+
json('POST', cookie, { name: 'Checkout' }),
|
|
77
|
+
)
|
|
78
|
+
const project = await TestApp.json(createdProject, Projects.schema.Project)
|
|
79
|
+
const keeper = await app.request(
|
|
80
|
+
`/v1/orgs/${org.id}/projects`,
|
|
81
|
+
json('POST', cookie, { name: 'Payments' }),
|
|
82
|
+
)
|
|
83
|
+
expect(keeper.status).toBe(200)
|
|
84
|
+
|
|
85
|
+
const stranger = await session(app)
|
|
86
|
+
const foreign = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
87
|
+
headers: { cookie: stranger },
|
|
88
|
+
method: 'DELETE',
|
|
89
|
+
})
|
|
90
|
+
expect(foreign.status).toBe(404)
|
|
91
|
+
|
|
92
|
+
const deleted = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
93
|
+
headers: { cookie },
|
|
94
|
+
method: 'DELETE',
|
|
95
|
+
})
|
|
96
|
+
expect(deleted.status).toBe(200)
|
|
97
|
+
expect(await TestApp.json(deleted, Projects.schema.deleteProject.Response)).toEqual({
|
|
98
|
+
id: project.id,
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const gone = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
102
|
+
headers: { cookie },
|
|
103
|
+
})
|
|
104
|
+
expect(gone.status).toBe(404)
|
|
105
|
+
|
|
106
|
+
const listed = await app.request(`/v1/orgs/${org.id}/projects`, { headers: { cookie } })
|
|
107
|
+
const list = await TestApp.json(listed, Projects.schema.listProjects.Response)
|
|
108
|
+
expect(list.data.map(({ name }) => name)).toEqual(['Payments'])
|
|
109
|
+
|
|
110
|
+
const orgStill = await app.request(`/v1/orgs/${org.id}`, { headers: { cookie } })
|
|
111
|
+
expect(orgStill.status).toBe(200)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('hides projects behind foreign organizations', async () => {
|
|
115
|
+
const app = createApp()
|
|
116
|
+
const owner = await session(app)
|
|
117
|
+
const created = await app.request('/v1/orgs', json('POST', owner, { name: 'Acme' }))
|
|
118
|
+
const org = await TestApp.json(created, Orgs.schema.Organization)
|
|
119
|
+
const createdProject = await app.request(
|
|
120
|
+
`/v1/orgs/${org.id}/projects`,
|
|
121
|
+
json('POST', owner, { name: 'Checkout' }),
|
|
122
|
+
)
|
|
123
|
+
const project = await TestApp.json(createdProject, Projects.schema.Project)
|
|
124
|
+
|
|
125
|
+
const stranger = await session(app)
|
|
126
|
+
const foreignList = await app.request(`/v1/orgs/${org.id}/projects`, {
|
|
127
|
+
headers: { cookie: stranger },
|
|
128
|
+
})
|
|
129
|
+
expect(foreignList.status).toBe(404)
|
|
130
|
+
|
|
131
|
+
const foreignDetail = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
132
|
+
headers: { cookie: stranger },
|
|
133
|
+
})
|
|
134
|
+
expect(foreignDetail.status).toBe(404)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('rejects cross-org project ids on every verb', async () => {
|
|
138
|
+
const app = createApp()
|
|
139
|
+
const owner = await session(app)
|
|
140
|
+
const created = await app.request('/v1/orgs', json('POST', owner, { name: 'Acme' }))
|
|
141
|
+
const org = await TestApp.json(created, Orgs.schema.Organization)
|
|
142
|
+
const createdProject = await app.request(
|
|
143
|
+
`/v1/orgs/${org.id}/projects`,
|
|
144
|
+
json('POST', owner, { name: 'Checkout' }),
|
|
145
|
+
)
|
|
146
|
+
const project = await TestApp.json(createdProject, Projects.schema.Project)
|
|
147
|
+
|
|
148
|
+
// The stranger owns a perfectly valid org of their own; the victim's
|
|
149
|
+
// project id still must not resolve through it (project ids are bound to
|
|
150
|
+
// their owning org, not just to any org the caller owns).
|
|
151
|
+
const stranger = await session(app)
|
|
152
|
+
const otherOrgResponse = await app.request('/v1/orgs', json('POST', stranger, { name: 'Other' })) // prettier-ignore
|
|
153
|
+
const otherOrg = await TestApp.json(otherOrgResponse, Orgs.schema.Organization)
|
|
154
|
+
|
|
155
|
+
const smuggled = `/v1/orgs/${otherOrg.id}/projects/${project.id}`
|
|
156
|
+
const smuggledRead = await app.request(smuggled, { headers: { cookie: stranger } })
|
|
157
|
+
expect(smuggledRead.status).toBe(404)
|
|
158
|
+
const smuggledRename = await app.request(smuggled, json('PATCH', stranger, { name: 'Hijack' })) // prettier-ignore
|
|
159
|
+
expect(smuggledRename.status).toBe(404)
|
|
160
|
+
const smuggledDelete = await app.request(smuggled, {
|
|
161
|
+
headers: { cookie: stranger },
|
|
162
|
+
method: 'DELETE',
|
|
163
|
+
})
|
|
164
|
+
expect(smuggledDelete.status).toBe(404)
|
|
165
|
+
|
|
166
|
+
// Mutations through the owning org's path fail at the org-ownership link.
|
|
167
|
+
const direct = `/v1/orgs/${org.id}/projects/${project.id}`
|
|
168
|
+
const foreignRename = await app.request(direct, json('PATCH', stranger, { name: 'Hijack' }))
|
|
169
|
+
expect(foreignRename.status).toBe(404)
|
|
170
|
+
const foreignDelete = await app.request(direct, {
|
|
171
|
+
headers: { cookie: stranger },
|
|
172
|
+
method: 'DELETE',
|
|
173
|
+
})
|
|
174
|
+
expect(foreignDelete.status).toBe(404)
|
|
175
|
+
|
|
176
|
+
// The project survives every attempt, unrenamed.
|
|
177
|
+
const detail = await app.request(direct, { headers: { cookie: owner } })
|
|
178
|
+
expect(detail.status).toBe(200)
|
|
179
|
+
expect((await TestApp.json(detail, Projects.schema.Project)).name).toBe('Checkout')
|
|
180
|
+
})
|
|
181
|
+
})
|