jsgui3-server 0.0.150 → 0.0.152

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 (86) hide show
  1. package/.github/instructions/copilot.instructions.md +1 -0
  2. package/AGENTS.md +2 -0
  3. package/README.md +89 -13
  4. package/admin-ui/v1/controls/admin_shell.js +702 -669
  5. package/admin-ui/v1/server.js +14 -1
  6. package/docs/api-reference.md +504 -306
  7. package/docs/books/creating-a-new-admin-ui/README.md +20 -20
  8. package/docs/books/website-design/01-introduction.md +73 -0
  9. package/docs/books/website-design/02-current-state.md +195 -0
  10. package/docs/books/website-design/03-base-class.md +181 -0
  11. package/docs/books/website-design/04-webpage.md +307 -0
  12. package/docs/books/website-design/05-website.md +456 -0
  13. package/docs/books/website-design/06-pages-storage.md +170 -0
  14. package/docs/books/website-design/07-api-layer.md +285 -0
  15. package/docs/books/website-design/08-server-integration.md +271 -0
  16. package/docs/books/website-design/09-cross-agent-review.md +190 -0
  17. package/docs/books/website-design/10-open-questions.md +196 -0
  18. package/docs/books/website-design/11-converged-recommendation.md +205 -0
  19. package/docs/books/website-design/12-content-model.md +395 -0
  20. package/docs/books/website-design/13-webpage-module-spec.md +404 -0
  21. package/docs/books/website-design/14-website-module-spec.md +541 -0
  22. package/docs/books/website-design/15-multi-repo-plan.md +275 -0
  23. package/docs/books/website-design/16-minimal-first.md +203 -0
  24. package/docs/books/website-design/17-implementation-report-codex.md +81 -0
  25. package/docs/books/website-design/README.md +43 -0
  26. package/docs/comprehensive-documentation.md +220 -220
  27. package/docs/configuration-reference.md +281 -204
  28. package/docs/middleware-guide.md +236 -0
  29. package/docs/proposals/jsgui3-website-and-webpage-design-jsgui3-server-support.md +257 -0
  30. package/docs/proposals/jsgui3-website-and-webpage-design-review.md +73 -0
  31. package/docs/proposals/jsgui3-website-and-webpage-design.md +732 -0
  32. package/docs/swagger.md +316 -0
  33. package/docs/system-architecture.md +24 -18
  34. package/examples/controls/1) window/server.js +6 -1
  35. package/examples/controls/21) mvvm and declarative api/check.js +94 -0
  36. package/examples/controls/21) mvvm and declarative api/check_output.txt +25 -0
  37. package/examples/controls/21) mvvm and declarative api/check_output_2.txt +27 -0
  38. package/examples/controls/21) mvvm and declarative api/client.js +241 -0
  39. declarative api/e2e-screenshot-1-name-change.png +0 -0
  40. declarative api/e2e-screenshot-2-toggled.png +0 -0
  41. declarative api/e2e-screenshot-3-final.png +0 -0
  42. declarative api/e2e-screenshot-final.png +0 -0
  43. package/examples/controls/21) mvvm and declarative api/e2e-test.js +175 -0
  44. package/examples/controls/21) mvvm and declarative api/out.html +1 -0
  45. package/examples/controls/21) mvvm and declarative api/page_out.html +1 -0
  46. package/examples/controls/21) mvvm and declarative api/server.js +18 -0
  47. package/examples/data-views/01) query-endpoint/server.js +61 -0
  48. package/labs/website-design/001-base-class-overhead/check.js +162 -0
  49. package/labs/website-design/002-pages-storage/check.js +244 -0
  50. package/labs/website-design/002-pages-storage/results.txt +0 -0
  51. package/labs/website-design/003-type-detection/check.js +193 -0
  52. package/labs/website-design/003-type-detection/results.txt +0 -0
  53. package/labs/website-design/004-two-stage-validation/check.js +314 -0
  54. package/labs/website-design/004-two-stage-validation/results.txt +0 -0
  55. package/labs/website-design/005-normalize-input/check.js +303 -0
  56. package/labs/website-design/006-serve-website-spike/check.js +290 -0
  57. package/labs/website-design/README.md +34 -0
  58. package/labs/website-design/manifest.json +68 -0
  59. package/labs/website-design/run-all.js +60 -0
  60. package/middleware/compression.js +217 -0
  61. package/middleware/index.js +15 -0
  62. package/middleware/json-body.js +126 -0
  63. package/module.js +3 -0
  64. package/openapi.js +474 -0
  65. package/package.json +11 -8
  66. package/publishers/Publishers.js +6 -5
  67. package/publishers/http-function-publisher.js +135 -126
  68. package/publishers/http-webpage-publisher.js +89 -11
  69. package/publishers/query-publisher.js +116 -0
  70. package/publishers/swagger-publisher.js +203 -0
  71. package/publishers/swagger-ui.js +578 -0
  72. package/resources/adapters/array-adapter.js +143 -0
  73. package/resources/query-resource.js +131 -0
  74. package/serve-factory.js +756 -18
  75. package/server.js +502 -123
  76. package/tests/README.md +23 -1
  77. package/tests/admin-ui-jsgui-controls.test.js +16 -1
  78. package/tests/helpers/playwright-e2e-harness.js +326 -0
  79. package/tests/openapi.test.js +319 -0
  80. package/tests/playwright-smoke.test.js +134 -0
  81. package/tests/publish-enhancements.test.js +673 -0
  82. package/tests/query-publisher.test.js +430 -0
  83. package/tests/quick-json-body-test.js +169 -0
  84. package/tests/serve.test.js +425 -122
  85. package/tests/swagger-publisher.test.js +1076 -0
  86. package/tests/test-runner.js +1 -0
