@getvision/core 0.0.1 → 0.0.2
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/index.js +5 -14
- package/dist/server/websocket.d.ts +0 -6
- package/dist/server/websocket.d.ts.map +1 -1
- package/dist/server/websocket.js +3 -117
- package/package.json +20 -8
- package/dist/__tests__/core.test.d.ts +0 -2
- package/dist/__tests__/core.test.d.ts.map +0 -1
- package/dist/__tests__/core.test.js +0 -88
- package/dist/__tests__/tracing.test.d.ts +0 -2
- package/dist/__tests__/tracing.test.d.ts.map +0 -1
- package/dist/__tests__/tracing.test.js +0 -108
- package/dist/ui/assets/index-5t7c-m29.js +0 -243
- package/dist/ui/assets/index-9ueE5-_1.js +0 -228
- package/dist/ui/assets/index-B2zDhd4y.js +0 -228
- package/dist/ui/assets/index-B6PCTRWI.js +0 -228
- package/dist/ui/assets/index-BAqOyMpS.js +0 -228
- package/dist/ui/assets/index-BBPymjIY.css +0 -1
- package/dist/ui/assets/index-BFZ9LDLI.js +0 -228
- package/dist/ui/assets/index-BK3A49yO.js +0 -243
- package/dist/ui/assets/index-BVC9j-JL.css +0 -1
- package/dist/ui/assets/index-BWzGTXsJ.js +0 -228
- package/dist/ui/assets/index-BZaQlF2p.js +0 -228
- package/dist/ui/assets/index-BbYLBWtj.css +0 -1
- package/dist/ui/assets/index-Bgf_12ju.js +0 -243
- package/dist/ui/assets/index-Bhxve5KF.css +0 -1
- package/dist/ui/assets/index-Bj-CWu-L.js +0 -228
- package/dist/ui/assets/index-BlJwGFyg.js +0 -243
- package/dist/ui/assets/index-BnD39P39.js +0 -228
- package/dist/ui/assets/index-C9X3l8Qf.js +0 -228
- package/dist/ui/assets/index-C9wDB-pp.js +0 -228
- package/dist/ui/assets/index-CAONCZtM.js +0 -243
- package/dist/ui/assets/index-CCtH3nj-.js +0 -243
- package/dist/ui/assets/index-CKzeeZJS.js +0 -228
- package/dist/ui/assets/index-Cctg6X14.js +0 -243
- package/dist/ui/assets/index-Ch3Kvj5x.js +0 -228
- package/dist/ui/assets/index-CkV-qXIH.css +0 -1
- package/dist/ui/assets/index-Cl2VKig8.js +0 -228
- package/dist/ui/assets/index-CoKjAtkW.css +0 -1
- package/dist/ui/assets/index-D4C4VyHp.css +0 -1
- package/dist/ui/assets/index-DHQw82rB.js +0 -228
- package/dist/ui/assets/index-DIfw1ZVL.css +0 -1
- package/dist/ui/assets/index-DJJX2zqa.js +0 -228
- package/dist/ui/assets/index-D_D2XkaS.js +0 -228
- package/dist/ui/assets/index-De-GZ9-w.js +0 -228
- package/dist/ui/assets/index-DoWtvKFs.js +0 -228
- package/dist/ui/assets/index-Dyseuj-Z.js +0 -223
- package/dist/ui/assets/index-ErxJEkTC.js +0 -243
- package/dist/ui/assets/index-HIUv_thh.css +0 -1
- package/dist/ui/assets/index-HhqjfP8c.js +0 -228
- package/dist/ui/assets/index-eUFXMYOK.js +0 -221
- package/dist/ui/assets/index-jabSppNC.js +0 -228
- package/dist/ui/assets/index-t88G2D4Q.js +0 -228
- package/dist/ui/assets/index-tl7-KOr9.css +0 -1
- package/dist/ui/assets/index-uyOJY0cv.js +0 -228
- package/dist/ui/assets/index-wmKPAJzR.js +0 -243
package/dist/server/websocket.js
CHANGED
|
@@ -63,125 +63,11 @@ export class VisionWebSocketServer {
|
|
|
63
63
|
const uiPath = getUIPath();
|
|
64
64
|
const served = await serveStatic(req, res, uiPath);
|
|
65
65
|
if (!served) {
|
|
66
|
-
//
|
|
67
|
-
res.writeHead(
|
|
68
|
-
res.end(
|
|
66
|
+
// No static UI available — return 404 (no legacy HTML fallback)
|
|
67
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
68
|
+
res.end('Vision Dashboard UI not found. Build the UI or ensure adapters are running.');
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Get embedded UI HTML
|
|
73
|
-
* For now, returns a simple page that connects to WebSocket
|
|
74
|
-
* In production, this would serve the built React app
|
|
75
|
-
*/
|
|
76
|
-
getEmbeddedUI() {
|
|
77
|
-
return `<!DOCTYPE html>
|
|
78
|
-
<html lang="en">
|
|
79
|
-
<head>
|
|
80
|
-
<meta charset="UTF-8">
|
|
81
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
82
|
-
<title>Vision Dashboard</title>
|
|
83
|
-
<style>
|
|
84
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
85
|
-
body {
|
|
86
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
87
|
-
background: #0a0a0a;
|
|
88
|
-
color: #fff;
|
|
89
|
-
display: flex;
|
|
90
|
-
align-items: center;
|
|
91
|
-
justify-content: center;
|
|
92
|
-
min-height: 100vh;
|
|
93
|
-
}
|
|
94
|
-
.container {
|
|
95
|
-
text-align: center;
|
|
96
|
-
max-width: 600px;
|
|
97
|
-
padding: 2rem;
|
|
98
|
-
}
|
|
99
|
-
h1 { font-size: 2.5rem; margin-bottom: 1rem; }
|
|
100
|
-
.status {
|
|
101
|
-
display: inline-flex;
|
|
102
|
-
align-items: center;
|
|
103
|
-
gap: 0.5rem;
|
|
104
|
-
padding: 0.5rem 1rem;
|
|
105
|
-
background: #1a1a1a;
|
|
106
|
-
border-radius: 8px;
|
|
107
|
-
margin: 1rem 0;
|
|
108
|
-
}
|
|
109
|
-
.dot {
|
|
110
|
-
width: 8px;
|
|
111
|
-
height: 8px;
|
|
112
|
-
border-radius: 50%;
|
|
113
|
-
background: #22c55e;
|
|
114
|
-
animation: pulse 2s infinite;
|
|
115
|
-
}
|
|
116
|
-
@keyframes pulse {
|
|
117
|
-
0%, 100% { opacity: 1; }
|
|
118
|
-
50% { opacity: 0.5; }
|
|
119
|
-
}
|
|
120
|
-
.info {
|
|
121
|
-
background: #1a1a1a;
|
|
122
|
-
border-radius: 8px;
|
|
123
|
-
padding: 1.5rem;
|
|
124
|
-
margin-top: 2rem;
|
|
125
|
-
text-align: left;
|
|
126
|
-
}
|
|
127
|
-
.info h2 { font-size: 1.2rem; margin-bottom: 1rem; }
|
|
128
|
-
.info p { color: #888; line-height: 1.6; margin-bottom: 0.5rem; }
|
|
129
|
-
code {
|
|
130
|
-
background: #0a0a0a;
|
|
131
|
-
padding: 0.2rem 0.4rem;
|
|
132
|
-
border-radius: 4px;
|
|
133
|
-
color: #22c55e;
|
|
134
|
-
font-family: 'Monaco', monospace;
|
|
135
|
-
}
|
|
136
|
-
a { color: #3b82f6; text-decoration: none; }
|
|
137
|
-
a:hover { text-decoration: underline; }
|
|
138
|
-
</style>
|
|
139
|
-
</head>
|
|
140
|
-
<body>
|
|
141
|
-
<div class="container">
|
|
142
|
-
<h1>🔮 Vision Dashboard</h1>
|
|
143
|
-
<div class="status">
|
|
144
|
-
<span class="dot"></span>
|
|
145
|
-
<span id="status">Connected to WebSocket</span>
|
|
146
|
-
</div>
|
|
147
|
-
|
|
148
|
-
<div class="info">
|
|
149
|
-
<h2>Dashboard UI Coming Soon!</h2>
|
|
150
|
-
<p>The Vision Dashboard backend is running and ready.</p>
|
|
151
|
-
<p>The React UI is currently in development. For now, you can:</p>
|
|
152
|
-
<ul style="margin-top: 1rem; padding-left: 1.5rem; color: #888;">
|
|
153
|
-
<li>Connect via WebSocket at <code>ws://${this.options.host}:${this.options.port}</code></li>
|
|
154
|
-
<li>Use JSON-RPC methods: <code>status</code>, <code>traces/list</code>, <code>routes/list</code></li>
|
|
155
|
-
<li>Watch traces in real-time as requests come in</li>
|
|
156
|
-
</ul>
|
|
157
|
-
<p style="margin-top: 1rem;">
|
|
158
|
-
See <a href="https://github.com/yourusername/vision" target="_blank">documentation</a> for more info.
|
|
159
|
-
</p>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
|
|
163
|
-
<script>
|
|
164
|
-
const ws = new WebSocket('ws://${this.options.host}:${this.options.port}');
|
|
165
|
-
const status = document.getElementById('status');
|
|
166
|
-
|
|
167
|
-
ws.onopen = () => {
|
|
168
|
-
status.textContent = 'Connected to WebSocket ✓';
|
|
169
|
-
console.log('🔮 Connected to Vision Dashboard');
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
ws.onclose = () => {
|
|
173
|
-
status.textContent = 'Disconnected';
|
|
174
|
-
status.style.color = '#ef4444';
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
ws.onmessage = (event) => {
|
|
178
|
-
const data = JSON.parse(event.data);
|
|
179
|
-
console.log('📨 Message:', data);
|
|
180
|
-
};
|
|
181
|
-
</script>
|
|
182
|
-
</body>
|
|
183
|
-
</html>`;
|
|
184
|
-
}
|
|
185
71
|
setupServer() {
|
|
186
72
|
// Start HTTP server
|
|
187
73
|
this.httpServer.listen(this.options.port, this.options.host, () => {
|
package/package.json
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getvision/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
|
-
".":
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"./server": {
|
|
11
|
+
"types": "./dist/server/index.d.ts",
|
|
12
|
+
"import": "./dist/server/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./tracing": {
|
|
15
|
+
"types": "./dist/tracing/index.d.ts",
|
|
16
|
+
"import": "./dist/tracing/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./types": {
|
|
19
|
+
"types": "./dist/types/index.d.ts",
|
|
20
|
+
"import": "./dist/types/index.js"
|
|
21
|
+
}
|
|
10
22
|
},
|
|
11
23
|
"scripts": {
|
|
12
24
|
"dev": "tsc --watch",
|
|
13
|
-
"build": "
|
|
25
|
+
"build": "tsc && bun build:ui",
|
|
14
26
|
"build:ui": "cd ../../apps/web && bun run build && mkdir -p ../../packages/core/dist/ui && cp -r dist/* ../../packages/core/dist/ui/",
|
|
15
27
|
"test": "bun test",
|
|
16
28
|
"test:watch": "bun test --watch",
|
|
@@ -32,8 +44,8 @@
|
|
|
32
44
|
},
|
|
33
45
|
"devDependencies": {
|
|
34
46
|
"zod": "^4.1.11",
|
|
35
|
-
"@repo/eslint-config": "0.0.
|
|
36
|
-
"@repo/typescript-config": "0.0.
|
|
47
|
+
"@repo/eslint-config": "0.0.1",
|
|
48
|
+
"@repo/typescript-config": "0.0.1",
|
|
37
49
|
"@types/mime-types": "^2.1.4",
|
|
38
50
|
"@types/node": "^20.14.9",
|
|
39
51
|
"@types/ws": "^8.5.12",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/core.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from 'bun:test';
|
|
2
|
-
import { VisionCore } from '../core';
|
|
3
|
-
describe('VisionCore (without server)', () => {
|
|
4
|
-
test('should create and complete trace', () => {
|
|
5
|
-
const vision = new VisionCore({
|
|
6
|
-
port: 0,
|
|
7
|
-
maxTraces: 100,
|
|
8
|
-
captureConsole: false
|
|
9
|
-
});
|
|
10
|
-
const trace = vision.createTrace('GET', '/test');
|
|
11
|
-
expect(trace).toBeDefined();
|
|
12
|
-
expect(trace.id).toBeDefined();
|
|
13
|
-
// Complete trace
|
|
14
|
-
vision.completeTrace(trace.id, 200, 50);
|
|
15
|
-
// Retrieve trace from store
|
|
16
|
-
const retrieved = vision.getTraceStore().getTrace(trace.id);
|
|
17
|
-
expect(retrieved).toBeDefined();
|
|
18
|
-
});
|
|
19
|
-
test('should use tracer', () => {
|
|
20
|
-
const vision = new VisionCore({ port: 0, captureConsole: false });
|
|
21
|
-
const tracer = vision.getTracer();
|
|
22
|
-
expect(tracer).toBeDefined();
|
|
23
|
-
});
|
|
24
|
-
test('should create span helper', () => {
|
|
25
|
-
const vision = new VisionCore({ port: 0, captureConsole: false });
|
|
26
|
-
const trace = vision.createTrace('GET', '/test');
|
|
27
|
-
const withSpan = vision.createSpanHelper(trace.id);
|
|
28
|
-
const result = withSpan('test.operation', { 'test.attr': 'value' }, () => {
|
|
29
|
-
return 'test result';
|
|
30
|
-
});
|
|
31
|
-
expect(result).toBe('test result');
|
|
32
|
-
// Check span was added
|
|
33
|
-
const retrieved = vision.getTraceStore().getTrace(trace.id);
|
|
34
|
-
expect(retrieved?.spans.length).toBeGreaterThan(0);
|
|
35
|
-
expect(retrieved?.spans[0].name).toBe('test.operation');
|
|
36
|
-
});
|
|
37
|
-
test('should handle errors in span helper', () => {
|
|
38
|
-
const vision = new VisionCore({ port: 0, captureConsole: false });
|
|
39
|
-
const trace = vision.createTrace('GET', '/test');
|
|
40
|
-
const withSpan = vision.createSpanHelper(trace.id);
|
|
41
|
-
expect(() => {
|
|
42
|
-
withSpan('test.error', {}, () => {
|
|
43
|
-
throw new Error('Test error');
|
|
44
|
-
});
|
|
45
|
-
}).toThrow('Test error');
|
|
46
|
-
// Check error was recorded in span
|
|
47
|
-
const retrieved = vision.getTraceStore().getTrace(trace.id);
|
|
48
|
-
const errorSpan = retrieved?.spans[0];
|
|
49
|
-
expect(errorSpan?.attributes?.error).toBe(true);
|
|
50
|
-
expect(errorSpan?.attributes?.['error.message']).toBe('Test error');
|
|
51
|
-
});
|
|
52
|
-
test('should register routes', () => {
|
|
53
|
-
const vision = new VisionCore({ port: 0, captureConsole: false });
|
|
54
|
-
const routes = [
|
|
55
|
-
{ method: 'GET', path: '/users', handler: 'getUsers' },
|
|
56
|
-
{ method: 'POST', path: '/users', handler: 'createUser' },
|
|
57
|
-
];
|
|
58
|
-
vision.registerRoutes(routes);
|
|
59
|
-
// Routes are registered, no easy way to verify without getter
|
|
60
|
-
expect(true).toBe(true);
|
|
61
|
-
});
|
|
62
|
-
test('should set app status', () => {
|
|
63
|
-
const vision = new VisionCore({ port: 0, captureConsole: false });
|
|
64
|
-
vision.setAppStatus({
|
|
65
|
-
name: 'Test App',
|
|
66
|
-
version: '1.0.0',
|
|
67
|
-
environment: 'test',
|
|
68
|
-
running: true,
|
|
69
|
-
});
|
|
70
|
-
expect(true).toBe(true);
|
|
71
|
-
});
|
|
72
|
-
test('should log messages', () => {
|
|
73
|
-
const vision = new VisionCore({ port: 0, captureConsole: false });
|
|
74
|
-
const entry = vision.log('info', 'Test log message', { key: 'value' });
|
|
75
|
-
expect(entry).toBeDefined();
|
|
76
|
-
expect(entry.level).toBe('info');
|
|
77
|
-
expect(entry.message).toBe('Test log message');
|
|
78
|
-
});
|
|
79
|
-
test('should broadcast events', () => {
|
|
80
|
-
const vision = new VisionCore({ port: 0, captureConsole: false });
|
|
81
|
-
// Just test that broadcast doesn't throw
|
|
82
|
-
vision.broadcast({
|
|
83
|
-
type: 'log.entry',
|
|
84
|
-
data: { id: "id", message: 'hello', level: "info", timestamp: Date.now() }
|
|
85
|
-
});
|
|
86
|
-
expect(true).toBe(true);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tracing.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tracing.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach } from 'bun:test';
|
|
2
|
-
import { TraceStore, Tracer } from '../tracing/index';
|
|
3
|
-
describe('TraceStore', () => {
|
|
4
|
-
let store;
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
store = new TraceStore(100);
|
|
7
|
-
});
|
|
8
|
-
test('should add trace', () => {
|
|
9
|
-
const trace = {
|
|
10
|
-
id: '123',
|
|
11
|
-
timestamp: Date.now(),
|
|
12
|
-
spans: [],
|
|
13
|
-
method: 'GET',
|
|
14
|
-
path: '/test',
|
|
15
|
-
metadata: {},
|
|
16
|
-
};
|
|
17
|
-
store.addTrace(trace);
|
|
18
|
-
const retrieved = store.getTrace('123');
|
|
19
|
-
expect(retrieved).toBeDefined();
|
|
20
|
-
expect(retrieved?.id).toBe('123');
|
|
21
|
-
expect(retrieved?.path).toBe('/test');
|
|
22
|
-
expect(retrieved?.method).toBe('GET');
|
|
23
|
-
});
|
|
24
|
-
test('should get traces with filters', () => {
|
|
25
|
-
const trace1 = {
|
|
26
|
-
id: '1',
|
|
27
|
-
method: 'GET',
|
|
28
|
-
path: '/users',
|
|
29
|
-
statusCode: 200,
|
|
30
|
-
timestamp: Date.now(),
|
|
31
|
-
spans: [],
|
|
32
|
-
metadata: {},
|
|
33
|
-
};
|
|
34
|
-
const trace2 = {
|
|
35
|
-
id: '2',
|
|
36
|
-
timestamp: Date.now(),
|
|
37
|
-
spans: [],
|
|
38
|
-
metadata: {},
|
|
39
|
-
method: 'POST',
|
|
40
|
-
path: '/users',
|
|
41
|
-
statusCode: 201
|
|
42
|
-
};
|
|
43
|
-
store.addTrace(trace1);
|
|
44
|
-
store.addTrace(trace2);
|
|
45
|
-
const getTraces = store.getTraces({ method: 'GET' });
|
|
46
|
-
expect(getTraces.length).toBe(1);
|
|
47
|
-
expect(getTraces[0].id).toBe('1');
|
|
48
|
-
const postTraces = store.getTraces({ method: 'POST' });
|
|
49
|
-
expect(postTraces.length).toBe(1);
|
|
50
|
-
expect(postTraces[0].id).toBe('2');
|
|
51
|
-
});
|
|
52
|
-
test('should limit number of traces', () => {
|
|
53
|
-
const smallStore = new TraceStore(2);
|
|
54
|
-
for (let i = 0; i < 5; i++) {
|
|
55
|
-
smallStore.addTrace({
|
|
56
|
-
id: `trace-${i}`,
|
|
57
|
-
timestamp: Date.now(),
|
|
58
|
-
method: "GET",
|
|
59
|
-
path: '/test',
|
|
60
|
-
spans: [],
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
const traces = smallStore.getAllTraces();
|
|
64
|
-
expect(traces.length).toBeLessThanOrEqual(2);
|
|
65
|
-
});
|
|
66
|
-
test('should clear all traces', () => {
|
|
67
|
-
store.addTrace({
|
|
68
|
-
id: '1',
|
|
69
|
-
timestamp: Date.now(),
|
|
70
|
-
method: "GET",
|
|
71
|
-
path: '/test',
|
|
72
|
-
spans: [],
|
|
73
|
-
});
|
|
74
|
-
store.clear();
|
|
75
|
-
const traces = store.getAllTraces();
|
|
76
|
-
expect(traces.length).toBe(0);
|
|
77
|
-
});
|
|
78
|
-
test('should filter by status code', () => {
|
|
79
|
-
store.addTrace({
|
|
80
|
-
id: '1',
|
|
81
|
-
timestamp: Date.now(),
|
|
82
|
-
spans: [],
|
|
83
|
-
method: "GET",
|
|
84
|
-
path: '/test',
|
|
85
|
-
statusCode: 200,
|
|
86
|
-
metadata: {},
|
|
87
|
-
});
|
|
88
|
-
store.addTrace({
|
|
89
|
-
id: '2',
|
|
90
|
-
timestamp: Date.now(),
|
|
91
|
-
spans: [],
|
|
92
|
-
method: "GET",
|
|
93
|
-
path: '/test2',
|
|
94
|
-
statusCode: 200,
|
|
95
|
-
metadata: {},
|
|
96
|
-
});
|
|
97
|
-
const successTraces = store.getTraces({ statusCode: 200 });
|
|
98
|
-
expect(successTraces.length).toBe(2);
|
|
99
|
-
expect(successTraces[0]?.statusCode).toBe(200);
|
|
100
|
-
expect(successTraces[1]?.statusCode).toBe(200);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
describe('Tracer', () => {
|
|
104
|
-
test('should create tracer instance', () => {
|
|
105
|
-
const tracer = new Tracer();
|
|
106
|
-
expect(tracer).toBeDefined();
|
|
107
|
-
});
|
|
108
|
-
});
|