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
@@ -32,30 +32,30 @@ Server.serve(options?: ServerOptions): Promise<Server>
32
32
  - `DiscoveryError`: Cannot find client files or controls
33
33
  - `BindingError`: Cannot bind to specified host/port
34
34
 
35
- **Example:**
36
- ```javascript
37
- const server = await Server.serve({
38
- port: 3000,
39
- ctrl: MyControl,
40
- resources: {
41
- worker_direct: {
42
- type: 'process',
43
- command: process.execPath,
44
- args: ['worker.js']
45
- },
46
- remote_worker: {
47
- type: 'remote',
48
- host: '127.0.0.1',
49
- port: 3400
50
- }
51
- },
52
- events: true
53
- });
54
- ```
55
-
56
- **Serve-specific options:**
57
- - `resources`: Registers managed resources (in-process resource objects, local process resources, remote HTTP process resources).
58
- - `events`: Enables built-in SSE publisher for resource lifecycle events (`/events` by default).
35
+ **Example:**
36
+ ```javascript
37
+ const server = await Server.serve({
38
+ port: 3000,
39
+ ctrl: MyControl,
40
+ resources: {
41
+ worker_direct: {
42
+ type: 'process',
43
+ command: process.execPath,
44
+ args: ['worker.js']
45
+ },
46
+ remote_worker: {
47
+ type: 'remote',
48
+ host: '127.0.0.1',
49
+ port: 3400
50
+ }
51
+ },
52
+ events: true
53
+ });
54
+ ```
55
+
56
+ **Serve-specific options:**
57
+ - `resources`: Registers managed resources (in-process resource objects, local process resources, remote HTTP process resources).
58
+ - `events`: Enables built-in SSE publisher for resource lifecycle events (`/events` by default).
59
59
 
60
60
  ### Server Constructor
61
61
 
@@ -71,42 +71,56 @@ new Server(options?: ServerOptions)
71
71
 
72
72
  **Returns:** Server instance
73
73
 
74
- **Events:**
75
- - `'ready'`: Emitted when bundling is complete
76
- - `'started'`: Emitted when HTTP server is listening
77
- - `'error'`: Emitted on server errors
78
-
79
- ### Module Exports
80
-
81
- ```javascript
82
- const jsgui = require('jsgui3-server');
83
-
84
- // Top-level exports
85
- jsgui.Process_Resource;
86
- jsgui.Remote_Process_Resource;
87
- jsgui.HTTP_SSE_Publisher;
88
-
89
- // Resource namespace aliases
90
- jsgui.Resource.Process;
91
- jsgui.Resource.Remote_Process;
92
- ```
93
-
94
- ## Server Instance Methods
95
-
96
- ### server.start(port, callback)
74
+ **Events:**
75
+ - `'ready'`: Emitted when bundling is complete
76
+ - `'started'`: Emitted when HTTP server is listening
77
+ - `'error'`: Emitted on server errors
78
+
79
+ ### Module Exports
80
+
81
+ ```javascript
82
+ const jsgui = require('jsgui3-server');
83
+
84
+ // Top-level exports
85
+ jsgui.Process_Resource;
86
+ jsgui.Remote_Process_Resource;
87
+ jsgui.HTTP_SSE_Publisher;
88
+
89
+ // Resource namespace aliases
90
+ jsgui.Resource.Process;
91
+ jsgui.Resource.Remote_Process;
92
+ ```
93
+
94
+ ## Server Instance Methods
95
+
96
+ ### server.start(port, callback, options)
97
97
 
98
98
  Starts the HTTP server (legacy API).
99
99
 
100
100
  **Signature:**
101
101
  ```javascript
102
- server.start(port?: number, callback?: (err?: Error) => void): void
102
+ server.start(
103
+ port?: number,
104
+ callback?: (err?: Error) => void,
105
+ options?: {
106
+ on_port_conflict?: 'error' | 'auto-loopback'
107
+ }
108
+ ): void
103
109
  ```
104
110
 
105
111
  **Parameters:**
106
112
  - `port` (number, optional): Port to listen on (default: 8080)
107
113
  - `callback` (function, optional): Called when server starts or fails
