@geekmidas/studio 2.0.1 → 10.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/package.json +8 -5
  2. package/CHANGELOG.md +0 -60
  3. package/src/Studio.ts +0 -367
  4. package/src/__tests__/Studio.spec.ts +0 -447
  5. package/src/data/DataBrowser.ts +0 -170
  6. package/src/data/__tests__/DataBrowser.integration.spec.ts +0 -418
  7. package/src/data/__tests__/filtering.integration.spec.ts +0 -741
  8. package/src/data/__tests__/introspection.integration.spec.ts +0 -352
  9. package/src/data/__tests__/pagination.spec.ts +0 -123
  10. package/src/data/filtering.ts +0 -191
  11. package/src/data/index.ts +0 -1
  12. package/src/data/introspection.ts +0 -220
  13. package/src/data/pagination.ts +0 -33
  14. package/src/index.ts +0 -29
  15. package/src/server/__tests__/hono.integration.spec.ts +0 -619
  16. package/src/server/hono.ts +0 -427
  17. package/src/types.ts +0 -278
  18. package/src/ui-assets.ts +0 -37
  19. package/tsconfig.json +0 -9
  20. package/tsdown.config.ts +0 -13
  21. package/ui/CHANGELOG.md +0 -26
  22. package/ui/index.html +0 -12
  23. package/ui/node_modules/.bin/tsc +0 -21
  24. package/ui/node_modules/.bin/tsserver +0 -21
  25. package/ui/node_modules/.bin/vite +0 -21
  26. package/ui/package.json +0 -30
  27. package/ui/src/App.tsx +0 -100
  28. package/ui/src/api.ts +0 -213
  29. package/ui/src/components/FilterPanel.tsx +0 -213
  30. package/ui/src/components/NavRail.tsx +0 -183
  31. package/ui/src/components/RowDetail.tsx +0 -119
  32. package/ui/src/components/StudioHeader.tsx +0 -109
  33. package/ui/src/components/TableList.tsx +0 -58
  34. package/ui/src/components/TableView.tsx +0 -564
  35. package/ui/src/main.tsx +0 -10
  36. package/ui/src/pages/DashboardPage.tsx +0 -500
  37. package/ui/src/pages/DatabasePage.tsx +0 -226
  38. package/ui/src/pages/EndpointDetailsPage.tsx +0 -288
  39. package/ui/src/pages/ExceptionsPage.tsx +0 -268
  40. package/ui/src/pages/LogsPage.tsx +0 -228
  41. package/ui/src/pages/MonitoringPage.tsx +0 -46
  42. package/ui/src/pages/PerformancePage.tsx +0 -307
  43. package/ui/src/pages/RequestsPage.tsx +0 -379
  44. package/ui/src/providers/StudioProvider.tsx +0 -194
  45. package/ui/src/styles.css +0 -105
  46. package/ui/src/types.ts +0 -174
  47. package/ui/src/vite-env.d.ts +0 -1
  48. package/ui/tsconfig.json +0 -21
  49. package/ui/tsconfig.tsbuildinfo +0 -1
  50. package/ui/vite.config.ts +0 -12
