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.
Files changed (57) hide show
  1. package/AGENTS.md +87 -0
  2. package/README.md +12 -0
  3. package/docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md +19 -0
  4. package/docs/advanced-usage-examples.md +1360 -0
  5. package/docs/agent-development-guide.md +386 -0
  6. package/docs/api-reference.md +916 -0
  7. package/docs/broken-functionality-tracker.md +285 -0
  8. package/docs/bundling-system-deep-dive.md +525 -0
  9. package/docs/cli-reference.md +393 -0
  10. package/docs/comprehensive-documentation.md +1403 -0
  11. package/docs/configuration-reference.md +808 -0
  12. package/docs/controls-development.md +859 -0
  13. package/docs/documentation-review/CURRENT_REVIEW.md +95 -0
  14. package/docs/function-publishers-json-apis.md +847 -0
  15. package/docs/getting-started-with-json.md +518 -0
  16. package/docs/minification-compression-sourcemaps-status.md +482 -0
  17. package/docs/minification-compression-sourcemaps-test-results.md +205 -0
  18. package/docs/publishers-guide.md +313 -0
  19. package/docs/resources-guide.md +615 -0
  20. package/docs/serve-helpers.md +406 -0
  21. package/docs/simple-server-api-design.md +13 -0
  22. package/docs/system-architecture.md +275 -0
  23. package/docs/troubleshooting.md +698 -0
  24. package/examples/json/README.md +115 -0
  25. package/examples/json/basic-api/README.md +345 -0
  26. package/examples/json/basic-api/server.js +199 -0
  27. package/examples/json/simple-api/README.md +125 -0
  28. package/examples/json/simple-api/diagnostic-report.json +73 -0
  29. package/examples/json/simple-api/diagnostic-test.js +433 -0
  30. package/examples/json/simple-api/server-debug.md +58 -0
  31. package/examples/json/simple-api/server.js +91 -0
  32. package/examples/json/simple-api/test.js +215 -0
  33. package/http/responders/static/Static_Route_HTTP_Responder.js +1 -2
  34. package/package.json +19 -8
  35. package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +65 -12
  36. package/publishers/helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer.js +6 -1
  37. package/publishers/http-function-publisher.js +59 -38
  38. package/publishers/http-webpage-publisher.js +48 -1
  39. package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +38 -146
  40. package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +54 -5
  41. package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +36 -4
  42. package/serve-factory.js +36 -9
  43. package/server.js +10 -4
  44. package/test-report.json +0 -0
  45. package/tests/README.md +250 -0
  46. package/tests/assigners.test.js +316 -0
  47. package/tests/bundlers.test.js +329 -0
  48. package/tests/configuration-validation.test.js +530 -0
  49. package/tests/content-analysis.test.js +641 -0
  50. package/tests/end-to-end.test.js +496 -0
  51. package/tests/error-handling.test.js +746 -0
  52. package/tests/performance.test.js +653 -0
  53. package/tests/publishers.test.js +395 -0
  54. package/tests/temp_invalid.js +7 -0
  55. package/tests/temp_invalid_utf8.js +1 -0
  56. package/tests/temp_malformed.js +10 -0
  57. 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
+ });