114
+ - `options` (object, optional): Startup behavior options
115
+ - `on_port_conflict: 'error' | 'auto-loopback'`
116
+ - `error` (default): Return startup error as usual.
117
+ - `auto-loopback`: If all requested interface binds fail with `EADDRINUSE`,
118
+ retry once on `127.0.0.1` using a free port.
108
119
 
109
- ### server.publish(route, handler)
120
+ When startup fails, the returned error may include `error.startup_diagnostics`
121
+ containing attempted addresses and per-address errors.
122
+
123
+ ### server.publish(route, handler)
110
124
 
111
125
  Adds an API endpoint (legacy API).
112
126
 
@@ -115,53 +129,227 @@ Adds an API endpoint (legacy API).
115
129
  server.publish(route: string, handler: Function): void
116
130
  ```
117
131
 
118
- **Parameters:**
119
- - `route` (string): Route path (automatically prefixed with `/api/`)
120
- - `handler` (Function): Request handler function
121
-
122
- ### server.publish_observable(route, observable, options)
123
-
124
- Adds an observable-backed SSE endpoint.
125
-
126
- **Signature:**
127
- ```javascript
128
- server.publish_observable(route: string, observable: Observable, options?: object): HTTP_Observable_Publisher
129
- ```
130
-
131
- **Parameters:**
132
- - `route` (string): Route path. If it does not start with `/`, it is prefixed with `/api/`.
133
- - `observable` (Observable): Source observable stream.
134
- - `options` (object, optional): Publisher options.
135
-
136
- **Returns:** `HTTP_Observable_Publisher` instance.
137
-
138
- **Alias:** `server.publishObservable(route, observable, options)`
139
-
140
- ### server.close(callback)
141
-
142
- Stops managed resources and closes all bound HTTP servers.
143
-
144
- **Signature:**
145
- ```javascript
146
- server.close(callback?: (err?: Error | null) => void): void
147
- ```
148
-
149
- **Behavior:**
150
- - Calls `resource_pool.stop()` when available
151
- - Stops `sse_publisher` when present
152
- - Closes all HTTP listeners
153
-
154
- ### server.use(middleware)
155
-
156
- Adds middleware to the server.
132
+ **Parameters:**
133
+ - `route` (string): Route path (automatically prefixed with `/api/`)
134
+ - `handler` (Function): Request handler function
135
+
136
+ ### server.publish_observable(route, observable, options)
137
+
138
+ Adds an observable-backed SSE endpoint.
139
+
140
+ **Signature:**
141
+ ```javascript
142
+ server.publish_observable(route: string, observable: Observable, options?: object): HTTP_Observable_Publisher
143
+ ```
144
+
145
+ **Parameters:**
146
+ - `route` (string): Route path. If it does not start with `/`, it is prefixed with `/api/`.
147
+ - `observable` (Observable): Source observable stream.
148
+ - `options` (object, optional): Publisher options.
149
+
150
+ **Returns:** `HTTP_Observable_Publisher` instance.
151
+
152
+ **Alias:** `server.publishObservable(route, observable, options)`
153
+
154
+ ### server.close(callback)
155
+
156
+ Stops managed resources and closes all bound HTTP servers.
157
+
158
+ **Signature:**
159
+ ```javascript
160
+ server.close(callback?: (err?: Error | null) => void): void
161
+ ```
162
+
163
+ **Behavior:**
164
+ - Calls `resource_pool.stop()` when available
165
+ - Stops `sse_publisher` when present
166
+ - Closes all HTTP listeners
167
+
168
+ ### server.get_listening_endpoints()
169
+
170
+ Returns the active listener endpoints (protocol, host, port, url) for the
171
+ current process. Useful when startup falls back from a requested fixed port to
172
+ an auto-selected loopback port.
173
+
174
+ **Signature:**
175
+ ```javascript
176
+ server.get_listening_endpoints(): Array<{
177
+ protocol: 'http' | 'https';
178
+ host: string;
179
+ port: number;
180
+ url: string;
181
+ }>
182
+ ```
183
+
184
+ **Example:**
185
+ ```javascript
186
+ server.start(52000, (err) => {
187
+ if (err) throw err;
188
+ console.log('Listening at', server.get_primary_endpoint());
189
+ }, {
190
+ on_port_conflict: 'auto-loopback'
191
+ });
192
+ ```
193
+
194
+ ### server.get_primary_endpoint()
195
+
196
+ Returns the primary endpoint URL string (first endpoint) or `null` if the
197
+ server is not listening.
198
+
199
+ **Signature:**
200
+ ```javascript
201
+ server.get_primary_endpoint(): string | null
202
+ ```
203
+
204
+ **Example:**
205
+ ```javascript
206
+ const url = server.get_primary_endpoint();
207
+ if (url) {
208
+ console.log('Primary endpoint:', url);
209
+ }
210
+ ```
211
+
212
+ ### server.print_endpoints(options)
213
+
214
+ Prints listening endpoint URLs and returns the printed lines.
215
+
216
+ **Signature:**
217
+ ```javascript
218
+ server.print_endpoints(options?: {
219
+ logger?: (line: string) => void;
220
+ include_index?: boolean;
221
+ prefix?: string;
222
+ }): string[]
223
+ ```
224
+
225
+ **Parameters:**
226
+ - `options.logger` (function, optional): Line logger (default: `console.log`)
227
+ - `options.include_index` (boolean, optional): Include endpoint index in output
228
+ - `options.prefix` (string, optional): Prefix text (default: `"listening endpoint"`)
229
+
230
+ **Example:**
231
+ ```javascript
232
+ server.start(52000, (err) => {
233
+ if (err) throw err;
234
+ server.print_endpoints({ include_index: true });
235
+ }, {
236
+ on_port_conflict: 'auto-loopback'
237
+ });
238
+ ```
239
+
240
+ ### server.get_startup_diagnostics()
241
+
242
+ Returns startup diagnostics information or `null` when unavailable.
243
+
244
+ **Signature:**
245
+ ```javascript
246
+ server.get_startup_diagnostics(): {
247
+ requested_port: number;
248
+ fallback_port?: number;
249
+ fallback_host?: string;
250
+ addresses_attempted: string[];
251
+ errors_by_address: Record<string, { code?: string; message?: string }>;
252
+ } | null
253
+ ```
254
+
255
+ **Example:**
256
+ ```javascript
257
+ server.start(52000, (err) => {
258
+ if (err) {
259
+ console.error(server.get_startup_diagnostics());
260
+ throw err;
261
+ }
262
+ console.log(server.get_startup_diagnostics());
263
+ }, {
264
+ on_port_conflict: 'auto-loopback'
265
+ });
266
+ ```
267
+
268
+ ### server.use(fn)
269
+
270
+ Register middleware to run before every request is routed. Middleware is executed
271
+ in registration order. The chain runs to completion before the router processes
272
+ the request.
157
273
 
158
274
  **Signature:**
159
275
  ```javascript