@@ -61,6 +61,37 @@ Configuration values are resolved in this order (later sources override earlier
61
61
  Server.serve({ port: 3000 });
62
62
  ```
63
63
 
64
+ #### `on_port_conflict`
65
+ - **Type:** `'error' | 'auto-loopback'`
66
+ - **Description:** Startup behavior when the requested port is already in use.
67
+ - **Default:** `'error'`
68
+
69
+ ```javascript
70
+ // If the configured port is busy on all selected interfaces,
71
+ // retry on 127.0.0.1 using a free ephemeral port.
72
+ Server.serve({
73
+ port: 52000,
74
+ on_port_conflict: 'auto-loopback'
75
+ });
76
+ ```
77
+
78
+ #### `start`
79
+ - **Type:** `object`
80
+ - **Description:** Advanced startup options passed to `server.start(...)`.
81
+
82
+ | Property | Type | Description |
83
+ |----------|------|-------------|
84
+ | `on_port_conflict` | `'error' \| 'auto-loopback'` | Same as top-level `on_port_conflict` |
85
+
86
+ ```javascript
87
+ Server.serve({
88
+ port: 52000,
89
+ start: {
90
+ on_port_conflict: 'auto-loopback'
91
+ }
92
+ });
93
+ ```
94
+
64
95
  #### `host`
65
96
  - **Type:** `string`
66
97
  - **Description:** Host interface to bind to
@@ -129,7 +160,7 @@ Configuration values are resolved in this order (later sources override earlier
129
160
  });
130
161
  ```
131
162
 
132
- ### API Configuration
163
+ ### API Configuration
133
164
 
134
165
  #### `api`
135
166
  - **Type:** `object`
@@ -154,81 +185,81 @@ Configuration values are resolved in this order (later sources override earlier
154
185
  'echo': (data) => data
155
186
  }
156
187
  });
