tapimo 0.15.1 → 0.18.1
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 +137 -0
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +4 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +37 -11
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +163 -10
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +13085 -11974
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +46 -15
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +1 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +1 -1
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +893 -191
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +5 -1
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +70 -70
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +8 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +66 -27
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +36 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +25 -25
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +5 -4
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/route-policies.d.ts +632 -0
- package/dist/admin/apps/route-policies.d.ts.map +1 -0
- package/dist/admin/apps/route-policies.js +257 -0
- package/dist/admin/apps/route-policies.js.map +1 -0
- package/dist/admin/apps/routes-support.js +39 -3
- package/dist/admin/apps/routes-support.js.map +1 -1
- package/dist/admin/apps/routes.d.ts +529 -76
- package/dist/admin/apps/routes.d.ts.map +1 -1
- package/dist/admin/apps/routes.js +82 -1
- package/dist/admin/apps/routes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +157 -157
- package/dist/admin/index.d.ts +0 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +0 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +205 -201
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +65 -1
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +1 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +58 -59
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +2709 -2670
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +357 -357
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +50 -0
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +248 -248
- package/dist/apps/data/routes/balances.d.ts +22 -22
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +5 -7
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +125 -125
- package/dist/apps/data/routes/coingecko.d.ts +54 -54
- package/dist/apps/data/routes/earn.d.ts +103 -12
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +456 -220
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +267 -97
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +109 -127
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +83 -54
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +43 -43
- package/dist/apps/data/routes/receipts.d.ts +235 -235
- package/dist/apps/data/routes/rpc.d.ts +30 -30
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +11 -6
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +2 -0
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +30 -22
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +77 -77
- package/dist/apps/data/routes/valuation.d.ts +32 -32
- package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +1 -1
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +31 -31
- package/dist/apps/management/App.d.ts +2909 -2064
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -0
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/Billing.d.ts +2 -4
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +65 -26
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +257 -245
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +70 -11
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +84 -84
- package/dist/apps/management/routes/cli.d.ts +912 -0
- package/dist/apps/management/routes/cli.d.ts.map +1 -0
- package/dist/apps/management/routes/cli.js +416 -0
- package/dist/apps/management/routes/cli.js.map +1 -0
- package/dist/apps/management/routes/faucet.d.ts +8 -8
- package/dist/apps/management/routes/invitations.d.ts +138 -138
- package/dist/apps/management/routes/invite-links.d.ts +172 -172
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +104 -104
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +8 -2
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +125 -125
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +86 -86
- package/dist/apps/management/routes/webhooks.d.ts +485 -485
- package/dist/apps/mpp/App.d.ts +44 -44
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +4 -2
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.js +6 -4
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
- package/dist/apps/relay/App.d.ts +8 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +16 -4
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -6
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +71 -60
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/apps/routes/Access.d.ts +53 -0
- package/dist/apps/routes/Access.d.ts.map +1 -1
- package/dist/apps/routes/Access.js +121 -0
- package/dist/apps/routes/Access.js.map +1 -1
- package/dist/apps/routes/App.d.ts +397 -158
- package/dist/apps/routes/App.d.ts.map +1 -1
- package/dist/apps/routes/App.js.map +1 -1
- package/dist/apps/routes/routes/chains.d.ts +25 -25
- package/dist/apps/routes/routes/deposit-addresses.d.ts +169 -61
- package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.js +217 -32
- package/dist/apps/routes/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/routes/routes/quotes.d.ts +171 -81
- package/dist/apps/routes/routes/quotes.d.ts.map +1 -1
- package/dist/apps/routes/routes/quotes.js +101 -27
- package/dist/apps/routes/routes/quotes.js.map +1 -1
- package/dist/apps/routes/routes/transfers.d.ts +532 -480
- package/dist/apps/routes/routes/transfers.d.ts.map +1 -1
- package/dist/apps/routes/routes/transfers.js +182 -37
- package/dist/apps/routes/routes/transfers.js.map +1 -1
- package/dist/cli/ApiKeys.d.ts +120 -0
- package/dist/cli/ApiKeys.d.ts.map +1 -0
- package/dist/cli/ApiKeys.js +138 -0
- package/dist/cli/ApiKeys.js.map +1 -0
- package/dist/cli/Cli.d.ts +92 -34
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +188 -11
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/Credentials.d.ts +95 -0
- package/dist/cli/Credentials.d.ts.map +1 -0
- package/dist/cli/Credentials.js +110 -0
- package/dist/cli/Credentials.js.map +1 -0
- package/dist/cli/Spec.d.ts +59 -0
- package/dist/cli/Spec.d.ts.map +1 -0
- package/dist/cli/Spec.js +77 -0
- package/dist/cli/Spec.js.map +1 -0
- package/dist/cli/bin.js +5 -1
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +5 -5
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/auth.d.ts +73 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +204 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/keys.d.ts +17 -0
- package/dist/cli/commands/keys.d.ts.map +1 -0
- package/dist/cli/commands/keys.js +109 -0
- package/dist/cli/commands/keys.js.map +1 -0
- package/dist/cloudflare.d.ts +27 -2
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +144 -17
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +23 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +413 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +44 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +56 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.d.ts +28 -2
- package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.js +65 -9
- package/dist/db/tables/apiKeyAdmissions.js.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts +2 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.js +2 -2
- package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -1
- package/dist/db/tables/authAccounts.d.ts.map +1 -1
- package/dist/db/tables/authAccounts.js +1 -0
- package/dist/db/tables/authAccounts.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +12 -1
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +4 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +8 -34
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +5 -1
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +10 -2
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.d.ts +13 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.js +11 -0
- package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -1
- package/dist/db/tables/rewardRuns.d.ts.map +1 -1
- package/dist/db/tables/rewardRuns.js +4 -0
- package/dist/db/tables/rewardRuns.js.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.js +2 -0
- package/dist/db/tables/rewardTransactionAttempts.js.map +1 -1
- package/dist/db/tables/routesDepositAddresses.d.ts +29 -0
- package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -1
- package/dist/db/tables/routesDepositAddresses.js +84 -31
- package/dist/db/tables/routesDepositAddresses.js.map +1 -1
- package/dist/db/tables/routesDeposits.d.ts.map +1 -1
- package/dist/db/tables/routesDeposits.js +31 -21
- package/dist/db/tables/routesDeposits.js.map +1 -1
- package/dist/db/tables/routesIdempotency.d.ts.map +1 -1
- package/dist/db/tables/routesIdempotency.js +2 -0
- package/dist/db/tables/routesIdempotency.js.map +1 -1
- package/dist/db/tables/routesPolicies.d.ts +58 -0
- package/dist/db/tables/routesPolicies.d.ts.map +1 -0
- package/dist/db/tables/routesPolicies.js +198 -0
- package/dist/db/tables/routesPolicies.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts +22 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidies.js +41 -0
- package/dist/db/tables/routesTransferSubsidies.js.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.js +12 -4
- package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -1
- package/dist/db/tables/routesTransfers.d.ts +26 -1
- package/dist/db/tables/routesTransfers.d.ts.map +1 -1
- package/dist/db/tables/routesTransfers.js +36 -6
- package/dist/db/tables/routesTransfers.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +45 -13
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +144 -33
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +2 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +11 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +1 -1
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +3 -2
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/relay.d.ts +2 -0
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +34 -15
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +57 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +182 -78
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/BetterAuth.d.ts +22 -0
- package/dist/internal/BetterAuth.d.ts.map +1 -1
- package/dist/internal/BetterAuth.js +17 -14
- package/dist/internal/BetterAuth.js.map +1 -1
- package/dist/internal/Cache.d.ts +5 -0
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +3 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/CliAuth.d.ts +243 -0
- package/dist/internal/CliAuth.d.ts.map +1 -0
- package/dist/internal/CliAuth.js +249 -0
- package/dist/internal/CliAuth.js.map +1 -0
- package/dist/internal/EarnSharePrices.d.ts +1 -1
- package/dist/internal/EarnSharePrices.d.ts.map +1 -1
- package/dist/internal/EarnSharePrices.js +7 -3
- package/dist/internal/EarnSharePrices.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +47 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +188 -4
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/EarnWithdrawals.d.ts +73 -0
- package/dist/internal/EarnWithdrawals.d.ts.map +1 -0
- package/dist/internal/EarnWithdrawals.js +189 -0
- package/dist/internal/EarnWithdrawals.js.map +1 -0
- package/dist/internal/ExecutionContext.d.ts +21 -0
- package/dist/internal/ExecutionContext.d.ts.map +1 -0
- package/dist/internal/ExecutionContext.js +16 -0
- package/dist/internal/ExecutionContext.js.map +1 -0
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +163 -130
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +26 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +67 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +174 -27
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Store.d.ts +6 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +4 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Timing.d.ts +6 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +21 -1
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/Tron.d.ts +124 -0
- package/dist/internal/Tron.d.ts.map +1 -0
- package/dist/internal/Tron.js +202 -0
- package/dist/internal/Tron.js.map +1 -0
- package/dist/internal/Viem.d.ts +4 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +25 -6
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/rewards/Read.d.ts +2 -2
- package/dist/internal/rewards/Read.d.ts.map +1 -1
- package/dist/internal/rewards/Read.js +11 -2
- package/dist/internal/rewards/Read.js.map +1 -1
- package/dist/internal/routes/Action.d.ts +27 -0
- package/dist/internal/routes/Action.d.ts.map +1 -1
- package/dist/internal/routes/Action.js +49 -1
- package/dist/internal/routes/Action.js.map +1 -1
- package/dist/internal/routes/Chain.d.ts +2 -0
- package/dist/internal/routes/Chain.d.ts.map +1 -1
- package/dist/internal/routes/Chain.js +4 -0
- package/dist/internal/routes/Chain.js.map +1 -1
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/DepositAddress.js +5 -0
- package/dist/internal/routes/DepositAddress.js.map +1 -1
- package/dist/internal/routes/Evidence.d.ts.map +1 -1
- package/dist/internal/routes/Evidence.js +6 -2
- package/dist/internal/routes/Evidence.js.map +1 -1
- package/dist/internal/routes/EvmTransferSettlement.d.ts +17 -0
- package/dist/internal/routes/EvmTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/EvmTransferSettlement.js +196 -0
- package/dist/internal/routes/EvmTransferSettlement.js.map +1 -0
- package/dist/internal/routes/Policy.d.ts +161 -0
- package/dist/internal/routes/Policy.d.ts.map +1 -0
- package/dist/internal/routes/Policy.js +249 -0
- package/dist/internal/routes/Policy.js.map +1 -0
- package/dist/internal/routes/Provider.d.ts +66 -3
- package/dist/internal/routes/Provider.d.ts.map +1 -1
- package/dist/internal/routes/Provider.js +106 -27
- package/dist/internal/routes/Provider.js.map +1 -1
- package/dist/internal/routes/Quota.d.ts +57 -0
- package/dist/internal/routes/Quota.d.ts.map +1 -0
- package/dist/internal/routes/Quota.js +144 -0
- package/dist/internal/routes/Quota.js.map +1 -0
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
- package/dist/internal/routes/Reconciliation.js +163 -47
- package/dist/internal/routes/Reconciliation.js.map +1 -1
- package/dist/internal/routes/SolanaTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/SolanaTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSettlement.js +220 -0
- package/dist/internal/routes/SolanaTransferSettlement.js.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts +172 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js +564 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/Subsidy.d.ts +2 -2
- package/dist/internal/routes/Subsidy.d.ts.map +1 -1
- package/dist/internal/routes/Subsidy.js +2 -2
- package/dist/internal/routes/Subsidy.js.map +1 -1
- package/dist/internal/routes/Transfer.d.ts +229 -1
- package/dist/internal/routes/Transfer.d.ts.map +1 -1
- package/dist/internal/routes/Transfer.js +644 -7
- package/dist/internal/routes/Transfer.js.map +1 -1
- package/dist/internal/routes/TransferReconciliation.d.ts +6 -0
- package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -1
- package/dist/internal/routes/TransferReconciliation.js +83 -159
- package/dist/internal/routes/TransferReconciliation.js.map +1 -1
- package/dist/internal/routes/TransferSettlement.d.ts +45 -0
- package/dist/internal/routes/TransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TransferSettlement.js +2 -0
- package/dist/internal/routes/TransferSettlement.js.map +1 -0
- package/dist/internal/routes/TransferSubsidy.d.ts +23 -8
- package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -1
- package/dist/internal/routes/TransferSubsidy.js +64 -5
- package/dist/internal/routes/TransferSubsidy.js.map +1 -1
- package/dist/internal/routes/TronTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/TronTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSettlement.js +201 -0
- package/dist/internal/routes/TronTransferSettlement.js.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts +174 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.js +439 -0
- package/dist/internal/routes/TronTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/index.d.ts +3 -0
- package/dist/internal/routes/index.d.ts.map +1 -1
- package/dist/internal/routes/index.js +3 -0
- package/dist/internal/routes/index.js.map +1 -1
- package/dist/internal/routes/providers/across.d.ts +3 -0
- package/dist/internal/routes/providers/across.d.ts.map +1 -1
- package/dist/internal/routes/providers/across.js +11 -0
- package/dist/internal/routes/providers/across.js.map +1 -1
- package/dist/internal/routes/providers/legacyMesh.d.ts +29 -0
- package/dist/internal/routes/providers/legacyMesh.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMesh.js +474 -0
- package/dist/internal/routes/providers/legacyMesh.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts +59 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js +229 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts +19 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js +457 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts +123 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js +333 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js.map +1 -0
- package/dist/internal/routes/providers/propAmm.d.ts +70 -0
- package/dist/internal/routes/providers/propAmm.d.ts.map +1 -0
- package/dist/internal/routes/providers/propAmm.js +524 -0
- package/dist/internal/routes/providers/propAmm.js.map +1 -0
- package/dist/internal/routes/providers/relay.d.ts +3 -0
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +352 -41
- package/dist/internal/routes/providers/relay.js.map +1 -1
- package/dist/internal/routes/providers/rhino.d.ts +3 -0
- package/dist/internal/routes/providers/rhino.d.ts.map +1 -1
- package/dist/internal/routes/providers/rhino.js +11 -0
- package/dist/internal/routes/providers/rhino.js.map +1 -1
- package/dist/internal/routes/providers/squid.d.ts +3 -0
- package/dist/internal/routes/providers/squid.d.ts.map +1 -1
- package/dist/internal/routes/providers/squid.js +19 -0
- package/dist/internal/routes/providers/squid.js.map +1 -1
- package/dist/internal/routes/providers/stargate.d.ts.map +1 -1
- package/dist/internal/routes/providers/stargate.js +22 -9
- package/dist/internal/routes/providers/stargate.js.map +1 -1
- package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -1
- package/dist/internal/routes/providers/symbiosis.js +13 -17
- package/dist/internal/routes/providers/symbiosis.js.map +1 -1
- package/dist/providers/index.d.ts +14 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +16 -6
- package/src/ApiKey.ts +7 -3
- package/src/ApiKeys.test.ts +652 -8
- package/src/ApiKeys.ts +191 -11
- package/src/App.test.ts +405 -18
- package/src/App.ts +51 -15
- package/src/Client.test-d.ts +157 -10
- package/src/Client.test.ts +4 -4
- package/src/Scope.ts +1 -2
- package/src/admin/App.ts +11 -5
- package/src/admin/apps/api-keys.test.ts +98 -2
- package/src/admin/apps/api-keys.ts +21 -12
- package/src/admin/apps/earn-vaults.test.ts +76 -7
- package/src/admin/apps/earn-vaults.ts +47 -8
- package/src/admin/apps/organizations.test.ts +147 -31
- package/src/admin/apps/organizations.ts +5 -4
- package/src/admin/apps/route-policies.test.ts +220 -0
- package/src/admin/apps/route-policies.ts +322 -0
- package/src/admin/apps/routes-support.test.ts +107 -2
- package/src/admin/apps/routes-support.ts +43 -3
- package/src/admin/apps/routes.test.ts +150 -0
- package/src/admin/apps/routes.ts +97 -1
- package/src/admin/apps/scopes.test.ts +1 -1
- package/src/admin/index.ts +0 -1
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/components/Dialog.tsx +1 -1
- package/src/admin/ui/src/components/EarnVaultForm.tsx +45 -0
- package/src/admin/ui/src/components/RoutePicker.tsx +79 -0
- package/src/admin/ui/src/lib/earn-vaults.ts +1 -1
- package/src/admin/ui/src/lib/route-policies.test.ts +452 -0
- package/src/admin/ui/src/lib/route-policies.ts +232 -0
- package/src/admin/ui/src/lib/routes.ts +34 -0
- package/src/admin/ui/src/routeTree.gen.ts +21 -0
- package/src/admin/ui/src/routes/api-keys.tsx +21 -2
- package/src/admin/ui/src/routes/early-access.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +22 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +10 -0
- package/src/admin/ui/src/routes/organizations.tsx +1 -0
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +18 -3
- package/src/admin/ui/src/routes/route-policies.tsx +678 -0
- package/src/admin/ui/src/routes/routes.tsx +85 -2
- package/src/admin/ui/src/routes/routes_.support.tsx +6 -22
- package/src/admin/ui/src/routes/subsidies.tsx +1 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +1 -0
- package/src/admin/ui.generated.ts +258 -202
- package/src/analytics/Analytics.test.ts +4 -50
- package/src/analytics/Analytics.ts +65 -1
- package/src/analytics/tables/requestEvents.test.ts +402 -1
- package/src/analytics/tables/requestEvents.ts +62 -93
- package/src/apps/data/routes/activities.test.ts +315 -14
- package/src/apps/data/routes/activities.ts +60 -0
- package/src/apps/data/routes/balances.ts +5 -7
- package/src/apps/data/routes/earn.bench.ts +18 -0
- package/src/apps/data/routes/earn.local.test.ts +507 -0
- package/src/apps/data/routes/earn.test.ts +405 -127
- package/src/apps/data/routes/earn.ts +660 -270
- package/src/apps/data/routes/exchanges.bench.ts +3 -1
- package/src/apps/data/routes/exchanges.test.ts +166 -2
- package/src/apps/data/routes/exchanges.ts +308 -101
- package/src/apps/data/routes/fee-amm.test.ts +134 -2
- package/src/apps/data/routes/fee-amm.ts +122 -60
- package/src/apps/data/routes/receipts.test.ts +21 -18
- package/src/apps/data/routes/rpc.test.ts +2 -2
- package/src/apps/data/routes/tokens.provenance.test.ts +157 -0
- package/src/apps/data/routes/tokens.test.ts +4 -4
- package/src/apps/data/routes/tokens.ts +11 -6
- package/src/apps/data/routes/transactions.test.ts +29 -0
- package/src/apps/data/routes/transactions.ts +33 -22
- package/src/apps/data/routes/webhooks.test.ts +12 -3
- package/src/apps/data/routes/webhooks.ts +2 -1
- package/src/apps/management/App.ts +4 -0
- package/src/apps/management/Billing.test.ts +253 -27
- package/src/apps/management/Billing.ts +83 -29
- package/src/apps/management/routes/api-keys.test.ts +1 -1
- package/src/apps/management/routes/api-keys.ts +85 -11
- package/src/apps/management/routes/billing.test.ts +68 -4
- package/src/apps/management/routes/cli.test.ts +370 -0
- package/src/apps/management/routes/cli.ts +533 -0
- package/src/apps/management/routes/me.test.ts +14 -4
- package/src/apps/management/routes/orgs.test.ts +108 -4
- package/src/apps/management/routes/orgs.ts +7 -2
- package/src/apps/management/routes/usage.test.ts +2 -2
- package/src/apps/mpp/internal/Policy.test.ts +51 -4
- package/src/apps/mpp/internal/Policy.ts +6 -2
- package/src/apps/mpp/internal/Sponsorship.test.ts +29 -0
- package/src/apps/mpp/internal/Sponsorship.ts +6 -4
- package/src/apps/relay/App.test.ts +85 -1
- package/src/apps/relay/App.ts +28 -4
- package/src/apps/relay/Sponsorships.test.ts +97 -1
- package/src/apps/relay/Sponsorships.ts +77 -66
- package/src/apps/routes/Access.test.ts +319 -0
- package/src/apps/routes/Access.ts +147 -0
- package/src/apps/routes/App.ts +10 -0
- package/src/apps/routes/routes/chains.test.ts +3 -2
- package/src/apps/routes/routes/deposit-addresses.test.ts +978 -34
- package/src/apps/routes/routes/deposit-addresses.ts +243 -32
- package/src/apps/routes/routes/propAmm.local.test.ts +951 -0
- package/src/apps/routes/routes/quotes.test.ts +81 -8
- package/src/apps/routes/routes/quotes.ts +109 -27
- package/src/apps/routes/routes/transfers.test.ts +252 -15
- package/src/apps/routes/routes/transfers.ts +212 -33
- package/src/cli/ApiKeys.test.ts +265 -0
- package/src/cli/ApiKeys.ts +189 -0
- package/src/cli/Cli.test.ts +188 -0
- package/src/cli/Cli.ts +280 -12
- package/src/cli/Credentials.test.ts +122 -0
- package/src/cli/Credentials.ts +144 -0
- package/src/cli/Spec.test.ts +133 -0
- package/src/cli/Spec.ts +132 -0
- package/src/cli/bin.test.ts +49 -0
- package/src/cli/bin.ts +5 -1
- package/src/cli/commands/auth.test.ts +138 -0
- package/src/cli/commands/auth.ts +254 -0
- package/src/cli/commands/keys.test.ts +68 -0
- package/src/cli/commands/keys.ts +125 -0
- package/src/cloudflare.ts +184 -36
- package/src/db/Db.test.ts +877 -0
- package/src/db/Db.ts +498 -1
- package/src/db/Schema.ts +75 -4
- package/src/db/tables/apiKeyAdmissions.test.ts +57 -0
- package/src/db/tables/apiKeyAdmissions.ts +101 -11
- package/src/db/tables/apiKeyOwnerTombstones.ts +2 -2
- package/src/db/tables/authAccounts.test.ts +30 -0
- package/src/db/tables/authAccounts.ts +1 -0
- package/src/db/tables/earnVaults.test.ts +34 -0
- package/src/db/tables/earnVaults.ts +17 -2
- package/src/db/tables/organizations.test.ts +148 -84
- package/src/db/tables/organizations.ts +11 -43
- package/src/db/tables/requestUsage.ts +13 -2
- package/src/db/tables/rewardCampaigns.test.ts +163 -0
- package/src/db/tables/rewardEligibilityAssociations.test.ts +14 -0
- package/src/db/tables/rewardEligibilityAssociations.ts +24 -0
- package/src/db/tables/rewardRuns.ts +4 -0
- package/src/db/tables/rewardTransactionAttempts.ts +2 -0
- package/src/db/tables/routesDepositAddresses.test.ts +263 -0
- package/src/db/tables/routesDepositAddresses.ts +118 -34
- package/src/db/tables/routesDeposits.test.ts +66 -5
- package/src/db/tables/routesDeposits.ts +47 -26
- package/src/db/tables/routesIdempotency.test.ts +80 -0
- package/src/db/tables/routesIdempotency.ts +2 -0
- package/src/db/tables/routesPolicies.test.ts +143 -0
- package/src/db/tables/routesPolicies.ts +251 -0
- package/src/db/tables/routesTransferSubsidies.ts +64 -0
- package/src/db/tables/routesTransferSubsidyNonces.ts +16 -4
- package/src/db/tables/routesTransfers.test.ts +183 -2
- package/src/db/tables/routesTransfers.ts +65 -6
- package/src/db/tables/sponsoredTransactions.test.ts +351 -76
- package/src/db/tables/sponsoredTransactions.ts +182 -38
- package/src/db/tables/users.test.ts +51 -0
- package/src/db/tables/users.ts +12 -0
- package/src/handlers/internal/multisig.store.test.ts +120 -0
- package/src/handlers/internal/multisig.test.ts +389 -0
- package/src/handlers/internal/multisig.ts +13 -10
- package/src/handlers/relay.test.ts +259 -83
- package/src/handlers/relay.ts +36 -17
- package/src/internal/Auth.test.ts +291 -8
- package/src/internal/Auth.ts +227 -96
- package/src/internal/BetterAuth.test.ts +58 -22
- package/src/internal/BetterAuth.ts +23 -17
- package/src/internal/Cache.ts +3 -1
- package/src/internal/CliAuth.test.ts +279 -0
- package/src/internal/CliAuth.ts +319 -0
- package/src/internal/EarnSharePrices.test.ts +25 -0
- package/src/internal/EarnSharePrices.ts +9 -2
- package/src/internal/EarnVaults.test.ts +67 -0
- package/src/internal/EarnVaults.ts +299 -4
- package/src/internal/EarnWithdrawals.test.ts +315 -0
- package/src/internal/EarnWithdrawals.ts +266 -0
- package/src/internal/ExecutionContext.ts +31 -0
- package/src/internal/Log.test.ts +210 -0
- package/src/internal/Log.ts +180 -142
- package/src/internal/MetricSink.test.ts +190 -15
- package/src/internal/MetricSink.ts +27 -1
- package/src/internal/RateLimit.test.ts +144 -8
- package/src/internal/RateLimit.ts +254 -26
- package/src/internal/Store.ts +4 -5
- package/src/internal/Timing.test.ts +32 -0
- package/src/internal/Timing.ts +20 -1
- package/src/internal/Tron.test-d.ts +22 -0
- package/src/internal/Tron.test.ts +94 -0
- package/src/internal/Tron.ts +289 -0
- package/src/internal/Viem.rpc.test.ts +76 -0
- package/src/internal/Viem.ts +29 -6
- package/src/internal/rewards/Read.test.ts +109 -0
- package/src/internal/rewards/Read.ts +13 -4
- package/src/internal/routes/Action.test.ts +70 -0
- package/src/internal/routes/Action.ts +76 -1
- package/src/internal/routes/Chain.test.ts +18 -0
- package/src/internal/routes/Chain.ts +5 -0
- package/src/internal/routes/DepositAddress.ts +5 -0
- package/src/internal/routes/Evidence.test.ts +64 -0
- package/src/internal/routes/Evidence.ts +11 -3
- package/src/internal/routes/EvmTransferSettlement.ts +213 -0
- package/src/internal/routes/Policy.test.ts +316 -0
- package/src/internal/routes/Policy.ts +399 -0
- package/src/internal/routes/Provider.test.ts +103 -2
- package/src/internal/routes/Provider.ts +149 -27
- package/src/internal/routes/Quota.test.ts +149 -0
- package/src/internal/routes/Quota.ts +226 -0
- package/src/internal/routes/Reconciliation.local.test.ts +285 -0
- package/src/internal/routes/Reconciliation.test.ts +371 -13
- package/src/internal/routes/Reconciliation.ts +193 -42
- package/src/internal/routes/SolanaTransferSettlement.ts +232 -0
- package/src/internal/routes/SolanaTransferSubsidy.test.ts +471 -0
- package/src/internal/routes/SolanaTransferSubsidy.ts +760 -0
- package/src/internal/routes/SourceObservation.test.ts +221 -0
- package/src/internal/routes/Subsidy.local.test.ts +46 -0
- package/src/internal/routes/Subsidy.ts +4 -2
- package/src/internal/routes/Transfer.solana.test.ts +389 -0
- package/src/internal/routes/Transfer.test.ts +130 -1
- package/src/internal/routes/Transfer.tron.test.ts +172 -0
- package/src/internal/routes/Transfer.ts +866 -8
- package/src/internal/routes/TransferReconciliation.test.ts +26 -4
- package/src/internal/routes/TransferReconciliation.ts +91 -166
- package/src/internal/routes/TransferSettlement.ts +48 -0
- package/src/internal/routes/TransferSubsidy.local.test.ts +143 -0
- package/src/internal/routes/TransferSubsidy.test.ts +34 -4
- package/src/internal/routes/TransferSubsidy.ts +87 -12
- package/src/internal/routes/TronTransferSettlement.ts +212 -0
- package/src/internal/routes/TronTransferSubsidy.test.ts +109 -0
- package/src/internal/routes/TronTransferSubsidy.ts +619 -0
- package/src/internal/routes/index.test.ts +3 -0
- package/src/internal/routes/index.ts +3 -0
- package/src/internal/routes/providers/across.ts +13 -0
- package/src/internal/routes/providers/index.test.ts +141 -0
- package/src/internal/routes/providers/legacyMesh.test.ts +484 -0
- package/src/internal/routes/providers/legacyMesh.ts +633 -0
- package/src/internal/routes/providers/legacyMeshDelivery.test.ts +306 -0
- package/src/internal/routes/providers/legacyMeshDelivery.ts +320 -0
- package/src/internal/routes/providers/legacyMeshOutbound.test.ts +401 -0
- package/src/internal/routes/providers/legacyMeshOutbound.ts +566 -0
- package/src/internal/routes/providers/legacyMeshOutboundDelivery.ts +473 -0
- package/src/internal/routes/providers/propAmm.ts +640 -0
- package/src/internal/routes/providers/relay.test.ts +1263 -41
- package/src/internal/routes/providers/relay.ts +423 -38
- package/src/internal/routes/providers/rhino.ts +14 -1
- package/src/internal/routes/providers/squid.ts +21 -0
- package/src/internal/routes/providers/stargate.test.ts +105 -1
- package/src/internal/routes/providers/stargate.ts +22 -9
- package/src/internal/routes/providers/symbiosis.ts +13 -47
- package/src/providers/index.test.ts +2 -0
- package/src/providers/index.ts +18 -0
- package/dist/admin/Access.d.ts +0 -39
- package/dist/admin/Access.d.ts.map +0 -1
- package/dist/admin/Access.js +0 -73
- package/dist/admin/Access.js.map +0 -1
- package/src/admin/Access.test.ts +0 -130
- package/src/admin/Access.ts +0 -85
package/src/cli/Cli.ts
CHANGED
|
@@ -1,33 +1,91 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as path from 'node:path'
|
|
2
|
+
import { Cli as incur_Cli, type Fetch, Openapi } from 'incur'
|
|
2
3
|
|
|
3
4
|
import type { mcp } from '../apps/mcp.js'
|
|
4
|
-
import * as
|
|
5
|
+
import * as Client from '../Client.js'
|
|
6
|
+
import * as ApiKeys from './ApiKeys.js'
|
|
7
|
+
import * as Auth from './commands/auth.js'
|
|
8
|
+
import * as Keys from './commands/keys.js'
|
|
9
|
+
import * as Credentials from './Credentials.js'
|
|
10
|
+
import * as Spec from './Spec.js'
|
|
5
11
|
|
|
6
|
-
/** Tool patterns hidden from MCP clients: super admin, partner-shaped gecko mirrors, browser session flows. */
|
|
7
|
-
const excludedTools = ['admin_*', 'gecko_*', 'v1_auth_*']
|
|
12
|
+
/** Tool patterns hidden from MCP clients: super admin, partner-shaped gecko mirrors, browser and interactive session flows. */
|
|
13
|
+
const excludedTools = ['admin_*', 'gecko_*', 'login', 'logout', 'v1_auth_*']
|
|
14
|
+
|
|
15
|
+
// Commands cover the versioned API; partner mirrors, `/rpc`, and `/mcp` stay reachable through the raw gateway.
|
|
16
|
+
const openapiConfig: Openapi.Config = {
|
|
17
|
+
groups: { v1: 'Call any Tempo API endpoint.' },
|
|
18
|
+
include: ({ path }) => path.startsWith('/v1/'),
|
|
19
|
+
mode: 'namespace',
|
|
20
|
+
}
|
|
8
21
|
|
|
9
22
|
/** Usage guidance surfaced to MCP clients on initialize (`<cli> --mcp`). */
|
|
10
23
|
const instructions =
|
|
11
|
-
'Tempo MCP provides access to the hosted Tempo API and documentation. Authenticated tools accept an `authorization` input (`Bearer <api key>`). List endpoints paginate via `cursor`/`nextCursor`. `docs_*` tools search the Tempo documentation.'
|
|
24
|
+
'Tempo MCP provides access to the hosted Tempo API and documentation. Authenticated tools accept an `authorization` input (`Bearer <api key>`); after `login`, management tools use the stored CLI session and protected API tools infer scoped project credentials. List endpoints paginate via `cursor`/`nextCursor`. `docs_*` tools search the Tempo documentation.'
|
|
25
|
+
|
|
26
|
+
// Explicit credentials always win over stored ones.
|
|
27
|
+
const credentialHeaders = ['authorization', 'cookie', 'tempo-api-key', 'x-api-key']
|
|
28
|
+
const credentialQuery = 'key'
|
|
12
29
|
|
|
13
30
|
/**
|
|
14
|
-
* Creates an incur CLI backed by a hosted Tempo API
|
|
15
|
-
* commands (
|
|
31
|
+
* Creates an incur CLI backed by a hosted Tempo API: generated API commands,
|
|
32
|
+
* session commands (`login`, `logout`, `whoami`), `keys create`, and the remote
|
|
33
|
+
* Tempo docs tools (`<cli> docs …`).
|
|
16
34
|
*/
|
|
17
35
|
export function from(url: string | URL, options: from.Options = {}) {
|
|
18
36
|
const {
|
|
37
|
+
apiKey,
|
|
38
|
+
credentials = Credentials.store(),
|
|
19
39
|
description = 'Tempo API CLI',
|
|
20
40
|
docs = 'https://mcp.tempo.xyz/mcp',
|
|
41
|
+
environment,
|
|
42
|
+
fetch = (request) => globalThis.fetch(request),
|
|
21
43
|
name = 'tapimo',
|
|
22
44
|
openapi = 'openapi.json',
|
|
45
|
+
orgId,
|
|
46
|
+
projectId,
|
|
23
47
|
request,
|
|
48
|
+
sourceKeyId,
|
|
49
|
+
update,
|
|
24
50
|
version = '0.0.0',
|
|
25
51
|
} = options
|
|
52
|
+
const apiUrl = new URL(url)
|
|
53
|
+
const send = (incoming: Request) => {
|
|
54
|
+
const { headers: configuredHeaders, ...options } = request ?? {}
|
|
55
|
+
const headers = new Headers(configuredHeaders)
|
|
56
|
+
// Gateway headers accompany prerequisite requests, but credentials belong to each operation.
|
|
57
|
+
for (const name of credentialHeaders) headers.delete(name)
|
|
58
|
+
incoming.headers.forEach((value, key) => headers.set(key, value))
|
|
59
|
+
return fetch(new Request(incoming, { ...options, headers }))
|
|
60
|
+
}
|
|
61
|
+
const context: Auth.Context = {
|
|
62
|
+
api: Client.create({
|
|
63
|
+
fetch: (input: Request | string | URL, init?: RequestInit) => send(new Request(input, init)),
|
|
64
|
+
url: apiUrl.href.replace(/\/$/, ''),
|
|
65
|
+
}),
|
|
66
|
+
apiUrl,
|
|
67
|
+
credentials,
|
|
68
|
+
fetch: send,
|
|
69
|
+
name: `${name} ${version}`,
|
|
70
|
+
}
|
|
26
71
|
|
|
27
72
|
const cli = incur_Cli
|
|
28
73
|
.create(name, {
|
|
29
74
|
description,
|
|
30
|
-
fetch:
|
|
75
|
+
fetch: source({
|
|
76
|
+
apiKey,
|
|
77
|
+
apiUrl,
|
|
78
|
+
context,
|
|
79
|
+
credentials,
|
|
80
|
+
environment,
|
|
81
|
+
fetch,
|
|
82
|
+
name,
|
|
83
|
+
openapi,
|
|
84
|
+
orgId,
|
|
85
|
+
projectId,
|
|
86
|
+
request,
|
|
87
|
+
sourceKeyId,
|
|
88
|
+
}),
|
|
31
89
|
mcp: {
|
|
32
90
|
instructions,
|
|
33
91
|
name: 'tempo',
|
|
@@ -35,31 +93,241 @@ export function from(url: string | URL, options: from.Options = {}) {
|
|
|
35
93
|
tools: { exclude: excludedTools },
|
|
36
94
|
},
|
|
37
95
|
openapi,
|
|
38
|
-
openapiConfig: options.openapiConfig ??
|
|
96
|
+
openapiConfig: options.openapiConfig ?? openapiConfig,
|
|
97
|
+
...(update === undefined ? {} : { update }),
|
|
39
98
|
version,
|
|
40
99
|
})
|
|
41
|
-
.command(
|
|
100
|
+
.command(Auth.login(context))
|
|
101
|
+
.command(Auth.logout(context))
|
|
102
|
+
.command(Auth.whoami(context))
|
|
103
|
+
.command(Keys.keys(context))
|
|
42
104
|
if (docs !== false)
|
|
43
105
|
cli.command('docs', { description: 'Search the Tempo documentation.', mcp: docs })
|
|
44
106
|
return cli
|
|
45
107
|
}
|
|
46
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Creates the CLI for the API at `TEMPO_API_URL` (default: hosted), sending
|
|
111
|
+
* `TEMPO_API_KEY` where sessions do not apply and storing sessions under `TEMPO_HOME`.
|
|
112
|
+
*/
|
|
113
|
+
export async function fromEnv(env: fromEnv.Env, options: from.Options = {}) {
|
|
114
|
+
if (env.TEMPO_API_ENV && env.TEMPO_API_ENV !== 'production' && env.TEMPO_API_ENV !== 'sandbox')
|
|
115
|
+
throw new Error('TEMPO_API_ENV must be production or sandbox.')
|
|
116
|
+
const url = env.TEMPO_API_URL || Client.defaultUrl
|
|
117
|
+
const credentialsFile = Credentials.defaultFile({ home: env.TEMPO_HOME })
|
|
118
|
+
// Loaded once, from a revalidated disk cache, so generated commands and session
|
|
119
|
+
// attachment share it and unchanged documents cost a 304. A supplied document skips it.
|
|
120
|
+
const openapi =
|
|
121
|
+
options.openapi ??
|
|
122
|
+
(await (async () => {
|
|
123
|
+
const spec = await Spec.load({
|
|
124
|
+
...(options.fetch ? { fetch: options.fetch } : {}),
|
|
125
|
+
file: Spec.cacheFile({ directory: path.join(path.dirname(credentialsFile), 'cache'), url }),
|
|
126
|
+
url,
|
|
127
|
+
})
|
|
128
|
+
if (spec.status !== 'current') {
|
|
129
|
+
const reason = spec.error instanceof Error ? spec.error.message : String(spec.error)
|
|
130
|
+
// Unreachable: help, version, and session commands still work, plus cached API commands.
|
|
131
|
+
process.stderr.write(
|
|
132
|
+
spec.status === 'cached'
|
|
133
|
+
? `Could not reach ${url} (${reason}); using cached API commands.\n`
|
|
134
|
+
: `Could not load API commands from ${url}: ${reason}\n`,
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
return spec.document
|
|
138
|
+
})())
|
|
139
|
+
return from(url, {
|
|
140
|
+
...(env.TEMPO_API_KEY ? { apiKey: env.TEMPO_API_KEY } : {}),
|
|
141
|
+
environment: env.TEMPO_API_ENV as 'production' | 'sandbox' | undefined,
|
|
142
|
+
orgId: env.TEMPO_API_ORG,
|
|
143
|
+
projectId: env.TEMPO_API_PROJECT,
|
|
144
|
+
sourceKeyId: env.TEMPO_API_SOURCE_KEY,
|
|
145
|
+
credentials: Credentials.store({ file: credentialsFile }),
|
|
146
|
+
...options,
|
|
147
|
+
openapi,
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export declare namespace fromEnv {
|
|
152
|
+
/** Environment variables the CLI reads; any other variables are ignored. */
|
|
153
|
+
type Env = Record<string, string | undefined> & {
|
|
154
|
+
/** Environment for inferred project credentials. */
|
|
155
|
+
TEMPO_API_ENV?: string | undefined
|
|
156
|
+
/** Explicit API key sent where sessions do not apply. */
|
|
157
|
+
TEMPO_API_KEY?: string | undefined
|
|
158
|
+
/** Organization for inferred project credentials. */
|
|
159
|
+
TEMPO_API_ORG?: string | undefined
|
|
160
|
+
/** Project for inferred project credentials. */
|
|
161
|
+
TEMPO_API_PROJECT?: string | undefined
|
|
162
|
+
/** Approved key to derive restricted scopes from. */
|
|
163
|
+
TEMPO_API_SOURCE_KEY?: string | undefined
|
|
164
|
+
/** Tempo API origin. @default 'https://api.tempo.xyz' */
|
|
165
|
+
TEMPO_API_URL?: string | undefined
|
|
166
|
+
/** Tempo CLI home directory. @default '~/.tempo' */
|
|
167
|
+
TEMPO_HOME?: string | undefined
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
47
171
|
export declare namespace from {
|
|
48
172
|
/** Options for creating a Tempo API CLI from a hosted API. */
|
|
49
173
|
type Options = {
|
|
174
|
+
/** API key sent on operations that do not accept the stored CLI session. */
|
|
175
|
+
apiKey?: string | undefined
|
|
176
|
+
/** Stored CLI sessions. @default Credentials.store() */
|
|
177
|
+
credentials?: Credentials.Store | undefined
|
|
50
178
|
/** CLI description. */
|
|
51
179
|
description?: string | undefined
|
|
52
180
|
/** Remote docs MCP source mounted as the `docs` command group, or `false` to omit it. @default 'https://mcp.tempo.xyz/mcp' */
|
|
53
181
|
docs?: mcp.Source | false | undefined
|
|
182
|
+
/** Environment for inferred project credentials. Defaults to production. */
|
|
183
|
+
environment?: 'production' | 'sandbox' | undefined
|
|
184
|
+
/** Sends requests to the Tempo API, such as an in-process app. @default globalThis.fetch */
|
|
185
|
+
fetch?: ((request: Request) => Promise<Response>) | undefined
|
|
54
186
|
/** CLI name. */
|
|
55
187
|
name?: string | undefined
|
|
56
|
-
/** OpenAPI document source.
|
|
188
|
+
/** OpenAPI document or its source. Pass a resolved document to avoid fetching it twice. */
|
|
57
189
|
openapi?: Openapi.OpenAPISource | undefined
|
|
58
|
-
/** OpenAPI command generation configuration. Defaults to namespace
|
|
190
|
+
/** OpenAPI command generation configuration. Defaults to namespace-mode commands for the `/v1` API. */
|
|
59
191
|
openapiConfig?: Openapi.Config | undefined
|
|
192
|
+
/** Organization for inferred project credentials. */
|
|
193
|
+
orgId?: string | undefined
|
|
194
|
+
/** Project for inferred project credentials. */
|
|
195
|
+
projectId?: string | undefined
|
|
60
196
|
/** Request options applied to API calls. */
|
|
61
197
|
request?: Fetch.fromRequest.Options | undefined
|
|
198
|
+
/** Approved source key when multiple restricted-scope grants exist. */
|
|
199
|
+
sourceKeyId?: string | undefined
|
|
200
|
+
/** How `--update` installs a new version and whether to check for one. @default npm, inferred from the installed package */
|
|
201
|
+
update?: incur_Cli.create.Options['update']
|
|
62
202
|
/** CLI version. */
|
|
63
203
|
version?: string | undefined
|
|
64
204
|
}
|
|
65
205
|
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Hosted request source for generated commands. Operations whose OpenAPI
|
|
209
|
+
* security accepts a session get the stored CLI session, and those accepting
|
|
210
|
+
* API keys get the configured key or scoped credentials inferred from login.
|
|
211
|
+
* Sign-in-only operations fail locally when signed out.
|
|
212
|
+
*/
|
|
213
|
+
function source(parameters: source.Parameters): Fetch.RequestSource {
|
|
214
|
+
const {
|
|
215
|
+
apiKey,
|
|
216
|
+
apiUrl,
|
|
217
|
+
context,
|
|
218
|
+
credentials,
|
|
219
|
+
environment,
|
|
220
|
+
fetch,
|
|
221
|
+
name,
|
|
222
|
+
openapi,
|
|
223
|
+
orgId,
|
|
224
|
+
projectId,
|
|
225
|
+
request = {},
|
|
226
|
+
sourceKeyId,
|
|
227
|
+
} = parameters
|
|
228
|
+
const { headers: defaultHeaders, ...init } = request
|
|
229
|
+
// Resolved once; a document that fails to load leaves every operation unknown.
|
|
230
|
+
const lanesFor = (async () =>
|
|
231
|
+
operationLanes(await Openapi.resolve(openapi, { baseUrl: apiUrl })))().catch(
|
|
232
|
+
() => () => undefined,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
url: apiUrl,
|
|
237
|
+
async fetch(incoming) {
|
|
238
|
+
const { pathname, search } = new URL(incoming.url)
|
|
239
|
+
const target = new URL(apiUrl)
|
|
240
|
+
target.pathname = `${apiUrl.pathname.replace(/\/$/, '')}${pathname}`
|
|
241
|
+
target.search = search
|
|
242
|
+
const headers = new Headers(defaultHeaders)
|
|
243
|
+
incoming.headers.forEach((value, key) => headers.set(key, value))
|
|
244
|
+
const explicit =
|
|
245
|
+
credentialHeaders.some((name) => headers.has(name)) ||
|
|
246
|
+
target.searchParams.has(credentialQuery)
|
|
247
|
+
if (!explicit) {
|
|
248
|
+
const lanes = (await lanesFor)(incoming.method, pathname)
|
|
249
|
+
const session = lanes?.session ? await credentials.get(apiUrl) : undefined
|
|
250
|
+
if (session) headers.set('authorization', `Bearer ${session.token}`)
|
|
251
|
+
// Unknown operations still get the key and let the API decide.
|
|
252
|
+
else if (apiKey && (lanes?.apiKey ?? true)) headers.set('tempo-api-key', apiKey)
|
|
253
|
+
else if (lanes?.apiKey && !lanes.public) {
|
|
254
|
+
const inferred = await ApiKeys.resolve(context, {
|
|
255
|
+
environment,
|
|
256
|
+
orgId,
|
|
257
|
+
projectId,
|
|
258
|
+
scopes: lanes.scopes,
|
|
259
|
+
sourceKeyId,
|
|
260
|
+
})
|
|
261
|
+
if (inferred && typeof inferred !== 'string') return inferred as Response
|
|
262
|
+
if (inferred) headers.set('tempo-api-key', inferred)
|
|
263
|
+
}
|
|
264
|
+
// Sending nothing (or an API key) would earn an unhelpful 401 or 403.
|
|
265
|
+
else if (lanes?.session && !lanes.apiKey && !lanes.public) {
|
|
266
|
+
const message = `Not signed in, or the session expired. Run \`${name} login\`.`
|
|
267
|
+
return Response.json({ error: { code: 'not_signed_in', message } }, { status: 401 })
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return fetch(new Request(new Request(target, incoming), { ...init, headers }))
|
|
271
|
+
},
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
declare namespace source {
|
|
276
|
+
type Parameters = {
|
|
277
|
+
apiKey: string | undefined
|
|
278
|
+
apiUrl: URL
|
|
279
|
+
context: Auth.Context
|
|
280
|
+
credentials: Credentials.Store
|
|
281
|
+
environment: 'production' | 'sandbox' | undefined
|
|
282
|
+
fetch: (request: Request) => Promise<Response>
|
|
283
|
+
name: string
|
|
284
|
+
openapi: Openapi.OpenAPISource
|
|
285
|
+
orgId: string | undefined
|
|
286
|
+
projectId: string | undefined
|
|
287
|
+
request: Fetch.fromRequest.Options | undefined
|
|
288
|
+
sourceKeyId: string | undefined
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** Builds a lookup of the credentials each operation accepts, from its OpenAPI security requirements. */
|
|
293
|
+
function operationLanes(spec: Openapi.OpenAPISpec) {
|
|
294
|
+
type Operation = {
|
|
295
|
+
security?: readonly Record<string, unknown>[] | undefined
|
|
296
|
+
'x-required-scopes'?: readonly string[] | undefined
|
|
297
|
+
}
|
|
298
|
+
const paths = (spec.paths ?? {}) as Record<string, Record<string, Operation>>
|
|
299
|
+
const operations = Object.entries(paths).flatMap(([path, item]) =>
|
|
300
|
+
Object.entries(item).map(([method, operation]) => {
|
|
301
|
+
const requirements = operation.security ?? spec.security ?? []
|
|
302
|
+
const has = (scheme: string) => requirements.some((requirement) => scheme in requirement)
|
|
303
|
+
return {
|
|
304
|
+
lanes: {
|
|
305
|
+
apiKey: has('apiKey') || has('queryApiKey'),
|
|
306
|
+
// An empty requirement (or none at all) admits anonymous callers.
|
|
307
|
+
public:
|
|
308
|
+
requirements.length === 0 ||
|
|
309
|
+
requirements.some((requirement) => Object.keys(requirement).length === 0),
|
|
310
|
+
session: has('session'),
|
|
311
|
+
scopes: operation['x-required-scopes'] ?? ['*'],
|
|
312
|
+
},
|
|
313
|
+
method: method.toUpperCase(),
|
|
314
|
+
pattern: pathPattern(path),
|
|
315
|
+
templated: path.split('{').length - 1,
|
|
316
|
+
}
|
|
317
|
+
}),
|
|
318
|
+
)
|
|
319
|
+
// Literal paths win over templated ones (`/v1/webhooks/event-types` over `/v1/webhooks/{id}`).
|
|
320
|
+
operations.sort((a, b) => a.templated - b.templated)
|
|
321
|
+
return (method: string, pathname: string) =>
|
|
322
|
+
operations.find((operation) => operation.method === method && operation.pattern.test(pathname))
|
|
323
|
+
?.lanes
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// `/v1/orgs/{orgId}` matches `/v1/orgs/org_123`.
|
|
327
|
+
function pathPattern(path: string) {
|
|
328
|
+
const source = path
|
|
329
|
+
.split(/(\{[^}]+\})/)
|
|
330
|
+
.map((part) => (part.startsWith('{') ? '[^/]+' : part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')))
|
|
331
|
+
.join('')
|
|
332
|
+
return new RegExp(`^${source}$`)
|
|
333
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as child_process from 'node:child_process'
|
|
2
|
+
import * as fs from 'node:fs/promises'
|
|
3
|
+
import * as os from 'node:os'
|
|
4
|
+
import * as path from 'node:path'
|
|
5
|
+
import * as util from 'node:util'
|
|
6
|
+
|
|
7
|
+
import * as Credentials from './Credentials.js'
|
|
8
|
+
|
|
9
|
+
const session = {
|
|
10
|
+
email: 'dev@example.com',
|
|
11
|
+
expiresAt: '2099-01-01T00:00:00.000Z',
|
|
12
|
+
token: `tempo:cli:${'ab'.repeat(32)}`,
|
|
13
|
+
userId: 'usr_1a2b3c4d5e6f7g8h9j0k1m2n',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function temporaryFile() {
|
|
17
|
+
const directory = await fs.mkdtemp(path.join(os.tmpdir(), 'tapimo-credentials-'))
|
|
18
|
+
return path.join(directory, 'nested', 'credentials.json')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
vi.useRealTimers()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('store', () => {
|
|
26
|
+
test('round-trips a session per API origin in a private file', async () => {
|
|
27
|
+
const file = await temporaryFile()
|
|
28
|
+
const store = Credentials.store({ file })
|
|
29
|
+
await store.set('https://api.tempo.xyz/', session)
|
|
30
|
+
|
|
31
|
+
expect(await store.get('https://api.tempo.xyz')).toEqual(session)
|
|
32
|
+
expect(await store.get('https://api.tempo-dev.workers.dev')).toBeUndefined()
|
|
33
|
+
expect((await fs.stat(file)).mode & 0o777).toBe(0o600)
|
|
34
|
+
expect((await fs.stat(path.dirname(file))).mode & 0o777).toBe(0o700)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('treats a missing or unreadable file as signed out', async () => {
|
|
38
|
+
const file = await temporaryFile()
|
|
39
|
+
expect(await Credentials.store({ file }).get('https://api.tempo.xyz')).toBeUndefined()
|
|
40
|
+
await fs.mkdir(path.dirname(file), { recursive: true })
|
|
41
|
+
await fs.writeFile(file, '{"version":2}')
|
|
42
|
+
expect(await Credentials.store({ file }).get('https://api.tempo.xyz')).toBeUndefined()
|
|
43
|
+
await fs.writeFile(file, '{not json')
|
|
44
|
+
expect(await Credentials.store({ file }).get('https://api.tempo.xyz')).toBeUndefined()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('hides expired sessions', async () => {
|
|
48
|
+
vi.useFakeTimers({ now: new Date('2099-01-01T00:00:00.000Z') })
|
|
49
|
+
const store = Credentials.store({ file: await temporaryFile() })
|
|
50
|
+
await store.set('https://api.tempo.xyz', session)
|
|
51
|
+
expect(await store.get('https://api.tempo.xyz')).toBeUndefined()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('removes one origin and keeps the rest', async () => {
|
|
55
|
+
const store = Credentials.store({ file: await temporaryFile() })
|
|
56
|
+
await store.set('https://api.tempo.xyz', session)
|
|
57
|
+
await store.set('https://api.tempo-dev.workers.dev', session)
|
|
58
|
+
await store.remove('https://api.tempo.xyz')
|
|
59
|
+
expect(await store.get('https://api.tempo.xyz')).toBeUndefined()
|
|
60
|
+
expect(await store.get('https://api.tempo-dev.workers.dev')).toEqual(session)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('serializes read-modify-write transactions across separate processes', async () => {
|
|
64
|
+
const file = await temporaryFile()
|
|
65
|
+
const store = Credentials.store({ file })
|
|
66
|
+
await store.set('https://api.tempo.xyz', { ...session, scopes: [] })
|
|
67
|
+
const execute = util.promisify(child_process.execFile)
|
|
68
|
+
const script = `
|
|
69
|
+
import * as Credentials from ${JSON.stringify(path.join(import.meta.dirname, 'Credentials.ts'))};
|
|
70
|
+
const store = Credentials.store({ file: ${JSON.stringify(file)} });
|
|
71
|
+
await store.withLock(async (credentials) => {
|
|
72
|
+
const session = await credentials.get('https://api.tempo.xyz');
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
74
|
+
await credentials.set('https://api.tempo.xyz', {
|
|
75
|
+
...session, scopes: [...session.scopes, process.argv[1]],
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
`
|
|
79
|
+
await Promise.all(
|
|
80
|
+
['data:read', 'routes:read', 'rpc-relay:read'].map((scope) =>
|
|
81
|
+
execute(process.execPath, [
|
|
82
|
+
'--experimental-transform-types',
|
|
83
|
+
'--input-type=module',
|
|
84
|
+
'-e',
|
|
85
|
+
script,
|
|
86
|
+
scope,
|
|
87
|
+
]),
|
|
88
|
+
),
|
|
89
|
+
)
|
|
90
|
+
expect((await store.get('https://api.tempo.xyz'))?.scopes?.sort()).toEqual([
|
|
91
|
+
'data:read',
|
|
92
|
+
'routes:read',
|
|
93
|
+
'rpc-relay:read',
|
|
94
|
+
])
|
|
95
|
+
expect((await fs.stat(file)).mode & 0o777).toBe(0o600)
|
|
96
|
+
expect(await fs.readdir(path.dirname(file))).toEqual(['credentials.json'])
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('releases the credentials lock after a transaction fails', async () => {
|
|
100
|
+
const file = await temporaryFile()
|
|
101
|
+
const first = Credentials.store({ file })
|
|
102
|
+
await expect(
|
|
103
|
+
first.withLock!(async () => {
|
|
104
|
+
throw new Error('Failed transaction')
|
|
105
|
+
}),
|
|
106
|
+
).rejects.toThrow('Failed transaction')
|
|
107
|
+
const second = Credentials.store({ file })
|
|
108
|
+
await second.set('https://api.tempo.xyz', session)
|
|
109
|
+
expect(await first.get('https://api.tempo.xyz')).toEqual(session)
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
describe('defaultFile', () => {
|
|
114
|
+
test('lives under the Tempo home directory', () => {
|
|
115
|
+
expect(Credentials.defaultFile({ home: '/tmp/tempo-home' })).toBe(
|
|
116
|
+
'/tmp/tempo-home/api/credentials.json',
|
|
117
|
+
)
|
|
118
|
+
expect(Credentials.defaultFile()).toBe(
|
|
119
|
+
path.join(os.homedir(), '.tempo', 'api', 'credentials.json'),
|
|
120
|
+
)
|
|
121
|
+
})
|
|
122
|
+
})
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises'
|
|
2
|
+
import * as os from 'node:os'
|
|
3
|
+
import * as path from 'node:path'
|
|
4
|
+
import * as lockfile from 'proper-lockfile'
|
|
5
|
+
import * as z from 'zod/mini'
|
|
6
|
+
|
|
7
|
+
/** Stored CLI credentials: one CLI session per API origin. */
|
|
8
|
+
export type Store = {
|
|
9
|
+
/** Reads the unexpired session for an API URL. */
|
|
10
|
+
get: (apiUrl: string | URL) => Promise<Session | undefined>
|
|
11
|
+
/** Forgets the session for an API URL. */
|
|
12
|
+
remove: (apiUrl: string | URL) => Promise<void>
|
|
13
|
+
/** Saves the session for an API URL. */
|
|
14
|
+
set: (apiUrl: string | URL, session: Session) => Promise<void>
|
|
15
|
+
/** Serializes credential operations across processes, passing an unlocked store to the callback. */
|
|
16
|
+
withLock?: (<result>(fn: (store: Store) => Promise<result>) => Promise<result>) | undefined
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Storage schemas for the credentials file. */
|
|
20
|
+
export namespace schema {
|
|
21
|
+
/** A project API key inferred from the approved CLI session. */
|
|
22
|
+
export const ApiKey = z.object({
|
|
23
|
+
environment: z.enum(['production', 'sandbox']),
|
|
24
|
+
expiresAt: z.optional(z.string()),
|
|
25
|
+
id: z.string(),
|
|
26
|
+
orgId: z.string(),
|
|
27
|
+
projectId: z.string(),
|
|
28
|
+
scopes: z.array(z.string()),
|
|
29
|
+
sourceKeyId: z.optional(z.string()),
|
|
30
|
+
token: z.string(),
|
|
31
|
+
})
|
|
32
|
+
/** A signed-in CLI session. */
|
|
33
|
+
export const Session = z.object({
|
|
34
|
+
apiKeys: z.optional(z.array(ApiKey)),
|
|
35
|
+
email: z.optional(z.string()),
|
|
36
|
+
expiresAt: z.string(),
|
|
37
|
+
scopes: z.optional(z.array(z.string())),
|
|
38
|
+
token: z.string(),
|
|
39
|
+
userId: z.string(),
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
/** The credentials file. */
|
|
43
|
+
export const File = z.object({
|
|
44
|
+
sessions: z.record(z.string(), Session),
|
|
45
|
+
version: z.literal(1),
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** A signed-in CLI session. */
|
|
50
|
+
export type Session = z.output<typeof schema.Session>
|
|
51
|
+
|
|
52
|
+
type File = z.output<typeof schema.File>
|
|
53
|
+
|
|
54
|
+
/** Default credentials file: `<home>/api/credentials.json`, with `home` defaulting to `~/.tempo`. */
|
|
55
|
+
export function defaultFile(options: defaultFile.Options = {}): string {
|
|
56
|
+
return path.join(options.home || path.join(os.homedir(), '.tempo'), 'api', 'credentials.json')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export declare namespace defaultFile {
|
|
60
|
+
/** Options for {@link defaultFile}. */
|
|
61
|
+
type Options = {
|
|
62
|
+
/** Tempo CLI home directory. @default '~/.tempo' */
|
|
63
|
+
home?: string | undefined
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Creates a credentials store backed by a private JSON file. */
|
|
68
|
+
export function store(options: store.Options = {}): Store {
|
|
69
|
+
const { file = defaultFile() } = options
|
|
70
|
+
|
|
71
|
+
async function read(): Promise<File> {
|
|
72
|
+
const text = await fs.readFile(file, 'utf8').catch((error: NodeJS.ErrnoException) => {
|
|
73
|
+
if (error.code === 'ENOENT') return undefined
|
|
74
|
+
throw error
|
|
75
|
+
})
|
|
76
|
+
if (text === undefined) return { sessions: {}, version: 1 }
|
|
77
|
+
// An unreadable file is treated as signed out rather than blocking every command.
|
|
78
|
+
const parsed = (() => {
|
|
79
|
+
try {
|
|
80
|
+
return schema.File.safeParse(JSON.parse(text))
|
|
81
|
+
} catch {
|
|
82
|
+
return undefined
|
|
83
|
+
}
|
|
84
|
+
})()
|
|
85
|
+
return parsed?.success ? parsed.data : { sessions: {}, version: 1 }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function write(value: File) {
|
|
89
|
+
await fs.mkdir(path.dirname(file), { mode: 0o700, recursive: true })
|
|
90
|
+
// Write then rename so a crash never leaves a truncated file; 0600 keeps tokens private.
|
|
91
|
+
const temporary = `${file}.${process.pid}.tmp`
|
|
92
|
+
await fs.writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 })
|
|
93
|
+
await fs.rename(temporary, file)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const unlocked: Store = {
|
|
97
|
+
async get(apiUrl) {
|
|
98
|
+
const session = (await read()).sessions[new URL(apiUrl).origin]
|
|
99
|
+
if (!session || Date.parse(session.expiresAt) <= Date.now()) return undefined
|
|
100
|
+
return session
|
|
101
|
+
},
|
|
102
|
+
async remove(apiUrl) {
|
|
103
|
+
const value = await read()
|
|
104
|
+
const origin = new URL(apiUrl).origin
|
|
105
|
+
if (!(origin in value.sessions)) return
|
|
106
|
+
delete value.sessions[origin]
|
|
107
|
+
await write(value)
|
|
108
|
+
},
|
|
109
|
+
async set(apiUrl, session) {
|
|
110
|
+
const value = await read()
|
|
111
|
+
value.sessions[new URL(apiUrl).origin] = session
|
|
112
|
+
await write(value)
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function withLock<result>(fn: (store: Store) => Promise<result>): Promise<result> {
|
|
117
|
+
await fs.mkdir(path.dirname(file), { mode: 0o700, recursive: true })
|
|
118
|
+
const directory = await fs.realpath(path.dirname(file))
|
|
119
|
+
const release = await lockfile.lock(path.join(directory, path.basename(file)), {
|
|
120
|
+
realpath: false,
|
|
121
|
+
retries: { factor: 1, maxTimeout: 100, minTimeout: 100, retries: 600 },
|
|
122
|
+
})
|
|
123
|
+
try {
|
|
124
|
+
return await fn(unlocked)
|
|
125
|
+
} finally {
|
|
126
|
+
await release()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
get: unlocked.get,
|
|
132
|
+
remove: (apiUrl) => withLock((store) => store.remove(apiUrl)),
|
|
133
|
+
set: (apiUrl, session) => withLock((store) => store.set(apiUrl, session)),
|
|
134
|
+
withLock,
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export declare namespace store {
|
|
139
|
+
/** Options for {@link store}. */
|
|
140
|
+
type Options = {
|
|
141
|
+
/** Credentials file path. @default defaultFile() */
|
|
142
|
+
file?: string | undefined
|
|
143
|
+
}
|
|
144
|
+
}
|