160
- server.use(middleware: Function): void
276
+ server.use(fn: Function): Server // returns `this` for chaining
161
277
  ```
162
278
 
163
279
  **Parameters:**
164
- - `middleware` (Function): Express-style middleware function
280
+ - `fn` (Function): Middleware function with signature `(req, res, next) => void`
281
+ - `req` — Node.js `http.IncomingMessage`
282
+ - `res` — Node.js `http.ServerResponse`
283
+ - `next` — Call `next()` to continue to the next middleware / router.
284
+ Call `next(err)` to skip remaining middleware and trigger the error handler
285
+ (500 response).
286
+
287
+ **Returns:** The server instance (for chaining).
288
+
289
+ **Throws:** `Error` if `fn` is not a function.
290
+
291
+ **Example:**
292
+ ```javascript
293
+ const { compression } = require('jsgui3-server/middleware');
294
+
295
+ server
296
+ .use((req, res, next) => {
297
+ console.log(`${req.method} ${req.url}`);
298
+ next();
299
+ })
300
+ .use(compression());
301
+ ```
302
+
303
+ **Execution order:**
304
+ ```
305
+ HTTP Request → middleware[0] → middleware[1] → … → router
306
+ ```
307
+
308
+ If no middleware is registered, the router is called directly with zero overhead.
309
+
310
+ **See also:** [Middleware Guide](middleware-guide.md) for response-wrapping
311
+ patterns, custom middleware examples, and the built-in compression reference.
312
+
313
+ ---
314
+
315
+ ### Built-in Middleware
316
+
317
+ #### `compression([options])`
318
+
319
+ Response-compression middleware. Transparently compresses response bodies
320
+ (gzip / deflate / brotli) when the client supports it and the content type
321
+ is compressible.
322
+
323
+ ```javascript
324
+ const { compression } = require('jsgui3-server/middleware');
325
+ server.use(compression()); // defaults
326
+ server.use(compression({ threshold: 512 })); // lower threshold
327
+ ```
328
+
329
+ **Options:**
330
+
331
+ | Option | Type | Default | Description |
332
+ |-----------|--------|---------------------------|-------------------------------------------|
333
+ | `threshold` | number | `1024` | Minimum body size in bytes to compress |
334
+ | `level` | number | `Z_DEFAULT_COMPRESSION` | zlib compression level (1–9, or -1) |
335
+
336
+ **Encoding priority:** gzip → deflate → brotli
337
+
338
+ **Compressible types:** `application/json`, `text/html`, `text/plain`,
339
+ `text/css`, `text/xml`, `text/csv`, `text/javascript`,
340
+ `application/javascript`, `application/xml`, `application/xhtml+xml`,
341
+ `application/manifest+json`, `image/svg+xml`.
342
+
343
+ **Not compressed:** bodies below threshold, binary content types, responses
344
+ with an existing `Content-Encoding`, and streaming responses (`res.write()`
345
+ before `res.end()` — e.g. SSE).
346
+
347
+ **Access paths:**
348
+ ```javascript
349
+ require('jsgui3-server/middleware').compression // direct
350
+ require('jsgui3-server').middleware.compression // via module
351
+ Server.middleware.compression // via class
352
+ ```
165
353
 
166
354
  ## Port Utilities
167
355
 
@@ -507,7 +695,7 @@ Serves CSS files.
507
695
  serve(request: IncomingMessage, response: ServerResponse): Promise<void>
508
696
  ```
