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,115 @@
|
|
|
1
|
+
# JSON API Examples
|
|
2
|
+
|
|
3
|
+
This directory contains examples of using JSGUI3 Server to create JSON APIs without HTML UI components.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### 1. Basic JSON API (`basic-api/`)
|
|
8
|
+
A simple JSON API server that demonstrates basic CRUD operations for a todo list.
|
|
9
|
+
|
|
10
|
+
**Features:**
|
|
11
|
+
- GET/POST endpoints for managing todos
|
|
12
|
+
- In-memory data storage
|
|
13
|
+
- Error handling
|
|
14
|
+
- JSON request/response handling
|
|
15
|
+
|
|
16
|
+
**Run:**
|
|
17
|
+
```bash
|
|
18
|
+
cd basic-api
|
|
19
|
+
node server.js
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Test:**
|
|
23
|
+
```bash
|
|
24
|
+
# Get all todos
|
|
25
|
+
curl http://localhost:3000/api/todos
|
|
26
|
+
|
|
27
|
+
# Create a todo
|
|
28
|
+
curl -X POST http://localhost:3000/api/todos \
|
|
29
|
+
-H "Content-Type: application/json" \
|
|
30
|
+
-d '{"title":"Learn JSGUI3","completed":false}'
|
|
31
|
+
|
|
32
|
+
# Get specific todo
|
|
33
|
+
curl http://localhost:3000/api/todo?id=1
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 2. Weather API (`weather-api/`)
|
|
37
|
+
A weather API that simulates external service calls.
|
|
38
|
+
|
|
39
|
+
**Features:**
|
|
40
|
+
- Simulated weather data
|
|
41
|
+
- Async operations
|
|
42
|
+
- Error handling for invalid requests
|
|
43
|
+
- Multiple endpoints for different data types
|
|
44
|
+
|
|
45
|
+
### 3. User Management API (`user-api/`)
|
|
46
|
+
A complete user management system with authentication simulation.
|
|
47
|
+
|
|
48
|
+
**Features:**
|
|
49
|
+
- User registration and login
|
|
50
|
+
- JWT-like token simulation
|
|
51
|
+
- Protected endpoints
|
|
52
|
+
- Data validation
|
|
53
|
+
|
|
54
|
+
## Architecture Notes
|
|
55
|
+
|
|
56
|
+
These examples demonstrate how to use JSGUI3 Server for pure API development:
|
|
57
|
+
|
|
58
|
+
1. **No UI Components**: Unlike other examples, these don't serve HTML/JS/CSS bundles
|
|
59
|
+
2. **Function Publishers**: Uses the `api` configuration option for endpoint definition
|
|
60
|
+
3. **Data Handling**: Demonstrates various patterns for data processing and storage
|
|
61
|
+
4. **Error Handling**: Shows proper error responses and validation
|
|
62
|
+
|
|
63
|
+
## Common Patterns
|
|
64
|
+
|
|
65
|
+
### API Structure
|
|
66
|
+
```javascript
|
|
67
|
+
Server.serve({
|
|
68
|
+
api: {
|
|
69
|
+
// GET/POST /api/endpoint
|
|
70
|
+
'endpoint': (requestData) => {
|
|
71
|
+
// Process request
|
|
72
|
+
return responseData;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
port: 3000
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Data Validation
|
|
80
|
+
```javascript
|
|
81
|
+
'create-item': (data) => {
|
|
82
|
+
if (!data.name) {
|
|
83
|
+
throw new Error('Name is required');
|
|
84
|
+
}
|
|
85
|
+
// Process valid data
|
|
86
|
+
return { success: true, item: newItem };
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Async Operations
|
|
91
|
+
```javascript
|
|
92
|
+
'async-endpoint': async (data) => {
|
|
93
|
+
const result = await someAsyncOperation(data);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Running Examples
|
|
99
|
+
|
|
100
|
+
Each example follows the same pattern:
|
|
101
|
+
|
|
102
|
+
1. `cd` into the example directory
|
|
103
|
+
2. Run `node server.js`
|
|
104
|
+
3. Test endpoints with curl or your preferred HTTP client
|
|
105
|
+
4. Check the README.md in each directory for specific instructions
|
|
106
|
+
|
|
107
|
+
## Development Notes
|
|
108
|
+
|
|
109
|
+
These examples are designed to be:
|
|
110
|
+
- **Simple**: Easy to understand and modify
|
|
111
|
+
- **Complete**: Working end-to-end implementations
|
|
112
|
+
- **Educational**: Demonstrating best practices
|
|
113
|
+
- **Extensible**: Easy to add features or modify behavior
|
|
114
|
+
|
|
115
|
+
For more advanced patterns, see the main documentation in `docs/`.
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# Basic JSON API Example
|
|
2
|
+
|
|
3
|
+
This example demonstrates a complete JSON API server using JSGUI3 Server for managing a todo list. Unlike other examples, this serves **only JSON APIs** with no HTML UI components.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- โ
**Pure JSON API**: No HTML, CSS, or JavaScript UI bundles
|
|
8
|
+
- โ
**Complete CRUD**: Create, Read, Update, Delete operations
|
|
9
|
+
- โ
**Data Validation**: Input validation with meaningful error messages
|
|
10
|
+
- โ
**Statistics**: Analytics endpoints for todo data
|
|
11
|
+
- โ
**Error Handling**: Proper HTTP error responses
|
|
12
|
+
- โ
**In-Memory Storage**: Simple data persistence (replace with database for production)
|
|
13
|
+
|
|
14
|
+
## API Endpoints
|
|
15
|
+
|
|
16
|
+
### Todos Management
|
|
17
|
+
|
|
18
|
+
#### `GET /api/todos`
|
|
19
|
+
Get all todos with summary statistics.
|
|
20
|
+
|
|
21
|
+
**Response:**
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"todos": [
|
|
25
|
+
{
|
|
26
|
+
"id": 1,
|
|
27
|
+
"title": "Learn JSGUI3 Server",
|
|
28
|
+
"completed": false,
|
|
29
|
+
"createdAt": "2025-11-02T01:00:00.000Z"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"total": 1,
|
|
33
|
+
"completed": 0
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### `GET /api/todo?id={id}`
|
|
38
|
+
Get a specific todo by ID.
|
|
39
|
+
|
|
40
|
+
**Parameters:**
|
|
41
|
+
- `id` (required): Todo ID number
|
|
42
|
+
|
|
43
|
+
**Response:**
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"id": 1,
|
|
47
|
+
"title": "Learn JSGUI3 Server",
|
|
48
|
+
"completed": false,
|
|
49
|
+
"createdAt": "2025-11-02T01:00:00.000Z"
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### `POST /api/create-todo`
|
|
54
|
+
Create a new todo item.
|
|
55
|
+
|
|
56
|
+
**Request Body:**
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"title": "New todo item",
|
|
60
|
+
"completed": false
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Response:**
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"success": true,
|
|
68
|
+
"todo": {
|
|
69
|
+
"id": 3,
|
|
70
|
+
"title": "New todo item",
|
|
71
|
+
"completed": false,
|
|
72
|
+
"createdAt": "2025-11-02T01:00:00.000Z",
|
|
73
|
+
"updatedAt": "2025-11-02T01:00:00.000Z"
|
|
74
|
+
},
|
|
75
|
+
"message": "Todo created successfully"
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### `POST /api/update-todo`
|
|
80
|
+
Update an existing todo.
|
|
81
|
+
|
|
82
|
+
**Request Body:**
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"id": 1,
|
|
86
|
+
"title": "Updated title",
|
|
87
|
+
"completed": true
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### `POST /api/delete-todo`
|
|
92
|
+
Delete a todo item.
|
|
93
|
+
|
|
94
|
+
**Request Body:**
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"id": 1
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### `POST /api/toggle-todo`
|
|
102
|
+
Toggle the completion status of a todo.
|
|
103
|
+
|
|
104
|
+
**Request Body:**
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"id": 1
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Analytics
|
|
112
|
+
|
|
113
|
+
#### `GET /api/stats`
|
|
114
|
+
Get todo statistics.
|
|
115
|
+
|
|
116
|
+
**Response:**
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"total": 2,
|
|
120
|
+
"completed": 1,
|
|
121
|
+
"pending": 1,
|
|
122
|
+
"completionRate": "50.0%"
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### `POST /api/clear-completed`
|
|
127
|
+
Remove all completed todos.
|
|
128
|
+
|
|
129
|
+
**Response:**
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"success": true,
|
|
133
|
+
"deletedCount": 1,
|
|
134
|
+
"remainingCount": 1,
|
|
135
|
+
"message": "Deleted 1 completed todos"
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Running the Example
|
|
140
|
+
|
|
141
|
+
1. **Start the server:**
|
|
142
|
+
```bash
|
|
143
|
+
cd examples/json/basic-api
|
|
144
|
+
node server.js
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
2. **Test the API:**
|
|
148
|
+
```bash
|
|
149
|
+
# Get all todos
|
|
150
|
+
curl http://localhost:3000/api/todos
|
|
151
|
+
|
|
152
|
+
# Create a new todo
|
|
153
|
+
curl -X POST http://localhost:3000/api/create-todo \
|
|
154
|
+
-H "Content-Type: application/json" \
|
|
155
|
+
-d '{"title":"Test todo","completed":false}'
|
|
156
|
+
|
|
157
|
+
# Get statistics
|
|
158
|
+
curl http://localhost:3000/api/stats
|
|
159
|
+
|
|
160
|
+
# Update a todo
|
|
161
|
+
curl -X POST http://localhost:3000/api/update-todo \
|
|
162
|
+
-H "Content-Type: application/json" \
|
|
163
|
+
-d '{"id":1,"completed":true}'
|
|
164
|
+
|
|
165
|
+
# Delete a todo
|
|
166
|
+
curl -X POST http://localhost:3000/api/delete-todo \
|
|
167
|
+
-H "Content-Type: application/json" \
|
|
168
|
+
-d '{"id":1}'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Code Structure
|
|
172
|
+
|
|
173
|
+
### Server Configuration
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
Server.serve({
|
|
177
|
+
// No UI control - pure API server
|
|
178
|
+
// ctrl: undefined,
|
|
179
|
+
|
|
180
|
+
api: {
|
|
181
|
+
// Define your endpoints here
|
|
182
|
+
'todos': () => { /* ... */ },
|
|
183
|
+
'create-todo': (data) => { /* ... */ },
|
|
184
|
+
// ...
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
port: 3000
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Data Validation
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
'create-todo': (data) => {
|
|
195
|
+
if (!data.title || typeof data.title !== 'string') {
|
|
196
|
+
throw new Error('Title is required and must be a string');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (data.title.length > 200) {
|
|
200
|
+
throw new Error('Title must be 200 characters or less');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Process valid data...
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Error Handling
|
|
208
|
+
|
|
209
|
+
All thrown errors are automatically converted to JSON error responses:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"error": "Title is required and must be a string"
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Key Differences from UI Examples
|
|
218
|
+
|
|
219
|
+
1. **No Control**: Unlike other examples, this doesn't specify a `ctrl` property
|
|
220
|
+
2. **No Bundling**: No JavaScript/CSS bundling occurs since there's no UI
|
|
221
|
+
3. **Pure API**: Only serves JSON responses to API endpoints
|
|
222
|
+
4. **No HTML**: No web pages are served - only API endpoints
|
|
223
|
+
|
|
224
|
+
## Production Considerations
|
|
225
|
+
|
|
226
|
+
This example uses in-memory storage. For production, consider:
|
|
227
|
+
|
|
228
|
+
- **Database Integration**: Replace the in-memory `todos` array with a database
|
|
229
|
+
- **Authentication**: Add user authentication and authorization
|
|
230
|
+
- **Rate Limiting**: Implement rate limiting to prevent abuse
|
|
231
|
+
- **Input Sanitization**: Add more comprehensive input validation
|
|
232
|
+
- **Logging**: Add request logging and monitoring
|
|
233
|
+
- **CORS**: Configure CORS policies for web clients
|
|
234
|
+
|
|
235
|
+
## Extending the Example
|
|
236
|
+
|
|
237
|
+
### Adding a Database
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
// Replace in-memory storage with database
|
|
241
|
+
const db = require('some-database-library');
|
|
242
|
+
|
|
243
|
+
const api = {
|
|
244
|
+
'todos': async () => {
|
|
245
|
+
const todos = await db.query('SELECT * FROM todos');
|
|
246
|
+
return { todos, total: todos.length };
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
'create-todo': async (data) => {
|
|
250
|
+
const result = await db.query('INSERT INTO todos (title, completed) VALUES (?, ?)',
|
|
251
|
+
[data.title, data.completed]);
|
|
252
|
+
return { success: true, id: result.insertId };
|
|
253
|
+
}
|
|
254
|
+
// ...
|
|
255
|
+
};
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Adding Authentication
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
// Add authentication middleware (conceptual)
|
|
262
|
+
const authenticate = (req) => {
|
|
263
|
+
const token = req.headers.authorization?.replace('Bearer ', '');
|
|
264
|
+
if (!token) throw new Error('No token provided');
|
|
265
|
+
// Verify token and return user info
|
|
266
|
+
return verifyToken(token);
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const api = {
|
|
270
|
+
'protected-endpoint': (data, req) => {
|
|
271
|
+
const user = authenticate(req);
|
|
272
|
+
// Only authenticated users can access this
|
|
273
|
+
return { user, data };
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Testing
|
|
279
|
+
|
|
280
|
+
### Manual Testing
|
|
281
|
+
|
|
282
|
+
Use curl or Postman to test all endpoints:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Create test data
|
|
286
|
+
curl -X POST http://localhost:3000/api/create-todo \
|
|
287
|
+
-H "Content-Type: application/json" \
|
|
288
|
+
-d '{"title":"Test API","completed":false}'
|
|
289
|
+
|
|
290
|
+
# Verify creation
|
|
291
|
+
curl http://localhost:3000/api/todos
|
|
292
|
+
|
|
293
|
+
# Test error handling
|
|
294
|
+
curl -X POST http://localhost:3000/api/create-todo \
|
|
295
|
+
-H "Content-Type: application/json" \
|
|
296
|
+
-d '{"title":"","completed":false}'
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Automated Testing
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
// test-api.js
|
|
303
|
+
const assert = require('assert');
|
|
304
|
+
|
|
305
|
+
async function testAPI() {
|
|
306
|
+
const baseUrl = 'http://localhost:3000/api';
|
|
307
|
+
|
|
308
|
+
// Test GET todos
|
|
309
|
+
const todosResponse = await fetch(`${baseUrl}/todos`);
|
|
310
|
+
const todosData = await todosResponse.json();
|
|
311
|
+
assert(Array.isArray(todosData.todos), 'Todos should be an array');
|
|
312
|
+
|
|
313
|
+
// Test POST create todo
|
|
314
|
+
const createResponse = await fetch(`${baseUrl}/create-todo`, {
|
|
315
|
+
method: 'POST',
|
|
316
|
+
headers: { 'Content-Type': 'application/json' },
|
|
317
|
+
body: JSON.stringify({ title: 'Test Todo', completed: false })
|
|
318
|
+
});
|
|
319
|
+
const createData = await createResponse.json();
|
|
320
|
+
assert(createData.success, 'Create should succeed');
|
|
321
|
+
|
|
322
|
+
console.log('โ
All API tests passed!');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
testAPI().catch(console.error);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Troubleshooting
|
|
329
|
+
|
|
330
|
+
### Common Issues
|
|
331
|
+
|
|
332
|
+
1. **"Route not found"**: Make sure the server is running and endpoints are correctly defined
|
|
333
|
+
2. **"Unexpected token"**: Check that Content-Type header is set to `application/json`
|
|
334
|
+
3. **"Title is required"**: Ensure request body includes required fields
|
|
335
|
+
4. **Server won't start**: Check that port 3000 is not already in use
|
|
336
|
+
|
|
337
|
+
### Debug Mode
|
|
338
|
+
|
|
339
|
+
Run with debug logging:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
DEBUG=* node server.js
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
This will show detailed request/response logging.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// Basic JSON API Example - Todo List API
|
|
2
|
+
// This example demonstrates a complete JSON API server with no HTML UI
|
|
3
|
+
|
|
4
|
+
const Server = require('../../../server');
|
|
5
|
+
|
|
6
|
+
// In-memory data store (in production, use a database)
|
|
7
|
+
let todos = [
|
|
8
|
+
{ id: 1, title: 'Learn JSGUI3 Server', completed: false, createdAt: new Date() },
|
|
9
|
+
{ id: 2, title: 'Build JSON API', completed: true, createdAt: new Date() }
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
let nextId = 3;
|
|
13
|
+
|
|
14
|
+
Server.serve({
|
|
15
|
+
// No UI control - pure API server
|
|
16
|
+
// ctrl: undefined,
|
|
17
|
+
|
|
18
|
+
api: {
|
|
19
|
+
// GET /api/todos - Get all todos
|
|
20
|
+
'todos': () => {
|
|
21
|
+
return {
|
|
22
|
+
todos: todos,
|
|
23
|
+
total: todos.length,
|
|
24
|
+
completed: todos.filter(t => t.completed).length
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// GET /api/todo?id=1 - Get specific todo
|
|
29
|
+
'todo': (data) => {
|
|
30
|
+
const id = parseInt(data.id);
|
|
31
|
+
if (!id) {
|
|
32
|
+
throw new Error('Todo ID is required');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const todo = todos.find(t => t.id === id);
|
|
36
|
+
if (!todo) {
|
|
37
|
+
throw new Error('Todo not found');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return todo;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// POST /api/create-todo - Create new todo
|
|
44
|
+
'create-todo': (data) => {
|
|
45
|
+
if (!data.title || typeof data.title !== 'string') {
|
|
46
|
+
throw new Error('Title is required and must be a string');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (data.title.length > 200) {
|
|
50
|
+
throw new Error('Title must be 200 characters or less');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const newTodo = {
|
|
54
|
+
id: nextId++,
|
|
55
|
+
title: data.title.trim(),
|
|
56
|
+
completed: Boolean(data.completed),
|
|
57
|
+
createdAt: new Date(),
|
|
58
|
+
updatedAt: new Date()
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
todos.push(newTodo);
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
success: true,
|
|
65
|
+
todo: newTodo,
|
|
66
|
+
message: 'Todo created successfully'
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// POST /api/update-todo - Update existing todo
|
|
71
|
+
'update-todo': (data) => {
|
|
72
|
+
const id = parseInt(data.id);
|
|
73
|
+
if (!id) {
|
|
74
|
+
throw new Error('Todo ID is required');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const todoIndex = todos.findIndex(t => t.id === id);
|
|
78
|
+
if (todoIndex === -1) {
|
|
79
|
+
throw new Error('Todo not found');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const todo = todos[todoIndex];
|
|
83
|
+
|
|
84
|
+
// Update allowed fields
|
|
85
|
+
if (data.title !== undefined) {
|
|
86
|
+
if (typeof data.title !== 'string' || data.title.length > 200) {
|
|
87
|
+
throw new Error('Title must be a string of 200 characters or less');
|
|
88
|
+
}
|
|
89
|
+
todo.title = data.title.trim();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (data.completed !== undefined) {
|
|
93
|
+
todo.completed = Boolean(data.completed);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
todo.updatedAt = new Date();
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
success: true,
|
|
100
|
+
todo: todo,
|
|
101
|
+
message: 'Todo updated successfully'
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// POST /api/delete-todo - Delete todo
|
|
106
|
+
'delete-todo': (data) => {
|
|
107
|
+
const id = parseInt(data.id);
|
|
108
|
+
if (!id) {
|
|
109
|
+
throw new Error('Todo ID is required');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const todoIndex = todos.findIndex(t => t.id === id);
|
|
113
|
+
if (todoIndex === -1) {
|
|
114
|
+
throw new Error('Todo not found');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const deletedTodo = todos.splice(todoIndex, 1)[0];
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
deletedTodo: deletedTodo,
|
|
122
|
+
message: 'Todo deleted successfully'
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
// POST /api/toggle-todo - Toggle completion status
|
|
127
|
+
'toggle-todo': (data) => {
|
|
128
|
+
const id = parseInt(data.id);
|
|
129
|
+
if (!id) {
|
|
130
|
+
throw new Error('Todo ID is required');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const todo = todos.find(t => t.id === id);
|
|
134
|
+
if (!todo) {
|
|
135
|
+
throw new Error('Todo not found');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
todo.completed = !todo.completed;
|
|
139
|
+
todo.updatedAt = new Date();
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
success: true,
|
|
143
|
+
todo: todo,
|
|
144
|
+
message: `Todo ${todo.completed ? 'completed' : 'marked incomplete'}`
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
// GET /api/stats - Get todo statistics
|
|
149
|
+
'stats': () => {
|
|
150
|
+
const total = todos.length;
|
|
151
|
+
const completed = todos.filter(t => t.completed).length;
|
|
152
|
+
const pending = total - completed;
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
total: total,
|
|
156
|
+
completed: completed,
|
|
157
|
+
pending: pending,
|
|
158
|
+
completionRate: total > 0 ? (completed / total * 100).toFixed(1) + '%' : '0%'
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
// POST /api/clear-completed - Remove all completed todos
|
|
163
|
+
'clear-completed': () => {
|
|
164
|
+
const initialCount = todos.length;
|
|
165
|
+
todos = todos.filter(t => !t.completed);
|
|
166
|
+
const deletedCount = initialCount - todos.length;
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
success: true,
|
|
170
|
+
deletedCount: deletedCount,
|
|
171
|
+
remainingCount: todos.length,
|
|
172
|
+
message: `Deleted ${deletedCount} completed todos`
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
port: 3000
|
|
178
|
+
}).then(server => {
|
|
179
|
+
console.log('๐ JSON API Server started successfully!');
|
|
180
|
+
console.log(`๐ก Server running at: http://localhost:${server.port}`);
|
|
181
|
+
console.log('\n๐ Available endpoints:');
|
|
182
|
+
console.log(' GET /api/todos - Get all todos');
|
|
183
|
+
console.log(' GET /api/todo?id=1 - Get specific todo');
|
|
184
|
+
console.log(' POST /api/create-todo - Create new todo');
|
|
185
|
+
console.log(' POST /api/update-todo - Update existing todo');
|
|
186
|
+
console.log(' POST /api/delete-todo - Delete todo');
|
|
187
|
+
console.log(' POST /api/toggle-todo - Toggle completion status');
|
|
188
|
+
console.log(' GET /api/stats - Get statistics');
|
|
189
|
+
console.log(' POST /api/clear-completed - Remove completed todos');
|
|
190
|
+
console.log('\n๐งช Test with:');
|
|
191
|
+
console.log(' curl http://localhost:3000/api/todos');
|
|
192
|
+
console.log(' curl -X POST http://localhost:3000/api/create-todo \\');
|
|
193
|
+
console.log(' -H "Content-Type: application/json" \\');
|
|
194
|
+
console.log(' -d \'{"title":"Test todo","completed":false}\'');
|
|
195
|
+
|
|
196
|
+
}).catch(err => {
|
|
197
|
+
console.error('โ Failed to start server:', err.message);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
});
|