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
|
@@ -10,14 +10,21 @@
|
|
|
10
10
|
|
|
11
11
|
import { Route as rootRouteImport } from './routes/__root'
|
|
12
12
|
import { Route as VerifiedTokensRouteImport } from './routes/verified-tokens'
|
|
13
|
+
import { Route as OrganizationsRouteImport } from './routes/organizations'
|
|
13
14
|
import { Route as ApiKeysRouteImport } from './routes/api-keys'
|
|
14
15
|
import { Route as IndexRouteImport } from './routes/index'
|
|
16
|
+
import { Route as OrganizationsOrgIdRouteImport } from './routes/organizations_.$orgId'
|
|
15
17
|
|
|
16
18
|
const VerifiedTokensRoute = VerifiedTokensRouteImport.update({
|
|
17
19
|
id: '/verified-tokens',
|
|
18
20
|
path: '/verified-tokens',
|
|
19
21
|
getParentRoute: () => rootRouteImport,
|
|
20
22
|
} as any)
|
|
23
|
+
const OrganizationsRoute = OrganizationsRouteImport.update({
|
|
24
|
+
id: '/organizations',
|
|
25
|
+
path: '/organizations',
|
|
26
|
+
getParentRoute: () => rootRouteImport,
|
|
27
|
+
} as any)
|
|
21
28
|
const ApiKeysRoute = ApiKeysRouteImport.update({
|
|
22
29
|
id: '/api-keys',
|
|
23
30
|
path: '/api-keys',
|
|
@@ -28,35 +35,54 @@ const IndexRoute = IndexRouteImport.update({
|
|
|
28
35
|
path: '/',
|
|
29
36
|
getParentRoute: () => rootRouteImport,
|
|
30
37
|
} as any)
|
|
38
|
+
const OrganizationsOrgIdRoute = OrganizationsOrgIdRouteImport.update({
|
|
39
|
+
id: '/organizations_/$orgId',
|
|
40
|
+
path: '/organizations/$orgId',
|
|
41
|
+
getParentRoute: () => rootRouteImport,
|
|
42
|
+
} as any)
|
|
31
43
|
|
|
32
44
|
export interface FileRoutesByFullPath {
|
|
33
45
|
'/': typeof IndexRoute
|
|
34
46
|
'/api-keys': typeof ApiKeysRoute
|
|
47
|
+
'/organizations': typeof OrganizationsRoute
|
|
35
48
|
'/verified-tokens': typeof VerifiedTokensRoute
|
|
49
|
+
'/organizations/$orgId': typeof OrganizationsOrgIdRoute
|
|
36
50
|
}
|
|
37
51
|
export interface FileRoutesByTo {
|
|
38
52
|
'/': typeof IndexRoute
|
|
39
53
|
'/api-keys': typeof ApiKeysRoute
|
|
54
|
+
'/organizations': typeof OrganizationsRoute
|
|
40
55
|
'/verified-tokens': typeof VerifiedTokensRoute
|
|
56
|
+
'/organizations/$orgId': typeof OrganizationsOrgIdRoute
|
|
41
57
|
}
|
|
42
58
|
export interface FileRoutesById {
|
|
43
59
|
__root__: typeof rootRouteImport
|
|
44
60
|
'/': typeof IndexRoute
|
|
45
61
|
'/api-keys': typeof ApiKeysRoute
|
|
62
|
+
'/organizations': typeof OrganizationsRoute
|
|
46
63
|
'/verified-tokens': typeof VerifiedTokensRoute
|
|
64
|
+
'/organizations_/$orgId': typeof OrganizationsOrgIdRoute
|
|
47
65
|
}
|
|
48
66
|
export interface FileRouteTypes {
|
|
49
67
|
fileRoutesByFullPath: FileRoutesByFullPath
|
|
50
|
-
fullPaths: '/' | '/api-keys' | '/verified-tokens'
|
|
68
|
+
fullPaths: '/' | '/api-keys' | '/organizations' | '/verified-tokens' | '/organizations/$orgId'
|
|
51
69
|
fileRoutesByTo: FileRoutesByTo
|
|
52
|
-
to: '/' | '/api-keys' | '/verified-tokens'
|
|
53
|
-
id:
|
|
70
|
+
to: '/' | '/api-keys' | '/organizations' | '/verified-tokens' | '/organizations/$orgId'
|
|
71
|
+
id:
|
|
72
|
+
| '__root__'
|
|
73
|
+
| '/'
|
|
74
|
+
| '/api-keys'
|
|
75
|
+
| '/organizations'
|
|
76
|
+
| '/verified-tokens'
|
|
77
|
+
| '/organizations_/$orgId'
|
|
54
78
|
fileRoutesById: FileRoutesById
|
|
55
79
|
}
|
|
56
80
|
export interface RootRouteChildren {
|
|
57
81
|
IndexRoute: typeof IndexRoute
|
|
58
82
|
ApiKeysRoute: typeof ApiKeysRoute
|
|
83
|
+
OrganizationsRoute: typeof OrganizationsRoute
|
|
59
84
|
VerifiedTokensRoute: typeof VerifiedTokensRoute
|
|
85
|
+
OrganizationsOrgIdRoute: typeof OrganizationsOrgIdRoute
|
|
60
86
|
}
|
|
61
87
|
|
|
62
88
|
declare module '@tanstack/react-router' {
|
|
@@ -68,6 +94,13 @@ declare module '@tanstack/react-router' {
|
|
|
68
94
|
preLoaderRoute: typeof VerifiedTokensRouteImport
|
|
69
95
|
parentRoute: typeof rootRouteImport
|
|
70
96
|
}
|
|
97
|
+
'/organizations': {
|
|
98
|
+
id: '/organizations'
|
|
99
|
+
path: '/organizations'
|
|
100
|
+
fullPath: '/organizations'
|
|
101
|
+
preLoaderRoute: typeof OrganizationsRouteImport
|
|
102
|
+
parentRoute: typeof rootRouteImport
|
|
103
|
+
}
|
|
71
104
|
'/api-keys': {
|
|
72
105
|
id: '/api-keys'
|
|
73
106
|
path: '/api-keys'
|
|
@@ -82,23 +115,33 @@ declare module '@tanstack/react-router' {
|
|
|
82
115
|
preLoaderRoute: typeof IndexRouteImport
|
|
83
116
|
parentRoute: typeof rootRouteImport
|
|
84
117
|
}
|
|
118
|
+
'/organizations_/$orgId': {
|
|
119
|
+
id: '/organizations_/$orgId'
|
|
120
|
+
path: '/organizations/$orgId'
|
|
121
|
+
fullPath: '/organizations/$orgId'
|
|
122
|
+
preLoaderRoute: typeof OrganizationsOrgIdRouteImport
|
|
123
|
+
parentRoute: typeof rootRouteImport
|
|
124
|
+
}
|
|
85
125
|
}
|
|
86
126
|
}
|
|
87
127
|
|
|
88
128
|
const rootRouteChildren: RootRouteChildren = {
|
|
89
129
|
IndexRoute: IndexRoute,
|
|
90
130
|
ApiKeysRoute: ApiKeysRoute,
|
|
131
|
+
OrganizationsRoute: OrganizationsRoute,
|
|
91
132
|
VerifiedTokensRoute: VerifiedTokensRoute,
|
|
133
|
+
OrganizationsOrgIdRoute: OrganizationsOrgIdRoute,
|
|
92
134
|
}
|
|
93
135
|
export const routeTree = rootRouteImport
|
|
94
136
|
._addFileChildren(rootRouteChildren)
|
|
95
137
|
._addFileTypes<FileRouteTypes>()
|
|
96
138
|
|
|
97
139
|
import type { getRouter } from './router.tsx'
|
|
98
|
-
import type {
|
|
140
|
+
import type { startInstance } from './start.ts'
|
|
99
141
|
declare module '@tanstack/react-start' {
|
|
100
142
|
interface Register {
|
|
101
143
|
ssr: true
|
|
102
144
|
router: Awaited<ReturnType<typeof getRouter>>
|
|
145
|
+
config: Awaited<ReturnType<typeof startInstance.getOptions>>
|
|
103
146
|
}
|
|
104
147
|
}
|
|
@@ -10,14 +10,16 @@ import type { QueryClient } from '@tanstack/react-query'
|
|
|
10
10
|
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
|
|
11
11
|
import { type ComponentType } from 'react'
|
|
12
12
|
import { Button, Identicon } from 'regen-ui'
|
|
13
|
-
import { BadgeCheck, KeyRound, LogOut } from 'lucide-react'
|
|
13
|
+
import { BadgeCheck, Building2, KeyRound, LogOut } from 'lucide-react'
|
|
14
14
|
import { WagmiProvider } from 'wagmi'
|
|
15
15
|
|
|
16
16
|
import appCss from '../styles.css?url'
|
|
17
17
|
import { TempoLogo, TempoMark } from '../components/TempoLogo'
|
|
18
18
|
import { identiconAddress } from '../components/MobileProfile'
|
|
19
|
+
import { ThemeToggle } from '../components/ThemeToggle'
|
|
19
20
|
import * as Config from '../lib/config'
|
|
20
21
|
import { persistOptions, queryClient } from '../lib/query-client'
|
|
22
|
+
import * as Theme from '../lib/theme'
|
|
21
23
|
import { config as wagmiConfig } from '../lib/wagmi'
|
|
22
24
|
|
|
23
25
|
export type RouterContext = { queryClient: QueryClient }
|
|
@@ -37,6 +39,7 @@ export const Route = createRootRouteWithContext<RouterContext>()({
|
|
|
37
39
|
{ content: 'width=device-width, initial-scale=1', name: 'viewport' },
|
|
38
40
|
{ title: 'Tempo API Admin' },
|
|
39
41
|
],
|
|
42
|
+
scripts: [{ children: Theme.bootstrap }],
|
|
40
43
|
}),
|
|
41
44
|
shellComponent: RootDocument,
|
|
42
45
|
component: AdminShell,
|
|
@@ -45,8 +48,14 @@ export const Route = createRootRouteWithContext<RouterContext>()({
|
|
|
45
48
|
|
|
46
49
|
function RootDocument({ children }: { children: React.ReactNode }) {
|
|
47
50
|
return (
|
|
48
|
-
<html lang="en" data-
|
|
51
|
+
<html lang="en" data-regen-radius="none" suppressHydrationWarning>
|
|
49
52
|
<head>
|
|
53
|
+
<base data-tempo-base="true" href="/" suppressHydrationWarning />
|
|
54
|
+
<script
|
|
55
|
+
data-tempo-config="true"
|
|
56
|
+
suppressHydrationWarning
|
|
57
|
+
dangerouslySetInnerHTML={{ __html: 'window.__TEMPO_API_CONFIG__=undefined' }}
|
|
58
|
+
/>
|
|
50
59
|
<HeadContent />
|
|
51
60
|
</head>
|
|
52
61
|
<body>
|
|
@@ -103,6 +112,7 @@ function Admin() {
|
|
|
103
112
|
}
|
|
104
113
|
|
|
105
114
|
const nav = [
|
|
115
|
+
{ exact: false, href: '/organizations', icon: Building2, label: 'Organizations' },
|
|
106
116
|
{ exact: false, href: '/api-keys', icon: KeyRound, label: 'API Keys' },
|
|
107
117
|
{ exact: false, href: '/verified-tokens', icon: BadgeCheck, label: 'Verified Tokens' },
|
|
108
118
|
] as const
|
|
@@ -129,7 +139,12 @@ function Sidebar(props: { email: string; logoutUrl?: string }) {
|
|
|
129
139
|
/>
|
|
130
140
|
))}
|
|
131
141
|
</nav>
|
|
132
|
-
<
|
|
142
|
+
<div className="flex w-full flex-col gap-1">
|
|
143
|
+
<div className="flex justify-start px-2.5 max-lg:justify-center max-lg:px-2">
|
|
144
|
+
<ThemeToggle />
|
|
145
|
+
</div>
|
|
146
|
+
<ProfileCard email={props.email} logoutUrl={props.logoutUrl} />
|
|
147
|
+
</div>
|
|
133
148
|
</aside>
|
|
134
149
|
)
|
|
135
150
|
}
|
|
@@ -10,18 +10,21 @@ import * as ApiKeys from '../lib/api-keys'
|
|
|
10
10
|
import * as Scopes from '../lib/scopes'
|
|
11
11
|
|
|
12
12
|
export const Route = createFileRoute('/api-keys')({
|
|
13
|
-
|
|
13
|
+
validateSearch: ApiKeys.search,
|
|
14
|
+
loaderDeps: ({ search }) => search,
|
|
15
|
+
loader: ({ context, deps }) =>
|
|
14
16
|
Promise.all([
|
|
15
|
-
context.queryClient.prefetchQuery(ApiKeys.get.options()),
|
|
17
|
+
context.queryClient.prefetchQuery(ApiKeys.get.options(deps)),
|
|
16
18
|
context.queryClient.prefetchQuery(Scopes.get.options()),
|
|
17
19
|
]),
|
|
18
20
|
component: RouteComponent,
|
|
19
21
|
})
|
|
20
22
|
|
|
21
23
|
function RouteComponent() {
|
|
24
|
+
const filters = Route.useSearch()
|
|
22
25
|
const [open, setOpen] = useState(false)
|
|
23
26
|
const [environment, setEnvironment] = useState<'production' | 'sandbox'>('production')
|
|
24
|
-
const keys = ApiKeys.get.useQuery()
|
|
27
|
+
const keys = ApiKeys.get.useQuery(filters)
|
|
25
28
|
const provision = ApiKeys.provision.useMutation()
|
|
26
29
|
|
|
27
30
|
function onSubmit(form: FormData) {
|
|
@@ -42,8 +45,10 @@ function RouteComponent() {
|
|
|
42
45
|
{
|
|
43
46
|
environment,
|
|
44
47
|
scopes: scopes as ApiKeys.provision.Input['scopes'],
|
|
48
|
+
...(filters.orgId ? { orgId: filters.orgId } : {}),
|
|
45
49
|
...(name ? { name } : {}),
|
|
46
50
|
...(perMinute === undefined ? {} : { rateLimits: { '*': { perMinute } } }),
|
|
51
|
+
...(filters.projectId ? { projectId: filters.projectId } : {}),
|
|
47
52
|
},
|
|
48
53
|
{ onError: (error) => alert(error.message), onSuccess: () => setOpen(false) },
|
|
49
54
|
)
|
|
@@ -53,7 +58,13 @@ function RouteComponent() {
|
|
|
53
58
|
<Dialog.Root onOpenChange={setOpen} open={open}>
|
|
54
59
|
<Page
|
|
55
60
|
title="API Keys"
|
|
56
|
-
description=
|
|
61
|
+
description={
|
|
62
|
+
filters.projectId
|
|
63
|
+
? `Keys for project ${filters.projectId}`
|
|
64
|
+
: filters.orgId
|
|
65
|
+
? `Keys for organization ${filters.orgId}`
|
|
66
|
+
: 'Manage keys that authenticate requests to the API'
|
|
67
|
+
}
|
|
57
68
|
action={
|
|
58
69
|
<>
|
|
59
70
|
<Select
|
|
@@ -88,7 +99,12 @@ function RouteComponent() {
|
|
|
88
99
|
loading={keys.isPending}
|
|
89
100
|
/>
|
|
90
101
|
<Dialog.Popup>
|
|
91
|
-
<ProvisionForm
|
|
102
|
+
<ProvisionForm
|
|
103
|
+
onSubmit={onSubmit}
|
|
104
|
+
orgId={filters.orgId}
|
|
105
|
+
pending={provision.isPending}
|
|
106
|
+
projectId={filters.projectId}
|
|
107
|
+
/>
|
|
92
108
|
</Dialog.Popup>
|
|
93
109
|
</Page>
|
|
94
110
|
</Dialog.Root>
|
|
@@ -132,12 +148,26 @@ function TokenBanner(props: { onDismiss: () => void; token: string }) {
|
|
|
132
148
|
)
|
|
133
149
|
}
|
|
134
150
|
|
|
135
|
-
function ProvisionForm(props: {
|
|
151
|
+
function ProvisionForm(props: {
|
|
152
|
+
onSubmit: (form: FormData) => void
|
|
153
|
+
orgId?: string | undefined
|
|
154
|
+
pending: boolean
|
|
155
|
+
projectId?: string | undefined
|
|
156
|
+
}) {
|
|
136
157
|
const scopes = Scopes.get.useQuery()
|
|
158
|
+
const destination = props.projectId
|
|
159
|
+
? { label: 'Project', value: props.projectId }
|
|
160
|
+
: props.orgId
|
|
161
|
+
? { label: 'Organization', value: props.orgId }
|
|
162
|
+
: undefined
|
|
137
163
|
return (
|
|
138
164
|
<>
|
|
139
165
|
<Dialog.Title>Provision a Key</Dialog.Title>
|
|
140
|
-
<Dialog.Description>
|
|
166
|
+
<Dialog.Description>
|
|
167
|
+
{destination
|
|
168
|
+
? `Create an API key owned by this ${destination.label.toLowerCase()}.`
|
|
169
|
+
: 'Create a key that authenticates requests to the API.'}
|
|
170
|
+
</Dialog.Description>
|
|
141
171
|
<form
|
|
142
172
|
className="mt-6 flex flex-col gap-8"
|
|
143
173
|
onSubmit={(event) => {
|
|
@@ -145,6 +175,21 @@ function ProvisionForm(props: { onSubmit: (form: FormData) => void; pending: boo
|
|
|
145
175
|
props.onSubmit(new FormData(event.currentTarget))
|
|
146
176
|
}}
|
|
147
177
|
>
|
|
178
|
+
{destination ? (
|
|
179
|
+
<div className="border border-border bg-secondary p-3">
|
|
180
|
+
<p className="text-label-12 text-foreground-secondary">
|
|
181
|
+
Destination {destination.label}
|
|
182
|
+
</p>
|
|
183
|
+
<p className="mt-1 truncate font-mono text-label-13 text-foreground">
|
|
184
|
+
{destination.value}
|
|
185
|
+
</p>
|
|
186
|
+
{props.projectId && props.orgId ? (
|
|
187
|
+
<p className="mt-1 truncate font-mono text-label-12 text-foreground-secondary">
|
|
188
|
+
Organization {props.orgId}
|
|
189
|
+
</p>
|
|
190
|
+
) : null}
|
|
191
|
+
</div>
|
|
192
|
+
) : null}
|
|
148
193
|
<Fields className="gap-6" variant="default">
|
|
149
194
|
<Input label="Name" name="name" placeholder="e.g. production-api" />
|
|
150
195
|
<div className="flex flex-col gap-2">
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { useSuspenseInfiniteQuery } from '@tanstack/react-query'
|
|
2
|
+
import {
|
|
3
|
+
createFileRoute,
|
|
4
|
+
type ErrorComponentProps,
|
|
5
|
+
Link,
|
|
6
|
+
useNavigate,
|
|
7
|
+
useRouter,
|
|
8
|
+
} from '@tanstack/react-router'
|
|
9
|
+
import { useEffect, useState } from 'react'
|
|
10
|
+
import { Button, Input, Rows } from 'regen-ui'
|
|
11
|
+
import { ChevronRight, Search } from 'lucide-react'
|
|
12
|
+
|
|
13
|
+
import { Card, Notice, Page } from '../components/Page'
|
|
14
|
+
import * as Organizations from '../lib/organizations'
|
|
15
|
+
|
|
16
|
+
export const Route = createFileRoute('/organizations')({
|
|
17
|
+
validateSearch: Organizations.schema.Search,
|
|
18
|
+
loaderDeps: ({ search }) => ({ query: search.query || undefined }),
|
|
19
|
+
loader: ({ context, deps }) =>
|
|
20
|
+
context.queryClient.ensureInfiniteQueryData(Organizations.list.options(deps)),
|
|
21
|
+
component: PageComponent,
|
|
22
|
+
errorComponent: LookupError,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
function PageComponent() {
|
|
26
|
+
const { query } = Route.useLoaderDeps()
|
|
27
|
+
const navigate = useNavigate({ from: Route.fullPath })
|
|
28
|
+
const [value, setValue] = useState(query ?? '')
|
|
29
|
+
const organizations = useSuspenseInfiniteQuery(Organizations.list.options({ query }))
|
|
30
|
+
const records = organizations.data.pages.flatMap((page) => page.data)
|
|
31
|
+
const invalid = value.trim().length > 0 && value.trim().length < 3
|
|
32
|
+
|
|
33
|
+
useEffect(() => setValue(query ?? ''), [query])
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Page title="Organizations" description="Look up organizations by id, name, or member email">
|
|
37
|
+
<form
|
|
38
|
+
className="flex gap-2"
|
|
39
|
+
onSubmit={(event) => {
|
|
40
|
+
event.preventDefault()
|
|
41
|
+
const next = value.trim()
|
|
42
|
+
if (invalid) return
|
|
43
|
+
void navigate({
|
|
44
|
+
search: Organizations.searchParameters({ query: next }),
|
|
45
|
+
to: '/organizations',
|
|
46
|
+
})
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
<div className="min-w-0 flex-1">
|
|
50
|
+
<Input
|
|
51
|
+
aria-label="Search organizations"
|
|
52
|
+
error={invalid ? 'Enter at least 3 characters.' : false}
|
|
53
|
+
onChange={(event) => setValue(event.target.value)}
|
|
54
|
+
placeholder="Organization id, user id, name, or member email"
|
|
55
|
+
value={value}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
<Button disabled={invalid} type="submit">
|
|
59
|
+
<Search className="size-4" />
|
|
60
|
+
Search
|
|
61
|
+
</Button>
|
|
62
|
+
</form>
|
|
63
|
+
|
|
64
|
+
<Card>
|
|
65
|
+
{records.length === 0 ? (
|
|
66
|
+
<Notice>{query ? `No organizations match “${query}”.` : 'No organizations yet.'}</Notice>
|
|
67
|
+
) : (
|
|
68
|
+
<Rows variant="surface">
|
|
69
|
+
{records.map((organization) => (
|
|
70
|
+
<Rows.Row
|
|
71
|
+
className="min-h-[64px] py-3"
|
|
72
|
+
key={organization.id}
|
|
73
|
+
render={
|
|
74
|
+
<Link
|
|
75
|
+
params={{ orgId: organization.id }}
|
|
76
|
+
search={Organizations.searchParameters({ query })}
|
|
77
|
+
to="/organizations/$orgId"
|
|
78
|
+
/>
|
|
79
|
+
}
|
|
80
|
+
style={{ height: 'auto' }}
|
|
81
|
+
>
|
|
82
|
+
<span className="flex min-w-0 flex-1 flex-col gap-1">
|
|
83
|
+
<span className="truncate text-label-14 text-foreground">
|
|
84
|
+
{organization.name}
|
|
85
|
+
</span>
|
|
86
|
+
<span className="truncate font-mono text-label-12 text-foreground-secondary">
|
|
87
|
+
{organization.id}
|
|
88
|
+
</span>
|
|
89
|
+
</span>
|
|
90
|
+
<span className="hidden shrink-0 text-right sm:block">
|
|
91
|
+
<span className="block text-label-13 text-foreground">
|
|
92
|
+
{formatCount(organization.memberCount, 'member')}
|
|
93
|
+
</span>
|
|
94
|
+
<span className="block text-label-12 text-foreground-secondary">
|
|
95
|
+
{formatCount(organization.projectCount, 'project')}
|
|
96
|
+
</span>
|
|
97
|
+
</span>
|
|
98
|
+
<span className="hidden w-28 shrink-0 text-right text-label-12 text-foreground-secondary md:block">
|
|
99
|
+
{formatDate(organization.createdAt)}
|
|
100
|
+
</span>
|
|
101
|
+
<ChevronRight className="size-4 shrink-0 text-foreground-secondary" />
|
|
102
|
+
</Rows.Row>
|
|
103
|
+
))}
|
|
104
|
+
</Rows>
|
|
105
|
+
)}
|
|
106
|
+
</Card>
|
|
107
|
+
|
|
108
|
+
{organizations.isFetchNextPageError ? (
|
|
109
|
+
<div
|
|
110
|
+
className="flex items-center justify-center gap-3 text-copy-14 text-negative"
|
|
111
|
+
role="alert"
|
|
112
|
+
>
|
|
113
|
+
<span>{organizations.error?.message ?? 'Failed to load more organizations.'}</span>
|
|
114
|
+
<Button onClick={() => organizations.fetchNextPage()}>Retry</Button>
|
|
115
|
+
</div>
|
|
116
|
+
) : organizations.hasNextPage ? (
|
|
117
|
+
<Button
|
|
118
|
+
className="self-center"
|
|
119
|
+
loading={organizations.isFetchingNextPage}
|
|
120
|
+
onClick={() => organizations.fetchNextPage()}
|
|
121
|
+
>
|
|
122
|
+
Load more
|
|
123
|
+
</Button>
|
|
124
|
+
) : null}
|
|
125
|
+
</Page>
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function LookupError(options: LookupError.Props) {
|
|
130
|
+
const router = useRouter()
|
|
131
|
+
return (
|
|
132
|
+
<Page title="Organizations" description="Look up organizations by id, name, or member email">
|
|
133
|
+
<Card className="flex flex-col items-center gap-4 px-6 py-12 text-center">
|
|
134
|
+
<p className="text-copy-14 text-negative">{options.error.message}</p>
|
|
135
|
+
<Button
|
|
136
|
+
onClick={() => {
|
|
137
|
+
options.reset()
|
|
138
|
+
void router.invalidate()
|
|
139
|
+
}}
|
|
140
|
+
>
|
|
141
|
+
Try again
|
|
142
|
+
</Button>
|
|
143
|
+
</Card>
|
|
144
|
+
</Page>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare namespace LookupError {
|
|
149
|
+
type Props = ErrorComponentProps
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function formatCount(value: number, label: string) {
|
|
153
|
+
return `${value} ${label}${value === 1 ? '' : 's'}`
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function formatDate(value: string) {
|
|
157
|
+
return new Intl.DateTimeFormat('en', { dateStyle: 'medium' }).format(new Date(value))
|
|
158
|
+
}
|