jsgui3-server 0.0.148 → 0.0.150
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/.github/agents/Mobile Developer.agent.md +89 -0
- package/.github/workflows/control-scan-manifest-check.yml +31 -0
- package/AGENTS.md +4 -0
- package/README.md +215 -3
- package/admin-ui/client.js +81 -51
- package/admin-ui/v1/admin_auth_service.js +197 -0
- package/admin-ui/v1/admin_user_store.js +71 -0
- package/admin-ui/v1/client.js +17 -0
- package/admin-ui/v1/controls/admin_shell.js +1399 -0
- package/admin-ui/v1/controls/group_box.js +84 -0
- package/admin-ui/v1/controls/stat_card.js +125 -0
- package/admin-ui/v1/server.js +658 -0
- package/admin-ui/v1/utils/formatters.js +68 -0
- package/dev-status.svg +139 -0
- package/docs/admin-extension-guide.md +345 -0
- package/docs/api-reference.md +301 -43
- package/docs/books/adaptive-control-improvements/01-control-candidate-matrix.md +122 -0
- package/docs/books/adaptive-control-improvements/02-tier-1-layout-playbooks.md +207 -0
- package/docs/books/adaptive-control-improvements/03-tier-2-navigation-form-overlay.md +140 -0
- package/docs/books/adaptive-control-improvements/04-cross-cutting-platform-functionality.md +141 -0
- package/docs/books/adaptive-control-improvements/05-styling-theming-density-upgrades.md +114 -0
- package/docs/books/adaptive-control-improvements/06-testing-quality-gates.md +97 -0
- package/docs/books/adaptive-control-improvements/07-delivery-roadmap-and-ownership.md +137 -0
- package/docs/books/adaptive-control-improvements/08-appendix-tier1-acceptance-and-pr-templates.md +261 -0
- package/docs/books/adaptive-control-improvements/README.md +66 -0
- package/docs/books/admin-ui-authentication/01-threat-model-and-goals.md +124 -0
- package/docs/books/admin-ui-authentication/02-session-model-and-token-model.md +75 -0
- package/docs/books/admin-ui-authentication/03-auth-middleware-patterns.md +77 -0
- package/docs/books/admin-ui-authentication/README.md +25 -0
- package/docs/books/creating-a-new-admin-ui/01-introduction-and-vision.md +130 -0
- package/docs/books/creating-a-new-admin-ui/02-architecture-and-data-flow.md +298 -0
- package/docs/books/creating-a-new-admin-ui/03-server-introspection.md +381 -0
- package/docs/books/creating-a-new-admin-ui/04-admin-module-adapter-layer.md +592 -0
- package/docs/books/creating-a-new-admin-ui/05-domain-controls-stat-cards-and-gauges.md +513 -0
- package/docs/books/creating-a-new-admin-ui/06-domain-controls-process-manager.md +544 -0
- package/docs/books/creating-a-new-admin-ui/07-domain-controls-resource-pool-inspector.md +493 -0
- package/docs/books/creating-a-new-admin-ui/08-domain-controls-route-table-and-api-explorer.md +586 -0
- package/docs/books/creating-a-new-admin-ui/09-domain-controls-log-viewer-and-activity-feed.md +490 -0
- package/docs/books/creating-a-new-admin-ui/10-domain-controls-build-status-and-bundle-inspector.md +526 -0
- package/docs/books/creating-a-new-admin-ui/11-domain-controls-configuration-panel.md +808 -0
- package/docs/books/creating-a-new-admin-ui/12-admin-shell-layout-sidebar-navigation.md +210 -0
- package/docs/books/creating-a-new-admin-ui/13-telemetry-integration.md +556 -0
- package/docs/books/creating-a-new-admin-ui/14-realtime-sse-observable-integration.md +485 -0
- package/docs/books/creating-a-new-admin-ui/15-styling-theming-aero-design-system.md +521 -0
- package/docs/books/creating-a-new-admin-ui/16-testing-and-quality-assurance.md +147 -0
- package/docs/books/creating-a-new-admin-ui/17-next-steps-process-resource-roadmap.md +356 -0
- package/docs/books/creating-a-new-admin-ui/README.md +68 -0
- package/docs/books/device-adaptive-composition/01-platform-feature-audit.md +177 -0
- package/docs/books/device-adaptive-composition/02-responsive-composition-model.md +187 -0
- package/docs/books/device-adaptive-composition/03-data-model-vs-view-model.md +231 -0
- package/docs/books/device-adaptive-composition/04-styling-theme-breakpoints.md +234 -0
- package/docs/books/device-adaptive-composition/05-showcase-app-multi-device-assessment.md +193 -0
- package/docs/books/device-adaptive-composition/06-implementation-patterns-and-apis.md +346 -0
- package/docs/books/device-adaptive-composition/07-testing-harness-and-quality-gates.md +265 -0
- package/docs/books/device-adaptive-composition/08-roadmap-and-adoption-plan.md +250 -0
- package/docs/books/device-adaptive-composition/README.md +47 -0
- package/docs/books/jsgui3-bundling-research-book/00-table-of-contents.md +35 -0
- package/docs/books/jsgui3-bundling-research-book/01-pipeline-and-runtime-semantics.md +34 -0
- package/docs/books/jsgui3-bundling-research-book/02-javascript-bundling-core.md +36 -0
- package/docs/books/jsgui3-bundling-research-book/03-style-extraction-and-css-compilation.md +35 -0
- package/docs/books/jsgui3-bundling-research-book/04-static-publishing-and-delivery.md +39 -0
- package/docs/books/jsgui3-bundling-research-book/05-current-limits-and-size-bloat-vectors.md +25 -0
- package/docs/books/jsgui3-bundling-research-book/06-unused-module-elimination-strategy.md +77 -0
- package/docs/books/jsgui3-bundling-research-book/07-jsgui3-html-control-and-mixin-pruning.md +63 -0
- package/docs/books/jsgui3-bundling-research-book/08-test-and-verification-methodology.md +43 -0
- package/docs/books/jsgui3-bundling-research-book/09-roadmap-and-rollout.md +42 -0
- package/docs/books/jsgui3-bundling-research-book/10-further-research-strategies-and-upgrades.md +211 -0
- package/docs/books/jsgui3-bundling-research-book/README.md +35 -0
- package/docs/bundling-system-deep-dive.md +9 -4
- package/docs/comparison-report-express-plex-cpanel.md +549 -0
- package/docs/comprehensive-documentation.md +49 -18
- package/docs/configuration-reference.md +152 -27
- package/docs/core/README.md +19 -0
- package/docs/core/jsgui3-server-core-book/00-table-of-contents.md +21 -0
- package/docs/core/jsgui3-server-core-book/01-startup-readiness-state-machine.md +41 -0
- package/docs/core/jsgui3-server-core-book/02-resource-abstraction-and-lifecycle.md +92 -0
- package/docs/core/jsgui3-server-core-book/03-resource-pool-and-event-topology.md +47 -0
- package/docs/core/jsgui3-server-core-book/04-sse-publisher-semantics.md +41 -0
- package/docs/core/jsgui3-server-core-book/05-serve-factory-resource-wiring.md +46 -0
- package/docs/core/jsgui3-server-core-book/06-e2e-testing-methodology.md +48 -0
- package/docs/core/jsgui3-server-core-book/07-defect-detection-and-hardening-loop.md +47 -0
- package/docs/designs/server-admin-interface-aero.svg +611 -0
- package/docs/publishers-guide.md +59 -4
- package/docs/resources-guide.md +184 -35
- package/docs/simple-server-api-design.md +72 -17
- package/docs/system-architecture.md +18 -14
- package/docs/troubleshooting.md +84 -53
- package/examples/controls/15) window, observable SSE/server.js +6 -1
- package/examples/controls/19) window, auto observable ui/server.js +9 -0
- package/examples/controls/20) window, task manager app/README.md +133 -0
- package/examples/controls/20) window, task manager app/client.js +797 -0
- package/examples/controls/20) window, task manager app/server.js +178 -0
- package/examples/controls/6) window, color_palette/client.js +165 -68
- package/examples/controls/9) window, date picker/client.js +362 -76
- package/examples/controls/9b) window, shared data.model mirrored date pickers/client.js +104 -83
- package/examples/jsgui3-html/06) theming/client.js +22 -1
- package/examples/jsgui3-html/10) binding-debugger/client.js +137 -1
- package/http/responders/static/Static_Route_HTTP_Responder.js +52 -34
- package/lab/experiments/capture-color-controls.js +196 -0
- package/lab/results/screenshots/color-controls/full_page.png +0 -0
- package/lab/results/screenshots/color-controls/section_1_color_grid_12x12.png +0 -0
- package/lab/results/screenshots/color-controls/section_2_color_grid_4x2.png +0 -0
- package/lab/results/screenshots/color-controls/section_3_color_palette.png +0 -0
- package/lab/results/screenshots/color-controls/section_4_palette_comparison.png +0 -0
- package/lab/results/screenshots/color-controls/section_5_raw_swatches.png +0 -0
- package/lab/results/screenshots/color-controls/section_6_optimized_crayola.png +0 -0
- package/lab/results/screenshots/color-controls/section_7_pastel_palette.png +0 -0
- package/lab/results/screenshots/color-controls/section_8_extended_144.png +0 -0
- package/lab/screenshot-utils.js +248 -0
- package/module.js +12 -0
- package/package.json +12 -2
- package/publishers/Publishers.js +4 -3
- package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +5 -5
- package/publishers/http-sse-publisher.js +341 -0
- package/resources/process-resource.js +950 -0
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +129 -33
- package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +18 -7
- package/resources/processors/bundlers/js/esbuild/JSGUI3_HTML_Control_Optimizer.js +829 -0
- package/resources/remote-process-resource.js +355 -0
- package/resources/server-resource-pool.js +354 -41
- package/serve-factory.js +442 -259
- package/server.js +288 -13
- package/tests/README.md +71 -4
- package/tests/admin-ui-jsgui-controls.test.js +581 -0
- package/tests/admin-ui-render.test.js +24 -0
- package/tests/assigners.test.js +56 -40
- package/tests/bundling-default-control-elimination.puppeteer.test.js +260 -0
- package/tests/configuration-validation.test.js +21 -18
- package/tests/content-analysis.test.js +7 -6
- package/tests/control-optimizer-cache-behavior.test.js +52 -0
- package/tests/control-scan-manifest-regression.test.js +144 -0
- package/tests/end-to-end.test.js +15 -14
- package/tests/error-handling.test.js +222 -179
- package/tests/fixtures/bundling-default-button-client.js +37 -0
- package/tests/fixtures/bundling-default-window-client.js +34 -0
- package/tests/fixtures/control_scan_manifest_expectations.json +48 -0
- package/tests/fixtures/resource-monitor-client.js +319 -0
- package/tests/helpers/puppeteer-e2e-harness.js +317 -0
- package/tests/http-sse-publisher.test.js +136 -0
- package/tests/performance.test.js +69 -65
- package/tests/process-resource.test.js +138 -0
- package/tests/publishers.test.js +7 -7
- package/tests/remote-process-resource.test.js +160 -0
- package/tests/sass-controls.e2e.test.js +7 -1
- package/tests/serve-resources.test.js +270 -0
- package/tests/serve.test.js +120 -50
- package/tests/server-resource-pool.test.js +106 -0
- package/tests/small-controls-bundle-size.test.js +252 -0
- package/tests/test-runner.js +14 -1
- package/tests/window-examples.puppeteer.test.js +204 -1
- package/tests/window-resource-integration.puppeteer.test.js +585 -0
- package/tests/temp_invalid.js +0 -7
- package/tests/temp_invalid_utf8.js +0 -1
- package/tests/temp_malformed.js +0 -10
|
@@ -129,7 +129,7 @@ Configuration values are resolved in this order (later sources override earlier
|
|
|
129
129
|
});
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
### API Configuration
|
|
132
|
+
### API Configuration
|
|
133
133
|
|
|
134
134
|
#### `api`
|
|
135
135
|
- **Type:** `object`
|
|
@@ -154,9 +154,81 @@ Configuration values are resolved in this order (later sources override earlier
|
|
|
154
154
|
'echo': (data) => data
|
|
155
155
|
}
|
|
156
156
|
});
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
###
|
|
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
|
|
160
232
|
|
|
161
233
|
#### `static`
|
|
162
234
|
- **Type:** `object`
|
|
@@ -349,21 +421,70 @@ Server.serve({
|
|
|
349
421
|
});
|
|
350
422
|
```
|
|
351
423
|
|
|
352
|
-
### Resource Pools
|
|
353
|
-
|
|
354
|
-
```javascript
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
366
|
-
|
|
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
|
+
```
|
|
367
488
|
|
|
368
489
|
### Middleware
|
|
369
490
|
|
|
@@ -402,14 +523,18 @@ Server.serve({ port: 'not-a-number' });
|
|
|
402
523
|
- **Required:** None (auto-discovery provides defaults)
|
|
403
524
|
- **Optional:** All options have sensible defaults
|
|
404
525
|
|
|
405
|
-
### Validation Rules
|
|
406
|
-
|
|
407
|
-
- `port`: Must be number between 1-65535 or 0 (ephemeral)
|
|
408
|
-
- `host`: Must be valid IPv4 address or hostname
|
|
409
|
-
- `debug`: Converted to boolean using truthy() function
|
|
410
|
-
- `pages`: Each page must have `content` property
|
|
411
|
-
- `api`: Values must be functions
|
|
412
|
-
- `static`: Values must be strings (directory paths)
|
|
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
|
|
413
538
|
|
|
414
539
|
## Configuration Patterns
|
|
415
540
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Core Documentation
|
|
2
|
+
|
|
3
|
+
This directory contains dense, implementation-first documentation for the active reliability surface of `jsgui3-server`.
|
|
4
|
+
|
|
5
|
+
Current focus:
|
|
6
|
+
|
|
7
|
+
- server startup and readiness semantics
|
|
8
|
+
- unified resource model (in-process, direct process, remote process)
|
|
9
|
+
- resource pool lifecycle and event forwarding
|
|
10
|
+
- SSE event transport for resource telemetry
|
|
11
|
+
- end-to-end browser testing methodology for control + resource integration
|
|
12
|
+
|
|
13
|
+
Primary text:
|
|
14
|
+
|
|
15
|
+
- `docs/core/jsgui3-server-core-book/00-table-of-contents.md`
|
|
16
|
+
|
|
17
|
+
Related deep-dive:
|
|
18
|
+
|
|
19
|
+
- `docs/books/jsgui3-bundling-research-book/README.md`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# jsgui3-server Core Book
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
This book specifies the currently critical execution path: `Server.serve(...)` startup, resource lifecycle control, resource event publication, and browser-level verification of those behaviors.
|
|
6
|
+
|
|
7
|
+
## Chapter Map
|
|
8
|
+
|
|
9
|
+
1. `01-startup-readiness-state-machine.md`
|
|
10
|
+
2. `02-resource-abstraction-and-lifecycle.md`
|
|
11
|
+
3. `03-resource-pool-and-event-topology.md`
|
|
12
|
+
4. `04-sse-publisher-semantics.md`
|
|
13
|
+
5. `05-serve-factory-resource-wiring.md`
|
|
14
|
+
6. `06-e2e-testing-methodology.md`
|
|
15
|
+
7. `07-defect-detection-and-hardening-loop.md`
|
|
16
|
+
|
|
17
|
+
## Reader Contract
|
|
18
|
+
|
|
19
|
+
- This text is dense by design.
|
|
20
|
+
- It assumes familiarity with Node.js HTTP servers, async control flow, and event-driven architecture.
|
|
21
|
+
- It prioritizes invariants, failure modes, and testability over introductory narrative.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 1. Startup Readiness State Machine
|
|
2
|
+
|
|
3
|
+
## Core Problem
|
|
4
|
+
|
|
5
|
+
A server that binds a socket before its route graph is installed can return transient `404` responses during cold start. This is a correctness defect, not a cosmetic delay.
|
|
6
|
+
|
|
7
|
+
## Current Model
|
|
8
|
+
|
|
9
|
+
`Server.serve(...)` now enforces a strict ordering:
|
|
10
|
+
|
|
11
|
+
1. construct `Server` instance
|
|
12
|
+
2. install API publishers and optional SSE publisher
|
|
13
|
+
3. wait for server `ready` event (emitted after webpage/website publisher route installation)
|
|
14
|
+
4. resolve additional page route preparations
|
|
15
|
+
5. bind sockets with `server.start(...)`
|
|
16
|
+
6. start configured resources
|
|
17
|
+
7. resolve `serve(...)` promise
|
|
18
|
+
|
|
19
|
+
## Removed Failure Pattern
|
|
20
|
+
|
|
21
|
+
Previous behavior had a fallback timer that could start listening before `ready`. This allowed requests to arrive before `/` and bundle routes were present.
|
|
22
|
+
|
|
23
|
+
That path is removed. Startup now rejects on readiness timeout instead of entering a half-ready listening state.
|
|
24
|
+
|
|
25
|
+
## Startup Timeout
|
|
26
|
+
|
|
27
|
+
`readyTimeoutMs` (default `120000`) bounds waiting for readiness. Timeout behavior:
|
|
28
|
+
|
|
29
|
+
- if readiness is not reached in time, `serve(...)` rejects
|
|
30
|
+
- no forced early listen occurs
|
|
31
|
+
|
|
32
|
+
This makes startup failure explicit and testable.
|
|
33
|
+
|
|
34
|
+
## Verification
|
|
35
|
+
|
|
36
|
+
`tests/serve.test.js` includes a delayed fake webpage publisher and asserts that:
|
|
37
|
+
|
|
38
|
+
- `serve(...)` does not resolve until delayed readiness arrives
|
|
39
|
+
- post-resolution `/` is immediately routable
|
|
40
|
+
|
|
41
|
+
This test prevents regression to pre-ready listening.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# 2. Resource Abstraction and Lifecycle
|
|
2
|
+
|
|
3
|
+
## Uniform Contract
|
|
4
|
+
|
|
5
|
+
`Process_Resource` and `Remote_Process_Resource` expose the same operational surface:
|
|
6
|
+
|
|
7
|
+
- `start()`
|
|
8
|
+
- `stop()`
|
|
9
|
+
- `restart()`
|
|
10
|
+
- `status` getter
|
|
11
|
+
- `get_abstract()`
|
|
12
|
+
|
|
13
|
+
The contract allows client/API code to remain management-backend agnostic.
|
|
14
|
+
|
|
15
|
+
## Process_Resource Modes
|
|
16
|
+
|
|
17
|
+
`Process_Resource` supports two process managers:
|
|
18
|
+
|
|
19
|
+
- `direct` (default): local child process (`spawn`)
|
|
20
|
+
- `pm2`: external manager integration (`pm2 start/stop/restart/jlist`)
|
|
21
|
+
|
|
22
|
+
PM2 path resolution is optional and automatic:
|
|
23
|
+
|
|
24
|
+
1. `processManager.pm2Path`
|
|
25
|
+
2. `PM2_PATH` env
|
|
26
|
+
3. local `node_modules/.bin/pm2(.cmd)`
|
|
27
|
+
4. `pm2` from `PATH`
|
|
28
|
+
|
|
29
|
+
Therefore explicit `pm2Path` is not required for default operation.
|
|
30
|
+
|
|
31
|
+
## State Machine
|
|
32
|
+
|
|
33
|
+
Nominal states:
|
|
34
|
+
|
|
35
|
+
- `stopped`
|
|
36
|
+
- `starting`
|
|
37
|
+
- `running`
|
|
38
|
+
- `stopping`
|
|
39
|
+
- `restarting`
|
|
40
|
+
- `crashed`
|
|
41
|
+
|
|
42
|
+
`Remote_Process_Resource` additionally uses `unreachable` for transport failure.
|
|
43
|
+
|
|
44
|
+
Each transition emits `state_change` with `{ from, to, timestamp }`.
|
|
45
|
+
|
|
46
|
+
## Operational Signals
|
|
47
|
+
|
|
48
|
+
`Process_Resource` emits:
|
|
49
|
+
|
|
50
|
+
- `stdout` / `stderr` (line-wise)
|
|
51
|
+
- `exit`
|
|
52
|
+
- `health_check`
|
|
53
|
+
- `unhealthy`
|
|
54
|
+
- `crashed`
|
|
55
|
+
|
|
56
|
+
`Remote_Process_Resource` emits:
|
|
57
|
+
|
|
58
|
+
- `state_change`
|
|
59
|
+
- `unreachable`
|
|
60
|
+
- `recovered`
|
|
61
|
+
|
|
62
|
+
## Failure Handling
|
|
63
|
+
|
|
64
|
+
### Local process
|
|
65
|
+
|
|
66
|
+
Unexpected non-zero exit with `autoRestart: true` enters exponential backoff restart.
|
|
67
|
+
|
|
68
|
+
Backoff progression:
|
|
69
|
+
|
|
70
|
+
- base `restartBackoffBaseMs` (default 1000)
|
|
71
|
+
- doubles per attempt
|
|
72
|
+
- capped at 60000ms
|
|
73
|
+
|
|
74
|
+
Exceeding `maxRestarts` transitions to `crashed` and halts auto-restart.
|
|
75
|
+
|
|
76
|
+
### Remote process
|
|
77
|
+
|
|
78
|
+
Transport failures do not map to `crashed`; they map to `unreachable`. Recovery is explicit via `recovered` event when polling succeeds again.
|
|
79
|
+
|
|
80
|
+
## Observability Payload
|
|
81
|
+
|
|
82
|
+
`status` normalizes operational metrics:
|
|
83
|
+
|
|
84
|
+
- state
|
|
85
|
+
- pid (if meaningful)
|
|
86
|
+
- uptime
|
|
87
|
+
- restartCount
|
|
88
|
+
- lastHealthCheck
|
|
89
|
+
- memoryUsage
|
|
90
|
+
- processManager metadata
|
|
91
|
+
|
|
92
|
+
The normalized shape is essential for stable API and UI projections.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# 3. Resource Pool and Event Topology
|
|
2
|
+
|
|
3
|
+
## Role
|
|
4
|
+
|
|
5
|
+
`Server_Resource_Pool` is the system-wide resource coordinator. It extends `Resource_Pool` and adds lifecycle orchestration plus event fan-in.
|
|
6
|
+
|
|
7
|
+
## Lifecycle Surface
|
|
8
|
+
|
|
9
|
+
Implemented operations:
|
|
10
|
+
|
|
11
|
+
- `add(resource)` / `push(resource)`
|
|
12
|
+
- `remove(name)` with stop-on-remove semantics
|
|
13
|
+
- `start(callback)` start-all
|
|
14
|
+
- `stop(callback)` stop-all
|
|
15
|
+
- `get_resources_by_type(type)`
|
|
16
|
+
- `summary` getter
|
|
17
|
+
|
|
18
|
+
## Event Fan-In
|
|
19
|
+
|
|
20
|
+
Pool-level forwarded events:
|
|
21
|
+
|
|
22
|
+
- `resource_state_change`
|
|
23
|
+
- `crashed`
|
|
24
|
+
- `unhealthy`
|
|
25
|
+
- `unreachable`
|
|
26
|
+
- `recovered`
|
|
27
|
+
|
|
28
|
+
Forwarding payload includes `resourceName` plus original event fields.
|
|
29
|
+
|
|
30
|
+
This gives a single subscription point for system telemetry.
|
|
31
|
+
|
|
32
|
+
## Summary as Fleet Snapshot
|
|
33
|
+
|
|
34
|
+
`summary` aggregates:
|
|
35
|
+
|
|
36
|
+
- totals by state (`running`, `stopped`, `crashed`, `unreachable`, ...)
|
|
37
|
+
- `byType` entries with `get_abstract()` output per resource
|
|
38
|
+
|
|
39
|
+
`summary` is designed for status APIs and dashboard views.
|
|
40
|
+
|
|
41
|
+
## Correctness Invariants
|
|
42
|
+
|
|
43
|
+
1. removing a resource must detach forwarded listeners
|
|
44
|
+
2. stop-all must tolerate mixed callback/promise resource implementations
|
|
45
|
+
3. no event should lose resource identity when forwarded
|
|
46
|
+
|
|
47
|
+
`tests/server-resource-pool.test.js` and `tests/serve-resources.test.js` exercise these invariants.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 4. SSE Publisher Semantics
|
|
2
|
+
|
|
3
|
+
## Component
|
|
4
|
+
|
|
5
|
+
`HTTP_SSE_Publisher` is a general-purpose server-sent events publisher, separate from observable-specific transport.
|
|
6
|
+
|
|
7
|
+
## Responsibilities
|
|
8
|
+
|
|
9
|
+
- maintain connection registry (`client_id -> response stream`)
|
|
10
|
+
- format protocol-correct SSE frames (`id`, `event`, `data`)
|
|
11
|
+
- provide `broadcast(event, data)`
|
|
12
|
+
- provide `send(client_id, event, data)`
|
|
13
|
+
- issue keepalive comments (`:keepalive`) to prevent idle timeout
|
|
14
|
+
- maintain bounded event history for replay
|
|
15
|
+
- support `Last-Event-ID` replay on reconnect
|
|
16
|
+
|
|
17
|
+
## Delivery Semantics
|
|
18
|
+
|
|
19
|
+
- event IDs are monotonic and server-local
|
|
20
|
+
- replay sends events with `id > last_event_id`
|
|
21
|
+
- delivery is best-effort per connected client
|
|
22
|
+
- failed writes trigger client disconnect cleanup
|
|
23
|
+
|
|
24
|
+
## Operational Constraints
|
|
25
|
+
|
|
26
|
+
- max client guard (`maxClients`)
|
|
27
|
+
- explicit `stop()` for deterministic shutdown
|
|
28
|
+
- keepalive timer lifecycle tied to active client count
|
|
29
|
+
|
|
30
|
+
## Integration Contract
|
|
31
|
+
|
|
32
|
+
When `Server.serve({ events: true })` is used, pool events are bridged into SSE broadcasts. Resource state transitions become browser-consumable without client polling loops.
|
|
33
|
+
|
|
34
|
+
## Verification
|
|
35
|
+
|
|
36
|
+
`tests/http-sse-publisher.test.js` validates:
|
|
37
|
+
|
|
38
|
+
- multi-client broadcast
|
|
39
|
+
- targeted delivery
|
|
40
|
+
- keepalive emission
|
|
41
|
+
- replay via `Last-Event-ID`
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# 5. Serve Factory Resource Wiring
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
|
|
5
|
+
`Server.serve(...)` must be a single-entry composition API that can instantiate and wire:
|
|
6
|
+
|
|
7
|
+
- pages / controls
|
|
8
|
+
- API handlers
|
|
9
|
+
- resources (process or remote)
|
|
10
|
+
- SSE endpoint for resource events
|
|
11
|
+
|
|
12
|
+
without requiring the caller to manually compose internals.
|
|
13
|
+
|
|
14
|
+
## Resource Configuration Forms
|
|
15
|
+
|
|
16
|
+
Accepted `resources` forms include:
|
|
17
|
+
|
|
18
|
+
- direct resource instance
|
|
19
|
+
- constructor function / class
|
|
20
|
+
- `{ class | Ctor | constructor_fn, ...spec }`
|
|
21
|
+
- `{ type: 'process' | 'remote', ...spec }`
|
|
22
|
+
|
|
23
|
+
Type inference fallbacks:
|
|
24
|
+
|
|
25
|
+
- `command` or `processManager` -> `Process_Resource`
|
|
26
|
+
- `host` or `endpoints` -> `Remote_Process_Resource`
|
|
27
|
+
|
|
28
|
+
## Event Bridge
|
|
29
|
+
|
|
30
|
+
With `events: true`:
|
|
31
|
+
|
|
32
|
+
- `HTTP_SSE_Publisher` mounted on `/events` (or configured route)
|
|
33
|
+
- pool events broadcast onto SSE stream
|
|
34
|
+
|
|
35
|
+
This creates a default telemetry channel with zero extra server code.
|
|
36
|
+
|
|
37
|
+
## Startup Ordering
|
|
38
|
+
|
|
39
|
+
1. configure APIs, events, and resource specs
|
|
40
|
+
2. wait for ready
|
|
41
|
+
3. start listening
|
|
42
|
+
4. start configured resources
|
|
43
|
+
|
|
44
|
+
## Shutdown Ordering
|
|
45
|
+
|
|
46
|
+
`server.close()` triggers resource pool stop and SSE stop before closing HTTP servers. This prevents orphan resources and dangling SSE clients.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 6. E2E Testing Methodology
|
|
2
|
+
|
|
3
|
+
## Principle
|
|
4
|
+
|
|
5
|
+
A browser E2E test is valid only if it asserts both:
|
|
6
|
+
|
|
7
|
+
- user-visible state (DOM/control behavior)
|
|
8
|
+
- server truth (resource/process state, event emission)
|
|
9
|
+
|
|
10
|
+
UI-only assertions are necessary but insufficient for fullstack correctness.
|
|
11
|
+
|
|
12
|
+
## Harness
|
|
13
|
+
|
|
14
|
+
`tests/helpers/puppeteer-e2e-harness.js` provides:
|
|
15
|
+
|
|
16
|
+
- deterministic step runner (`run_interaction_story`)
|
|
17
|
+
- browser probe capture (`console`, `pageerror`, request failures)
|
|
18
|
+
- shared page/server boot helpers
|
|
19
|
+
- stable interaction primitives (input event dispatch, drag)
|
|
20
|
+
|
|
21
|
+
This converts long imperative test scripts into explicit state-transition stories.
|
|
22
|
+
|
|
23
|
+
## Story Pattern
|
|
24
|
+
|
|
25
|
+
Each step has:
|
|
26
|
+
|
|
27
|
+
- `name`
|
|
28
|
+
- `run(page)`
|
|
29
|
+
- optional `assert(page)`
|
|
30
|
+
|
|
31
|
+
Failure is annotated with `[story :: step]` to localize defects quickly.
|
|
32
|
+
|
|
33
|
+
## Current High-Value Scenarios
|
|
34
|
+
|
|
35
|
+
1. control interaction precision (`Date_Picker` + `Datetime_Picker`)
|
|
36
|
+
2. client-driven resource lifecycle control (`start/stop/restart`)
|
|
37
|
+
3. SSE propagation to browser and UI projection
|
|
38
|
+
4. parity check between browser-observed state and server-side resource state
|
|
39
|
+
|
|
40
|
+
Implemented in:
|
|
41
|
+
|
|
42
|
+
- `tests/window-resource-integration.puppeteer.test.js`
|
|
43
|
+
|
|
44
|
+
## Stability Guards
|
|
45
|
+
|
|
46
|
+
- route readiness gate before browser navigation in resource integration tests
|
|
47
|
+
- allowlist-based probe assertions for expected disconnect noise (`/events` abort on close)
|
|
48
|
+
- strict no-unexpected-console-error policy
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# 7. Defect Detection and Hardening Loop
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Maximize bug discovery rate while minimizing false confidence.
|
|
6
|
+
|
|
7
|
+
## Loop
|
|
8
|
+
|
|
9
|
+
1. define invariant
|
|
10
|
+
2. encode invariant as automated test
|
|
11
|
+
3. reproduce failure deterministically
|
|
12
|
+
4. implement smallest correctness-preserving fix
|
|
13
|
+
5. re-run focused suite
|
|
14
|
+
6. run regression suites touching adjacent surfaces
|
|
15
|
+
7. document invariant and fix rationale
|
|
16
|
+
|
|
17
|
+
## Practical Invariants for Current Surface
|
|
18
|
+
|
|
19
|
+
### Startup / Routing
|
|
20
|
+
|
|
21
|
+
- `serve()` must not resolve before root route availability
|
|
22
|
+
- startup timeout must fail explicitly, not partially start
|
|
23
|
+
|
|
24
|
+
### Resource Management
|
|
25
|
+
|
|
26
|
+
- `stop()` semantics are idempotent for already-stopped resources
|
|
27
|
+
- crash vs unreachable classification must remain distinct
|
|
28
|
+
- process manager backend must not leak into consumer API shape
|
|
29
|
+
|
|
30
|
+
### Eventing
|
|
31
|
+
|
|
32
|
+
- every forwarded resource event must include `resourceName`
|
|
33
|
+
- SSE replay must preserve event ordering by event ID
|
|
34
|
+
|
|
35
|
+
### Browser Integration
|
|
36
|
+
|
|
37
|
+
- client action routes must be observable in captured API call log
|
|
38
|
+
- SSE state transitions must drive UI state within bounded time
|
|
39
|
+
|
|
40
|
+
## Recommended Additional Test Work
|
|
41
|
+
|
|
42
|
+
1. Add a chaos-style resource test with rapid start/stop/restart bursts and assert no deadlock.
|
|
43
|
+
2. Add remote resource failure flapping test (unreachable/recovered oscillation) with threshold validation.
|
|
44
|
+
3. Add SSE reconnection E2E test in browser with explicit `Last-Event-ID` continuity assertion.
|
|
45
|
+
4. Add matrix tests across process manager modes (`direct`, `pm2` if available) under the same API contract assertions.
|
|
46
|
+
|
|
47
|
+
These increase confidence in concurrency and degraded-network behavior, where latent bugs usually appear.
|