@geekmidas/telescope 9.0.2 → 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 (128) hide show
  1. package/README.md +14 -4
  2. package/dist/{http-D5kn3_Mt.d.mts → http-DULM1u2L.d.cts} +3 -3
  3. package/dist/{http-Dvca6fC3.d.cts.map → http-DULM1u2L.d.cts.map} +1 -1
  4. package/dist/{http-Dvca6fC3.d.cts → http-GB-Nlvwc.d.mts} +3 -3
  5. package/dist/{http-D5kn3_Mt.d.mts.map → http-GB-Nlvwc.d.mts.map} +1 -1
  6. package/dist/instrumentation/http.d.cts +1 -1
  7. package/dist/instrumentation/http.d.mts +1 -1
  8. package/dist/instrumentation/index.cjs +2 -2
  9. package/dist/instrumentation/index.d.cts +3 -3
  10. package/dist/instrumentation/index.d.mts +3 -3
  11. package/dist/instrumentation/index.mjs +2 -2
  12. package/dist/instrumentation/middleware.cjs +1 -1
  13. package/dist/instrumentation/middleware.d.cts +1 -1
  14. package/dist/instrumentation/middleware.d.mts +1 -1
  15. package/dist/instrumentation/middleware.mjs +1 -1
  16. package/dist/instrumentation/otel.cjs +1 -1
  17. package/dist/instrumentation/otel.d.cts +1 -1
  18. package/dist/instrumentation/otel.d.mts +1 -1
  19. package/dist/instrumentation/otel.mjs +1 -1
  20. package/dist/logger/console.d.cts.map +1 -1
  21. package/dist/logger/console.d.mts.map +1 -1
  22. package/dist/logger/pino.d.cts +2 -2
  23. package/dist/{middleware-DqPQpcup.cjs → middleware-Bcq6XXGG.cjs} +2 -2
  24. package/dist/middleware-Bcq6XXGG.cjs.map +1 -0
  25. package/dist/{middleware-4-GrQlOT.mjs → middleware-D1XEHvyy.mjs} +2 -2
  26. package/dist/middleware-D1XEHvyy.mjs.map +1 -0
  27. package/dist/{middleware-CA84nsNN.d.cts → middleware-PeyS-9Ny.d.cts} +2 -2
  28. package/dist/{middleware-CA84nsNN.d.cts.map → middleware-PeyS-9Ny.d.cts.map} +1 -1
  29. package/dist/{middleware-DAceVpfw.d.mts → middleware-oHvo_ZgU.d.mts} +2 -2
  30. package/dist/{middleware-DAceVpfw.d.mts.map → middleware-oHvo_ZgU.d.mts.map} +1 -1
  31. package/dist/{otel-40udNP5g.mjs → otel-B9bNoeZ2.mjs} +3 -3
  32. package/dist/otel-B9bNoeZ2.mjs.map +1 -0
  33. package/dist/{otel-1bJPb2Z7.d.mts → otel-Bk89b1lX.d.cts} +3 -3
  34. package/dist/{otel-1bJPb2Z7.d.mts.map → otel-Bk89b1lX.d.cts.map} +1 -1
  35. package/dist/{otel-COrpz_GZ.cjs → otel-BzjOtVxZ.cjs} +3 -3
  36. package/dist/otel-BzjOtVxZ.cjs.map +1 -0
  37. package/dist/{otel-SBVoVEHr.d.cts → otel-lPMsM26e.d.mts} +3 -3
  38. package/dist/{otel-SBVoVEHr.d.cts.map → otel-lPMsM26e.d.mts.map} +1 -1
  39. package/dist/storage/kysely.cjs +48 -38
  40. package/dist/storage/kysely.cjs.map +1 -1
  41. package/dist/storage/kysely.d.cts +29 -9
  42. package/dist/storage/kysely.d.cts.map +1 -1
  43. package/dist/storage/kysely.d.mts +29 -9
  44. package/dist/storage/kysely.d.mts.map +1 -1
  45. package/dist/storage/kysely.mjs +48 -38
  46. package/dist/storage/kysely.mjs.map +1 -1
  47. package/dist/tracing-BX8uY2nR.d.cts.map +1 -1
  48. package/dist/types-B1EIa_cQ.d.mts.map +1 -1
  49. package/dist/types-l7Rlb5Mg.d.cts.map +1 -1
  50. package/package.json +6 -3
  51. package/CHANGELOG.md +0 -72
  52. package/dist/middleware-4-GrQlOT.mjs.map +0 -1
  53. package/dist/middleware-DqPQpcup.cjs.map +0 -1
  54. package/dist/otel-40udNP5g.mjs.map +0 -1
  55. package/dist/otel-COrpz_GZ.cjs.map +0 -1
  56. package/src/Telescope.ts +0 -561
  57. package/src/__tests__/Telescope.spec.ts +0 -438
  58. package/src/__tests__/pino-transport.spec.ts +0 -115
  59. package/src/__tests__/redact.spec.ts +0 -336
  60. package/src/adapters/__tests__/lambda.spec.ts +0 -318
  61. package/src/adapters/__tests__/middy.spec.ts +0 -741
  62. package/src/adapters/index.ts +0 -22
  63. package/src/adapters/lambda.ts +0 -432
  64. package/src/adapters/middy.ts +0 -402
  65. package/src/adapters/types.ts +0 -181
  66. package/src/core.ts +0 -51
  67. package/src/index.ts +0 -34
  68. package/src/instrumentation/__tests__/core.spec.ts +0 -248
  69. package/src/instrumentation/__tests__/hono.spec.ts +0 -348
  70. package/src/instrumentation/__tests__/middleware.spec.ts +0 -528
  71. package/src/instrumentation/__tests__/otel.spec.ts +0 -291
  72. package/src/instrumentation/__tests__/tracing.spec.ts +0 -208
  73. package/src/instrumentation/core.ts +0 -228
  74. package/src/instrumentation/hono.ts +0 -270
  75. package/src/instrumentation/http.ts +0 -306
  76. package/src/instrumentation/index.ts +0 -90
  77. package/src/instrumentation/middleware.ts +0 -297
  78. package/src/instrumentation/otel.ts +0 -271
  79. package/src/instrumentation/setup.ts +0 -246
  80. package/src/instrumentation/tracing.ts +0 -145
  81. package/src/logger/__tests__/console.spec.ts +0 -366
  82. package/src/logger/__tests__/pino.spec.ts +0 -217
  83. package/src/logger/console.ts +0 -230
  84. package/src/logger/pino.ts +0 -201
  85. package/src/metrics/MetricsAggregator.ts +0 -555
  86. package/src/metrics/__tests__/MetricsAggregator.spec.ts +0 -298
  87. package/src/metrics/index.ts +0 -2
  88. package/src/metrics/storage/InMemoryMetricsStorage.ts +0 -380
  89. package/src/metrics/storage/MetricsStorage.ts +0 -74
  90. package/src/metrics/storage/index.ts +0 -3
  91. package/src/metrics/storage/types.ts +0 -243
  92. package/src/otlp/__tests__/receiver.spec.ts +0 -367
  93. package/src/otlp/__tests__/transformer.spec.ts +0 -455
  94. package/src/otlp/hono.ts +0 -120
  95. package/src/otlp/index.ts +0 -22
  96. package/src/otlp/receiver.ts +0 -162
  97. package/src/otlp/transformer.ts +0 -367
  98. package/src/otlp/types.ts +0 -364
  99. package/src/redact.ts +0 -116
  100. package/src/server/__tests__/hono.spec.ts +0 -814
  101. package/src/server/hono.ts +0 -442
  102. package/src/storage/__tests__/kysely.spec.ts +0 -715
  103. package/src/storage/__tests__/memory.spec.ts +0 -694
  104. package/src/storage/kysely.ts +0 -599
  105. package/src/storage/memory.ts +0 -204
  106. package/src/types.ts +0 -447
  107. package/src/ui-assets.ts +0 -40
  108. package/tsconfig.json +0 -9
  109. package/ui/CHANGELOG.md +0 -7
  110. package/ui/index.html +0 -12
  111. package/ui/node_modules/.bin/tsc +0 -21
  112. package/ui/node_modules/.bin/tsserver +0 -21
  113. package/ui/node_modules/.bin/vite +0 -21
  114. package/ui/package.json +0 -24
  115. package/ui/src/App.tsx +0 -595
  116. package/ui/src/api.ts +0 -88
  117. package/ui/src/components/ExceptionDetail.tsx +0 -100
  118. package/ui/src/components/FilterBar.tsx +0 -162
  119. package/ui/src/components/LogDetail.tsx +0 -91
  120. package/ui/src/components/RequestDetail.tsx +0 -143
  121. package/ui/src/main.tsx +0 -10
  122. package/ui/src/styles.css +0 -11
  123. package/ui/src/types.ts +0 -63
  124. package/ui/src/vite-env.d.ts +0 -1
  125. package/ui/src/vite-plugin-gkm-config.ts +0 -54
  126. package/ui/tsconfig.json +0 -20
  127. package/ui/tsconfig.tsbuildinfo +0 -1
  128. package/ui/vite.config.ts +0 -13