509
697
 
510
- ### HTTP_API_Publisher
698
+ ### HTTP_API_Publisher
511
699
 
512
700
  Handles API endpoints.
513
701
 
@@ -525,162 +713,162 @@ new HTTP_API_Publisher(spec?: PublisherSpec)
525
713
  Handles API requests.
526
714
 
527
715
  **Signature:**
528
- ```javascript
529
- serve(request: IncomingMessage, response: ServerResponse): Promise<void>
530
- ```
531
-
532
- ### HTTP_SSE_Publisher
533
-
534
- General-purpose SSE publisher for explicit event fan-out.
535
-
536
- **Extends:** `HTTP_Publisher`
537
-
538
- **Constructor:**
539
- ```javascript
540
- new HTTP_SSE_Publisher(spec?: {
541
- name?: string,
542
- keepaliveIntervalMs?: number,
543
- maxClients?: number,
544
- eventHistorySize?: number
545
- })
546
- ```
547
-
548
- **Methods:**
549
- - `handle_http(req, res)`
550
- - `broadcast(event_name, data_value)`
551
- - `send(client_id, event_name, data_value)`
552
- - `stop(callback?)`
553
-
554
- **Properties:**
555
- - `client_count` (number)
556
-
557
- ## Resource Classes
558
-
559
- ### Process_Resource
560
-
561
- Represents a local process as a resource with a unified lifecycle API.
562
-
563
- **Extends:** `Resource`
564
-
565
- **Constructor:**
566
- ```javascript
567
- new Process_Resource(spec?: {
568
- name?: string,
569
- command?: string,
570
- args?: string[],
571
- cwd?: string,
572
- env?: object,
573
- autoRestart?: boolean,
574
- maxRestarts?: number,
575
- processManager?: 'direct' | {
576
- type: 'direct' | 'pm2',
577
- pm2Path?: string,
578
- ecosystem?: string
579
- },
580
- healthCheck?: {
581
- type: 'http' | 'tcp' | 'custom',
582
- url?: string,
583
- host?: string,
584
- port?: number,
585
- fn?: Function,
586
- intervalMs?: number,
587
- timeoutMs?: number,
588
- failuresBeforeUnhealthy?: number
589
- }
590
- })
591
- ```
592
-
593
- **Core Methods:**
594
- - `start(callback?)`
595
- - `stop(callback?)`
596
- - `restart(callback?)`
597
- - `get_abstract()`
598
-
599
- **Status:**
600
- ```javascript
601
- {
602
- state: 'stopped' | 'starting' | 'running' | 'stopping' | 'restarting' | 'crashed',
603
- pid: number | null,
604
- uptime: number,
605
- restartCount: number,
606
- lastHealthCheck: object | null,
607
- memoryUsage: object | null,
608
- processManager: { type: 'direct' | 'pm2' }
609
- }
610
- ```
611
-
612
- **Events:**
613
- - `state_change`
614
- - `stdout`
615
- - `stderr`
616
- - `exit`
617
- - `health_check`
618
- - `unhealthy`
619
- - `crashed`
620
-
621
- ### Remote_Process_Resource
622
-
623
- Represents a remote HTTP-controlled process using the same lifecycle-oriented API style as `Process_Resource`.
624
-
625
- **Extends:** `Resource`
626
-
627
- **Constructor:**
628
- ```javascript
629
- new Remote_Process_Resource(spec?: {
630
- name?: string,
631
- host: string,
632
- port: number,
633
- protocol?: 'http' | 'https',
634
- pollIntervalMs?: number,
635
- httpTimeoutMs?: number,
636
- historySize?: number,
637
- unreachableFailuresBeforeEvent?: number,
638
- endpoints?: {
639
- status?: string,
640
- start?: string,
641
- stop?: string,
642
- health?: string
643
- }
644
- })
645
- ```
646
-
647
- **Core Methods:**
648
- - `start(callback?)`
649
- - `stop(callback?)`
650
- - `restart(callback?)`
651
- - `get_abstract()`
652
-
653
- **Status:** Includes `state`, `pid`, `uptime`, `restartCount`, `lastHealthCheck`, `memoryUsage`, and `processManager: { type: 'remote' }`.
654
-
655
- **Events:**
656
- - `state_change`
657
- - `unreachable`
658
- - `recovered`
659
-
660
- ### Server_Resource_Pool
661
-
662
- Server-specific resource pool with lifecycle orchestration and event forwarding.
663
-
664
- **Extends:** `Resource_Pool`
665
-
666
- **Methods:**
667
- - `add(resource)`
668
- - `remove(name, callback?)`
669
- - `start(callback?)`
670
- - `stop(callback?)`
671
- - `get_resources_by_type(type)`
672
-
673
- **Properties:**
674
- - `summary`: Aggregated state summary grouped by resource type.
675
-
676
- **Forwarded Events:**
677
- - `resource_state_change`
678
- - `crashed`
679
- - `unhealthy`
680
- - `unreachable`
681
- - `recovered`
682
-
683
- ### File_System_Resource
716
+ ```javascript
717
+ serve(request: IncomingMessage, response: ServerResponse): Promise<void>
718
+ ```
719
+
720
+ ### HTTP_SSE_Publisher
721
+
722
+ General-purpose SSE publisher for explicit event fan-out.
723
+
724
+ **Extends:** `HTTP_Publisher`
725
+
726
+ **Constructor:**
727
+ ```javascript
728
+ new HTTP_SSE_Publisher(spec?: {
729
+ name?: string,
730
+ keepaliveIntervalMs?: number,
731
+ maxClients?: number,
732
+ eventHistorySize?: number
733
+ })
734
+ ```
735
+
736
+ **Methods:**
737
+ - `handle_http(req, res)`
738
+ - `broadcast(event_name, data_value)`
739
+ - `send(client_id, event_name, data_value)`
740
+ - `stop(callback?)`
741
+
742
+ **Properties:**
743
+ - `client_count` (number)
744
+
745
+ ## Resource Classes
746
+
747
+ ### Process_Resource
748
+
749
+ Represents a local process as a resource with a unified lifecycle API.
750
+
751
+ **Extends:** `Resource`
752
+
753
+ **Constructor:**
754
+ ```javascript
755
+ new Process_Resource(spec?: {
756
+ name?: string,
757
+ command?: string,
758
+ args?: string[],
759
+ cwd?: string,
760
+ env?: object,
761
+ autoRestart?: boolean,
762
+ maxRestarts?: number,
763
+ processManager?: 'direct' | {
764
+ type: 'direct' | 'pm2',
765
+ pm2Path?: string,
766
+ ecosystem?: string
767
+ },
768
+ healthCheck?: {
769
+ type: 'http' | 'tcp' | 'custom',
770
+ url?: string,
771
+ host?: string,
772
+ port?: number,
773
+ fn?: Function,
774
+ intervalMs?: number,
775
+ timeoutMs?: number,
776
+ failuresBeforeUnhealthy?: number
777
+ }
778
+ })
779
+ ```
780
+
781
+ **Core Methods:**
782
+ - `start(callback?)`
783
+ - `stop(callback?)`
784
+ - `restart(callback?)`
785
+ - `get_abstract()`
786
+
787
+ **Status:**
788
+ ```javascript
789
+ {
790
+ state: 'stopped' | 'starting' | 'running' | 'stopping' | 'restarting' | 'crashed',
791
+ pid: number | null,
792
+ uptime: number,
793
+ restartCount: number,
794
+ lastHealthCheck: object | null,
795
+ memoryUsage: object | null,
796
+ processManager: { type: 'direct' | 'pm2' }
797
+ }
798
+ ```
799
+
800
+ **Events:**
801
+ - `state_change`
802
+ - `stdout`
803
+ - `stderr`
804
+ - `exit`
805
+ - `health_check`
806
+ - `unhealthy`
807
+ - `crashed`
808
+
809
+ ### Remote_Process_Resource
810
+
811
+ Represents a remote HTTP-controlled process using the same lifecycle-oriented API style as `Process_Resource`.
812
+
813
+ **Extends:** `Resource`
814
+
815
+ **Constructor:**
816
+ ```javascript
817
+ new Remote_Process_Resource(spec?: {
818
+ name?: string,
819
+ host: string,
820
+ port: number,
821
+ protocol?: 'http' | 'https',
822
+ pollIntervalMs?: number,
823
+ httpTimeoutMs?: number,
824
+ historySize?: number,
825
+ unreachableFailuresBeforeEvent?: number,
826
+ endpoints?: {
827
+ status?: string,
828
+ start?: string,
829
+ stop?: string,
830
+ health?: string
831
+ }
832
+ })
833
+ ```
834
+
835
+ **Core Methods:**
836
+ - `start(callback?)`
837
+ - `stop(callback?)`
838
+ - `restart(callback?)`
839
+ - `get_abstract()`
840
+
841
+ **Status:** Includes `state`, `pid`, `uptime`, `restartCount`, `lastHealthCheck`, `memoryUsage`, and `processManager: { type: 'remote' }`.
842
+
843
+ **Events:**
844
+ - `state_change`
845
+ - `unreachable`
846
+ - `recovered`
847
+
848
+ ### Server_Resource_Pool
849
+
850
+ Server-specific resource pool with lifecycle orchestration and event forwarding.
851
+
852
+ **Extends:** `Resource_Pool`
853
+
854
+ **Methods:**
855
+ - `add(resource)`
856
+ - `remove(name, callback?)`
857
+ - `start(callback?)`
858
+ - `stop(callback?)`
859
+ - `get_resources_by_type(type)`
860
+
861
+ **Properties:**
862
+ - `summary`: Aggregated state summary grouped by resource type.
863
+
864
+ **Forwarded Events:**
865
+ - `resource_state_change`
866
+ - `crashed`
867
+ - `unhealthy`
868
+ - `unreachable`
869
+ - `recovered`
870
+
871
+ ### File_System_Resource
684
872
 