157
- ```
158
-
159
- ### Resource and Event Options
160
-
161
- #### `resources`
162
- - **Type:** `object | array`
163
- - **Description:** Resource definitions to register in the server resource pool and start after server startup.
164
- - **Lifecycle:** Resources are started automatically after the HTTP server is listening and stopped automatically during `server.close()`.
165
- - **Supported forms:**
166
- - In-process resource instance
167
- - In-process resource constructor/class config
168
- - Process resource config (`type: 'process'` or inferred from `command`)
169
- - Remote process resource config (`type: 'remote'` or inferred from `host`/`endpoints`)
170
- - **Example:**
171
- ```javascript
172
- Server.serve({
173
- resources: {
174
- // In-process resource instance
175
- cache: new In_Process_Cache_Resource({ name: 'cache' }),
176
-
177
- // Process_Resource in direct mode (default)
178
- worker_direct: {
179
- type: 'process',
180
- command: process.execPath,
181
- args: ['worker.js'],
182
- autoRestart: true
183
- },
184
-
185
- // Process_Resource in PM2 mode (pm2Path optional)
186
- worker_pm2: {
187
- type: 'process',
188
- processManager: { type: 'pm2' },
189
- command: process.execPath,
190
- args: ['worker.js']
191
- },
192
-
193
- // Remote_Process_Resource
194
- remote_worker: {
195
- type: 'remote',
196
- host: '127.0.0.1',
197
- port: 3400,
198
- pollIntervalMs: 30000
199
- }
200
- }
201
- });
202
- ```
203
-
204
- **Process resource notes:**
205
- - `processManager` defaults to `direct`.
206
- - PM2 works without explicitly setting `pm2Path`:
207
- - `processManager.pm2Path` (if provided)
208
- - `PM2_PATH` env var (if provided)
209
- - local `node_modules/.bin/pm2` (if present)
210
- - `pm2` from `PATH`
211
-
212
- #### `events`
213
- - **Type:** `boolean | object`
214
- - **Description:** Enables a built-in SSE endpoint for resource lifecycle events.
215
- - **Default:** `false`
216
- - **When `true`:**
217
- - Registers `HTTP_SSE_Publisher` at `/events`
218
- - Forwards resource pool lifecycle events (`resource_state_change`, `crashed`, `unhealthy`, `unreachable`, `recovered`)
219
- - **When object:** Supports publisher options such as `route`, `name`, `keepaliveIntervalMs`, `maxClients`.
220
- - **Example:**
221
- ```javascript
222
- Server.serve({
223
- events: {
224
- route: '/events',
225
- keepaliveIntervalMs: 15000,
226
- maxClients: 200
227
- }
228
- });
229
- ```
230
-
231
- ### Static File Serving
188
+ ```
189
+
190
+ ### Resource and Event Options
191
+
192
+ #### `resources`
193
+ - **Type:** `object | array`
194
+ - **Description:** Resource definitions to register in the server resource pool and start after server startup.
195
+ - **Lifecycle:** Resources are started automatically after the HTTP server is listening and stopped automatically during `server.close()`.
196
+ - **Supported forms:**
197
+ - In-process resource instance
198
+ - In-process resource constructor/class config
199
+ - Process resource config (`type: 'process'` or inferred from `command`)
200
+ - Remote process resource config (`type: 'remote'` or inferred from `host`/`endpoints`)
201
+ - **Example:**
202
+ ```javascript
203
+ Server.serve({
204
+ resources: {
205
+ // In-process resource instance
206
+ cache: new In_Process_Cache_Resource({ name: 'cache' }),
207
+
208
+ // Process_Resource in direct mode (default)
209
+ worker_direct: {
210
+ type: 'process',
211
+ command: process.execPath,
212
+ args: ['worker.js'],
213
+ autoRestart: true
214
+ },
215
+
216
+ // Process_Resource in PM2 mode (pm2Path optional)
217
+ worker_pm2: {
218
+ type: 'process',
219
+ processManager: { type: 'pm2' },
220
+ command: process.execPath,
221
+ args: ['worker.js']
222
+ },
223
+
224
+ // Remote_Process_Resource
225
+ remote_worker: {
226
+ type: 'remote',
227
+ host: '127.0.0.1',
228
+ port: 3400,
229
+ pollIntervalMs: 30000
230
+ }
231
+ }
232
+ });
233
+ ```
234
+
235
+ **Process resource notes:**
236
+ - `processManager` defaults to `direct`.
237
+ - PM2 works without explicitly setting `pm2Path`:
238
+ - `processManager.pm2Path` (if provided)
239
+ - `PM2_PATH` env var (if provided)
240
+ - local `node_modules/.bin/pm2` (if present)
241
+ - `pm2` from `PATH`
242
+
243
+ #### `events`
244
+ - **Type:** `boolean | object`
245
+ - **Description:** Enables a built-in SSE endpoint for resource lifecycle events.
246
+ - **Default:** `false`
247
+ - **When `true`:**
248
+ - Registers `HTTP_SSE_Publisher` at `/events`
249
+ - Forwards resource pool lifecycle events (`resource_state_change`, `crashed`, `unhealthy`, `unreachable`, `recovered`)
250
+ - **When object:** Supports publisher options such as `route`, `name`, `keepaliveIntervalMs`, `maxClients`.
251
+ - **Example:**
252
+ ```javascript
253
+ Server.serve({
254
+ events: {
255
+ route: '/events',
256
+ keepaliveIntervalMs: 15000,
257
+ maxClients: 200
258
+ }
259
+ });
260
+ ```
261
+
262
+ ### Static File Serving
232
263
 
233
264
  #### `static`
234
265
  - **Type:** `object`
@@ -270,51 +301,51 @@ Configuration values are resolved in this order (later sources override earlier
270
301
  });
