tapimo 0.4.1 → 0.4.3
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 +1 -1
- package/dist/ApiKey.d.ts +1 -9
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +2 -3
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +53 -27
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +32 -17
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +2451 -1533
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +23 -9
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +10 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +4 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Auth.d.ts +2 -1
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js +2 -1
- package/dist/Auth.js.map +1 -1
- package/dist/Scope.d.ts +40 -15
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +44 -13
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +560 -9
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +38 -6
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +10 -24
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +10 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +833 -0
- package/dist/admin/apps/organizations.d.ts.map +1 -0
- package/dist/admin/apps/organizations.js +733 -0
- package/dist/admin/apps/organizations.js.map +1 -0
- package/dist/admin/apps/scopes.d.ts +8 -0
- package/dist/admin/apps/scopes.d.ts.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 +53 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +10 -0
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +8 -0
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +9 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +14 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +1354 -984
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/FundingRouteProviders.d.ts +94 -5
- package/dist/apps/data/FundingRouteProviders.d.ts.map +1 -1
- package/dist/apps/data/FundingRouteProviders.js +196 -5
- package/dist/apps/data/FundingRouteProviders.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +38 -38
- package/dist/apps/data/routes/addresses.d.ts +24 -24
- package/dist/apps/data/routes/blocks.d.ts +39 -39
- package/dist/apps/data/routes/exchanges.d.ts +453 -453
- package/dist/apps/data/routes/fee-amm.d.ts +101 -101
- package/dist/apps/data/routes/funding.d.ts +730 -138
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +234 -0
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/transactions.d.ts +281 -281
- package/dist/apps/data/routes/transfers.d.ts +58 -58
- package/dist/apps/data/routes/verified-tokens.d.ts +81 -81
- package/dist/apps/management/App.d.ts +1156 -615
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -2
- package/dist/apps/management/Billing.d.ts +3 -0
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +7 -2
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +106 -90
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +41 -30
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +278 -146
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +14 -14
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +93 -20
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +12 -15
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/members.d.ts +89 -18
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +10 -10
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +130 -70
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +19 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +137 -48
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +12 -13
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts +4 -18
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +6 -7
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +63 -19
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +9 -10
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +35 -3
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/relay/App.d.ts +26 -4
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +17 -14
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/db/Db.d.ts +5 -3
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +52 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +13 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +16 -1
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/adminAuditLogs.d.ts +27 -0
- package/dist/db/tables/adminAuditLogs.d.ts.map +1 -0
- package/dist/db/tables/adminAuditLogs.js +19 -0
- package/dist/db/tables/adminAuditLogs.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +1 -1
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/memberships.d.ts +32 -4
- package/dist/db/tables/memberships.d.ts.map +1 -1
- package/dist/db/tables/memberships.js +31 -0
- package/dist/db/tables/memberships.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +43 -1
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +103 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +25 -0
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +22 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts +26 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +37 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/internal/Auth.d.ts +13 -18
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +78 -58
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cursor.d.ts +1 -1
- package/dist/internal/Cursor.d.ts.map +1 -1
- package/dist/internal/Cursor.js +4 -0
- package/dist/internal/Cursor.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +2 -0
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/FundingRoutes.d.ts +170 -0
- package/dist/internal/FundingRoutes.d.ts.map +1 -1
- package/dist/internal/FundingRoutes.js +68 -6
- package/dist/internal/FundingRoutes.js.map +1 -1
- package/dist/internal/Log.d.ts +16 -1
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +5 -3
- package/dist/internal/Log.js.map +1 -1
- package/package.json +2 -2
- package/src/ApiKey.ts +2 -3
- package/src/ApiKeys.ts +95 -17
- package/src/App.test.ts +44 -2
- package/src/App.ts +29 -9
- package/src/Assets.ts +8 -0
- package/src/Auth.test-d.ts +36 -0
- package/src/Auth.ts +20 -1
- package/src/Client.test-d.ts +64 -17
- package/src/Scope.test.ts +34 -0
- package/src/Scope.ts +53 -17
- package/src/admin/App.test.ts +33 -3
- package/src/admin/App.ts +49 -14
- package/src/admin/apps/api-keys.ts +10 -3
- package/src/admin/apps/organizations.test.ts +455 -0
- package/src/admin/apps/organizations.ts +953 -0
- package/src/admin/apps/scopes.test.ts +10 -0
- package/src/admin/ui/plugin.ts +1 -1
- package/src/admin/ui/src/components/MobileProfile.tsx +2 -0
- package/src/admin/ui/src/components/ThemeToggle.tsx +20 -0
- package/src/admin/ui/src/lib/api-keys.ts +36 -19
- package/src/admin/ui/src/lib/config.ts +2 -3
- package/src/admin/ui/src/lib/organizations.test.ts +89 -0
- package/src/admin/ui/src/lib/organizations.ts +262 -0
- package/src/admin/ui/src/lib/query-client.ts +3 -1
- package/src/admin/ui/src/lib/theme.ts +57 -0
- package/src/admin/ui/src/routeTree.gen.ts +47 -4
- package/src/admin/ui/src/routes/__root.tsx +18 -3
- package/src/admin/ui/src/routes/api-keys.tsx +52 -7
- package/src/admin/ui/src/routes/index.tsx +1 -1
- package/src/admin/ui/src/routes/organizations.tsx +158 -0
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +710 -0
- package/src/admin/ui/src/start.ts +6 -0
- package/src/admin/ui.generated.ts +63 -13
- package/src/analytics/Analytics.ts +25 -0
- package/src/analytics/tables/requestEvents.ts +33 -0
- package/src/apps/composition.test.ts +82 -2
- package/src/apps/data/FundingRouteProviders.test.ts +204 -0
- package/src/apps/data/FundingRouteProviders.ts +294 -9
- package/src/apps/data/routes/funding.test.ts +90 -23
- package/src/apps/data/routes/funding.ts +315 -0
- package/src/apps/management/App.ts +2 -2
- package/src/apps/management/Billing.ts +10 -2
- package/src/apps/management/routes/api-keys.test.ts +137 -1
- package/src/apps/management/routes/api-keys.ts +63 -38
- package/src/apps/management/routes/billing.ts +14 -14
- package/src/apps/management/routes/invitations.test.ts +102 -1
- package/src/apps/management/routes/invitations.ts +13 -15
- package/src/apps/management/routes/members.ts +10 -10
- package/src/apps/management/routes/orgs.test.ts +78 -16
- package/src/apps/management/routes/orgs.ts +21 -20
- package/src/apps/management/routes/projects.ts +12 -13
- package/src/apps/management/routes/scopes.test.ts +16 -0
- package/src/apps/management/routes/scopes.ts +6 -7
- package/src/apps/management/routes/usage.ts +9 -14
- package/src/apps/mcp.test.ts +25 -1
- package/src/apps/mcp.ts +43 -3
- package/src/apps/relay/App.test.ts +23 -18
- package/src/apps/relay/App.ts +35 -14
- package/src/db/Db.ts +59 -3
- package/src/db/Schema.ts +20 -1
- package/src/db/tables/adminAuditLogs.ts +47 -0
- package/src/db/tables/invitations.ts +1 -1
- package/src/db/tables/memberships.ts +59 -3
- package/src/db/tables/organizations.ts +148 -1
- package/src/db/tables/projects.ts +47 -0
- package/src/db/tables/webhookDeliveries.ts +83 -0
- package/src/internal/Auth.test.ts +174 -7
- package/src/internal/Auth.ts +90 -62
- package/src/internal/Cursor.test.ts +10 -0
- package/src/internal/Cursor.ts +5 -1
- package/src/internal/EdgeCache.test.ts +11 -0
- package/src/internal/EdgeCache.ts +2 -0
- package/src/internal/FundingRoutes.test.ts +26 -0
- package/src/internal/FundingRoutes.ts +187 -18
- package/src/internal/Log.test.ts +41 -3
- package/src/internal/Log.ts +23 -4
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import * as z from 'zod/mini';
|
|
3
|
+
import * as Analytics from '../../analytics/Analytics.js';
|
|
4
|
+
import * as ApiKeys from '../../ApiKeys.js';
|
|
5
|
+
import * as core_Billing from '../../apps/management/Billing.js';
|
|
6
|
+
import * as BillingSettings from '../../db/tables/billingSettings.js';
|
|
7
|
+
import * as Db from '../../db/Db.js';
|
|
8
|
+
import * as Memberships from '../../db/tables/memberships.js';
|
|
9
|
+
import * as Organizations from '../../db/tables/organizations.js';
|
|
10
|
+
import * as Projects from '../../db/tables/projects.js';
|
|
11
|
+
import * as SponsoredTransactions from '../../db/tables/sponsoredTransactions.js';
|
|
12
|
+
import * as StripeCustomers from '../../db/tables/stripeCustomers.js';
|
|
13
|
+
import * as WebhookDeliveries from '../../db/tables/webhookDeliveries.js';
|
|
14
|
+
import * as WebhookSubscriptions from '../../db/tables/webhookSubscriptions.js';
|
|
15
|
+
import * as Cursor from '../../internal/Cursor.js';
|
|
16
|
+
import * as OpenApi from '../../internal/OpenApi.js';
|
|
17
|
+
import * as Response from '../../internal/Response.js';
|
|
18
|
+
import * as Schema from '../../internal/Schema.js';
|
|
19
|
+
import * as Viem from '../../internal/Viem.js';
|
|
20
|
+
/** Zod schemas owned by the admin organizations handler. */
|
|
21
|
+
export var schema;
|
|
22
|
+
(function (schema) {
|
|
23
|
+
const timestamp = z
|
|
24
|
+
.string()
|
|
25
|
+
.check(z.describe('An ISO 8601 timestamp.'), z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }));
|
|
26
|
+
const Organization = Schema.describe(z.object({
|
|
27
|
+
createdAt: timestamp,
|
|
28
|
+
createdBy: z
|
|
29
|
+
.nullable(z.string())
|
|
30
|
+
.check(z.describe('Identity that created the organization, or null.'), z.meta({ examples: ['admin@tempo.xyz'] })),
|
|
31
|
+
id: z
|
|
32
|
+
.string()
|
|
33
|
+
.check(z.describe('Stable organization id.'), z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] })),
|
|
34
|
+
name: z
|
|
35
|
+
.string()
|
|
36
|
+
.check(z.describe('Human-readable organization name.'), z.meta({ examples: ['Acme'] })),
|
|
37
|
+
updatedAt: timestamp,
|
|
38
|
+
userId: z
|
|
39
|
+
.nullable(z.string())
|
|
40
|
+
.check(z.describe('Owning user id, or null for a super-admin-created organization.'), z.meta({ examples: ['usr_1a2b3c4d5e6f7g8h9j0k1m2n'] })),
|
|
41
|
+
}), 'An organization visible to an authenticated administrator.');
|
|
42
|
+
/** Schemas for the listOrganizations operation. */
|
|
43
|
+
let listOrganizations;
|
|
44
|
+
(function (listOrganizations) {
|
|
45
|
+
/** Query parameters for organization lookup. */
|
|
46
|
+
listOrganizations.Query = z
|
|
47
|
+
.strictObject({
|
|
48
|
+
cursor: Schema.Cursor,
|
|
49
|
+
limit: Schema.Limit,
|
|
50
|
+
query: z
|
|
51
|
+
.optional(z
|
|
52
|
+
.pipe(z.string(), z.transform((value) => value.trim()))
|
|
53
|
+
.check(z.minLength(3), z.maxLength(200)))
|
|
54
|
+
.check(z.describe('Exact organization or user id, or a name or member-email prefix.'), z.meta({ examples: ['acme@example.com'] })),
|
|
55
|
+
})
|
|
56
|
+
.check(z.describe('Query parameters for listing organizations.'));
|
|
57
|
+
/** Organization summary shown in lookup results. */
|
|
58
|
+
listOrganizations.OrganizationSummary = Schema.describe(z.extend(Organization, {
|
|
59
|
+
memberCount: z
|
|
60
|
+
.number()
|
|
61
|
+
.check(z.int(), z.nonnegative(), z.describe('Number of organization members.'), z.meta({ examples: [3] })),
|
|
62
|
+
projectCount: z
|
|
63
|
+
.number()
|
|
64
|
+
.check(z.int(), z.nonnegative(), z.describe('Number of organization projects.'), z.meta({ examples: [2] })),
|
|
65
|
+
}), 'An organization lookup result.');
|
|
66
|
+
/** Cursor-paginated organization lookup results. */
|
|
67
|
+
listOrganizations.Response = Schema.describe(z.object({
|
|
68
|
+
data: z
|
|
69
|
+
.array(listOrganizations.OrganizationSummary)
|
|
70
|
+
.check(z.describe('Organizations on this page, newest first.')),
|
|
71
|
+
nextCursor: Schema.NextCursor,
|
|
72
|
+
}), 'A page of organization lookup results.');
|
|
73
|
+
})(listOrganizations = schema.listOrganizations || (schema.listOrganizations = {}));
|
|
74
|
+
/** Schemas for the getOrganization operation. */
|
|
75
|
+
let getOrganization;
|
|
76
|
+
(function (getOrganization) {
|
|
77
|
+
/** Path parameters identifying an organization. */
|
|
78
|
+
getOrganization.Params = z
|
|
79
|
+
.object({
|
|
80
|
+
orgId: z
|
|
81
|
+
.string()
|
|
82
|
+
.check(z.minLength(1), z.describe('Stable organization id.'), z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] })),
|
|
83
|
+
})
|
|
84
|
+
.check(z.describe('Path parameters for one organization.'));
|
|
85
|
+
const BillingSettingsRecord = Schema.describe(z.object({
|
|
86
|
+
currency: z
|
|
87
|
+
.enum(BillingSettings.currencies)
|
|
88
|
+
.check(z.describe('Limit currency.'), z.meta({ examples: ['usd'] })),
|
|
89
|
+
period: z
|
|
90
|
+
.enum(BillingSettings.periods)
|
|
91
|
+
.check(z.describe('Spend-limit period.'), z.meta({ examples: ['month'] })),
|
|
92
|
+
spendLimit: z
|
|
93
|
+
.nullable(z.string())
|
|
94
|
+
.check(z.describe('Configured period spend limit, or null.'), z.meta({ examples: ['250'] })),
|
|
95
|
+
txFeeLimit: z
|
|
96
|
+
.nullable(z.string())
|
|
97
|
+
.check(z.describe('Configured per-transaction fee limit, or null.'), z.meta({ examples: ['0.50'] })),
|
|
98
|
+
updatedAt: timestamp,
|
|
99
|
+
}), 'Stored billing limits for one environment.');
|
|
100
|
+
const BillingSource = Schema.describe(z.object({
|
|
101
|
+
status: z
|
|
102
|
+
.enum(StripeCustomers.statuses)
|
|
103
|
+
.check(z.describe('Billing status derived from Stripe.'), z.meta({ examples: ['active'] })),
|
|
104
|
+
stripeCustomerId: z
|
|
105
|
+
.string()
|
|
106
|
+
.check(z.describe('Backing Stripe customer id.'), z.meta({ examples: ['cus_abc123'] })),
|
|
107
|
+
updatedAt: timestamp,
|
|
108
|
+
}), 'Stored Stripe billing source for one environment.');
|
|
109
|
+
const Billing = Schema.describe(z.object({
|
|
110
|
+
settings: z.nullable(BillingSettingsRecord).check(z.describe('Configured billing limits, or null when absent.'), z.meta({
|
|
111
|
+
examples: [
|
|
112
|
+
{
|
|
113
|
+
currency: 'usd',
|
|
114
|
+
period: 'month',
|
|
115
|
+
spendLimit: '250',
|
|
116
|
+
txFeeLimit: '0.50',
|
|
117
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
})),
|
|
121
|
+
source: z.nullable(BillingSource).check(z.describe('Connected billing source, or null when absent.'), z.meta({
|
|
122
|
+
examples: [
|
|
123
|
+
{
|
|
124
|
+
status: 'active',
|
|
125
|
+
stripeCustomerId: 'cus_abc123',
|
|
126
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
})),
|
|
130
|
+
}), 'Billing state for one environment.');
|
|
131
|
+
/** An organization member with resolved identity. */
|
|
132
|
+
getOrganization.Member = Schema.describe(z.object({
|
|
133
|
+
address: z
|
|
134
|
+
.nullable(z.string())
|
|
135
|
+
.check(z.describe('Member wallet address, or null.'), z.meta({ examples: [`0x${'ab'.repeat(20)}`] })),
|
|
136
|
+
createdAt: timestamp,
|
|
137
|
+
email: z
|
|
138
|
+
.nullable(z.string())
|
|
139
|
+
.check(z.describe('Verified member email, or null.'), z.meta({ examples: ['owner@acme.example'] })),
|
|
140
|
+
role: z
|
|
141
|
+
.enum(Memberships.roles)
|
|
142
|
+
.check(z.describe('Member role.'), z.meta({ examples: ['owner'] })),
|
|
143
|
+
updatedAt: timestamp,
|
|
144
|
+
userId: z
|
|
145
|
+
.string()
|
|
146
|
+
.check(z.describe('Member user id.'), z.meta({ examples: ['usr_1a2b3c4d5e6f7g8h9j0k1m2n'] })),
|
|
147
|
+
}), 'An organization member and their resolved identity.');
|
|
148
|
+
/** A project owned by an organization. */
|
|
149
|
+
getOrganization.Project = Schema.describe(z.object({
|
|
150
|
+
createdAt: timestamp,
|
|
151
|
+
id: z
|
|
152
|
+
.string()
|
|
153
|
+
.check(z.describe('Stable project id.'), z.meta({ examples: ['prj_1a2b3c4d5e6f7g8h9j0k1m2n'] })),
|
|
154
|
+
name: z
|
|
155
|
+
.string()
|
|
156
|
+
.check(z.describe('Human-readable project name.'), z.meta({ examples: ['Checkout'] })),
|
|
157
|
+
updatedAt: timestamp,
|
|
158
|
+
}), 'A project owned by the organization.');
|
|
159
|
+
/** Detailed organization lookup response. */
|
|
160
|
+
getOrganization.Response = Schema.describe(z.extend(listOrganizations.OrganizationSummary, {
|
|
161
|
+
billing: z.object({ production: Billing, sandbox: Billing }).check(z.describe('Billing state split by environment.'), z.meta({
|
|
162
|
+
examples: [
|
|
163
|
+
{
|
|
164
|
+
production: {
|
|
165
|
+
settings: null,
|
|
166
|
+
source: {
|
|
167
|
+
status: 'active',
|
|
168
|
+
stripeCustomerId: 'cus_abc123',
|
|
169
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
sandbox: { settings: null, source: null },
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
})),
|
|
176
|
+
}), 'Detailed organization information for administrators.');
|
|
177
|
+
})(getOrganization = schema.getOrganization || (schema.getOrganization = {}));
|
|
178
|
+
/** Schemas for the listOrganizationMembers operation. */
|
|
179
|
+
let listOrganizationMembers;
|
|
180
|
+
(function (listOrganizationMembers) {
|
|
181
|
+
/** Query parameters for paginating organization members. */
|
|
182
|
+
listOrganizationMembers.Query = z
|
|
183
|
+
.strictObject({ cursor: Schema.Cursor, limit: Schema.Limit })
|
|
184
|
+
.check(z.describe('Query parameters for listing organization members.'));
|
|
185
|
+
/** Cursor-paginated organization members. */
|
|
186
|
+
listOrganizationMembers.Response = Schema.describe(z.object({
|
|
187
|
+
data: z
|
|
188
|
+
.array(getOrganization.Member)
|
|
189
|
+
.check(z.describe('Organization members, oldest first.')),
|
|
190
|
+
nextCursor: Schema.NextCursor,
|
|
191
|
+
}), 'A page of organization members.');
|
|
192
|
+
})(listOrganizationMembers = schema.listOrganizationMembers || (schema.listOrganizationMembers = {}));
|
|
193
|
+
/** Schemas for the listOrganizationProjects operation. */
|
|
194
|
+
let listOrganizationProjects;
|
|
195
|
+
(function (listOrganizationProjects) {
|
|
196
|
+
/** Query parameters for paginating organization projects. */
|
|
197
|
+
listOrganizationProjects.Query = z
|
|
198
|
+
.strictObject({ cursor: Schema.Cursor, limit: Schema.Limit })
|
|
199
|
+
.check(z.describe('Query parameters for listing organization projects.'));
|
|
200
|
+
/** Cursor-paginated organization projects. */
|
|
201
|
+
listOrganizationProjects.Response = Schema.describe(z.object({
|
|
202
|
+
data: z
|
|
203
|
+
.array(getOrganization.Project)
|
|
204
|
+
.check(z.describe('Organization projects, newest first.')),
|
|
205
|
+
nextCursor: Schema.NextCursor,
|
|
206
|
+
}), 'A page of organization projects.');
|
|
207
|
+
})(listOrganizationProjects = schema.listOrganizationProjects || (schema.listOrganizationProjects = {}));
|
|
208
|
+
/** Schemas for the listOrganizationApiKeys operation. */
|
|
209
|
+
let listOrganizationApiKeys;
|
|
210
|
+
(function (listOrganizationApiKeys) {
|
|
211
|
+
/** Active organization API keys. */
|
|
212
|
+
listOrganizationApiKeys.Response = Schema.describe(z.object({
|
|
213
|
+
data: z.array(ApiKeys.schema.Record),
|
|
214
|
+
}), 'Active API keys owned by an organization.');
|
|
215
|
+
})(listOrganizationApiKeys = schema.listOrganizationApiKeys || (schema.listOrganizationApiKeys = {}));
|
|
216
|
+
/** Schemas for the getOrganizationUsage operation. */
|
|
217
|
+
let getOrganizationUsage;
|
|
218
|
+
(function (getOrganizationUsage) {
|
|
219
|
+
/** Recent-usage window. */
|
|
220
|
+
getOrganizationUsage.Query = z
|
|
221
|
+
.object({
|
|
222
|
+
period: z
|
|
223
|
+
._default(z.enum(['24h', '7d', '30d']), '7d')
|
|
224
|
+
.check(z.describe('Recent usage window.'), z.meta({ examples: ['7d'] })),
|
|
225
|
+
})
|
|
226
|
+
.check(z.describe('Query parameters for organization usage.'));
|
|
227
|
+
const Breakdown = z.object({
|
|
228
|
+
errors: z
|
|
229
|
+
.number()
|
|
230
|
+
.check(z.describe('Requests returning an error.'), z.meta({ examples: [4] })),
|
|
231
|
+
requests: z.number().check(z.describe('Total requests.'), z.meta({ examples: [120] })),
|
|
232
|
+
});
|
|
233
|
+
/** Recent API usage and error breakdowns. */
|
|
234
|
+
getOrganizationUsage.Response = Schema.describe(z.object({
|
|
235
|
+
byError: z.array(z.object({
|
|
236
|
+
code: z
|
|
237
|
+
.string()
|
|
238
|
+
.check(z.describe('Stable API error code.'), z.meta({ examples: ['rate_limited'] })),
|
|
239
|
+
requests: z
|
|
240
|
+
.number()
|
|
241
|
+
.check(z.describe('Requests returning this error.'), z.meta({ examples: [4] })),
|
|
242
|
+
})),
|
|
243
|
+
byRoute: z.array(z.extend(Breakdown, {
|
|
244
|
+
averageDurationMs: z
|
|
245
|
+
.number()
|
|
246
|
+
.check(z.describe('Average request duration in milliseconds.'), z.meta({ examples: [18.4] })),
|
|
247
|
+
route: z
|
|
248
|
+
.string()
|
|
249
|
+
.check(z.describe('Matched API route.'), z.meta({ examples: ['/v1/transactions'] })),
|
|
250
|
+
})),
|
|
251
|
+
byStatus: z.array(z.object({
|
|
252
|
+
requests: z
|
|
253
|
+
.number()
|
|
254
|
+
.check(z.describe('Requests returning this status.'), z.meta({ examples: [4] })),
|
|
255
|
+
status: z
|
|
256
|
+
.number()
|
|
257
|
+
.check(z.int(), z.describe('HTTP response status.'), z.meta({ examples: [429] })),
|
|
258
|
+
})),
|
|
259
|
+
from: timestamp,
|
|
260
|
+
period: z
|
|
261
|
+
.enum(['24h', '7d', '30d'])
|
|
262
|
+
.check(z.describe('Usage window.'), z.meta({ examples: ['7d'] })),
|
|
263
|
+
to: timestamp,
|
|
264
|
+
totals: z.extend(Breakdown, {
|
|
265
|
+
averageDurationMs: z
|
|
266
|
+
.number()
|
|
267
|
+
.check(z.describe('Average request duration in milliseconds.'), z.meta({ examples: [18.4] })),
|
|
268
|
+
}),
|
|
269
|
+
}), 'Recent API usage for an organization.');
|
|
270
|
+
})(getOrganizationUsage = schema.getOrganizationUsage || (schema.getOrganizationUsage = {}));
|
|
271
|
+
/** Schemas for the getOrganizationSponsorship operation. */
|
|
272
|
+
let getOrganizationSponsorship;
|
|
273
|
+
(function (getOrganizationSponsorship) {
|
|
274
|
+
const Environment = z.object({
|
|
275
|
+
committedSpend: z
|
|
276
|
+
.string()
|
|
277
|
+
.check(z.describe('Committed spend in decimal currency units.'), z.meta({ examples: ['1.20'] })),
|
|
278
|
+
currency: z
|
|
279
|
+
.enum(BillingSettings.currencies)
|
|
280
|
+
.check(z.describe('Spend currency.'), z.meta({ examples: ['usd'] })),
|
|
281
|
+
from: timestamp,
|
|
282
|
+
period: z
|
|
283
|
+
.enum(BillingSettings.periods)
|
|
284
|
+
.check(z.describe('Spend-limit period.'), z.meta({ examples: ['month'] })),
|
|
285
|
+
});
|
|
286
|
+
/** Current-period sponsorship spend by key environment. */
|
|
287
|
+
getOrganizationSponsorship.Response = Schema.describe(z.object({
|
|
288
|
+
production: Environment,
|
|
289
|
+
sandbox: Environment,
|
|
290
|
+
to: timestamp,
|
|
291
|
+
}), 'Current-period sponsorship spend for an organization.');
|
|
292
|
+
})(getOrganizationSponsorship = schema.getOrganizationSponsorship || (schema.getOrganizationSponsorship = {}));
|
|
293
|
+
/** Schemas for the getOrganizationWebhooks operation. */
|
|
294
|
+
let getOrganizationWebhooks;
|
|
295
|
+
(function (getOrganizationWebhooks) {
|
|
296
|
+
const Failure = z.object({
|
|
297
|
+
attempt: z
|
|
298
|
+
.number()
|
|
299
|
+
.check(z.int(), z.describe('Delivery attempt number.'), z.meta({ examples: [3] })),
|
|
300
|
+
createdAt: timestamp,
|
|
301
|
+
error: z
|
|
302
|
+
.nullable(z.string())
|
|
303
|
+
.check(z.describe('Failure detail, or null.'), z.meta({ examples: ['Connection timed out'] })),
|
|
304
|
+
id: z.string().check(z.describe('Delivery id.'), z.meta({ examples: ['whd_123'] })),
|
|
305
|
+
responseStatus: z
|
|
306
|
+
.nullable(z.number())
|
|
307
|
+
.check(z.describe('HTTP response status, or null.'), z.meta({ examples: [500] })),
|
|
308
|
+
subscriptionId: z
|
|
309
|
+
.string()
|
|
310
|
+
.check(z.describe('Owning subscription id.'), z.meta({ examples: ['wh_123'] })),
|
|
311
|
+
});
|
|
312
|
+
const Subscription = z.object({
|
|
313
|
+
chainId: z
|
|
314
|
+
.number()
|
|
315
|
+
.check(z.int(), z.describe('Subscribed chain id.'), z.meta({ examples: [42431] })),
|
|
316
|
+
createdAt: timestamp,
|
|
317
|
+
destination: z
|
|
318
|
+
.string()
|
|
319
|
+
.check(z.describe('Redacted delivery destination.'), z.meta({ examples: ['https://hooks.example.com/…'] })),
|
|
320
|
+
eventType: z
|
|
321
|
+
.string()
|
|
322
|
+
.check(z.describe('Subscribed event type.'), z.meta({ examples: ['transfer'] })),
|
|
323
|
+
failureCount: z
|
|
324
|
+
.number()
|
|
325
|
+
.check(z.int(), z.nonnegative(), z.describe('Consecutive delivery failures.'), z.meta({ examples: [2] })),
|
|
326
|
+
id: z.string().check(z.describe('Subscription id.'), z.meta({ examples: ['wh_123'] })),
|
|
327
|
+
lastDeliveryAt: z.nullable(timestamp).check(z.describe('Last successful delivery, or null.')),
|
|
328
|
+
status: z
|
|
329
|
+
.enum(['active', 'disabled', 'paused'])
|
|
330
|
+
.check(z.describe('Subscription status.'), z.meta({ examples: ['active'] })),
|
|
331
|
+
});
|
|
332
|
+
/** Webhook subscriptions and recent failures. */
|
|
333
|
+
getOrganizationWebhooks.Response = Schema.describe(z.object({
|
|
334
|
+
failureCount: z
|
|
335
|
+
.number()
|
|
336
|
+
.check(z.int(), z.nonnegative(), z.describe('Failed deliveries in the response window.'), z.meta({ examples: [2] })),
|
|
337
|
+
failures: z.array(Failure),
|
|
338
|
+
failuresTruncated: z
|
|
339
|
+
.boolean()
|
|
340
|
+
.check(z.describe('Whether additional failures are omitted.'), z.meta({ examples: [false] })),
|
|
341
|
+
from: timestamp,
|
|
342
|
+
subscriptions: z.array(Subscription),
|
|
343
|
+
to: timestamp,
|
|
344
|
+
}), 'Webhook health for an organization.');
|
|
345
|
+
})(getOrganizationWebhooks = schema.getOrganizationWebhooks || (schema.getOrganizationWebhooks = {}));
|
|
346
|
+
})(schema || (schema = {}));
|
|
347
|
+
/** Read-only organization lookup routes for administrators. */
|
|
348
|
+
export function organizations() {
|
|
349
|
+
return new Hono()
|
|
350
|
+
.get('/', OpenApi.validate('query', schema.listOrganizations.Query, {
|
|
351
|
+
code: 'query_invalid',
|
|
352
|
+
message: 'Invalid query parameters',
|
|
353
|
+
}), OpenApi.describeRoute({
|
|
354
|
+
operationId: 'listAdminOrganizations',
|
|
355
|
+
responses: OpenApi.responses({
|
|
356
|
+
success: {
|
|
357
|
+
description: 'Organizations matching the lookup query.',
|
|
358
|
+
schema: schema.listOrganizations.Response,
|
|
359
|
+
},
|
|
360
|
+
}),
|
|
361
|
+
summary: 'List organizations',
|
|
362
|
+
tags: ['Organizations'],
|
|
363
|
+
}), async (c) => {
|
|
364
|
+
const { cursor, limit, query } = c.req.valid('query');
|
|
365
|
+
const decoded = cursor ? Cursor.decode(cursor, ['timestamp', 'id']) : undefined;
|
|
366
|
+
const db = Db.get(c.get('db'));
|
|
367
|
+
try {
|
|
368
|
+
const records = await Organizations.search(db, {
|
|
369
|
+
...(decoded
|
|
370
|
+
? { cursor: { createdAt: String(decoded[0]), id: String(decoded[1]) } }
|
|
371
|
+
: {}),
|
|
372
|
+
limit,
|
|
373
|
+
...(query ? { query } : {}),
|
|
374
|
+
});
|
|
375
|
+
const page = Cursor.paginate({
|
|
376
|
+
key: (record) => [record.createdAt, record.id],
|
|
377
|
+
limit,
|
|
378
|
+
rows: records,
|
|
379
|
+
});
|
|
380
|
+
return c.json(Response.validated(schema.listOrganizations.Response, {
|
|
381
|
+
data: page.rows,
|
|
382
|
+
nextCursor: page.nextCursor,
|
|
383
|
+
}), 200);
|
|
384
|
+
}
|
|
385
|
+
catch (cause) {
|
|
386
|
+
return Response.upstream(c, cause);
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
.get('/:orgId', OpenApi.validate('param', schema.getOrganization.Params, {
|
|
390
|
+
code: 'param_invalid',
|
|
391
|
+
message: 'Invalid path parameters',
|
|
392
|
+
}), OpenApi.describeRoute({
|
|
393
|
+
operationId: 'getAdminOrganization',
|
|
394
|
+
responses: OpenApi.responses({
|
|
395
|
+
errors: { 404: 'Organization not found.' },
|
|
396
|
+
success: {
|
|
397
|
+
description: 'Detailed organization information.',
|
|
398
|
+
schema: schema.getOrganization.Response,
|
|
399
|
+
},
|
|
400
|
+
}),
|
|
401
|
+
summary: 'Get organization',
|
|
402
|
+
tags: ['Organizations'],
|
|
403
|
+
}), async (c) => {
|
|
404
|
+
const { orgId } = c.req.valid('param');
|
|
405
|
+
const db = Db.get(c.get('db'));
|
|
406
|
+
try {
|
|
407
|
+
const organization = await Organizations.getSummary(db, orgId);
|
|
408
|
+
if (!organization)
|
|
409
|
+
return organizationNotFound(c);
|
|
410
|
+
const [productionSettings, productionSource, sandboxSettings, sandboxSource] = await Promise.all([
|
|
411
|
+
BillingSettings.get(db, orgId, 'production'),
|
|
412
|
+
StripeCustomers.get(db, orgId, 'production'),
|
|
413
|
+
BillingSettings.get(db, orgId, 'sandbox'),
|
|
414
|
+
StripeCustomers.get(db, orgId, 'sandbox'),
|
|
415
|
+
]);
|
|
416
|
+
return c.json(Response.validated(schema.getOrganization.Response, {
|
|
417
|
+
...organization,
|
|
418
|
+
billing: {
|
|
419
|
+
production: serializeBilling(productionSettings, productionSource),
|
|
420
|
+
sandbox: serializeBilling(sandboxSettings, sandboxSource),
|
|
421
|
+
},
|
|
422
|
+
}), 200);
|
|
423
|
+
}
|
|
424
|
+
catch (cause) {
|
|
425
|
+
return Response.upstream(c, cause);
|
|
426
|
+
}
|
|
427
|
+
})
|
|
428
|
+
.get('/:orgId/members', OpenApi.validate('param', schema.getOrganization.Params, {
|
|
429
|
+
code: 'param_invalid',
|
|
430
|
+
message: 'Invalid path parameters',
|
|
431
|
+
}), OpenApi.validate('query', schema.listOrganizationMembers.Query, {
|
|
432
|
+
code: 'query_invalid',
|
|
433
|
+
message: 'Invalid query parameters',
|
|
434
|
+
}), OpenApi.describeRoute({
|
|
435
|
+
operationId: 'listAdminOrganizationMembers',
|
|
436
|
+
responses: OpenApi.responses({
|
|
437
|
+
errors: { 404: 'Organization not found.' },
|
|
438
|
+
success: {
|
|
439
|
+
description: 'Organization members.',
|
|
440
|
+
schema: schema.listOrganizationMembers.Response,
|
|
441
|
+
},
|
|
442
|
+
}),
|
|
443
|
+
summary: 'List organization members',
|
|
444
|
+
tags: ['Organizations'],
|
|
445
|
+
}), async (c) => {
|
|
446
|
+
const { orgId } = c.req.valid('param');
|
|
447
|
+
const { cursor, limit } = c.req.valid('query');
|
|
448
|
+
const decoded = cursor ? Cursor.decode(cursor, ['timestamp', 'id']) : undefined;
|
|
449
|
+
const db = Db.get(c.get('db'));
|
|
450
|
+
try {
|
|
451
|
+
if (!(await Organizations.get(db, orgId)))
|
|
452
|
+
return organizationNotFound(c);
|
|
453
|
+
const records = await Memberships.listByOrgDetailedPage(db, orgId, {
|
|
454
|
+
...(decoded
|
|
455
|
+
? { cursor: { createdAt: String(decoded[0]), userId: String(decoded[1]) } }
|
|
456
|
+
: {}),
|
|
457
|
+
limit,
|
|
458
|
+
});
|
|
459
|
+
const page = Cursor.paginate({
|
|
460
|
+
key: (record) => [record.createdAt, record.userId],
|
|
461
|
+
limit,
|
|
462
|
+
rows: records,
|
|
463
|
+
});
|
|
464
|
+
return c.json(Response.validated(schema.listOrganizationMembers.Response, {
|
|
465
|
+
data: page.rows.map(({ orgId: _orgId, ...member }) => member),
|
|
466
|
+
nextCursor: page.nextCursor,
|
|
467
|
+
}), 200);
|
|
468
|
+
}
|
|
469
|
+
catch (cause) {
|
|
470
|
+
return Response.upstream(c, cause);
|
|
471
|
+
}
|
|
472
|
+
})
|
|
473
|
+
.get('/:orgId/projects', OpenApi.validate('param', schema.getOrganization.Params, {
|
|
474
|
+
code: 'param_invalid',
|
|
475
|
+
message: 'Invalid path parameters',
|
|
476
|
+
}), OpenApi.validate('query', schema.listOrganizationProjects.Query, {
|
|
477
|
+
code: 'query_invalid',
|
|
478
|
+
message: 'Invalid query parameters',
|
|
479
|
+
}), OpenApi.describeRoute({
|
|
480
|
+
operationId: 'listAdminOrganizationProjects',
|
|
481
|
+
responses: OpenApi.responses({
|
|
482
|
+
errors: { 404: 'Organization not found.' },
|
|
483
|
+
success: {
|
|
484
|
+
description: 'Organization projects.',
|
|
485
|
+
schema: schema.listOrganizationProjects.Response,
|
|
486
|
+
},
|
|
487
|
+
}),
|
|
488
|
+
summary: 'List organization projects',
|
|
489
|
+
tags: ['Organizations'],
|
|
490
|
+
}), async (c) => {
|
|
491
|
+
const { orgId } = c.req.valid('param');
|
|
492
|
+
const { cursor, limit } = c.req.valid('query');
|
|
493
|
+
const decoded = cursor ? Cursor.decode(cursor, ['timestamp', 'id']) : undefined;
|
|
494
|
+
const db = Db.get(c.get('db'));
|
|
495
|
+
try {
|
|
496
|
+
if (!(await Organizations.get(db, orgId)))
|
|
497
|
+
return organizationNotFound(c);
|
|
498
|
+
const records = await Projects.listByOrgPage(db, orgId, {
|
|
499
|
+
...(decoded
|
|
500
|
+
? { cursor: { createdAt: String(decoded[0]), id: String(decoded[1]) } }
|
|
501
|
+
: {}),
|
|
502
|
+
limit,
|
|
503
|
+
});
|
|
504
|
+
const page = Cursor.paginate({
|
|
505
|
+
key: (record) => [record.createdAt, record.id],
|
|
506
|
+
limit,
|
|
507
|
+
rows: records,
|
|
508
|
+
});
|
|
509
|
+
return c.json(Response.validated(schema.listOrganizationProjects.Response, {
|
|
510
|
+
data: page.rows.map(({ orgId: _orgId, ...project }) => project),
|
|
511
|
+
nextCursor: page.nextCursor,
|
|
512
|
+
}), 200);
|
|
513
|
+
}
|
|
514
|
+
catch (cause) {
|
|
515
|
+
return Response.upstream(c, cause);
|
|
516
|
+
}
|
|
517
|
+
})
|
|
518
|
+
.get('/:orgId/api-keys', OpenApi.validate('param', schema.getOrganization.Params, {
|
|
519
|
+
code: 'param_invalid',
|
|
520
|
+
message: 'Invalid path parameters',
|
|
521
|
+
}), OpenApi.describeRoute({
|
|
522
|
+
operationId: 'listAdminOrganizationApiKeys',
|
|
523
|
+
responses: OpenApi.responses({
|
|
524
|
+
errors: { 404: 'Organization not found.' },
|
|
525
|
+
success: {
|
|
526
|
+
description: 'Organization API keys.',
|
|
527
|
+
schema: schema.listOrganizationApiKeys.Response,
|
|
528
|
+
},
|
|
529
|
+
}),
|
|
530
|
+
summary: 'List organization keys',
|
|
531
|
+
tags: ['Organizations'],
|
|
532
|
+
}), async (c) => {
|
|
533
|
+
const { orgId } = c.req.valid('param');
|
|
534
|
+
try {
|
|
535
|
+
if (!(await Organizations.get(Db.get(c.get('db')), orgId)))
|
|
536
|
+
return organizationNotFound(c);
|
|
537
|
+
const records = await ApiKeys.listByOrg(c.get('kv').store, orgId);
|
|
538
|
+
return c.json(Response.validated(schema.listOrganizationApiKeys.Response, {
|
|
539
|
+
data: records,
|
|
540
|
+
}), 200);
|
|
541
|
+
}
|
|
542
|
+
catch (cause) {
|
|
543
|
+
return Response.upstream(c, cause);
|
|
544
|
+
}
|
|
545
|
+
})
|
|
546
|
+
.get('/:orgId/usage', OpenApi.validate('param', schema.getOrganization.Params, {
|
|
547
|
+
code: 'param_invalid',
|
|
548
|
+
message: 'Invalid path parameters',
|
|
549
|
+
}), OpenApi.validate('query', schema.getOrganizationUsage.Query, {
|
|
550
|
+
code: 'query_invalid',
|
|
551
|
+
message: 'Invalid query parameters',
|
|
552
|
+
}), OpenApi.describeRoute({
|
|
553
|
+
operationId: 'getAdminOrganizationUsage',
|
|
554
|
+
responses: OpenApi.responses({
|
|
555
|
+
errors: { 404: 'Organization not found.' },
|
|
556
|
+
success: {
|
|
557
|
+
description: 'Recent organization API usage.',
|
|
558
|
+
schema: schema.getOrganizationUsage.Response,
|
|
559
|
+
},
|
|
560
|
+
}),
|
|
561
|
+
summary: 'Get organization usage',
|
|
562
|
+
tags: ['Organizations'],
|
|
563
|
+
}), async (c) => {
|
|
564
|
+
const { orgId } = c.req.valid('param');
|
|
565
|
+
const { period } = c.req.valid('query');
|
|
566
|
+
try {
|
|
567
|
+
if (!(await Organizations.get(Db.get(c.get('db')), orgId)))
|
|
568
|
+
return organizationNotFound(c);
|
|
569
|
+
const to = new Date().toISOString();
|
|
570
|
+
const from = new Date(Date.now() - usagePeriods[period]).toISOString();
|
|
571
|
+
const options = {
|
|
572
|
+
attributions: [{}],
|
|
573
|
+
from,
|
|
574
|
+
interval: period === '24h' ? 'hour' : 'day',
|
|
575
|
+
orgId,
|
|
576
|
+
to,
|
|
577
|
+
};
|
|
578
|
+
const [usage, byError] = await Promise.all([
|
|
579
|
+
Analytics.readProjectUsage(c.get('analytics'), options),
|
|
580
|
+
Analytics.readErrorBreakdown(c.get('analytics'), options),
|
|
581
|
+
]);
|
|
582
|
+
return c.json(Response.validated(schema.getOrganizationUsage.Response, {
|
|
583
|
+
byError,
|
|
584
|
+
byRoute: usage.byRoute,
|
|
585
|
+
byStatus: usage.byStatus,
|
|
586
|
+
from,
|
|
587
|
+
period,
|
|
588
|
+
to,
|
|
589
|
+
totals: usage.totals,
|
|
590
|
+
}), 200);
|
|
591
|
+
}
|
|
592
|
+
catch (cause) {
|
|
593
|
+
return Response.upstream(c, cause);
|
|
594
|
+
}
|
|
595
|
+
})
|
|
596
|
+
.get('/:orgId/sponsorship', OpenApi.validate('param', schema.getOrganization.Params, {
|
|
597
|
+
code: 'param_invalid',
|
|
598
|
+
message: 'Invalid path parameters',
|
|
599
|
+
}), OpenApi.describeRoute({
|
|
600
|
+
operationId: 'getAdminOrganizationSponsorship',
|
|
601
|
+
responses: OpenApi.responses({
|
|
602
|
+
errors: { 404: 'Organization not found.' },
|
|
603
|
+
success: {
|
|
604
|
+
description: 'Recent organization sponsorship activity.',
|
|
605
|
+
schema: schema.getOrganizationSponsorship.Response,
|
|
606
|
+
},
|
|
607
|
+
}),
|
|
608
|
+
summary: 'Get sponsorship activity',
|
|
609
|
+
tags: ['Organizations'],
|
|
610
|
+
}), async (c) => {
|
|
611
|
+
const { orgId } = c.req.valid('param');
|
|
612
|
+
const db = Db.get(c.get('db'));
|
|
613
|
+
try {
|
|
614
|
+
if (!(await Organizations.get(db, orgId)))
|
|
615
|
+
return organizationNotFound(c);
|
|
616
|
+
const now = new Date();
|
|
617
|
+
const to = now.toISOString();
|
|
618
|
+
const [production, sandbox] = await Promise.all(['production', 'sandbox'].map(async (environment) => {
|
|
619
|
+
const settings = await BillingSettings.get(db, orgId, environment);
|
|
620
|
+
const currency = settings?.currency ?? 'usd';
|
|
621
|
+
const period = settings?.period ?? 'month';
|
|
622
|
+
const from = core_Billing.periodStart(period, now);
|
|
623
|
+
const committedSpend = await SponsoredTransactions.spend(db, {
|
|
624
|
+
chainIds: [
|
|
625
|
+
environment === 'production' ? Viem.chainId.mainnet : Viem.chainId.testnet,
|
|
626
|
+
],
|
|
627
|
+
environment,
|
|
628
|
+
orgId,
|
|
629
|
+
since: from,
|
|
630
|
+
});
|
|
631
|
+
return {
|
|
632
|
+
committedSpend: core_Billing.fromBaseUnits(committedSpend),
|
|
633
|
+
currency,
|
|
634
|
+
from,
|
|
635
|
+
period,
|
|
636
|
+
};
|
|
637
|
+
}));
|
|
638
|
+
return c.json(Response.validated(schema.getOrganizationSponsorship.Response, {
|
|
639
|
+
production,
|
|
640
|
+
sandbox,
|
|
641
|
+
to,
|
|
642
|
+
}), 200);
|
|
643
|
+
}
|
|
644
|
+
catch (cause) {
|
|
645
|
+
return Response.upstream(c, cause);
|
|
646
|
+
}
|
|
647
|
+
})
|
|
648
|
+
.get('/:orgId/webhooks', OpenApi.validate('param', schema.getOrganization.Params, {
|
|
649
|
+
code: 'param_invalid',
|
|
650
|
+
message: 'Invalid path parameters',
|
|
651
|
+
}), OpenApi.describeRoute({
|
|
652
|
+
operationId: 'getAdminOrganizationWebhooks',
|
|
653
|
+
responses: OpenApi.responses({
|
|
654
|
+
errors: { 404: 'Organization not found.' },
|
|
655
|
+
success: {
|
|
656
|
+
description: 'Organization webhook health.',
|
|
657
|
+
schema: schema.getOrganizationWebhooks.Response,
|
|
658
|
+
},
|
|
659
|
+
}),
|
|
660
|
+
summary: 'Get webhook health',
|
|
661
|
+
tags: ['Organizations'],
|
|
662
|
+
}), async (c) => {
|
|
663
|
+
const { orgId } = c.req.valid('param');
|
|
664
|
+
const db = Db.get(c.get('db'));
|
|
665
|
+
try {
|
|
666
|
+
if (!(await Organizations.get(db, orgId)))
|
|
667
|
+
return organizationNotFound(c);
|
|
668
|
+
const to = new Date().toISOString();
|
|
669
|
+
const from = new Date(Date.now() - usagePeriods['7d']).toISOString();
|
|
670
|
+
const [subscriptions, failures, failureCount] = await Promise.all([
|
|
671
|
+
WebhookSubscriptions.list(db, { orgId, type: 'api_key' }, { limit: 25, now: to }),
|
|
672
|
+
WebhookDeliveries.listFailuresByOrg(db, orgId, { from, limit: 25, now: to }),
|
|
673
|
+
WebhookDeliveries.countFailuresByOrg(db, orgId, { from, now: to }),
|
|
674
|
+
]);
|
|
675
|
+
return c.json(Response.validated(schema.getOrganizationWebhooks.Response, {
|
|
676
|
+
failureCount,
|
|
677
|
+
failures,
|
|
678
|
+
failuresTruncated: failureCount > failures.length,
|
|
679
|
+
from,
|
|
680
|
+
subscriptions: subscriptions.map((subscription) => ({
|
|
681
|
+
chainId: subscription.chainId,
|
|
682
|
+
createdAt: subscription.createdAt,
|
|
683
|
+
destination: redactDestination(subscription.destination.url),
|
|
684
|
+
eventType: subscription.eventType,
|
|
685
|
+
failureCount: subscription.failureCount,
|
|
686
|
+
id: subscription.id,
|
|
687
|
+
lastDeliveryAt: subscription.lastDeliveryAt ?? null,
|
|
688
|
+
status: subscription.status,
|
|
689
|
+
})),
|
|
690
|
+
to,
|
|
691
|
+
}), 200);
|
|
692
|
+
}
|
|
693
|
+
catch (cause) {
|
|
694
|
+
return Response.upstream(c, cause);
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
const usagePeriods = {
|
|
699
|
+
'24h': 24 * 60 * 60 * 1_000,
|
|
700
|
+
'30d': 30 * 24 * 60 * 60 * 1_000,
|
|
701
|
+
'7d': 7 * 24 * 60 * 60 * 1_000,
|
|
702
|
+
};
|
|
703
|
+
function redactDestination(value) {
|
|
704
|
+
return `${new URL(value).origin}/…`;
|
|
705
|
+
}
|
|
706
|
+
function organizationNotFound(c) {
|
|
707
|
+
return Response.error(c, {
|
|
708
|
+
code: 'not_found',
|
|
709
|
+
message: 'Organization not found.',
|
|
710
|
+
status: 404,
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
function serializeBilling(settings, source) {
|
|
714
|
+
return {
|
|
715
|
+
settings: settings
|
|
716
|
+
? {
|
|
717
|
+
currency: settings.currency,
|
|
718
|
+
period: settings.period,
|
|
719
|
+
spendLimit: settings.spendLimit,
|
|
720
|
+
txFeeLimit: settings.txFeeLimit,
|
|
721
|
+
updatedAt: settings.updatedAt,
|
|
722
|
+
}
|
|
723
|
+
: null,
|
|
724
|
+
source: source
|
|
725
|
+
? {
|
|
726
|
+
status: source.status,
|
|
727
|
+
stripeCustomerId: source.stripeCustomerId,
|
|
728
|
+
updatedAt: source.updatedAt,
|
|
729
|
+
}
|
|
730
|
+
: null,
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
//# sourceMappingURL=organizations.js.map
|