jsgui3-server 0.0.138 → 0.0.140
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/AGENTS.md +87 -0
- package/README.md +12 -0
- package/docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md +19 -0
- package/docs/advanced-usage-examples.md +1360 -0
- package/docs/agent-development-guide.md +386 -0
- package/docs/api-reference.md +916 -0
- package/docs/broken-functionality-tracker.md +285 -0
- package/docs/bundling-system-deep-dive.md +525 -0
- package/docs/cli-reference.md +393 -0
- package/docs/comprehensive-documentation.md +1403 -0
- package/docs/configuration-reference.md +808 -0
- package/docs/controls-development.md +859 -0
- package/docs/documentation-review/CURRENT_REVIEW.md +95 -0
- package/docs/function-publishers-json-apis.md +847 -0
- package/docs/getting-started-with-json.md +518 -0
- package/docs/minification-compression-sourcemaps-status.md +482 -0
- package/docs/minification-compression-sourcemaps-test-results.md +205 -0
- package/docs/publishers-guide.md +313 -0
- package/docs/resources-guide.md +615 -0
- package/docs/serve-helpers.md +406 -0
- package/docs/simple-server-api-design.md +13 -0
- package/docs/system-architecture.md +275 -0
- package/docs/troubleshooting.md +698 -0
- package/examples/json/README.md +115 -0
- package/examples/json/basic-api/README.md +345 -0
- package/examples/json/basic-api/server.js +199 -0
- package/examples/json/simple-api/README.md +125 -0
- package/examples/json/simple-api/diagnostic-report.json +73 -0
- package/examples/json/simple-api/diagnostic-test.js +433 -0
- package/examples/json/simple-api/server-debug.md +58 -0
- package/examples/json/simple-api/server.js +91 -0
- package/examples/json/simple-api/test.js +215 -0
- package/http/responders/static/Static_Route_HTTP_Responder.js +1 -2
- package/package.json +19 -8
- package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +65 -12
- package/publishers/helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer.js +6 -1
- package/publishers/http-function-publisher.js +59 -38
- package/publishers/http-webpage-publisher.js +48 -1
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +38 -146
- package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +54 -5
- package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +36 -4
- package/serve-factory.js +36 -9
- package/server.js +10 -4
- package/test-report.json +0 -0
- package/tests/README.md +250 -0
- package/tests/assigners.test.js +316 -0
- package/tests/bundlers.test.js +329 -0
- package/tests/configuration-validation.test.js +530 -0
- package/tests/content-analysis.test.js +641 -0
- package/tests/end-to-end.test.js +496 -0
- package/tests/error-handling.test.js +746 -0
- package/tests/performance.test.js +653 -0
- package/tests/publishers.test.js +395 -0
- package/tests/temp_invalid.js +7 -0
- package/tests/temp_invalid_utf8.js +1 -0
- package/tests/temp_malformed.js +10 -0
- package/tests/test-runner.js +261 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Simple JSON API Example
|
|
2
|
+
|
|
3
|
+
This is the simplest possible JSON API server using JSGUI3 Server. It demonstrates basic CRUD operations with minimal code.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Minimal code**: ~70 lines total
|
|
8
|
+
- ✅ **4 API endpoints**: GET status, GET messages, POST add message, POST clear messages
|
|
9
|
+
- ✅ **Data validation**: Input checking with error handling
|
|
10
|
+
- ✅ **In-memory storage**: Simple data persistence
|
|
11
|
+
- ✅ **No UI components**: Pure JSON API server
|
|
12
|
+
|
|
13
|
+
## API Endpoints
|
|
14
|
+
|
|
15
|
+
### `GET /api/status`
|
|
16
|
+
Returns server status information.
|
|
17
|
+
|
|
18
|
+
**Response:**
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"status": "running",
|
|
22
|
+
"timestamp": "2025-11-02T01:48:00.000Z",
|
|
23
|
+
"version": "1.0.0",
|
|
24
|
+
"uptime": 123.456
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### `GET /api/messages`
|
|
29
|
+
Returns all messages with count.
|
|
30
|
+
|
|
31
|
+
**Response:**
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"messages": [
|
|
35
|
+
{
|
|
36
|
+
"id": 1,
|
|
37
|
+
"text": "Hello, World!",
|
|
38
|
+
"author": "System",
|
|
39
|
+
"timestamp": "2025-11-02T01:48:00.000Z"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"count": 1
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `POST /api/add-message`
|
|
47
|
+
Adds a new message.
|
|
48
|
+
|
|
49
|
+
**Request Body:**
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"text": "Your message here",
|
|
53
|
+
"author": "Your Name"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Response:**
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"success": true,
|
|
61
|
+
"message": {
|
|
62
|
+
"id": 3,
|
|
63
|
+
"text": "Your message here",
|
|
64
|
+
"author": "Your Name",
|
|
65
|
+
"timestamp": "2025-11-02T01:48:00.000Z"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### `POST /api/clear-messages`
|
|
71
|
+
Clears all messages.
|
|
72
|
+
|
|
73
|
+
**Response:**
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"success": true,
|
|
77
|
+
"clearedCount": 2,
|
|
78
|
+
"message": "Cleared 2 messages"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Running
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
cd examples/json/simple-api
|
|
86
|
+
node server.js
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Testing
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Get server status
|
|
93
|
+
curl http://localhost:3002/api/status
|
|
94
|
+
|
|
95
|
+
# Get messages
|
|
96
|
+
curl http://localhost:3002/api/messages
|
|
97
|
+
|
|
98
|
+
# Add a message
|
|
99
|
+
curl -X POST http://localhost:3002/api/add-message \
|
|
100
|
+
-H "Content-Type: application/json" \
|
|
101
|
+
-d '{"text":"Hello from curl!","author":"Tester"}'
|
|
102
|
+
|
|
103
|
+
# Clear all messages
|
|
104
|
+
curl -X POST http://localhost:3002/api/clear-messages \
|
|
105
|
+
-H "Content-Type: application/json" \
|
|
106
|
+
-d '{}'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Code Structure
|
|
110
|
+
|
|
111
|
+
The entire server is in `server.js`:
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
Server.serve({
|
|
115
|
+
api: {
|
|
116
|
+
'status': () => ({ /* status data */ }),
|
|
117
|
+
'messages': () => ({ /* messages data */ }),
|
|
118
|
+
'add-message': (data) => ({ /* add logic */ }),
|
|
119
|
+
'clear-messages': () => ({ /* clear logic */ })
|
|
120
|
+
},
|
|
121
|
+
port: 3002
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
This demonstrates the absolute minimum code needed for a working JSON API server.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"timestamp": "2025-11-02T03:33:18.682Z",
|
|
3
|
+
"tests": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Module Loading - Server",
|
|
6
|
+
"status": "passed",
|
|
7
|
+
"timestamp": "2025-11-02T03:33:19.335Z"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"name": "Module Loading - Server.serve",
|
|
11
|
+
"status": "passed",
|
|
12
|
+
"timestamp": "2025-11-02T03:33:19.336Z"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "Module Loading - serve-factory",
|
|
16
|
+
"status": "passed",
|
|
17
|
+
"timestamp": "2025-11-02T03:33:19.336Z"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "Server Construction - Instance Creation",
|
|
21
|
+
"status": "passed",
|
|
22
|
+
"timestamp": "2025-11-02T03:33:19.342Z"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "Server Construction - Resource Pool",
|
|
26
|
+
"status": "passed",
|
|
27
|
+
"timestamp": "2025-11-02T03:33:19.343Z"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "Server Construction - Router",
|
|
31
|
+
"status": "passed",
|
|
32
|
+
"timestamp": "2025-11-02T03:33:19.343Z"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "Server Construction - Publish Method",
|
|
36
|
+
"status": "passed",
|
|
37
|
+
"timestamp": "2025-11-02T03:33:19.343Z"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "API Setup - Publishing Endpoints",
|
|
41
|
+
"status": "passed",
|
|
42
|
+
"timestamp": "2025-11-02T03:33:19.346Z"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "API Setup - Router Access",
|
|
46
|
+
"status": "passed",
|
|
47
|
+
"timestamp": "2025-11-02T03:33:19.346Z"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "HTTP Serving - Server Start",
|
|
51
|
+
"status": "passed",
|
|
52
|
+
"timestamp": "2025-11-02T03:33:19.370Z"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "HTTP Serving - API Response",
|
|
56
|
+
"status": "passed",
|
|
57
|
+
"timestamp": "2025-11-02T03:33:20.396Z"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "End-to-End - Server Startup",
|
|
61
|
+
"status": "failed",
|
|
62
|
+
"timestamp": "2025-11-02T03:33:35.422Z",
|
|
63
|
+
"error": "Server startup timeout"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"summary": {
|
|
67
|
+
"total": 12,
|
|
68
|
+
"passed": 11,
|
|
69
|
+
"failed": 1,
|
|
70
|
+
"errors": [],
|
|
71
|
+
"successRate": "91.7%"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
// Comprehensive Diagnostic Test System for JSON API Server
|
|
2
|
+
// Tests each component individually to pinpoint failures
|
|
3
|
+
|
|
4
|
+
const { spawn } = require('child_process');
|
|
5
|
+
const http = require('http');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
class DiagnosticTestSystem {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.results = {
|
|
12
|
+
timestamp: new Date(),
|
|
13
|
+
tests: [],
|
|
14
|
+
summary: {
|
|
15
|
+
total: 0,
|
|
16
|
+
passed: 0,
|
|
17
|
+
failed: 0,
|
|
18
|
+
errors: []
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
this.serverProcess = null;
|
|
22
|
+
this.testPort = 3003; // Different port to avoid conflicts
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
log(message, level = 'info') {
|
|
26
|
+
const timestamp = new Date().toISOString();
|
|
27
|
+
const prefix = level === 'error' ? '❌' : level === 'success' ? '✅' : '🔍';
|
|
28
|
+
console.log(`[${timestamp}] ${prefix} ${message}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
recordTest(name, status, details = {}) {
|
|
32
|
+
const test = {
|
|
33
|
+
name,
|
|
34
|
+
status,
|
|
35
|
+
timestamp: new Date(),
|
|
36
|
+
...details
|
|
37
|
+
};
|
|
38
|
+
this.results.tests.push(test);
|
|
39
|
+
this.results.summary.total++;
|
|
40
|
+
|
|
41
|
+
if (status === 'passed') {
|
|
42
|
+
this.results.summary.passed++;
|
|
43
|
+
this.log(`${name}: PASSED`, 'success');
|
|
44
|
+
} else if (status === 'failed') {
|
|
45
|
+
this.results.summary.failed++;
|
|
46
|
+
this.log(`${name}: FAILED - ${details.error || 'Unknown error'}`, 'error');
|
|
47
|
+
} else if (status === 'error') {
|
|
48
|
+
this.results.summary.errors.push(details.error);
|
|
49
|
+
this.log(`${name}: ERROR - ${details.error}`, 'error');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return test;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async testModuleLoading() {
|
|
56
|
+
this.log('Testing module loading...');
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
// Test 1: Load Server module
|
|
60
|
+
const Server = require('../../../server');
|
|
61
|
+
if (!Server) {
|
|
62
|
+
throw new Error('Server module not loaded');
|
|
63
|
+
}
|
|
64
|
+
this.recordTest('Module Loading - Server', 'passed');
|
|
65
|
+
|
|
66
|
+
// Test 2: Check Server.serve method
|
|
67
|
+
if (typeof Server.serve !== 'function') {
|
|
68
|
+
throw new Error('Server.serve is not a function');
|
|
69
|
+
}
|
|
70
|
+
this.recordTest('Module Loading - Server.serve', 'passed');
|
|
71
|
+
|
|
72
|
+
// Test 3: Load serve-factory
|
|
73
|
+
const serveFactory = require('../../../serve-factory');
|
|
74
|
+
if (typeof serveFactory !== 'function') {
|
|
75
|
+
throw new Error('serve-factory module not loaded');
|
|
76
|
+
}
|
|
77
|
+
this.recordTest('Module Loading - serve-factory', 'passed');
|
|
78
|
+
|
|
79
|
+
return true;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.recordTest('Module Loading', 'error', { error: error.message, stack: error.stack });
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async testServerConstruction() {
|
|
87
|
+
this.log('Testing server construction...');
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const Server = require('../../../server');
|
|
91
|
+
|
|
92
|
+
// Test 1: Create server instance
|
|
93
|
+
const server = new Server({
|
|
94
|
+
name: 'Diagnostic Test Server',
|
|
95
|
+
debug: true
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!server) {
|
|
99
|
+
throw new Error('Server instance not created');
|
|
100
|
+
}
|
|
101
|
+
this.recordTest('Server Construction - Instance Creation', 'passed');
|
|
102
|
+
|
|
103
|
+
// Test 2: Check required properties
|
|
104
|
+
if (!server.resource_pool) {
|
|
105
|
+
throw new Error('Server missing resource_pool');
|
|
106
|
+
}
|
|
107
|
+
this.recordTest('Server Construction - Resource Pool', 'passed');
|
|
108
|
+
|
|
109
|
+
if (!server.server_router) {
|
|
110
|
+
throw new Error('Server missing server_router');
|
|
111
|
+
}
|
|
112
|
+
this.recordTest('Server Construction - Router', 'passed');
|
|
113
|
+
|
|
114
|
+
// Test 3: Check publish method exists
|
|
115
|
+
if (typeof server.publish !== 'function') {
|
|
116
|
+
throw new Error('Server missing publish method');
|
|
117
|
+
}
|
|
118
|
+
this.recordTest('Server Construction - Publish Method', 'passed');
|
|
119
|
+
|
|
120
|
+
return server;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
this.recordTest('Server Construction', 'error', { error: error.message, stack: error.stack });
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async testAPISetup(server) {
|
|
128
|
+
this.log('Testing API setup...');
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
// Test 1: Publish API endpoints
|
|
132
|
+
const api = {
|
|
133
|
+
'test-status': () => ({ status: 'test', timestamp: new Date() }),
|
|
134
|
+
'test-data': () => ({ data: [1, 2, 3], count: 3 })
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
for (const [name, handler] of Object.entries(api)) {
|
|
138
|
+
server.publish(name, handler);
|
|
139
|
+
}
|
|
140
|
+
this.recordTest('API Setup - Publishing Endpoints', 'passed');
|
|
141
|
+
|
|
142
|
+
// Test 2: Check router has routes
|
|
143
|
+
const router = server.router;
|
|
144
|
+
if (!router) {
|
|
145
|
+
throw new Error('Router not accessible');
|
|
146
|
+
}
|
|
147
|
+
this.recordTest('API Setup - Router Access', 'passed');
|
|
148
|
+
|
|
149
|
+
return true;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
this.recordTest('API Setup', 'error', { error: error.message, stack: error.stack });
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async testHTTPServing(server) {
|
|
157
|
+
this.log('Testing HTTP serving...');
|
|
158
|
+
|
|
159
|
+
return new Promise((resolve) => {
|
|
160
|
+
try {
|
|
161
|
+
// Test 1: Start server
|
|
162
|
+
server.start(this.testPort, (err) => {
|
|
163
|
+
if (err) {
|
|
164
|
+
this.recordTest('HTTP Serving - Server Start', 'error', { error: err.message });
|
|
165
|
+
resolve(false);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.recordTest('HTTP Serving - Server Start', 'passed');
|
|
170
|
+
|
|
171
|
+
// Test 2: Make HTTP request
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
this.makeTestRequest('/api/test-status')
|
|
174
|
+
.then(response => {
|
|
175
|
+
if (response && response.status === 'test') {
|
|
176
|
+
this.recordTest('HTTP Serving - API Response', 'passed');
|
|
177
|
+
resolve(true);
|
|
178
|
+
} else {
|
|
179
|
+
this.recordTest('HTTP Serving - API Response', 'failed', {
|
|
180
|
+
error: 'Invalid response',
|
|
181
|
+
response
|
|
182
|
+
});
|
|
183
|
+
resolve(false);
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
.catch(error => {
|
|
187
|
+
this.recordTest('HTTP Serving - API Response', 'error', { error: error.message });
|
|
188
|
+
resolve(false);
|
|
189
|
+
})
|
|
190
|
+
.finally(() => {
|
|
191
|
+
// Clean up server
|
|
192
|
+
if (server && server.close) {
|
|
193
|
+
server.close(() => {
|
|
194
|
+
this.log('Test server closed');
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}, 1000); // Wait for server to be ready
|
|
199
|
+
});
|
|
200
|
+
} catch (error) {
|
|
201
|
+
this.recordTest('HTTP Serving', 'error', { error: error.message, stack: error.stack });
|
|
202
|
+
resolve(false);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async testEndToEndIntegration() {
|
|
208
|
+
this.log('Testing end-to-end integration...');
|
|
209
|
+
|
|
210
|
+
return new Promise((resolve) => {
|
|
211
|
+
try {
|
|
212
|
+
// Start the actual server process
|
|
213
|
+
this.serverProcess = spawn('node', ['server.js'], {
|
|
214
|
+
cwd: path.dirname(__filename),
|
|
215
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
let serverOutput = '';
|
|
219
|
+
let serverStarted = false;
|
|
220
|
+
|
|
221
|
+
const timeout = setTimeout(() => {
|
|
222
|
+
if (!serverStarted) {
|
|
223
|
+
this.recordTest('End-to-End - Server Startup', 'failed', {
|
|
224
|
+
error: 'Server startup timeout'
|
|
225
|
+
});
|
|
226
|
+
this.cleanup();
|
|
227
|
+
resolve(false);
|
|
228
|
+
}
|
|
229
|
+
}, 15000);
|
|
230
|
+
|
|
231
|
+
this.serverProcess.stdout.on('data', (data) => {
|
|
232
|
+
serverOutput += data.toString();
|
|
233
|
+
if (serverOutput.includes('🚀 Simple JSON API Server started!') && !serverStarted) {
|
|
234
|
+
serverStarted = true;
|
|
235
|
+
clearTimeout(timeout);
|
|
236
|
+
this.recordTest('End-to-End - Server Startup', 'passed');
|
|
237
|
+
|
|
238
|
+
// Now test the API endpoints
|
|
239
|
+
setTimeout(async () => {
|
|
240
|
+
try {
|
|
241
|
+
// Test status endpoint
|
|
242
|
+
const statusResponse = await this.makeTestRequest('/api/status', 3002);
|
|
243
|
+
if (!statusResponse || statusResponse.status !== 'running') {
|
|
244
|
+
throw new Error('Status endpoint failed');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Test messages endpoint
|
|
248
|
+
const messagesResponse = await this.makeTestRequest('/api/messages', 3002);
|
|
249
|
+
if (!messagesResponse || !Array.isArray(messagesResponse.messages)) {
|
|
250
|
+
throw new Error('Messages endpoint failed');
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Test add message
|
|
254
|
+
const addResponse = await this.makeTestRequest('/api/add-message', 3002, 'POST', {
|
|
255
|
+
text: 'Diagnostic test message',
|
|
256
|
+
author: 'Diagnostic System'
|
|
257
|
+
});
|
|
258
|
+
if (!addResponse || !addResponse.success) {
|
|
259
|
+
throw new Error('Add message endpoint failed');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
this.recordTest('End-to-End - API Functionality', 'passed');
|
|
263
|
+
resolve(true);
|
|
264
|
+
|
|
265
|
+
} catch (error) {
|
|
266
|
+
this.recordTest('End-to-End - API Functionality', 'error', { error: error.message });
|
|
267
|
+
resolve(false);
|
|
268
|
+
} finally {
|
|
269
|
+
this.cleanup();
|
|
270
|
+
}
|
|
271
|
+
}, 1000);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
this.serverProcess.stderr.on('data', (data) => {
|
|
276
|
+
console.error('Server stderr:', data.toString());
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
this.serverProcess.on('error', (error) => {
|
|
280
|
+
this.recordTest('End-to-End - Server Process', 'error', { error: error.message });
|
|
281
|
+
clearTimeout(timeout);
|
|
282
|
+
resolve(false);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
} catch (error) {
|
|
286
|
+
this.recordTest('End-to-End Integration', 'error', { error: error.message, stack: error.stack });
|
|
287
|
+
resolve(false);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async makeTestRequest(path, port = this.testPort, method = 'GET', data = null) {
|
|
293
|
+
return new Promise((resolve, reject) => {
|
|
294
|
+
const options = {
|
|
295
|
+
hostname: 'localhost',
|
|
296
|
+
port: port,
|
|
297
|
+
path: path,
|
|
298
|
+
method: method,
|
|
299
|
+
headers: {
|
|
300
|
+
'Content-Type': 'application/json'
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const req = http.request(options, (res) => {
|
|
305
|
+
let body = '';
|
|
306
|
+
|
|
307
|
+
res.on('data', (chunk) => {
|
|
308
|
+
body += chunk;
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
res.on('end', () => {
|
|
312
|
+
try {
|
|
313
|
+
// Handle empty response body
|
|
314
|
+
if (body.trim() === '') {
|
|
315
|
+
resolve(null);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const response = JSON.parse(body);
|
|
319
|
+
resolve(response);
|
|
320
|
+
} catch (error) {
|
|
321
|
+
reject(new Error(`Failed to parse response: ${body}`));
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
req.on('error', (error) => {
|
|
327
|
+
reject(error);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
if (data && method === 'POST') {
|
|
331
|
+
req.write(JSON.stringify(data));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
req.end();
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
cleanup() {
|
|
339
|
+
if (this.serverProcess) {
|
|
340
|
+
this.serverProcess.kill('SIGTERM');
|
|
341
|
+
setTimeout(() => {
|
|
342
|
+
if (!this.serverProcess.killed) {
|
|
343
|
+
this.serverProcess.kill('SIGKILL');
|
|
344
|
+
}
|
|
345
|
+
}, 2000);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
generateReport() {
|
|
350
|
+
const report = {
|
|
351
|
+
...this.results,
|
|
352
|
+
summary: {
|
|
353
|
+
...this.results.summary,
|
|
354
|
+
successRate: this.results.summary.total > 0 ?
|
|
355
|
+
((this.results.summary.passed / this.results.summary.total) * 100).toFixed(1) + '%' : '0%'
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// Write to file
|
|
360
|
+
const reportPath = path.join(__dirname, 'diagnostic-report.json');
|
|
361
|
+
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
362
|
+
|
|
363
|
+
return report;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
async runAllTests() {
|
|
367
|
+
this.log('🧪 Starting Comprehensive Diagnostic Tests');
|
|
368
|
+
this.log('==========================================\n');
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
// Test 1: Module Loading
|
|
372
|
+
const modulesLoaded = await this.testModuleLoading();
|
|
373
|
+
if (!modulesLoaded) {
|
|
374
|
+
this.log('❌ Module loading failed - cannot continue with other tests');
|
|
375
|
+
return this.generateReport();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Test 2: Server Construction
|
|
379
|
+
const server = await this.testServerConstruction();
|
|
380
|
+
if (!server) {
|
|
381
|
+
this.log('❌ Server construction failed - cannot continue with other tests');
|
|
382
|
+
return this.generateReport();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Test 3: API Setup
|
|
386
|
+
const apiSetup = await this.testAPISetup(server);
|
|
387
|
+
if (!apiSetup) {
|
|
388
|
+
this.log('❌ API setup failed - cannot continue with HTTP tests');
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Test 4: HTTP Serving
|
|
392
|
+
await this.testHTTPServing(server);
|
|
393
|
+
|
|
394
|
+
// Test 5: End-to-End Integration
|
|
395
|
+
await this.testEndToEndIntegration();
|
|
396
|
+
|
|
397
|
+
} catch (error) {
|
|
398
|
+
this.log(`❌ Unexpected error during testing: ${error.message}`, 'error');
|
|
399
|
+
this.recordTest('Unexpected Error', 'error', { error: error.message, stack: error.stack });
|
|
400
|
+
} finally {
|
|
401
|
+
this.cleanup();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const report = this.generateReport();
|
|
405
|
+
|
|
406
|
+
this.log('\n📊 Diagnostic Test Summary');
|
|
407
|
+
this.log('==========================');
|
|
408
|
+
this.log(`Total Tests: ${report.summary.total}`);
|
|
409
|
+
this.log(`Passed: ${report.summary.passed}`);
|
|
410
|
+
this.log(`Failed: ${report.summary.failed}`);
|
|
411
|
+
this.log(`Success Rate: ${report.summary.successRate}`);
|
|
412
|
+
|
|
413
|
+
if (report.summary.errors.length > 0) {
|
|
414
|
+
this.log('\n❌ Errors Found:');
|
|
415
|
+
report.summary.errors.forEach((error, index) => {
|
|
416
|
+
this.log(` ${index + 1}. ${error}`);
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
this.log(`\n📄 Detailed report saved to: diagnostic-report.json`);
|
|
421
|
+
|
|
422
|
+
return report;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Export for use in other files
|
|
427
|
+
module.exports = DiagnosticTestSystem;
|
|
428
|
+
|
|
429
|
+
// Run if called directly
|
|
430
|
+
if (require.main === module) {
|
|
431
|
+
const diagnostic = new DiagnosticTestSystem();
|
|
432
|
+
diagnostic.runAllTests().catch(console.error);
|
|
433
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Server Startup Debug Document
|
|
2
|
+
|
|
3
|
+
## Expected Server Behavior
|
|
4
|
+
|
|
5
|
+
1. **Server.serve() call** - Server should initialize with API configuration
|
|
6
|
+
2. **Route setup** - API routes should be registered (we see "pre routing tree set route" messages)
|
|
7
|
+
3. **Server start** - HTTP server should start listening on port 3002
|
|
8
|
+
4. **Ready event** - Server should emit 'ready' event when fully started
|
|
9
|
+
5. **HTTP requests** - Server should accept and respond to HTTP requests
|
|
10
|
+
|
|
11
|
+
## Actual Server Behavior
|
|
12
|
+
|
|
13
|
+
1. **Server.serve() call** - ✅ Server initializes successfully (DEBUG: Starting Server.serve() call)
|
|
14
|
+
2. **Route setup** - ✅ Routes are registered (DEBUG: Publishing API route messages/status/add-message/clear-messages)
|
|
15
|
+
3. **Server start** - ❌ Server never calls server_instance.start() - execution stops after route setup
|
|
16
|
+
4. **Ready event** - ❌ Never emitted because server.start() is never called
|
|
17
|
+
5. **HTTP requests** - ❌ ECONNREFUSED because server never binds to port
|
|
18
|
+
|
|
19
|
+
## Issues Identified
|
|
20
|
+
|
|
21
|
+
- Server execution stops after API route setup - never reaches the server start phase
|
|
22
|
+
- The Promise returned by Server.serve() never resolves because start_server() is never called
|
|
23
|
+
- No debug messages from server_instance.start() or resource_pool.start()
|
|
24
|
+
- The server hangs indefinitely after route setup, never proceeding to bind to the port
|
|
25
|
+
- Ready event listener is set up but never fires (no "Ready event fired" message)
|
|
26
|
+
- Fallback timeout is set up but doesn't trigger start_server() either
|
|
27
|
+
|
|
28
|
+
## Root Cause Analysis
|
|
29
|
+
|
|
30
|
+
The server has a syntax error in the constructor - `Object.defineProperty(this, 'router', { get: () => server_router });` is missing a semicolon before it, causing a syntax error that prevents the module from loading.
|
|
31
|
+
|
|
32
|
+
The server never emits a 'ready' event because the constructor fails to execute properly. The 'ready' event is only raised in two places:
|
|
33
|
+
|
|
34
|
+
1. In the Ctrl (control) branch when wp_publisher emits 'ready'
|
|
35
|
+
2. In the else branch when ws_publisher emits 'ready'
|
|
36
|
+
|
|
37
|
+
Since we're using API-only mode (no Ctrl specified), we should be in the else branch, but the constructor fails before reaching that logic.
|
|
38
|
+
|
|
39
|
+
## Issues Identified
|
|
40
|
+
|
|
41
|
+
1. **Syntax Error**: Missing semicolon before `Object.defineProperty` call
|
|
42
|
+
2. **Server Constructor Failure**: Constructor throws before completing initialization
|
|
43
|
+
3. **No Ready Event**: Server never raises 'ready' event due to constructor failure
|
|
44
|
+
4. **Module Load Failure**: Server module cannot be required due to syntax error
|
|
45
|
+
|
|
46
|
+
## Debug Steps Taken
|
|
47
|
+
|
|
48
|
+
- Increased wait times from 5s to 50s after route setup
|
|
49
|
+
- Verified route setup messages are being detected
|
|
50
|
+
- Confirmed server process starts without errors
|
|
51
|
+
- Added detailed error logging for HTTP requests
|
|
52
|
+
|
|
53
|
+
## Next Steps
|
|
54
|
+
|
|
55
|
+
- Add console.log statements in server startup code to trace execution
|
|
56
|
+
- Check if server.start() is actually being called
|
|
57
|
+
- Verify port binding is successful
|
|
58
|
+
- Look for any async operations that might be blocking startup
|