271
302
  ```
272
303
 
273
- #### `config`
274
- - **Type:** `string`
275
- - **Description:** Path to configuration file
276
- - **Default:** `'jsgui.config.js'` (if exists)
277
- - **Example:**
278
- ```javascript
279
- Server.serve({
280
- config: './my-config.js'
281
- });
282
- ```
283
-
284
- #### `style`
285
- - **Type:** `object`
286
- - **Description:** Style pipeline options for CSS/SCSS/Sass extraction and compilation.
287
- - **Default:** `{}` (inherits debug behavior for sourcemaps)
288
- - **Example:**
289
- ```javascript
290
- Server.serve({
291
- ctrl: MyControl,
292
- debug: true,
293
- style: {
294
- sourcemaps: {
295
- enabled: true,
296
- inline: true,
297
- include_sources: true
298
- },
299
- load_paths: ['styles', 'controls'],
300
- output_style: 'expanded',
301
- quiet_dependencies: true,
302
- compile_css_with_sass: true
303
- }
304
- });
305
- ```
306
-
307
- **Style options:**
308
- - `sourcemaps.enabled` (`boolean`): Enable CSS sourcemaps. Defaults to `true` when `debug` is enabled.
309
- - `sourcemaps.inline` (`boolean`): Inline sourcemaps into compiled CSS (default `true`).
310
- - `sourcemaps.include_sources` (`boolean`): Embed sources content in the sourcemap (default `true`).
311
- - `load_paths` (`string[]`): Sass load paths for `@use`/`@import`.
312
- - `output_style` (`string`): Sass output style (e.g., `expanded`, `compressed`).
313
- - `quiet_dependencies` (`boolean`): Suppress dependency warnings during Sass compilation.
314
- - `compile_css_with_sass` (`boolean`): Compile `.css` blocks through Sass when mixing with SCSS (default `true`).
315
- - `scss_sources` / `sass_sources` (`string[]`): Extra Sass/SCSS sources appended during compilation.
316
-
317
- Inline CSS sourcemaps are emitted only when a single compilation pass is possible. Mixed `.sass` plus `.scss`/`.css` inputs skip inline maps to avoid inaccurate mappings.
304
+ #### `config`
305
+ - **Type:** `string`
306
+ - **Description:** Path to configuration file
307
+ - **Default:** `'jsgui.config.js'` (if exists)
308
+ - **Example:**
309
+ ```javascript
310
+ Server.serve({
311
+ config: './my-config.js'
312
+ });
313
+ ```
314
+
315
+ #### `style`
316
+ - **Type:** `object`
317
+ - **Description:** Style pipeline options for CSS/SCSS/Sass extraction and compilation.
318
+ - **Default:** `{}` (inherits debug behavior for sourcemaps)
319
+ - **Example:**
320
+ ```javascript
321
+ Server.serve({
322
+ ctrl: MyControl,
323
+ debug: true,
324
+ style: {
325
+ sourcemaps: {
326
+ enabled: true,
327
+ inline: true,
328
+ include_sources: true
329
+ },
330
+ load_paths: ['styles', 'controls'],
331
+ output_style: 'expanded',
332
+ quiet_dependencies: true,
333
+ compile_css_with_sass: true
334
+ }
335
+ });
336
+ ```
337
+
338
+ **Style options:**
339
+ - `sourcemaps.enabled` (`boolean`): Enable CSS sourcemaps. Defaults to `true` when `debug` is enabled.
340
+ - `sourcemaps.inline` (`boolean`): Inline sourcemaps into compiled CSS (default `true`).
341
+ - `sourcemaps.include_sources` (`boolean`): Embed sources content in the sourcemap (default `true`).
342
+ - `load_paths` (`string[]`): Sass load paths for `@use`/`@import`.
343
+ - `output_style` (`string`): Sass output style (e.g., `expanded`, `compressed`).
344
+ - `quiet_dependencies` (`boolean`): Suppress dependency warnings during Sass compilation.
345
+ - `compile_css_with_sass` (`boolean`): Compile `.css` blocks through Sass when mixing with SCSS (default `true`).
346
+ - `scss_sources` / `sass_sources` (`string[]`): Extra Sass/SCSS sources appended during compilation.
347
+
348
+ Inline CSS sourcemaps are emitted only when a single compilation pass is possible. Mixed `.sass` plus `.scss`/`.css` inputs skip inline maps to avoid inaccurate mappings.
318
349
 
319
350
  ## Environment Variables
320
351
 
@@ -421,81 +452,81 @@ Server.serve({
421
452
  });
422
453
  ```