685
873
  Provides access to local file system.
686
874
 
@@ -912,12 +1100,16 @@ ensure_route_leading_slash(route: string): string
912
1100
  ### ServerOptions
913
1101
 
914
1102
  ```typescript
915
- interface ServerOptions {
916
- ctrl?: Function;
917
- Ctrl?: Function;
918
- src_path_client_js?: string;
1103
+ interface ServerOptions {
1104
+ ctrl?: Function;
1105
+ Ctrl?: Function;
1106
+ src_path_client_js?: string;
919
1107
  port?: number;
920
1108
  host?: string;
1109
+ on_port_conflict?: 'error' | 'auto-loopback';
1110
+ start?: {
1111
+ on_port_conflict?: 'error' | 'auto-loopback';
1112
+ };
921
1113
  debug?: boolean;
922
1114
  name?: string;
923
1115
  root?: string;
@@ -928,60 +1120,66 @@ interface ServerOptions {
928
1120
  api?: Record<string, Function>;
929
1121
  static?: Record<string, string>;
930
1122
 
931
- // Advanced options
932
- cors?: CorsConfig;
933
- https?: HttpsConfig;
934
- middleware?: Function[];
935
- publishers?: Record<string, Publisher>;
936
- resources?: ResourceEntries;
937
- events?: boolean | EventsOptions;
938
- bundler?: BundlerConfig;
939
- }
940
- ```
941
-
942
- ```typescript
943
- type ResourceEntries = Record<string, ResourceEntry> | ResourceEntry[];
944
-
945
- type ResourceEntry =
946
- | Resource
947
- | {
948
- type?: 'process' | 'local';
949
- command?: string;
950
- args?: string[];
951
- processManager?: 'direct' | {
952
- type?: 'direct' | 'pm2';
953
- pm2Path?: string;
954
- ecosystem?: string;
955
- };
956
- [key: string]: any;
957
- }
958
- | {
959
- type?: 'remote' | 'http';
960
- host?: string;
961
- port?: number;
962
- protocol?: 'http' | 'https';
963
- endpoints?: Record<string, string>;
964
- [key: string]: any;
965
- }
966
- | {
967
- type?: 'resource' | 'in_process' | 'in-process';
968
- instance?: Resource;
969
- resource?: Resource;
970
- class?: new (spec?: any) => Resource;
971
- Ctor?: new (spec?: any) => Resource;
972
- constructor_fn?: new (spec?: any) => Resource;
973
- spec?: Record<string, any>;
974
- [key: string]: any;
975
- };
976
-
977
- interface EventsOptions {
978
- route?: string;
979
- name?: string;
980
- keepaliveIntervalMs?: number;
981
- maxClients?: number;
982
- eventHistorySize?: number;
983
- }
984
- ```
1123
+ // Middleware & compression
1124
+ middleware?: Function | Function[]; // (req, res, next) middleware functions
1125
+ compression?: boolean | { // Enable built-in compression middleware
1126
+ threshold?: number; // Min body size to compress (default 1024)
1127
+ level?: number; // zlib level (default Z_DEFAULT_COMPRESSION)
1128
+ };
1129
+
1130
+ // Advanced options
1131
+ cors?: CorsConfig;
1132
+ https?: HttpsConfig;
1133
+ publishers?: Record<string, Publisher>;
1134
+ resources?: ResourceEntries;
1135
+ events?: boolean | EventsOptions;
1136
+ bundler?: BundlerConfig;
1137
+ }
1138
+ ```
1139
+
1140
+ ```typescript
1141
+ type ResourceEntries = Record<string, ResourceEntry> | ResourceEntry[];
1142
+
1143
+ type ResourceEntry =
1144
+ | Resource
1145
+ | {
1146
+ type?: 'process' | 'local';
1147
+ command?: string;
1148
+ args?: string[];
1149
+ processManager?: 'direct' | {
1150
+ type?: 'direct' | 'pm2';
1151
+ pm2Path?: string;
1152
+ ecosystem?: string;
1153
+ };
1154
+ [key: string]: any;
1155
+ }
1156
+ | {
1157
+ type?: 'remote' | 'http';
1158
+ host?: string;
1159
+ port?: number;
1160
+ protocol?: 'http' | 'https';
1161
+ endpoints?: Record<string, string>;
1162
+ [key: string]: any;
1163
+ }
1164
+ | {
1165
+ type?: 'resource' | 'in_process' | 'in-process';
1166
+ instance?: Resource;
1167
+ resource?: Resource;
1168
+ class?: new (spec?: any) => Resource;
1169
+ Ctor?: new (spec?: any) => Resource;
1170
+ constructor_fn?: new (spec?: any) => Resource;
1171
+ spec?: Record<string, any>;
1172
+ [key: string]: any;
1173
+ };
1174
+
1175
+ interface EventsOptions {
1176
+ route?: string;
1177
+ name?: string;
1178
+ keepaliveIntervalMs?: number;
1179
+ maxClients?: number;
1180
+ eventHistorySize?: number;
1181
+ }
1182
+ ```
985
1183
 
986
1184
  ### PageConfig
987
1185
 
@@ -1287,4 +1485,4 @@ const server = await Server.serve({
1287
1485
 
1288
1486
  ---
1289
1487
 
1290
- This API reference provides comprehensive technical documentation for JSGUI3 Server internals. For practical usage examples and tutorials, refer to the user-facing documentation.
1488
+ This API reference provides comprehensive technical documentation for JSGUI3 Server internals. For practical usage examples and tutorials, refer to the user-facing documentation.