@@ -1,194 +0,0 @@
1
- import {
2
- createContext,
3
- type ReactNode,
4
- useCallback,
5
- useContext,
6
- useEffect,
7
- useState,
8
- } from 'react';
9
- import * as api from '../api';
10
- import type {
11
- ExceptionEntry,
12
- LogEntry,
13
- MetricsSnapshot,
14
- RequestEntry,
15
- StudioStats,
16
- WebSocketMessage,
17
- } from '../types';
18
-
19
- interface StudioContextValue {
20
- // Connection state
21
- connected: boolean;
22
-
23
- // Stats
24
- stats: StudioStats | null;
25
-
26
- // Data
27
- requests: RequestEntry[];
28
- logs: LogEntry[];
29
- exceptions: ExceptionEntry[];
30
-
31
- // Real-time metrics from WebSocket
32
- realtimeMetrics: MetricsSnapshot | null;
33
-
34
- // Loading state
35
- loading: boolean;
36
-
37
- // Actions
38
- refresh: () => Promise<void>;
39
- addRequest: (request: RequestEntry) => void;
40
- addLog: (log: LogEntry) => void;
41
- addException: (exception: ExceptionEntry) => void;
42
- }
43
-
44
- const StudioContext = createContext<StudioContextValue | null>(null);
45
-
46
- export function useStudio() {
47
- const context = useContext(StudioContext);
48
- if (!context) {
49
- throw new Error('useStudio must be used within a StudioProvider');
50
- }
51
- return context;
52
- }
53
-
54
- interface StudioProviderProps {
55
- children: ReactNode;
56
- }
57
-
58
- export function StudioProvider({ children }: StudioProviderProps) {
59
- const [connected, setConnected] = useState(false);
60
- const [stats, setStats] = useState<StudioStats | null>(null);
61
- const [requests, setRequests] = useState<RequestEntry[]>([]);
62
- const [logs, setLogs] = useState<LogEntry[]>([]);
63
- const [exceptions, setExceptions] = useState<ExceptionEntry[]>([]);
64
- const [realtimeMetrics, setRealtimeMetrics] =
65
- useState<MetricsSnapshot | null>(null);
66
- const [loading, setLoading] = useState(true);
67
-
68
- // Load initial data
69
- const loadInitialData = useCallback(async () => {
70
- try {
71
- setLoading(true);
72
- const [statsData, requestsData, exceptionsData, logsData] =
73
- await Promise.all([
74
- api.getStats(),
75
- api.getRequests({ limit: 100 }),
76
- api.getExceptions({ limit: 100 }),
77
- api.getLogs({ limit: 100 }),
78
- ]);
79
-
80
- setStats(statsData);
81
- setRequests(requestsData);
82
- setExceptions(exceptionsData);
83
- setLogs(logsData);
84
- } catch (_error) {
85
- } finally {
86
- setLoading(false);
87
- }
88
- }, []);
89
-
90
- // Refresh data
91
- const refresh = useCallback(async () => {
92
- await loadInitialData();
93
- }, [loadInitialData]);
94
-
95
- // Add new entries
96
- const addRequest = useCallback((request: RequestEntry) => {
97
- setRequests((prev) => [request, ...prev].slice(0, 100));
98
- setStats((prev) =>
99
- prev ? { ...prev, requests: prev.requests + 1 } : prev,
100
- );
101
- }, []);
102
-
103
- const addLog = useCallback((log: LogEntry) => {
104
- setLogs((prev) => [log, ...prev].slice(0, 100));
105
- setStats((prev) => (prev ? { ...prev, logs: prev.logs + 1 } : prev));
106
- }, []);
107
-
108
- const addException = useCallback((exception: ExceptionEntry) => {
109
- setExceptions((prev) => [exception, ...prev].slice(0, 100));
110
- setStats((prev) =>
111
- prev ? { ...prev, exceptions: prev.exceptions + 1 } : prev,
112
- );
113
- }, []);
114
-
115
- // Load data on mount
116
- useEffect(() => {
117
- loadInitialData();
118
- }, [loadInitialData]);
119
-
120
- // WebSocket connection for real-time updates
121
- useEffect(() => {
122
- let ws: WebSocket | null = null;
123
- let reconnectTimeout: ReturnType<typeof setTimeout>;
124
-
125
- function connect() {
126
- try {
127
- ws = api.createWebSocket();
128
-
129
- ws.onopen = () => {
130
- setConnected(true);
131
- };
132
-
133
- ws.onclose = () => {
134
- setConnected(false);
135
- reconnectTimeout = setTimeout(connect, 3000);
136
- };
137
-
138
- ws.onerror = () => {
139
- ws?.close();
140
- };
141
-
142
- ws.onmessage = (event) => {
143
- try {
144
- const message: WebSocketMessage = JSON.parse(event.data);
145
-
146
- switch (message.type) {
147
- case 'request':
148
- addRequest(message.payload as RequestEntry);
149
- break;
150
- case 'exception':
151
- addException(message.payload as ExceptionEntry);
152
- break;
153
- case 'log':
154
- addLog(message.payload as LogEntry);
155
- break;
156
- case 'metrics':
157
- setRealtimeMetrics(message.payload as MetricsSnapshot);
158
- break;
159
- }
160
- } catch {
161
- // Ignore parse errors
162
- }
163
- };
164
- } catch {
165
- reconnectTimeout = setTimeout(connect, 3000);
166
- }
167
- }
168
-
169
- connect();
170
-
171
- return () => {
172
- clearTimeout(reconnectTimeout);
173
- ws?.close();
174
- };
175
- }, [addRequest, addLog, addException]);
176
-
177
- const value: StudioContextValue = {
178
- connected,
179
- stats,
180
- requests,
181
- logs,
182
- exceptions,
183
- realtimeMetrics,
184
- loading,
185
- refresh,
186
- addRequest,
187
- addLog,
188
- addException,
189
- };
190
-
191
- return (
192
- <StudioContext.Provider value={value}>{children}</StudioContext.Provider>
193
- );
194
- }
package/ui/src/styles.css DELETED
@@ -1,105 +0,0 @@
1
- @import "tailwindcss";
2
- @import "@geekmidas/ui/styles";
3
-
4
- @theme {
5
- /* Dev Studio theme - extends @geekmidas/ui theme */
6
- --color-studio-bg: var(--color-background);
7
- --color-studio-surface: var(--color-surface);
8
- --color-studio-border: var(--color-border);
9
- --color-studio-hover: var(--color-surface-hover);
10
- --color-studio-active: #333333;
11
- --color-studio-accent: var(--color-accent);
12
- --color-studio-accent-hover: #4ade94;
13
-
14
- /* Legacy colors for compatibility */
15
- --color-bg-primary: var(--color-background);
16
- --color-bg-secondary: var(--color-surface);
17
- --color-bg-tertiary: var(--color-surface-hover);
18
- }
19
-
20
- * {
21
- box-sizing: border-box;
22
- }
23
-
24
- body {
25
- margin: 0;
26
- padding: 0;
27
- font-family:
28
- -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
29
- Arial, sans-serif;
30
- -webkit-font-smoothing: antialiased;
31
- -moz-osx-font-smoothing: grayscale;
32
- background: var(--color-background);
33
- }
34
-
35
- /* Custom scrollbar */
36
- ::-webkit-scrollbar {
37
- width: 8px;
38
- height: 8px;
39
- }
40
-
41
- ::-webkit-scrollbar-track {
42
- background: transparent;
43
- }
44
-
45
- ::-webkit-scrollbar-thumb {
46
- background: #404040;
47
- border-radius: 4px;
48
- }
49
-
50
- ::-webkit-scrollbar-thumb:hover {
51
- background: #525252;
52
- }
53
-
54
- /* Table styles */
55
- .data-grid {
56
- border-collapse: collapse;
57
- width: 100%;
58
- }
59
-
60
- .data-grid th {
61
- position: sticky;
62
- top: 0;
63
- background: var(--color-surface);
64
- z-index: 10;
65
- }
66
-
67
- .data-grid th,
68
- .data-grid td {
69
- border-bottom: 1px solid var(--color-border);
70
- text-align: left;
71
- }
72
-
73
- .data-grid tbody tr:hover {
74
- background: var(--color-surface-hover);
75
- }
76
-
77
- /* Row number column */
78
- .row-number {
79
- color: #525252;
80
- font-size: 12px;
81
- font-variant-numeric: tabular-nums;
82
- user-select: none;
83
- }
84
-
85
- /* NULL value styling */
86
- .cell-null {
87
- color: #525252;
88
- font-style: italic;
89
- }
90
-
91
- /* Filter panel animation */
92
- .filter-panel {
93
- animation: slideDown 0.15s ease-out;
94
- }
95
-
96
- @keyframes slideDown {
97
- from {
98
- opacity: 0;
99
- transform: translateY(-8px);
100
- }
101
- to {
102
- opacity: 1;
103
- transform: translateY(0);
104
- }
105
- }
package/ui/src/types.ts DELETED
@@ -1,174 +0,0 @@
1
- // ============================================================================
2
- // Database Types
3
- // ============================================================================
4
-
5
- export interface ColumnInfo {
6
- name: string;
7
- type: string;
8
- rawType: string;
9
- nullable: boolean;
10
- isPrimaryKey: boolean;
11
- isForeignKey: boolean;
12
- foreignKeyTable?: string;
13
- foreignKeyColumn?: string;
14
- defaultValue?: string;
15
- }
16
-
17
- export interface TableInfo {
18
- name: string;
19
- schema: string;
20
- columns: ColumnInfo[];
21
- primaryKey: string[];
22
- estimatedRowCount?: number;
23
- }
24
-
25
- export interface TableSummary {
26
- name: string;
27
- schema: string;
28
- columnCount: number;
29
- primaryKey: string[];
30
- estimatedRowCount?: number;
31
- }
32
-
33
- export interface SchemaInfo {
34
- tables: TableInfo[];
35
- updatedAt: string;
36
- }
37
-
38
- export interface QueryResult {
39
- rows: Record<string, unknown>[];
40
- hasMore: boolean;
41
- nextCursor: string | null;
42
- prevCursor: string | null;
43
- }
44
-
45
- export interface FilterConfig {
46
- column: string;
47
- operator: string;
48
- value: string;
49
- }
50
-
51
- export interface SortConfig {
52
- column: string;
53
- direction: 'asc' | 'desc';
54
- }
55
-
56
- // ============================================================================
57
- // Monitoring Types (from Telescope)
58
- // ============================================================================
59
-
60
- export interface RequestEntry {
61
- id: string;
62
- method: string;
63
- path: string;
64
- status: number;
65
- duration: number;
66
- timestamp: string;
67
- requestHeaders?: Record<string, string>;
68
- requestBody?: unknown;
69
- responseHeaders?: Record<string, string>;
70
- responseBody?: unknown;
71
- ip?: string;
72
- userAgent?: string;
73
- }
74
-
75
- export interface ExceptionEntry {
76
- id: string;
77
- name: string;
78
- message: string;
79
- stack: string;
80
- timestamp: string;
81
- context?: Record<string, unknown>;
82
- request?: {
83
- method: string;
84
- path: string;
85
- };
86
- }
87
-
88
- export interface LogEntry {
89
- id: string;
90
- level: string;
91
- message: string;
92
- timestamp: string;
93
- context?: Record<string, unknown>;
94
- requestId?: string;
95
- }
96
-
97
- export interface StudioStats {
98
- requests: number;
99
- exceptions: number;
100
- logs: number;
101
- }
102
-
103
- export type WebSocketMessage =
104
- | { type: 'request'; payload: RequestEntry }
105
- | { type: 'exception'; payload: ExceptionEntry }
106
- | { type: 'log'; payload: LogEntry }
107
- | { type: 'metrics'; payload: MetricsSnapshot };
108
-
109
- // ============================================================================
110
- // Metrics Types
111
- // ============================================================================
112
-
113
- export interface TimeSeriesPoint {
114
- timestamp: number;
115
- count: number;
116
- avgDuration: number;
117
- errorCount: number;
118
- }
119
-
120
- export interface RequestMetrics {
121
- totalRequests: number;
122
- avgDuration: number;
123
- p50Duration: number;
124
- p95Duration: number;
125
- p99Duration: number;
126
- errorRate: number;
127
- successRate: number;
128
- requestsPerSecond: number;
129
- timeSeries: TimeSeriesPoint[];
130
- }
131
-
132
- export interface EndpointMetrics {
133
- method: string;
134
- path: string;
135
- count: number;
136
- avgDuration: number;
137
- p95Duration: number;
138
- errorRate: number;
139
- lastSeen: number;
140
- }
141
-
142
- export interface EndpointDetails {
143
- method: string;
144
- path: string;
145
- count: number;
146
- avgDuration: number;
147
- p50Duration: number;
148
- p95Duration: number;
149
- p99Duration: number;
150
- errorRate: number;
151
- successRate: number;
152
- lastSeen: number;
153
- statusDistribution: StatusDistribution;
154
- timeSeries: TimeSeriesPoint[];
155
- }
156
-
157
- export interface StatusDistribution {
158
- '2xx': number;
159
- '3xx': number;
160
- '4xx': number;
161
- '5xx': number;
162
- }
163
-
164
- export interface MetricsSnapshot {
165
- timestamp: number;
166
- totalRequests: number;
167
- requestsPerSecond: number;
168
- avgDuration: number;
169
- errorRate: number;
170
- p50: number;
171
- p95: number;
172
- p99: number;
173
- statusDistribution: StatusDistribution;
174
- }
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />
package/ui/tsconfig.json DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "useDefineForClassFields": true,
5
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
- "module": "ESNext",
7
- "skipLibCheck": true,
8
- "moduleResolution": "bundler",
9
- "allowImportingTsExtensions": true,
10
- "isolatedModules": true,
11
- "moduleDetection": "force",
12
- "noEmit": true,
13
- "jsx": "react-jsx",
14
- "strict": true,
15
- "noUnusedLocals": true,
16
- "noUnusedParameters": true,
17
- "noFallthroughCasesInSwitch": true,
18
- "noUncheckedSideEffectImports": true
19
- },
20
- "include": ["src"]
21
- }
@@ -1 +0,0 @@
1
- {"root":["./src/app.tsx","./src/api.ts","./src/main.tsx","./src/types.ts","./src/vite-env.d.ts","./src/components/filterpanel.tsx","./src/components/navrail.tsx","./src/components/rowdetail.tsx","./src/components/studioheader.tsx","./src/components/tablelist.tsx","./src/components/tableview.tsx","./src/pages/dashboardpage.tsx","./src/pages/databasepage.tsx","./src/pages/endpointdetailspage.tsx","./src/pages/exceptionspage.tsx","./src/pages/logspage.tsx","./src/pages/monitoringpage.tsx","./src/pages/performancepage.tsx","./src/pages/requestspage.tsx","./src/providers/studioprovider.tsx"],"version":"5.8.2"}
package/ui/vite.config.ts DELETED
@@ -1,12 +0,0 @@
1
- import tailwindcss from '@tailwindcss/vite';
2
- import react from '@vitejs/plugin-react';
3
- import { defineConfig } from 'vite';
4
-
5
- export default defineConfig({
6
- plugins: [react(), tailwindcss()],
7
- base: '/__studio/',
8
- build: {
9
- outDir: '../dist/ui',
10
- emptyOutDir: true,
11
- },
12
- });