423
454
 
424
- ### Resource Pools
425
-
426
- ```javascript
427
- let server;
428
- server = await Server.serve({
429
- resources: {
430
- cache: new In_Process_Cache_Resource({
431
- name: 'cache'
432
- }),
433
- worker_direct: {
434
- type: 'process',
435
- command: process.execPath,
436
- args: ['worker.js']
437
- },
438
- remote_worker: {
439
- type: 'remote',
440
- host: '127.0.0.1',
441
- port: 3400
442
- }
443
- },
444
- events: true,
445
- api: {
446
- 'resources/summary': () => server.resource_pool.summary,
447
- 'resources/restart': async ({ name }) => {
448
- const resource = server.resource_pool.get_resource(name);
449
- if (!resource || typeof resource.restart !== 'function') {
450
- return { ok: false, error: 'Resource restart not supported' };
451
- }
452
- await resource.restart();
453
- return { ok: true, status: resource.status };
454
- }
455
- }
456
- });
457
- ```
458
-
459
- For strongly typed in-process resources you can also provide constructor-based entries:
460
-
461
- ```javascript
462
- Server.serve({
463
- resources: {
464
- in_process_metrics: {
465
- type: 'resource',
466
- class: In_Process_Metrics_Resource,
467
- spec: {
468
- sampleIntervalMs: 1000
469
- }
470
- },
471
- in_process_events: {
472
- constructor_fn: In_Process_Event_Bus_Resource,
473
- spec: {
474
- maxHistory: 500
475
- }
476
- },
477
- in_process_cache: {
478
- resource: new In_Process_Cache_Resource({
479
- name: 'in_process_cache'
480
- })
481
- },
482
- in_process_singleton: new In_Process_Registry_Resource({
483
- name: 'in_process_singleton'
484
- })
485
- }
486
- });
487
- ```
488
-
489
- ### Middleware
455
+ ### Resource Pools
490
456
 
491
457
  ```javascript
492
- const express = require('express');
493
- const compression = require('compression');
458
+ let server;
459
+ server = await Server.serve({
460
+ resources: {
461
+ cache: new In_Process_Cache_Resource({
462
+ name: 'cache'
463
+ }),
464
+ worker_direct: {
465
+ type: 'process',
466
+ command: process.execPath,
467
+ args: ['worker.js']
468
+ },
469
+ remote_worker: {
470
+ type: 'remote',
471
+ host: '127.0.0.1',
472
+ port: 3400
473
+ }
474
+ },
475
+ events: true,
476
+ api: {
477
+ 'resources/summary': () => server.resource_pool.summary,
478
+ 'resources/restart': async ({ name }) => {
479
+ const resource = server.resource_pool.get_resource(name);
480
+ if (!resource || typeof resource.restart !== 'function') {
481
+ return { ok: false, error: 'Resource restart not supported' };
482
+ }
483
+ await resource.restart();
484
+ return { ok: true, status: resource.status };
485
+ }
486
+ }
487
+ });
488
+ ```
489
+
490
+ For strongly typed in-process resources you can also provide constructor-based entries:
491
+
492
+ ```javascript
493
+ Server.serve({
494
+ resources: {
495
+ in_process_metrics: {
496
+ type: 'resource',
497
+ class: In_Process_Metrics_Resource,
498
+ spec: {
499
+ sampleIntervalMs: 1000
500
+ }
501
+ },
502
+ in_process_events: {
503
+ constructor_fn: In_Process_Event_Bus_Resource,
504
+ spec: {
505
+ maxHistory: 500
506
+ }
507
+ },
508
+ in_process_cache: {
509
+ resource: new In_Process_Cache_Resource({
510
+ name: 'in_process_cache'
511
+ })
512
+ },
513
+ in_process_singleton: new In_Process_Registry_Resource({
514
+ name: 'in_process_singleton'
515
+ })
516
+ }
517
+ });
518
+ ```
519
+
520
+ ### `middleware`
521
+ - **Type:** `Function | Function[]`
522
+ - **Description:** One or more Express-style middleware functions `(req, res, next)` to run before every request reaches the router. Middleware is executed in array order.
523
+
524
+ ```javascript
525
+ const { compression } = require('jsgui3-server/middleware');
494
526
 
495
527
  Server.serve({
496
528
  middleware: [
497
- compression(),
498
- express.json({ limit: '10mb' }),
529
+ compression({ threshold: 512 }),
499
530
  (req, res, next) => {
500
531
  console.log(`${req.method} ${req.url}`);
501
532
  next();
@@ -504,6 +535,52 @@ Server.serve({
504
535
  });
505
536
  ```