@@ -1,100 +0,0 @@
1
- import type { ExceptionEntry } from '../types';
2
-
3
- interface ExceptionDetailProps {
4
- exception: ExceptionEntry;
5
- onClose: () => void;
6
- }
7
-
8
- export function ExceptionDetail({ exception, onClose }: ExceptionDetailProps) {
9
- return (
10
- <div className="fixed top-0 right-0 bottom-0 w-1/2 max-w-3xl bg-bg-secondary border-l border-border flex flex-col z-50 shadow-2xl">
11
- <div className="flex items-center justify-between p-4 border-b border-border">
12
- <h2 className="text-base font-semibold text-red-400">
13
- {exception.name}
14
- </h2>
15
- <button
16
- className="text-slate-400 hover:text-slate-100 p-2 text-xl leading-none"
17
- onClick={onClose}
18
- >
19
- &times;
20
- </button>
21
- </div>
22
-
23
- <div className="flex-1 overflow-y-auto p-4">
24
- <section className="mb-6">
25
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
26
- Overview
27
- </h3>
28
- <div className="space-y-2 text-sm">
29
- <div className="flex py-2 border-b border-border">
30
- <span className="text-slate-500 min-w-32">Message</span>
31
- <span className="wrap-break-word">{exception.message}</span>
32
- </div>
33
- <div className="flex py-2 border-b border-border">
34
- <span className="text-slate-500 min-w-32">Handled</span>
35
- <span>{exception.handled ? 'Yes' : 'No'}</span>
36
- </div>
37
- <div className="flex py-2 border-b border-border">
38
- <span className="text-slate-500 min-w-32">Timestamp</span>
39
- <span>{new Date(exception.timestamp).toLocaleString()}</span>
40
- </div>
41
- {exception.requestId && (
42
- <div className="flex py-2 border-b border-border">
43
- <span className="text-slate-500 min-w-32">Request ID</span>
44
- <span className="font-mono text-xs">{exception.requestId}</span>
45
- </div>
46
- )}
47
- {exception.tags && exception.tags.length > 0 && (
48
- <div className="flex py-2">
49
- <span className="text-slate-500 min-w-32">Tags</span>
50
- <span>{exception.tags.join(', ')}</span>
51
- </div>
52
- )}
53
- </div>
54
- </section>
55
-
56
- {exception.source && (
57
- <section className="mb-6">
58
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
59
- Source
60
- </h3>
61
- <div className="text-sm mb-2">
62
- <span className="text-slate-500">File: </span>
63
- <span>
64
- {exception.source.file}
65
- {exception.source.line && `:${exception.source.line}`}
66
- </span>
67
- </div>
68
- {exception.source.code && (
69
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed">
70
- {exception.source.code}
71
- </pre>
72
- )}
73
- </section>
74
- )}
75
-
76
- <section className="mb-6">
77
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
78
- Stack Trace
79
- </h3>
80
- <div className="text-xs leading-relaxed space-y-1">
81
- {exception.stack.map((frame, index) => (
82
- <div key={index} className="text-slate-400">
83
- <span className="text-blue-400">
84
- {frame.function || '<anonymous>'}
85
- </span>
86
- {frame.file && (
87
- <span className="text-slate-500 ml-2">
88
- at {frame.file}
89
- {frame.line !== undefined && `:${frame.line}`}
90
- {frame.column !== undefined && `:${frame.column}`}
91
- </span>
92
- )}
93
- </div>
94
- ))}
95
- </div>
96
- </section>
97
- </div>
98
- </div>
99
- );
100
- }
@@ -1,162 +0,0 @@
1
- import type { Tab } from '../types';
2
-
3
- export interface RequestFilters {
4
- search: string;
5
- method: string;
6
- status: string;
7
- }
8
-
9
- export interface LogFilters {
10
- search: string;
11
- level: string;
12
- }
13
-
14
- export interface ExceptionFilters {
15
- search: string;
16
- }
17
-
18
- interface FilterBarProps {
19
- tab: Tab;
20
- requestFilters: RequestFilters;
21
- logFilters: LogFilters;
22
- exceptionFilters: ExceptionFilters;
23
- onRequestFiltersChange: (filters: RequestFilters) => void;
24
- onLogFiltersChange: (filters: LogFilters) => void;
25
- onExceptionFiltersChange: (filters: ExceptionFilters) => void;
26
- onClear: () => void;
27
- }
28
-
29
- const HTTP_METHODS = ['', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
30
- const STATUS_RANGES = [
31
- { value: '', label: 'All Status' },
32
- { value: '2xx', label: '2xx Success' },
33
- { value: '3xx', label: '3xx Redirect' },
34
- { value: '4xx', label: '4xx Client Error' },
35
- { value: '5xx', label: '5xx Server Error' },
36
- ];
37
- const LOG_LEVELS = ['', 'debug', 'info', 'warn', 'error'];
38
-
39
- export function FilterBar({
40
- tab,
41
- requestFilters,
42
- logFilters,
43
- exceptionFilters,
44
- onRequestFiltersChange,
45
- onLogFiltersChange,
46
- onExceptionFiltersChange,
47
- onClear,
48
- }: FilterBarProps) {
49
- const hasActiveFilters =
50
- (tab === 'requests' &&
51
- (requestFilters.search ||
52
- requestFilters.method ||
53
- requestFilters.status)) ||
54
- (tab === 'logs' && (logFilters.search || logFilters.level)) ||
55
- (tab === 'exceptions' && exceptionFilters.search);
56
-
57
- return (
58
- <div className="bg-bg-secondary border-b border-border px-4 py-3 flex items-center gap-3">
59
- {tab === 'requests' && (
60
- <>
61
- <input
62
- type="text"
63
- placeholder="Search path..."
64
- value={requestFilters.search}
65
- onChange={(e) =>
66
- onRequestFiltersChange({
67
- ...requestFilters,
68
- search: e.target.value,
69
- })
70
- }
71
- className="bg-bg-tertiary border border-border rounded px-3 py-1.5 text-sm text-slate-100 placeholder-slate-500 focus:outline-none focus:border-blue-500 w-64"
72
- />
73
- <select
74
- value={requestFilters.method}
75
- onChange={(e) =>
76
- onRequestFiltersChange({
77
- ...requestFilters,
78
- method: e.target.value,
79
- })
80
- }
81
- className="bg-bg-tertiary border border-border rounded px-3 py-1.5 text-sm text-slate-100 focus:outline-none focus:border-blue-500"
82
- >
83
- <option value="">All Methods</option>
84
- {HTTP_METHODS.filter(Boolean).map((method) => (
85
- <option key={method} value={method}>
86
- {method}
87
- </option>
88
- ))}
89
- </select>
90
- <select
91
- value={requestFilters.status}
92
- onChange={(e) =>
93
- onRequestFiltersChange({
94
- ...requestFilters,
95
- status: e.target.value,
96
- })
97
- }
98
- className="bg-bg-tertiary border border-border rounded px-3 py-1.5 text-sm text-slate-100 focus:outline-none focus:border-blue-500"
99
- >
100
- {STATUS_RANGES.map((range) => (
101
- <option key={range.value} value={range.value}>
102
- {range.label}
103
- </option>
104
- ))}
105
- </select>
106
- </>
107
- )}
108
-
109
- {tab === 'logs' && (
110
- <>
111
- <input
112
- type="text"
113
- placeholder="Search message..."
114
- value={logFilters.search}
115
- onChange={(e) =>
116
- onLogFiltersChange({ ...logFilters, search: e.target.value })
117
- }
118
- className="bg-bg-tertiary border border-border rounded px-3 py-1.5 text-sm text-slate-100 placeholder-slate-500 focus:outline-none focus:border-blue-500 w-64"
119
- />
120
- <select
121
- value={logFilters.level}
122
- onChange={(e) =>
123
- onLogFiltersChange({ ...logFilters, level: e.target.value })
124
- }
125
- className="bg-bg-tertiary border border-border rounded px-3 py-1.5 text-sm text-slate-100 focus:outline-none focus:border-blue-500"
126
- >
127
- <option value="">All Levels</option>
128
- {LOG_LEVELS.filter(Boolean).map((level) => (
129
- <option key={level} value={level}>
130
- {level}
131
- </option>
132
- ))}
133
- </select>
134
- </>
135
- )}
136
-
137
- {tab === 'exceptions' && (
138
- <input
139
- type="text"
140
- placeholder="Search exception..."
141
- value={exceptionFilters.search}
142
- onChange={(e) =>
143
- onExceptionFiltersChange({
144
- ...exceptionFilters,
145
- search: e.target.value,
146
- })
147
- }
148
- className="bg-bg-tertiary border border-border rounded px-3 py-1.5 text-sm text-slate-100 placeholder-slate-500 focus:outline-none focus:border-blue-500 w-64"
149
- />
150
- )}
151
-
152
- {hasActiveFilters && (
153
- <button
154
- onClick={onClear}
155
- className="text-xs text-slate-400 hover:text-slate-200 px-2 py-1 rounded hover:bg-bg-tertiary transition-colors"
156
- >
157
- Clear filters
158
- </button>
159
- )}
160
- </div>
161
- );
162
- }
@@ -1,91 +0,0 @@
1
- import type { LogEntry } from '../types';
2
-
3
- interface LogDetailProps {
4
- log: LogEntry;
5
- onClose: () => void;
6
- }
7
-
8
- export function LogDetail({ log, onClose }: LogDetailProps) {
9
- const formatJson = (data: unknown) => {
10
- try {
11
- return JSON.stringify(data, null, 2);
12
- } catch {
13
- return String(data);
14
- }
15
- };
16
-
17
- const getLogLevelColor = (level: string) => {
18
- const colors: Record<string, string> = {
19
- debug: 'bg-slate-500/20 text-slate-400',
20
- info: 'bg-blue-500/20 text-blue-400',
21
- warn: 'bg-amber-500/20 text-amber-400',
22
- error: 'bg-red-500/20 text-red-400',
23
- };
24
- return colors[level] || 'bg-slate-500/20 text-slate-400';
25
- };
26
-
27
- return (
28
- <div className="fixed top-0 right-0 bottom-0 w-1/2 max-w-3xl bg-bg-secondary border-l border-border flex flex-col z-50 shadow-2xl">
29
- <div className="flex items-center justify-between p-4 border-b border-border">
30
- <h2 className="text-base font-semibold flex items-center gap-2">
31
- <span
32
- className={`px-2 py-1 rounded text-xs ${getLogLevelColor(log.level)}`}
33
- >
34
- {log.level}
35
- </span>
36
- Log Entry
37
- </h2>
38
- <button
39
- className="text-slate-400 hover:text-slate-100 p-2 text-xl leading-none"
40
- onClick={onClose}
41
- >
42
- &times;
43
- </button>
44
- </div>
45
-
46
- <div className="flex-1 overflow-y-auto p-4">
47
- <section className="mb-6">
48
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
49
- Overview
50
- </h3>
51
- <div className="space-y-2 text-sm">
52
- <div className="flex py-2 border-b border-border">
53
- <span className="text-slate-500 min-w-32">Level</span>
54
- <span>{log.level}</span>
55
- </div>
56
- <div className="flex py-2 border-b border-border">
57
- <span className="text-slate-500 min-w-32">Timestamp</span>
58
- <span>{new Date(log.timestamp).toLocaleString()}</span>
59
- </div>
60
- {log.requestId && (
61
- <div className="flex py-2">
62
- <span className="text-slate-500 min-w-32">Request ID</span>
63
- <span className="font-mono text-xs">{log.requestId}</span>
64
- </div>
65
- )}
66
- </div>
67
- </section>
68
-
69
- <section className="mb-6">
70
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
71
- Message
72
- </h3>
73
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed whitespace-pre-wrap">
74
- {log.message}
75
- </pre>
76
- </section>
77
-
78
- {log.context && Object.keys(log.context).length > 0 && (
79
- <section className="mb-6">
80
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
81
- Context
82
- </h3>
83
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed">
84
- {formatJson(log.context)}
85
- </pre>
86
- </section>
87
- )}
88
- </div>
89
- </div>
90
- );
91
- }
@@ -1,143 +0,0 @@
1
- import type { RequestEntry } from '../types';
2
-
3
- interface RequestDetailProps {
4
- request: RequestEntry;
5
- onClose: () => void;
6
- }
7
-
8
- export function RequestDetail({ request, onClose }: RequestDetailProps) {
9
- const formatJson = (data: unknown) => {
10
- try {
11
- return JSON.stringify(data, null, 2);
12
- } catch {
13
- return String(data);
14
- }
15
- };
16
-
17
- const getMethodColor = (method: string) => {
18
- const colors: Record<string, string> = {
19
- GET: 'bg-green-500/20 text-green-400',
20
- POST: 'bg-blue-500/20 text-blue-400',
21
- PUT: 'bg-amber-500/20 text-amber-400',
22
- PATCH: 'bg-purple-500/20 text-purple-400',
23
- DELETE: 'bg-red-500/20 text-red-400',
24
- };
25
- return colors[method] || 'bg-slate-500/20 text-slate-400';
26
- };
27
-
28
- return (
29
- <div className="fixed top-0 right-0 bottom-0 w-1/2 max-w-3xl bg-bg-secondary border-l border-border flex flex-col z-50 shadow-2xl">
30
- <div className="flex items-center justify-between p-4 border-b border-border">
31
- <h2 className="text-base font-semibold flex items-center gap-2">
32
- <span
33
- className={`px-2 py-1 rounded text-xs ${getMethodColor(request.method)}`}
34
- >
35
- {request.method}
36
- </span>
37
- <span className="truncate">{request.path}</span>
38
- </h2>
39
- <button
40
- className="text-slate-400 hover:text-slate-100 p-2 text-xl leading-none"
41
- onClick={onClose}
42
- >
43
- &times;
44
- </button>
45
- </div>
46
-
47
- <div className="flex-1 overflow-y-auto p-4">
48
- <section className="mb-6">
49
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
50
- Overview
51
- </h3>
52
- <div className="space-y-2 text-sm">
53
- <div className="flex py-2 border-b border-border">
54
- <span className="text-slate-500 min-w-32">Status</span>
55
- <span>{request.status}</span>
56
- </div>
57
- <div className="flex py-2 border-b border-border">
58
- <span className="text-slate-500 min-w-32">Duration</span>
59
- <span>{request.duration.toFixed(2)}ms</span>
60
- </div>
61
- <div className="flex py-2 border-b border-border">
62
- <span className="text-slate-500 min-w-32">URL</span>
63
- <span className="break-all">{request.url}</span>
64
- </div>
65
- <div className="flex py-2 border-b border-border">
66
- <span className="text-slate-500 min-w-32">Timestamp</span>
67
- <span>{new Date(request.timestamp).toLocaleString()}</span>
68
- </div>
69
- {request.ip && (
70
- <div className="flex py-2 border-b border-border">
71
- <span className="text-slate-500 min-w-32">IP</span>
72
- <span>{request.ip}</span>
73
- </div>
74
- )}
75
- {request.userId && (
76
- <div className="flex py-2 border-b border-border">
77
- <span className="text-slate-500 min-w-32">User ID</span>
78
- <span>{request.userId}</span>
79
- </div>
80
- )}
81
- {request.tags && request.tags.length > 0 && (
82
- <div className="flex py-2">
83
- <span className="text-slate-500 min-w-32">Tags</span>
84
- <span>{request.tags.join(', ')}</span>
85
- </div>
86
- )}
87
- </div>
88
- </section>
89
-
90
- <section className="mb-6">
91
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
92
- Request Headers
93
- </h3>
94
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed">
95
- {formatJson(request.headers)}
96
- </pre>
97
- </section>
98
-
99
- {request.query && Object.keys(request.query).length > 0 && (
100
- <section className="mb-6">
101
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
102
- Query Parameters
103
- </h3>
104
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed">
105
- {formatJson(request.query)}
106
- </pre>
107
- </section>
108
- )}
109
-
110
- {request.body !== undefined && (
111
- <section className="mb-6">
112
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
113
- Request Body
114
- </h3>
115
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed">
116
- {formatJson(request.body)}
117
- </pre>
118
- </section>
119
- )}
120
-
121
- <section className="mb-6">
122
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
123
- Response Headers
124
- </h3>
125
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed">
126
- {formatJson(request.responseHeaders)}
127
- </pre>
128
- </section>
129
-
130
- {request.responseBody !== undefined && (
131
- <section className="mb-6">
132
- <h3 className="text-xs font-semibold uppercase text-slate-500 mb-2">
133
- Response Body
134
- </h3>
135
- <pre className="bg-bg-primary border border-border rounded-lg p-4 overflow-x-auto text-xs leading-relaxed">
136
- {formatJson(request.responseBody)}
137
- </pre>
138
- </section>
139
- )}
140
- </div>
141
- </div>
142
- );
143
- }
package/ui/src/main.tsx DELETED
@@ -1,10 +0,0 @@
1
- import { StrictMode } from 'react';
2
- import { createRoot } from 'react-dom/client';
3
- import { App } from './App';
4
- import './styles.css';
5
-
6
- createRoot(document.getElementById('root')!).render(
7
- <StrictMode>
8
- <App />
9
- </StrictMode>,
10
- );
package/ui/src/styles.css DELETED
@@ -1,11 +0,0 @@
1
- @import "tailwindcss";
2
-
3
- @theme {
4
- --color-bg-primary: #0f172a;
5
- --color-bg-secondary: #1e293b;
6
- --color-bg-tertiary: #334155;
7
- --color-border: #334155;
8
- --font-family-mono:
9
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono",
10
- monospace;
11
- }
package/ui/src/types.ts DELETED
@@ -1,63 +0,0 @@
1
- export interface RequestEntry {
2
- id: string;
3
- method: string;
4
- path: string;
5
- url: string;
6
- headers: Record<string, string>;
7
- body?: unknown;
8
- query?: Record<string, string>;
9
- status: number;
10
- responseHeaders: Record<string, string>;
11
- responseBody?: unknown;
12
- duration: number;
13
- timestamp: string;
14
- ip?: string;
15
- userId?: string;
16
- tags?: string[];
17
- }
18
-
19
- export interface ExceptionEntry {
20
- id: string;
21
- name: string;
22
- message: string;
23
- stack: Array<{
24
- file?: string;
25
- line?: number;
26
- column?: number;
27
- function?: string;
28
- }>;
29
- source?: {
30
- file?: string;
31
- line?: number;
32
- code?: string;
33
- };
34
- requestId?: string;
35
- timestamp: string;
36
- handled: boolean;
37
- tags?: string[];
38
- }
39
-
40
- export interface LogEntry {
41
- id: string;
42
- level: 'debug' | 'info' | 'warn' | 'error';
43
- message: string;
44
- context?: Record<string, unknown>;
45
- requestId?: string;
46
- timestamp: string;
47
- }
48
-
49
- export interface TelescopeStats {
50
- requests: number;
51
- exceptions: number;
52
- logs: number;
53
- oldestEntry?: string;
54
- newestEntry?: string;
55
- }
56
-
57
- export type Tab = 'requests' | 'exceptions' | 'logs';
58
-
59
- export interface WebSocketMessage {
60
- type: 'request' | 'exception' | 'log' | 'connected';
61
- payload: unknown;
62
- timestamp: number;
63
- }
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />
@@ -1,54 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
- import type { Plugin } from 'vite';
4
-
5
- interface GkmConfig {
6
- server?: boolean | { port?: number };
7
- telescope?: { port?: number };
8
- }
9
-
10
- /**
11
- * Vite plugin that reads configuration from gkm.config.ts
12
- * to configure the dev server proxy.
13
- */
14
- export function gkmConfigPlugin(): Plugin {
15
- let serverPort = 3000;
16
-
17
- return {
18
- name: 'gkm-config',
19
- async config() {
20
- const cwd = process.cwd();
21
- const configPath = resolve(cwd, 'gkm.config.ts');
22
-
23
- if (existsSync(configPath)) {
24
- try {
25
- const config = (await import(configPath)).default as GkmConfig;
26
-
27
- // Check for telescope.port first, then server.port
28
- if (config.telescope?.port) {
29
- serverPort = config.telescope.port;
30
- } else if (typeof config.server === 'object' && config.server.port) {
31
- serverPort = config.server.port;
32
- }
33
- } catch {
34
- // Silently fall back to default port
35
- }
36
- }
37
-
38
- return {
39
- server: {
40
- proxy: {
41
- '/__telescope/api': {
42
- target: `http://localhost:${serverPort}`,
43
- changeOrigin: true,
44
- },
45
- '/__telescope/ws': {
46
- target: `ws://localhost:${serverPort}`,
47
- ws: true,
48
- },
49
- },
50
- },
51
- };
52
- },
53
- };
54
- }
package/ui/tsconfig.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
- "module": "ESNext",
6
- "skipLibCheck": true,
7
- "moduleResolution": "bundler",
8
- "allowImportingTsExtensions": true,
9
- "isolatedModules": true,
10
- "moduleDetection": "force",
11
- "noEmit": true,
12
- "jsx": "react-jsx",
13
- "strict": true,
14
- "noUnusedLocals": true,
15
- "noUnusedParameters": true,
16
- "noFallthroughCasesInSwitch": true,
17
- "noUncheckedSideEffectImports": true
18
- },
19
- "include": ["src"]
20
- }
@@ -1 +0,0 @@
1
- {"root":["./src/app.tsx","./src/api.ts","./src/main.tsx","./src/types.ts","./src/vite-env.d.ts","./src/vite-plugin-gkm-config.ts","./src/components/exceptiondetail.tsx","./src/components/filterbar.tsx","./src/components/logdetail.tsx","./src/components/requestdetail.tsx"],"version":"5.8.2"}
package/ui/vite.config.ts DELETED
@@ -1,13 +0,0 @@
1
- import tailwindcss from '@tailwindcss/vite';
2
- import react from '@vitejs/plugin-react';
3
- import { defineConfig } from 'vite';
4
- import { gkmConfigPlugin } from './src/vite-plugin-gkm-config';
5
-
6
- export default defineConfig({
7
- plugins: [react(), tailwindcss(), gkmConfigPlugin()],
8
- base: '/__telescope/',
9
- build: {
10
- outDir: '../dist/ui',
11
- emptyOutDir: true,
12
- },
13
- });