@syncular/console 0.0.6-159 → 0.0.6-165
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/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useConsoleApi.d.ts +113 -97
- package/dist/hooks/useConsoleApi.d.ts.map +1 -1
- package/dist/hooks/useConsoleApi.js +368 -520
- package/dist/hooks/useConsoleApi.js.map +1 -1
- package/dist/hooks/useLiveEvents.d.ts.map +1 -1
- package/dist/hooks/useLiveEvents.js +2 -94
- package/dist/hooks/useLiveEvents.js.map +1 -1
- package/dist/lib/topology.d.ts +2 -2
- package/dist/lib/topology.d.ts.map +1 -1
- package/dist/lib/topology.js.map +1 -1
- package/dist/lib/types.d.ts +58 -170
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +1 -1
- package/dist/pages/Config.d.ts.map +1 -1
- package/dist/pages/Config.js +2 -1
- package/dist/pages/Config.js.map +1 -1
- package/package.json +4 -4
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useConsoleApi.ts +552 -756
- package/src/hooks/useLiveEvents.ts +2 -115
- package/src/lib/topology.ts +3 -3
- package/src/lib/types.ts +104 -187
- package/src/pages/Config.tsx +3 -1
- package/web-dist/assets/index-BXJahjhP.js +86 -0
- package/web-dist/index.html +1 -1
- package/dist/hooks/useRequestEvents.d.ts +0 -7
- package/dist/hooks/useRequestEvents.d.ts.map +0 -1
- package/dist/hooks/useRequestEvents.js +0 -33
- package/dist/hooks/useRequestEvents.js.map +0 -1
- package/src/hooks/useRequestEvents.ts +0 -35
- package/web-dist/assets/index-DWD8MzCy.js +0 -86
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
6
|
-
import type {
|
|
6
|
+
import type { LiveEvent } from '../lib/types';
|
|
7
7
|
import { useConnection } from './ConnectionContext';
|
|
8
8
|
import { useInstanceContext } from './useInstanceContext';
|
|
9
9
|
|
|
@@ -35,11 +35,6 @@ interface UseLiveEventsResult {
|
|
|
35
35
|
clearEvents: () => void;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
function isServiceWorkerServerMode(): boolean {
|
|
39
|
-
if (typeof window === 'undefined') return false;
|
|
40
|
-
return new URLSearchParams(window.location.search).get('swServer') === '1';
|
|
41
|
-
}
|
|
42
|
-
|
|
43
38
|
export function useLiveEvents(
|
|
44
39
|
options: UseLiveEventsOptions = {}
|
|
45
40
|
): UseLiveEventsResult {
|
|
@@ -70,12 +65,10 @@ export function useLiveEvents(
|
|
|
70
65
|
const reconnectAttemptsRef = useRef(0);
|
|
71
66
|
const lastActivityAtRef = useRef(0);
|
|
72
67
|
const lastEventTimestampRef = useRef<string | null>(null);
|
|
73
|
-
const lastEventIdRef = useRef<number | null>(null);
|
|
74
68
|
|
|
75
69
|
const clearEvents = useCallback(() => {
|
|
76
70
|
setEvents([]);
|
|
77
71
|
lastEventTimestampRef.current = null;
|
|
78
|
-
lastEventIdRef.current = null;
|
|
79
72
|
}, []);
|
|
80
73
|
|
|
81
74
|
useEffect(() => {
|
|
@@ -87,113 +80,7 @@ export function useLiveEvents(
|
|
|
87
80
|
const normalizedReplayLimit = Number.isFinite(replayLimit)
|
|
88
81
|
? Math.max(1, Math.min(500, Math.floor(replayLimit)))
|
|
89
82
|
: 100;
|
|
90
|
-
|
|
91
|
-
isServiceWorkerServerMode() || typeof WebSocket === 'undefined';
|
|
92
|
-
|
|
93
|
-
if (usePollingFallback) {
|
|
94
|
-
setConnectionState('connecting');
|
|
95
|
-
setIsConnected(false);
|
|
96
|
-
|
|
97
|
-
let pollTimer: ReturnType<typeof setInterval> | null = null;
|
|
98
|
-
let isPolling = false;
|
|
99
|
-
|
|
100
|
-
const poll = async () => {
|
|
101
|
-
if (isCleanedUp || isPolling) return;
|
|
102
|
-
isPolling = true;
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
const baseUrl = new URL(config.serverUrl, window.location.origin);
|
|
106
|
-
const normalizedPath = baseUrl.pathname.endsWith('/')
|
|
107
|
-
? baseUrl.pathname.slice(0, -1)
|
|
108
|
-
: baseUrl.pathname;
|
|
109
|
-
baseUrl.pathname = `${normalizedPath}/console/events`;
|
|
110
|
-
baseUrl.search = '';
|
|
111
|
-
baseUrl.searchParams.set('limit', String(normalizedReplayLimit));
|
|
112
|
-
baseUrl.searchParams.set('offset', '0');
|
|
113
|
-
if (partitionId) {
|
|
114
|
-
baseUrl.searchParams.set('partitionId', partitionId);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const response = await fetch(baseUrl.toString(), {
|
|
118
|
-
headers: {
|
|
119
|
-
Authorization: `Bearer ${config.token}`,
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
if (!response.ok) {
|
|
124
|
-
throw new Error(`Live event polling failed (${response.status})`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const payload = (await response.json()) as {
|
|
128
|
-
items?: ConsoleRequestEvent[];
|
|
129
|
-
};
|
|
130
|
-
const rows = Array.isArray(payload.items) ? payload.items : [];
|
|
131
|
-
const filtered = rows
|
|
132
|
-
.filter((row) =>
|
|
133
|
-
effectiveInstanceId
|
|
134
|
-
? row.instanceId === effectiveInstanceId
|
|
135
|
-
: true
|
|
136
|
-
)
|
|
137
|
-
.sort((a, b) => a.eventId - b.eventId);
|
|
138
|
-
|
|
139
|
-
const previousLastId = lastEventIdRef.current ?? -1;
|
|
140
|
-
const newRows = filtered.filter(
|
|
141
|
-
(row) => row.eventId > previousLastId
|
|
142
|
-
);
|
|
143
|
-
if (newRows.length > 0) {
|
|
144
|
-
const mapped: LiveEvent[] = newRows
|
|
145
|
-
.map((row) => ({
|
|
146
|
-
type: row.eventType,
|
|
147
|
-
timestamp: row.createdAt,
|
|
148
|
-
data: row as unknown as Record<string, unknown>,
|
|
149
|
-
}))
|
|
150
|
-
.reverse();
|
|
151
|
-
|
|
152
|
-
setEvents((prev) => [...mapped, ...prev].slice(0, maxEvents));
|
|
153
|
-
const newest = newRows[newRows.length - 1]!;
|
|
154
|
-
lastEventIdRef.current = newest.eventId;
|
|
155
|
-
lastEventTimestampRef.current = newest.createdAt;
|
|
156
|
-
} else if (filtered.length > 0) {
|
|
157
|
-
const newest = filtered[filtered.length - 1]!;
|
|
158
|
-
lastEventIdRef.current = Math.max(
|
|
159
|
-
lastEventIdRef.current ?? -1,
|
|
160
|
-
newest.eventId
|
|
161
|
-
);
|
|
162
|
-
lastEventTimestampRef.current = newest.createdAt;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
setError(null);
|
|
166
|
-
setIsConnected(true);
|
|
167
|
-
setConnectionState('connected');
|
|
168
|
-
} catch (err) {
|
|
169
|
-
if (!isCleanedUp) {
|
|
170
|
-
setIsConnected(false);
|
|
171
|
-
setConnectionState('disconnected');
|
|
172
|
-
setError(
|
|
173
|
-
err instanceof Error
|
|
174
|
-
? err
|
|
175
|
-
: new Error('Live event polling failed')
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
} finally {
|
|
179
|
-
isPolling = false;
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
void poll();
|
|
184
|
-
pollTimer = setInterval(() => {
|
|
185
|
-
void poll();
|
|
186
|
-
}, 2_000);
|
|
187
|
-
|
|
188
|
-
return () => {
|
|
189
|
-
isCleanedUp = true;
|
|
190
|
-
if (pollTimer) {
|
|
191
|
-
clearInterval(pollTimer);
|
|
192
|
-
}
|
|
193
|
-
setIsConnected(false);
|
|
194
|
-
setConnectionState('disconnected');
|
|
195
|
-
};
|
|
196
|
-
}
|
|
83
|
+
if (typeof WebSocket === 'undefined') return;
|
|
197
84
|
|
|
198
85
|
const clearReconnectTimeout = () => {
|
|
199
86
|
if (!reconnectTimeoutRef.current) return;
|
package/src/lib/topology.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SyncClientNode } from '@syncular/ui';
|
|
2
2
|
import type { ConsoleClient, SyncStats } from './types';
|
|
3
3
|
|
|
4
4
|
interface TopologyAdapterOptions {
|
|
@@ -55,7 +55,7 @@ function inferLagCommitCount(
|
|
|
55
55
|
function inferStatus(
|
|
56
56
|
client: ConsoleClient,
|
|
57
57
|
lagCommitCount: number
|
|
58
|
-
):
|
|
58
|
+
): SyncClientNode['status'] {
|
|
59
59
|
if (client.activityState === 'stale') {
|
|
60
60
|
return 'offline';
|
|
61
61
|
}
|
|
@@ -80,7 +80,7 @@ export function adaptConsoleClientsToTopology(
|
|
|
80
80
|
clients: ConsoleClient[],
|
|
81
81
|
stats?: SyncStats,
|
|
82
82
|
options: TopologyAdapterOptions = {}
|
|
83
|
-
):
|
|
83
|
+
): SyncClientNode[] {
|
|
84
84
|
const maxNodes = options.maxNodes ?? 10;
|
|
85
85
|
|
|
86
86
|
return clients.slice(0, maxNodes).map((client, index) => {
|
package/src/lib/types.ts
CHANGED
|
@@ -1,180 +1,132 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Console API types
|
|
2
|
+
* Console API types derived from generated OpenAPI operations.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export interface ConsoleApiKey {
|
|
8
|
-
keyId: string;
|
|
9
|
-
keyPrefix: string;
|
|
10
|
-
name: string;
|
|
11
|
-
keyType: ApiKeyType;
|
|
12
|
-
scopeKeys: string[];
|
|
13
|
-
actorId: string | null;
|
|
14
|
-
createdAt: string;
|
|
15
|
-
expiresAt: string | null;
|
|
16
|
-
lastUsedAt: string | null;
|
|
17
|
-
revokedAt: string | null;
|
|
18
|
-
}
|
|
5
|
+
import type { operations } from '@syncular/transport-http';
|
|
19
6
|
|
|
20
|
-
|
|
21
|
-
requestedCount: number;
|
|
22
|
-
revokedCount: number;
|
|
23
|
-
alreadyRevokedCount: number;
|
|
24
|
-
notFoundCount: number;
|
|
25
|
-
revokedKeyIds: string[];
|
|
26
|
-
alreadyRevokedKeyIds: string[];
|
|
27
|
-
notFoundKeyIds: string[];
|
|
28
|
-
}
|
|
7
|
+
type OperationName = keyof operations;
|
|
29
8
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
createdAt: string;
|
|
36
|
-
changeCount: number;
|
|
37
|
-
affectedTables: string[];
|
|
38
|
-
instanceId?: string;
|
|
39
|
-
federatedCommitId?: string;
|
|
40
|
-
localCommitSeq?: number;
|
|
9
|
+
type JsonResponse<
|
|
10
|
+
TOperation extends OperationName,
|
|
11
|
+
TStatus extends keyof operations[TOperation]['responses'],
|
|
12
|
+
> = operations[TOperation]['responses'][TStatus] extends {
|
|
13
|
+
content: { 'application/json': infer TJson };
|
|
41
14
|
}
|
|
15
|
+
? TJson
|
|
16
|
+
: never;
|
|
42
17
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
rowJson: unknown | null;
|
|
49
|
-
rowVersion: number | null;
|
|
50
|
-
scopes: Record<string, unknown>;
|
|
51
|
-
}
|
|
18
|
+
type OperationWithResponse<TStatus extends PropertyKey> = {
|
|
19
|
+
[TName in OperationName]: TStatus extends keyof operations[TName]['responses']
|
|
20
|
+
? TName
|
|
21
|
+
: never;
|
|
22
|
+
}[OperationName];
|
|
52
23
|
|
|
53
|
-
|
|
54
|
-
|
|
24
|
+
type JsonSuccessResponse<TOperation extends OperationWithResponse<200>> =
|
|
25
|
+
JsonResponse<TOperation, 200>;
|
|
26
|
+
|
|
27
|
+
type JsonRequestBody<TOperation extends OperationName> =
|
|
28
|
+
NonNullable<operations[TOperation]['requestBody']> extends {
|
|
29
|
+
content: { 'application/json': infer TJson };
|
|
30
|
+
}
|
|
31
|
+
? TJson
|
|
32
|
+
: never;
|
|
33
|
+
|
|
34
|
+
type PaginatedItem<TOperation extends OperationWithResponse<200>> =
|
|
35
|
+
JsonSuccessResponse<TOperation> extends { items: Array<infer TItem> }
|
|
36
|
+
? TItem
|
|
37
|
+
: never;
|
|
38
|
+
|
|
39
|
+
interface GatewayFailure {
|
|
40
|
+
instanceId: string;
|
|
41
|
+
reason: string;
|
|
42
|
+
status?: number;
|
|
55
43
|
}
|
|
56
44
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
cursor: number;
|
|
61
|
-
lagCommitCount: number;
|
|
62
|
-
connectionPath: 'direct' | 'relay';
|
|
63
|
-
connectionMode: 'polling' | 'realtime';
|
|
64
|
-
realtimeConnectionCount: number;
|
|
65
|
-
isRealtimeConnected: boolean;
|
|
66
|
-
activityState: 'active' | 'idle' | 'stale';
|
|
67
|
-
lastRequestAt: string | null;
|
|
68
|
-
lastRequestType: 'push' | 'pull' | null;
|
|
69
|
-
lastRequestOutcome: string | null;
|
|
70
|
-
effectiveScopes: Record<string, unknown>;
|
|
71
|
-
updatedAt: string;
|
|
72
|
-
instanceId?: string;
|
|
73
|
-
federatedClientId?: string;
|
|
45
|
+
interface GatewayAggregateMetadata {
|
|
46
|
+
partial?: boolean;
|
|
47
|
+
failedInstances?: GatewayFailure[];
|
|
74
48
|
}
|
|
75
49
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
50
|
+
interface GatewayCommitFields {
|
|
51
|
+
instanceId?: string;
|
|
52
|
+
federatedCommitId?: string;
|
|
53
|
+
localCommitSeq?: number;
|
|
80
54
|
}
|
|
81
55
|
|
|
82
|
-
|
|
83
|
-
eventId: number;
|
|
84
|
-
partitionId: string;
|
|
85
|
-
requestId: string;
|
|
86
|
-
traceId: string | null;
|
|
87
|
-
spanId: string | null;
|
|
88
|
-
eventType: 'push' | 'pull';
|
|
89
|
-
syncPath: 'http-combined' | 'ws-push';
|
|
90
|
-
transportPath: 'direct' | 'relay';
|
|
91
|
-
actorId: string;
|
|
92
|
-
clientId: string;
|
|
93
|
-
statusCode: number;
|
|
94
|
-
outcome: string;
|
|
95
|
-
responseStatus: string;
|
|
96
|
-
errorCode: string | null;
|
|
97
|
-
durationMs: number;
|
|
98
|
-
commitSeq: number | null;
|
|
99
|
-
operationCount: number | null;
|
|
100
|
-
rowCount: number | null;
|
|
101
|
-
subscriptionCount: number | null;
|
|
102
|
-
scopesSummary: Record<string, string | string[]> | null;
|
|
103
|
-
tables: string[];
|
|
104
|
-
errorMessage: string | null;
|
|
105
|
-
payloadRef: string | null;
|
|
106
|
-
createdAt: string;
|
|
56
|
+
interface GatewayClientFields {
|
|
107
57
|
instanceId?: string;
|
|
108
|
-
|
|
109
|
-
localEventId?: number;
|
|
58
|
+
federatedClientId?: string;
|
|
110
59
|
}
|
|
111
60
|
|
|
112
|
-
|
|
113
|
-
payloadRef: string;
|
|
114
|
-
partitionId: string;
|
|
115
|
-
requestPayload: unknown;
|
|
116
|
-
responsePayload: unknown | null;
|
|
117
|
-
createdAt: string;
|
|
61
|
+
interface GatewayEventFields {
|
|
118
62
|
instanceId?: string;
|
|
119
63
|
federatedEventId?: string;
|
|
120
64
|
localEventId?: number;
|
|
121
65
|
}
|
|
122
66
|
|
|
123
|
-
|
|
124
|
-
type: 'commit' | 'event';
|
|
125
|
-
timestamp: string;
|
|
126
|
-
commit: ConsoleCommitListItem | null;
|
|
127
|
-
event: ConsoleRequestEvent | null;
|
|
67
|
+
interface GatewayTimelineFields {
|
|
128
68
|
instanceId?: string;
|
|
129
69
|
federatedTimelineId?: string;
|
|
130
70
|
localCommitSeq?: number | null;
|
|
131
71
|
localEventId?: number | null;
|
|
132
72
|
}
|
|
133
73
|
|
|
134
|
-
|
|
135
|
-
| 'prune'
|
|
136
|
-
| 'compact'
|
|
137
|
-
| 'notify_data_change'
|
|
138
|
-
| 'evict_client';
|
|
139
|
-
|
|
140
|
-
export interface ConsoleOperationEvent {
|
|
141
|
-
operationId: number;
|
|
142
|
-
operationType: ConsoleOperationType;
|
|
143
|
-
consoleUserId: string | null;
|
|
144
|
-
partitionId: string | null;
|
|
145
|
-
targetClientId: string | null;
|
|
146
|
-
requestPayload: unknown | null;
|
|
147
|
-
resultPayload: unknown | null;
|
|
148
|
-
createdAt: string;
|
|
74
|
+
interface GatewayOperationFields {
|
|
149
75
|
instanceId?: string;
|
|
150
76
|
federatedOperationId?: string;
|
|
151
77
|
localOperationId?: number;
|
|
152
78
|
}
|
|
153
79
|
|
|
154
|
-
export
|
|
155
|
-
commitSeq: number;
|
|
156
|
-
tables: string[];
|
|
157
|
-
deletedChunks: number;
|
|
158
|
-
}
|
|
80
|
+
export type ApiKeyType = JsonRequestBody<'postConsoleApiKeys'>['keyType'];
|
|
159
81
|
|
|
160
|
-
export
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
82
|
+
export type ConsoleApiKey = JsonSuccessResponse<'getConsoleApiKeysById'>;
|
|
83
|
+
|
|
84
|
+
export type ConsoleApiKeyBulkRevokeResponse =
|
|
85
|
+
JsonSuccessResponse<'postConsoleApiKeysBulkRevoke'>;
|
|
86
|
+
|
|
87
|
+
export type ConsoleCommitListItem = PaginatedItem<'getConsoleCommits'> &
|
|
88
|
+
GatewayCommitFields;
|
|
89
|
+
|
|
90
|
+
export type ConsoleCommitDetail =
|
|
91
|
+
JsonSuccessResponse<'getConsoleCommitsBySeq'> & GatewayCommitFields;
|
|
92
|
+
|
|
93
|
+
export type ConsoleClient = PaginatedItem<'getConsoleClients'> &
|
|
94
|
+
GatewayClientFields;
|
|
95
|
+
|
|
96
|
+
export type ConsoleHandler =
|
|
97
|
+
JsonSuccessResponse<'getConsoleHandlers'>['items'][number];
|
|
98
|
+
|
|
99
|
+
export type ConsoleRequestEvent = PaginatedItem<'getConsoleEvents'> &
|
|
100
|
+
GatewayEventFields;
|
|
101
|
+
|
|
102
|
+
export type ConsoleRequestPayload =
|
|
103
|
+
JsonSuccessResponse<'getConsoleEventsByIdPayload'> & GatewayEventFields;
|
|
104
|
+
|
|
105
|
+
type BaseConsoleTimelineItem = PaginatedItem<'getConsoleTimeline'>;
|
|
106
|
+
|
|
107
|
+
export type ConsoleTimelineItem = Omit<
|
|
108
|
+
BaseConsoleTimelineItem,
|
|
109
|
+
'commit' | 'event'
|
|
110
|
+
> &
|
|
111
|
+
GatewayTimelineFields & {
|
|
112
|
+
commit: ConsoleCommitListItem | null;
|
|
113
|
+
event: ConsoleRequestEvent | null;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type ConsoleOperationType =
|
|
117
|
+
PaginatedItem<'getConsoleOperations'>['operationType'];
|
|
118
|
+
|
|
119
|
+
export type ConsoleOperationEvent = PaginatedItem<'getConsoleOperations'> &
|
|
120
|
+
GatewayOperationFields;
|
|
121
|
+
|
|
122
|
+
export type ConsoleNotifyDataChangeResponse =
|
|
123
|
+
JsonSuccessResponse<'postConsoleNotifyDataChange'>;
|
|
124
|
+
|
|
125
|
+
export type SyncStats = JsonSuccessResponse<'getConsoleStats'> &
|
|
126
|
+
GatewayAggregateMetadata & {
|
|
127
|
+
minCommitSeqByInstance?: Record<string, number>;
|
|
128
|
+
maxCommitSeqByInstance?: Record<string, number>;
|
|
129
|
+
};
|
|
178
130
|
|
|
179
131
|
export interface PaginatedResponse<T> {
|
|
180
132
|
items: T[];
|
|
@@ -183,38 +135,18 @@ export interface PaginatedResponse<T> {
|
|
|
183
135
|
limit: number;
|
|
184
136
|
}
|
|
185
137
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
export type TimeseriesRange = '1h' | '6h' | '24h' | '7d' | '30d';
|
|
138
|
+
export type TimeseriesInterval =
|
|
139
|
+
JsonSuccessResponse<'getConsoleStatsTimeseries'>['interval'];
|
|
189
140
|
|
|
190
|
-
export
|
|
191
|
-
|
|
192
|
-
pushCount: number;
|
|
193
|
-
pullCount: number;
|
|
194
|
-
errorCount: number;
|
|
195
|
-
avgLatencyMs: number;
|
|
196
|
-
}
|
|
141
|
+
export type TimeseriesRange =
|
|
142
|
+
JsonSuccessResponse<'getConsoleStatsTimeseries'>['range'];
|
|
197
143
|
|
|
198
|
-
export
|
|
199
|
-
|
|
200
|
-
interval: TimeseriesInterval;
|
|
201
|
-
range: TimeseriesRange;
|
|
202
|
-
}
|
|
144
|
+
export type TimeseriesStatsResponse =
|
|
145
|
+
JsonSuccessResponse<'getConsoleStatsTimeseries'> & GatewayAggregateMetadata;
|
|
203
146
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
p50: number;
|
|
207
|
-
p90: number;
|
|
208
|
-
p99: number;
|
|
209
|
-
}
|
|
147
|
+
export type LatencyStatsResponse =
|
|
148
|
+
JsonSuccessResponse<'getConsoleStatsLatency'> & GatewayAggregateMetadata;
|
|
210
149
|
|
|
211
|
-
export interface LatencyStatsResponse {
|
|
212
|
-
push: LatencyPercentiles;
|
|
213
|
-
pull: LatencyPercentiles;
|
|
214
|
-
range: TimeseriesRange;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Live events types
|
|
218
150
|
export interface LiveEvent {
|
|
219
151
|
type:
|
|
220
152
|
| 'push'
|
|
@@ -227,19 +159,4 @@ export interface LiveEvent {
|
|
|
227
159
|
data: Record<string, unknown>;
|
|
228
160
|
}
|
|
229
161
|
|
|
230
|
-
|
|
231
|
-
// Blob storage
|
|
232
|
-
// ---------------------------------------------------------------------------
|
|
233
|
-
|
|
234
|
-
export interface ConsoleBlob {
|
|
235
|
-
key: string;
|
|
236
|
-
size: number;
|
|
237
|
-
uploaded: string;
|
|
238
|
-
httpMetadata?: { contentType?: string };
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export interface ConsoleBlobListResponse {
|
|
242
|
-
items: ConsoleBlob[];
|
|
243
|
-
truncated: boolean;
|
|
244
|
-
cursor: string | null;
|
|
245
|
-
}
|
|
162
|
+
export type ConsoleBlobListResponse = JsonSuccessResponse<'getConsoleStorage'>;
|
package/src/pages/Config.tsx
CHANGED
|
@@ -26,8 +26,8 @@ import {
|
|
|
26
26
|
TableHead,
|
|
27
27
|
TableHeader,
|
|
28
28
|
TableRow,
|
|
29
|
+
Toggle,
|
|
29
30
|
ToggleGroup,
|
|
30
|
-
ToggleGroupItem,
|
|
31
31
|
} from '@syncular/ui';
|
|
32
32
|
import { useEffect, useMemo, useState } from 'react';
|
|
33
33
|
import {
|
|
@@ -48,6 +48,8 @@ import type {
|
|
|
48
48
|
ConsoleApiKeyBulkRevokeResponse,
|
|
49
49
|
} from '../lib/types';
|
|
50
50
|
|
|
51
|
+
const ToggleGroupItem = Toggle;
|
|
52
|
+
|
|
51
53
|
export function Config({ children }: { children?: import('react').ReactNode }) {
|
|
52
54
|
return (
|
|
53
55
|
<div className="space-y-4 px-5 py-5">
|