506
537
 
538
+ ### `compression`
539
+ - **Type:** `boolean | Object`
540
+ - **Description:** Convenience shorthand that enables the built-in response-compression middleware. Pass `true` for defaults or an options object.
541
+ - **Default:** Disabled (no compression)
542
+
543
+ | Sub-option | Type | Default | Description |
544
+ |------------|--------|---------------------------|--------------------------------------------|
545
+ | `threshold` | number | `1024` | Minimum body size (bytes) to compress |
546
+ | `level` | number | `Z_DEFAULT_COMPRESSION` | zlib compression level (1–9, or -1 for default) |
547
+
548
+ ```javascript
549
+ // Enable with defaults (1024 byte threshold, gzip preferred)
550
+ Server.serve({ compression: true });
551
+
552
+ // Enable with custom options
553
+ Server.serve({ compression: { threshold: 256, level: 6 } });
554
+ ```
555
+
556
+ > **Note:** `compression` and `middleware` can be used together. The `middleware` array runs first (in order), then the compression middleware is appended.
557
+
558
+ See [Middleware Guide](middleware-guide.md) for the full API, response-wrapping patterns, and custom middleware examples.
559
+
560
+ ### Runtime Introspection Helpers
561
+
562
+ After startup, these server instance methods are useful for runtime endpoint
563
+ inspection and diagnostics:
564
+
565
+ - `server.get_listening_endpoints()`
566
+ - `server.get_primary_endpoint()`
567
+ - `server.print_endpoints(options)`
568
+ - `server.get_startup_diagnostics()`
569
+
570
+ ```javascript
571
+ const server = await Server.serve({
572
+ Ctrl: MyControl,
573
+ port: 52000,
574
+ on_port_conflict: 'auto-loopback'
575
+ });
576
+
577
+ console.log('Primary endpoint:', server.get_primary_endpoint());
578
+ server.print_endpoints({ include_index: true });
579
+ console.log('Startup diagnostics:', server.get_startup_diagnostics());
580
+ ```
581
+
582
+ See [API Reference](api-reference.md) for full method signatures.
583
+
507
584
  ## Configuration Validation
508
585
 
509
586
  ### Type Checking
@@ -523,18 +600,18 @@ Server.serve({ port: 'not-a-number' });
523
600
  - **Required:** None (auto-discovery provides defaults)
524
601
  - **Optional:** All options have sensible defaults
525
602
 
526
- ### Validation Rules
527
-
528
- - `port`: Must be number between 1-65535 or 0 (ephemeral)
529
- - `host`: Must be valid IPv4 address or hostname
530
- - `debug`: Converted to boolean using truthy() function
531
- - `pages`: Each page must have `content` property
532
- - `api`: Values must be functions
533
- - `static`: Values must be strings (directory paths)
534
- - `resources`: Must be an object map or array of supported resource entries
535
- - `resources.<name>.type`: Supported values include `process`, `remote`, `resource`, `in_process`, `in-process`
536
- - `resources.<name>.processManager.type`: Supported values include `direct`, `pm2`
537
- - `events`: Must be boolean or object
603
+ ### Validation Rules
604
+
605
+ - `port`: Must be number between 1-65535 or 0 (ephemeral)
606
+ - `host`: Must be valid IPv4 address or hostname
607
+ - `debug`: Converted to boolean using truthy() function
608
+ - `pages`: Each page must have `content` property
609
+ - `api`: Values must be functions
610
+ - `static`: Values must be strings (directory paths)
611
+ - `resources`: Must be an object map or array of supported resource entries
612
+ - `resources.<name>.type`: Supported values include `process`, `remote`, `resource`, `in_process`, `in-process`
613
+ - `resources.<name>.processManager.type`: Supported values include `direct`, `pm2`
614
+ - `events`: Must be boolean or object
538
615
 
539
616
  ## Configuration Patterns
540
617
 
@@ -965,4 +1042,4 @@ Solution: port: 3000 instead of port: "3000"
965
1042
 
966
1043
  ---
967
1044
 
968
- This configuration reference provides comprehensive coverage of all JSGUI3 Server configuration options. Remember that most options have sensible defaults, so you only need to specify what differs from the defaults for your use case.
1045
+ This configuration reference provides comprehensive coverage of all JSGUI3 Server configuration options. Remember that most options have sensible defaults, so you only need to specify what differs from the defaults for your use case.