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.
Files changed (154) hide show
  1. package/.github/agents/Mobile Developer.agent.md +89 -0
  2. package/.github/workflows/control-scan-manifest-check.yml +31 -0
  3. package/AGENTS.md +4 -0
  4. package/README.md +215 -3
  5. package/admin-ui/client.js +81 -51
  6. package/admin-ui/v1/admin_auth_service.js +197 -0
  7. package/admin-ui/v1/admin_user_store.js +71 -0
  8. package/admin-ui/v1/client.js +17 -0
  9. package/admin-ui/v1/controls/admin_shell.js +1399 -0
  10. package/admin-ui/v1/controls/group_box.js +84 -0
  11. package/admin-ui/v1/controls/stat_card.js +125 -0
  12. package/admin-ui/v1/server.js +658 -0
  13. package/admin-ui/v1/utils/formatters.js +68 -0
  14. package/dev-status.svg +139 -0
  15. package/docs/admin-extension-guide.md +345 -0
  16. package/docs/api-reference.md +301 -43
  17. package/docs/books/adaptive-control-improvements/01-control-candidate-matrix.md +122 -0
  18. package/docs/books/adaptive-control-improvements/02-tier-1-layout-playbooks.md +207 -0
  19. package/docs/books/adaptive-control-improvements/03-tier-2-navigation-form-overlay.md +140 -0
  20. package/docs/books/adaptive-control-improvements/04-cross-cutting-platform-functionality.md +141 -0
  21. package/docs/books/adaptive-control-improvements/05-styling-theming-density-upgrades.md +114 -0
  22. package/docs/books/adaptive-control-improvements/06-testing-quality-gates.md +97 -0
  23. package/docs/books/adaptive-control-improvements/07-delivery-roadmap-and-ownership.md +137 -0
  24. package/docs/books/adaptive-control-improvements/08-appendix-tier1-acceptance-and-pr-templates.md +261 -0
  25. package/docs/books/adaptive-control-improvements/README.md +66 -0
  26. package/docs/books/admin-ui-authentication/01-threat-model-and-goals.md +124 -0
  27. package/docs/books/admin-ui-authentication/02-session-model-and-token-model.md +75 -0
  28. package/docs/books/admin-ui-authentication/03-auth-middleware-patterns.md +77 -0
  29. package/docs/books/admin-ui-authentication/README.md +25 -0
  30. package/docs/books/creating-a-new-admin-ui/01-introduction-and-vision.md +130 -0
  31. package/docs/books/creating-a-new-admin-ui/02-architecture-and-data-flow.md +298 -0
  32. package/docs/books/creating-a-new-admin-ui/03-server-introspection.md +381 -0
  33. package/docs/books/creating-a-new-admin-ui/04-admin-module-adapter-layer.md +592 -0
  34. package/docs/books/creating-a-new-admin-ui/05-domain-controls-stat-cards-and-gauges.md +513 -0
  35. package/docs/books/creating-a-new-admin-ui/06-domain-controls-process-manager.md +544 -0
  36. package/docs/books/creating-a-new-admin-ui/07-domain-controls-resource-pool-inspector.md +493 -0
  37. package/docs/books/creating-a-new-admin-ui/08-domain-controls-route-table-and-api-explorer.md +586 -0
  38. package/docs/books/creating-a-new-admin-ui/09-domain-controls-log-viewer-and-activity-feed.md +490 -0
  39. package/docs/books/creating-a-new-admin-ui/10-domain-controls-build-status-and-bundle-inspector.md +526 -0
  40. package/docs/books/creating-a-new-admin-ui/11-domain-controls-configuration-panel.md +808 -0
  41. package/docs/books/creating-a-new-admin-ui/12-admin-shell-layout-sidebar-navigation.md +210 -0
  42. package/docs/books/creating-a-new-admin-ui/13-telemetry-integration.md +556 -0
  43. package/docs/books/creating-a-new-admin-ui/14-realtime-sse-observable-integration.md +485 -0
  44. package/docs/books/creating-a-new-admin-ui/15-styling-theming-aero-design-system.md +521 -0
  45. package/docs/books/creating-a-new-admin-ui/16-testing-and-quality-assurance.md +147 -0
  46. package/docs/books/creating-a-new-admin-ui/17-next-steps-process-resource-roadmap.md +356 -0
  47. package/docs/books/creating-a-new-admin-ui/README.md +68 -0
  48. package/docs/books/device-adaptive-composition/01-platform-feature-audit.md +177 -0
  49. package/docs/books/device-adaptive-composition/02-responsive-composition-model.md +187 -0
  50. package/docs/books/device-adaptive-composition/03-data-model-vs-view-model.md +231 -0
  51. package/docs/books/device-adaptive-composition/04-styling-theme-breakpoints.md +234 -0
  52. package/docs/books/device-adaptive-composition/05-showcase-app-multi-device-assessment.md +193 -0
  53. package/docs/books/device-adaptive-composition/06-implementation-patterns-and-apis.md +346 -0
  54. package/docs/books/device-adaptive-composition/07-testing-harness-and-quality-gates.md +265 -0
  55. package/docs/books/device-adaptive-composition/08-roadmap-and-adoption-plan.md +250 -0
  56. package/docs/books/device-adaptive-composition/README.md +47 -0
  57. package/docs/books/jsgui3-bundling-research-book/00-table-of-contents.md +35 -0
  58. package/docs/books/jsgui3-bundling-research-book/01-pipeline-and-runtime-semantics.md +34 -0
  59. package/docs/books/jsgui3-bundling-research-book/02-javascript-bundling-core.md +36 -0
  60. package/docs/books/jsgui3-bundling-research-book/03-style-extraction-and-css-compilation.md +35 -0
  61. package/docs/books/jsgui3-bundling-research-book/04-static-publishing-and-delivery.md +39 -0
  62. package/docs/books/jsgui3-bundling-research-book/05-current-limits-and-size-bloat-vectors.md +25 -0
  63. package/docs/books/jsgui3-bundling-research-book/06-unused-module-elimination-strategy.md +77 -0
  64. package/docs/books/jsgui3-bundling-research-book/07-jsgui3-html-control-and-mixin-pruning.md +63 -0
  65. package/docs/books/jsgui3-bundling-research-book/08-test-and-verification-methodology.md +43 -0
  66. package/docs/books/jsgui3-bundling-research-book/09-roadmap-and-rollout.md +42 -0
  67. package/docs/books/jsgui3-bundling-research-book/10-further-research-strategies-and-upgrades.md +211 -0
  68. package/docs/books/jsgui3-bundling-research-book/README.md +35 -0
  69. package/docs/bundling-system-deep-dive.md +9 -4
  70. package/docs/comparison-report-express-plex-cpanel.md +549 -0
  71. package/docs/comprehensive-documentation.md +49 -18
  72. package/docs/configuration-reference.md +152 -27
  73. package/docs/core/README.md +19 -0
  74. package/docs/core/jsgui3-server-core-book/00-table-of-contents.md +21 -0
  75. package/docs/core/jsgui3-server-core-book/01-startup-readiness-state-machine.md +41 -0
  76. package/docs/core/jsgui3-server-core-book/02-resource-abstraction-and-lifecycle.md +92 -0
  77. package/docs/core/jsgui3-server-core-book/03-resource-pool-and-event-topology.md +47 -0
  78. package/docs/core/jsgui3-server-core-book/04-sse-publisher-semantics.md +41 -0
  79. package/docs/core/jsgui3-server-core-book/05-serve-factory-resource-wiring.md +46 -0
  80. package/docs/core/jsgui3-server-core-book/06-e2e-testing-methodology.md +48 -0
  81. package/docs/core/jsgui3-server-core-book/07-defect-detection-and-hardening-loop.md +47 -0
  82. package/docs/designs/server-admin-interface-aero.svg +611 -0
  83. package/docs/publishers-guide.md +59 -4
  84. package/docs/resources-guide.md +184 -35
  85. package/docs/simple-server-api-design.md +72 -17
  86. package/docs/system-architecture.md +18 -14
  87. package/docs/troubleshooting.md +84 -53
  88. package/examples/controls/15) window, observable SSE/server.js +6 -1
  89. package/examples/controls/19) window, auto observable ui/server.js +9 -0
  90. package/examples/controls/20) window, task manager app/README.md +133 -0
  91. package/examples/controls/20) window, task manager app/client.js +797 -0
  92. package/examples/controls/20) window, task manager app/server.js +178 -0
  93. package/examples/controls/6) window, color_palette/client.js +165 -68
  94. package/examples/controls/9) window, date picker/client.js +362 -76
  95. package/examples/controls/9b) window, shared data.model mirrored date pickers/client.js +104 -83
  96. package/examples/jsgui3-html/06) theming/client.js +22 -1
  97. package/examples/jsgui3-html/10) binding-debugger/client.js +137 -1
  98. package/http/responders/static/Static_Route_HTTP_Responder.js +52 -34
  99. package/lab/experiments/capture-color-controls.js +196 -0
  100. package/lab/results/screenshots/color-controls/full_page.png +0 -0
  101. package/lab/results/screenshots/color-controls/section_1_color_grid_12x12.png +0 -0
  102. package/lab/results/screenshots/color-controls/section_2_color_grid_4x2.png +0 -0
  103. package/lab/results/screenshots/color-controls/section_3_color_palette.png +0 -0
  104. package/lab/results/screenshots/color-controls/section_4_palette_comparison.png +0 -0
  105. package/lab/results/screenshots/color-controls/section_5_raw_swatches.png +0 -0
  106. package/lab/results/screenshots/color-controls/section_6_optimized_crayola.png +0 -0
  107. package/lab/results/screenshots/color-controls/section_7_pastel_palette.png +0 -0
  108. package/lab/results/screenshots/color-controls/section_8_extended_144.png +0 -0
  109. package/lab/screenshot-utils.js +248 -0
  110. package/module.js +12 -0
  111. package/package.json +12 -2
  112. package/publishers/Publishers.js +4 -3
  113. package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +5 -5
  114. package/publishers/http-sse-publisher.js +341 -0
  115. package/resources/process-resource.js +950 -0
  116. package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +129 -33
  117. package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +18 -7
  118. package/resources/processors/bundlers/js/esbuild/JSGUI3_HTML_Control_Optimizer.js +829 -0
  119. package/resources/remote-process-resource.js +355 -0
  120. package/resources/server-resource-pool.js +354 -41
  121. package/serve-factory.js +442 -259
  122. package/server.js +288 -13
  123. package/tests/README.md +71 -4
  124. package/tests/admin-ui-jsgui-controls.test.js +581 -0
  125. package/tests/admin-ui-render.test.js +24 -0
  126. package/tests/assigners.test.js +56 -40
  127. package/tests/bundling-default-control-elimination.puppeteer.test.js +260 -0
  128. package/tests/configuration-validation.test.js +21 -18
  129. package/tests/content-analysis.test.js +7 -6
  130. package/tests/control-optimizer-cache-behavior.test.js +52 -0
  131. package/tests/control-scan-manifest-regression.test.js +144 -0
  132. package/tests/end-to-end.test.js +15 -14
  133. package/tests/error-handling.test.js +222 -179
  134. package/tests/fixtures/bundling-default-button-client.js +37 -0
  135. package/tests/fixtures/bundling-default-window-client.js +34 -0
  136. package/tests/fixtures/control_scan_manifest_expectations.json +48 -0
  137. package/tests/fixtures/resource-monitor-client.js +319 -0
  138. package/tests/helpers/puppeteer-e2e-harness.js +317 -0
  139. package/tests/http-sse-publisher.test.js +136 -0
  140. package/tests/performance.test.js +69 -65
  141. package/tests/process-resource.test.js +138 -0
  142. package/tests/publishers.test.js +7 -7
  143. package/tests/remote-process-resource.test.js +160 -0
  144. package/tests/sass-controls.e2e.test.js +7 -1
  145. package/tests/serve-resources.test.js +270 -0
  146. package/tests/serve.test.js +120 -50
  147. package/tests/server-resource-pool.test.js +106 -0
  148. package/tests/small-controls-bundle-size.test.js +252 -0
  149. package/tests/test-runner.js +14 -1
  150. package/tests/window-examples.puppeteer.test.js +204 -1
  151. package/tests/window-resource-integration.puppeteer.test.js +585 -0
  152. package/tests/temp_invalid.js +0 -7
  153. package/tests/temp_invalid_utf8.js +0 -1
  154. package/tests/temp_malformed.js +0 -10
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: Mobile Developer
3
+
4
+ description: Device-adaptive UI specialist for jsgui3-html. Uses the Device-Adaptive Composition book to guide responsive layout, composition, theming, and testing across phone, tablet, and desktop.
5
+
6
+ tools: [vscode, execute, read, agent, edit, search, web, 'playwright/*', todo]
7
+
8
+
9
+ argument-hint: A responsive/adaptive UI task, layout question, or multi-device composition problem.
10
+ ---
11
+ # Mission
12
+ For any work involving responsive layout, multi-device composition, adaptive styling, or mobile/tablet support in jsgui3-html, anchor all decisions in the **Device-Adaptive Composition & Styling** book at `docs/books/device-adaptive-composition/`.
13
+
14
+ # Reference Book — Required Reading
15
+
16
+ Before starting any task, read the relevant chapters:
17
+
18
+ | Chapter | File | When to consult |
19
+ |---------|------|----------------|
20
+ | 1 — Platform Feature Audit | `docs/books/device-adaptive-composition/01-platform-feature-audit.md` | Understanding what layout primitives, tokens, and MVVM infrastructure already exist |
21
+ | 2 — Responsive Composition Model | `docs/books/device-adaptive-composition/02-responsive-composition-model.md` | Designing adaptive shells, choosing between CSS and JS composition, the four-layer model |
22
+ | 3 — Data Model vs View Model | `docs/books/device-adaptive-composition/03-data-model-vs-view-model.md` | Deciding where adaptive state lives (view.data.model, never data.model) |
23
+ | 4 — Styling, Themes, and Breakpoints | `docs/books/device-adaptive-composition/04-styling-theme-breakpoints.md` | Token overrides, density modes, mode attributes, touch target sizing |
24
+ | 5 — Showcase App Assessment | `docs/books/device-adaptive-composition/05-showcase-app-multi-device-assessment.md` | Understanding how the showcase app should adapt per device category |
25
+ | 6 — Implementation Patterns and APIs | `docs/books/device-adaptive-composition/06-implementation-patterns-and-apis.md` | Using View_Environment, compose_adaptive(), responsive params, container-aware utilities |
26
+ | 7 — Testing Harness and Quality Gates | `docs/books/device-adaptive-composition/07-testing-harness-and-quality-gates.md` | Writing viewport-matrix Playwright tests, assertion categories (P0/P1/P2) |
27
+ | 8 — Roadmap and Adoption Plan | `docs/books/device-adaptive-composition/08-roadmap-and-adoption-plan.md` | Phased rollout priorities, what to build vs what to skip |
28
+
29
+ # Non-negotiables
30
+
31
+ - **Consult the book first**: before proposing any adaptive/responsive solution, read the relevant chapter(s) and identify which patterns apply.
32
+ - **Use the four-layer model** (Chapter 2): separate Domain Composition, View Composition, Adaptive Resolution, and Concrete Render concerns.
33
+ - **Keep adaptive state in view models** (Chapter 3): never put layout_mode, density, viewport dimensions, or panel visibility in `data.model`.
34
+ - **Use mode attributes over scattered breakpoints** (Chapter 4): prefer `[data-layout-mode="phone"]` CSS selectors over raw `@media` queries.
35
+ - **Follow the snake_case convention**: all variables, methods, and file names use snake_case per AGENTS.md.
36
+ - **Name the pattern(s)** from the book that you're applying and cite the chapter.
37
+
38
+ # When this applies
39
+
40
+ - Any change involving responsive layout, adaptive composition, or multi-device support
41
+ - Adding or modifying layout primitives (Stack, Drawer, Grid_Gap, Split_Pane)
42
+ - Implementing density modes, touch target sizing, or interaction-mode awareness
43
+ - Writing viewport-matrix Playwright tests
44
+ - Theme profile work involving density or layout-mode token overrides
45
+ - Assessing how a control or app behaves on phone, tablet, or desktop
46
+
47
+ # Key Concepts from the Book
48
+
49
+ ## Four-Layer Composition (Chapter 2)
50
+ - **Layer A** (Domain): business data — device-agnostic, lives in `data.model`
51
+ - **Layer B** (View): regions and component hierarchy — expresses adaptive intent
52
+ - **Layer C** (Adaptive Resolution): environment service resolves mode from viewport/input/preferences
53
+ - **Layer D** (Concrete Render): resolved CSS classes, token values, DOM attributes
54
+
55
+ ## Environment Contract (Chapters 2, 6)
56
+ ```js
57
+ context.view_environment = {
58
+ viewport: { width, height, orientation },
59
+ layout_mode: 'phone' | 'tablet' | 'desktop',
60
+ density_mode: 'compact' | 'cozy' | 'comfortable',
61
+ interaction_mode: 'touch' | 'pointer' | 'hybrid',
62
+ motion_mode: 'normal' | 'reduced'
63
+ };
64
+
65
+ Composition Helper (Chapter 6)
66
+
67
+ compose_adaptive(this, {
68
+ phone: () => this.compose_phone_shell(),
69
+ tablet: () => this.compose_tablet_shell(),
70
+ desktop: () => this.compose_desktop_shell()
71
+ });
72
+
73
+ Viewport Test Matrix (Chapter 7)
74
+ Phone portrait (390×844), Phone landscape (844×390), Tablet portrait (768×1024), Tablet landscape (1024×768), Desktop narrow (1280×720), Desktop wide (1920×1080).
75
+
76
+ If the book doesn't cover it, consult:
77
+ AGENTS.md — project-wide naming conventions, testing patterns, coding style
78
+ docs/accessibility_and_semantics.md — WCAG/ARIA guidance
79
+ control_mixins/keyboard_navigation.js — orientation-aware keyboard handling
80
+ css/jsgui-tokens.css — current token definitions
81
+ controls/organised/AGENT.md — control creation and theming guide
82
+ Output format for adaptive UI tasks
83
+ Include:
84
+
85
+ Book reference: which chapter(s) and pattern(s) apply
86
+ Layer analysis: which of the four layers (A/B/C/D) are affected
87
+ Model placement: what state goes in data.model vs view.data.model vs view.model
88
+ Composition approach: CSS-only (continuous) vs JS composition (discrete) vs both
89
+ Test coverage: which viewport profiles to test, which assertion categories (P0/P1/P2)
@@ -0,0 +1,31 @@
1
+ name: Control Scan Manifest Check
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - master
8
+ pull_request:
9
+
10
+ jobs:
11
+ control-scan-manifest:
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Node
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: '20'
22
+ cache: 'npm'
23
+
24
+ - name: Install dependencies
25
+ run: npm ci
26
+
27
+ - name: Strict manifest regression test
28
+ run: node tests/test-runner.js --test=control-scan-manifest-regression.test.js
29
+
30
+ - name: Small controls bundle check
31
+ run: node tests/test-runner.js --test=small-controls-bundle-size.test.js
package/AGENTS.md CHANGED
@@ -36,6 +36,9 @@
36
36
  - **[docs/agent-development-guide.md](docs/agent-development-guide.md)** - Guide for AI agents working on this codebase
37
37
  - **[docs/broken-functionality-tracker.md](docs/broken-functionality-tracker.md)** - Tracker for broken/incomplete functionality
38
38
 
39
+ ### Admin UI
40
+ - **[docs/admin-extension-guide.md](docs/admin-extension-guide.md)** - Admin UI extension API: custom sections, endpoints, plugins, exported classes
41
+
39
42
  ### Review and Maintenance
40
43
  - **[docs/documentation-review/CURRENT_REVIEW.md](docs/documentation-review/CURRENT_REVIEW.md)** - Current documentation review status and known issues
41
44
 
@@ -58,6 +61,7 @@
58
61
  - **Custom control development** → `docs/controls-development.md`
59
62
  - **Publisher system** → `docs/publishers-guide.md`
60
63
  - **Resource management** → `docs/resources-guide.md`
64
+ - **Admin UI extensions** → `docs/admin-extension-guide.md`
61
65
 
62
66
  ### Agent Development
63
67
  - **Agentic workflow patterns** → `docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md`
package/README.md CHANGED
@@ -8,7 +8,7 @@ This is the primary entry point for understanding the JSGUI3 Server project. Rea
8
8
  - You're looking for quick start guides and basic usage examples
9
9
  - You need to understand the project's capabilities and limitations
10
10
 
11
- **Note:** For detailed API documentation, see [docs/comprehensive-documentation.md](docs/comprehensive-documentation.md). For advanced server API design, see [docs/simple-server-api-design.md](docs/simple-server-api-design.md).
11
+ **Note:** For detailed API documentation, see [docs/comprehensive-documentation.md](docs/comprehensive-documentation.md). For advanced server API design, see [docs/simple-server-api-design.md](docs/simple-server-api-design.md). For dense internals focused on startup, resources, SSE, and E2E verification, see [docs/core/jsgui3-server-core-book/00-table-of-contents.md](docs/core/jsgui3-server-core-book/00-table-of-contents.md). For deep bundling research and lightweight-bundle strategy, see [docs/books/jsgui3-bundling-research-book/README.md](docs/books/jsgui3-bundling-research-book/README.md).
12
12
 
13
13
  # Jsgui3 Server
14
14
 
@@ -72,6 +72,66 @@ Server.serve({
72
72
  });
73
73
  ```
74
74
 
75
+ ### Managed Resources (In-Process, Direct Process, Remote Process)
76
+
77
+ ```javascript
78
+ const Server = require('jsgui3-server');
79
+ const { Resource } = require('jsgui3-server');
80
+
81
+ class In_Process_Cache_Resource extends Resource {
82
+ constructor(spec = {}) {
83
+ super(spec);
84
+ this.cache = new Map();
85
+ }
86
+ start(callback) { callback(null, true); }
87
+ stop(callback) { this.cache.clear(); callback(null, true); }
88
+ }
89
+
90
+ const server = await Server.serve({
91
+ port: 3000,
92
+ api: {
93
+ 'resources/summary': () => server.resource_pool.summary
94
+ },
95
+ resources: {
96
+ // Existing in-process resource instance
97
+ cache: new In_Process_Cache_Resource({ name: 'cache' }),
98
+
99
+ // Local child process (default process_manager is direct)
100
+ worker_direct: {
101
+ type: 'process',
102
+ command: process.execPath,
103
+ args: ['worker.js'],
104
+ autoRestart: true
105
+ },
106
+
107
+ // Local process managed by PM2 (pm2Path is optional)
108
+ worker_pm2: {
109
+ type: 'process',
110
+ processManager: {
111
+ type: 'pm2'
112
+ },
113
+ command: process.execPath,
114
+ args: ['worker.js']
115
+ },
116
+
117
+ // Remote process controlled over HTTP
118
+ remote_worker: {
119
+ type: 'remote',
120
+ host: '127.0.0.1',
121
+ port: 3400
122
+ }
123
+ },
124
+ events: true // creates /events SSE endpoint and forwards pool resource lifecycle events
125
+ });
126
+ ```
127
+
128
+ All process-style resources expose a consistent API:
129
+ - `start()`
130
+ - `stop()`
131
+ - `restart()`
132
+ - `status` (includes `state`, `pid`, `uptime`, `restartCount`, `lastHealthCheck`, `memoryUsage`, `processManager`)
133
+ - `get_abstract()`
134
+
75
135
  ### Real-time SSE Streams
76
136
 
77
137
  ```javascript
@@ -83,13 +143,161 @@ const obs = observable(next => {
83
143
 
84
144
  // Start server and publish stream
85
145
  const server = await Server.serve(MyControl);
86
- server.publish_observable('/api/stream', obs);
87
- // Server publishes SSE stream at http://localhost:3000/api/stream
146
+
147
+ // Simple name - auto-prefixes /api/
148
+ server.publish_observable('stream', obs);
149
+ // Server publishes SSE stream at http://localhost:8080/api/stream
150
+
151
+ // Or use full route path for custom routes
152
+ server.publish_observable('/custom/events', obs);
153
+ // Server publishes SSE stream at http://localhost:8080/custom/events
154
+
88
155
  // Client connects via EventSource or Remote_Observable
89
156
  ```
90
157
 
158
+ ### General SSE Publisher
159
+
160
+ ```javascript
161
+ const HTTP_SSE_Publisher = require('jsgui3-server/publishers/http-sse-publisher');
162
+
163
+ const sse_publisher = new HTTP_SSE_Publisher({ name: 'events' });
164
+ server.server_router.set_route('/events', sse_publisher, sse_publisher.handle_http);
165
+
166
+ sse_publisher.broadcast('resource_update', { running: 3, total: 5 });
167
+ ```
168
+
91
169
  > **Note:** The new `Server.serve()` API is the recommended approach for most use cases. See [Simple Server API Design](docs/simple-server-api-design.md) for complete documentation and advanced features.
92
170
 
171
+ ## Admin UI Dashboard
172
+
173
+ Every jsgui3-server instance includes a built-in admin dashboard at `/admin/v1` with live stats, resource inspection, route listing, and SSE-driven heartbeat updates. The dashboard is session-authenticated (default dev credentials: `admin` / `admin`).
174
+
175
+ The admin shell is implemented with jsgui controls for navigation and dynamic panel rendering (control-first composition), and is covered by the interaction regression suite in `tests/admin-ui-jsgui-controls.test.js`.
176
+
177
+ ### Disabling the Admin UI
178
+
179
+ ```javascript
180
+ Server.serve({ Ctrl: MyControl, admin: false });
181
+
182
+ // or
183
+ Server.serve({ Ctrl: MyControl, admin: { enabled: false } });
184
+ ```
185
+
186
+ ### Adding Custom Sections
187
+
188
+ Custom sections appear in the admin sidebar. When clicked, the shell fetches data from the section's API endpoint and auto-renders it as a table (arrays) or key-value panel (objects).
189
+
190
+ ```javascript
191
+ const server = await Server.serve(MyControl);
192
+
193
+ server.admin_v1.add_section({
194
+ id: 'crawlers',
195
+ label: 'Crawlers',
196
+ icon: '\uD83D\uDD77\uFE0F',
197
+ api_path: '/api/admin/v1/crawlers',
198
+ handler: (req, res) => {
199
+ res.writeHead(200, { 'Content-Type': 'application/json' });
200
+ res.end(JSON.stringify([
201
+ { name: 'Site A', status: 'running', pages: 1234 },
202
+ { name: 'Site B', status: 'idle', pages: 0 }
203
+ ]));
204
+ }
205
+ });
206
+ ```
207
+
208
+ ### Adding Custom Protected Endpoints
209
+
210
+ ```javascript
211
+ server.admin_v1.add_endpoint({
212
+ path: '/api/admin/v1/crawlers/start',
213
+ role: 'admin_write',
214
+ handler: (req, res) => {
215
+ // start crawler logic
216
+ res.writeHead(200, { 'Content-Type': 'application/json' });
217
+ res.end(JSON.stringify({ ok: true }));
218
+ }
219
+ });
220
+ ```
221
+
222
+ ### Plugin Pattern
223
+
224
+ ```javascript
225
+ server.admin_v1.use((admin) => {
226
+ admin.add_section({
227
+ id: 'logs',
228
+ label: 'Logs',
229
+ icon: '\uD83D\uDCDC',
230
+ api_path: '/api/admin/v1/logs',
231
+ handler: (req, res) => {
232
+ res.writeHead(200, { 'Content-Type': 'application/json' });
233
+ res.end(JSON.stringify({ recent: ['log1', 'log2'] }));
234
+ }
235
+ });
236
+ });
237
+ ```
238
+
239
+ ### Admin UI Regression Test
240
+
241
+ ```bash
242
+ node tests/test-runner.js --test=admin-ui-jsgui-controls.test.js
243
+ ```
244
+
245
+ ### Declarative Configuration via `Server.serve()`
246
+
247
+ Custom sections and endpoints can also be declared in the `Server.serve()` call:
248
+
249
+ ```javascript
250
+ Server.serve({
251
+ Ctrl: MyControl,
252
+ port: 8080,
253
+ admin: {
254
+ sections: [
255
+ {
256
+ id: 'jobs',
257
+ label: 'Jobs',
258
+ icon: '\u2699\uFE0F',
259
+ api_path: '/api/admin/v1/jobs',
260
+ handler: (req, res) => {
261
+ res.writeHead(200, { 'Content-Type': 'application/json' });
262
+ res.end(JSON.stringify([{ name: 'nightly-sync', status: 'complete' }]));
263
+ }
264
+ }
265
+ ],
266
+ endpoints: [
267
+ {
268
+ path: '/api/admin/v1/jobs/run',
269
+ role: 'admin_write',
270
+ handler: (req, res) => {
271
+ res.writeHead(200, { 'Content-Type': 'application/json' });
272
+ res.end(JSON.stringify({ ok: true }));
273
+ }
274
+ }
275
+ ]
276
+ }
277
+ });
278
+ ```
279
+
280
+ ### Exported Admin Classes
281
+
282
+ For advanced customisation, the admin classes are exported from the package:
283
+
284
+ ```javascript
285
+ const Server = require('jsgui3-server');
286
+
287
+ // Available on the Server constructor:
288
+ Server.Admin_Module_V1 // Admin adapter (sections, endpoints, auth, SSE)
289
+ Server.Admin_Auth_Service // Session management, cookie handling, role checking
290
+ Server.Admin_User_Store // In-memory user credential store (scrypt)
291
+
292
+ // Also available from the npm module entry:
293
+ const jsgui = require('jsgui3-server');
294
+ jsgui.Admin_Module_V1
295
+ jsgui.Admin_Auth_Service
296
+ jsgui.Admin_User_Store
297
+ ```
298
+
299
+ See [Admin Extension Guide](docs/admin-extension-guide.md) for detailed API reference.
300
+
93
301
  ## Architecture Overview
94
302
 
95
303
  The server operates as a bridge between server-side JavaScript applications and browser clients, offering:
@@ -909,11 +1117,15 @@ Minimal example:
909
1117
  ```javascript
910
1118
  // Inside your server bootstrap (after constructing Server)
911
1119
  server.on('ready', () => {
1120
+ // Simple name - auto-prefixes /api/
912
1121
  // Returns text/plain at GET/POST /api/hello
913
1122
  server.publish('hello', name => `Hello ${name || 'world'}`);
914
1123
 
915
1124
  // Returns application/json at GET/POST /api/sum
916
1125
  server.publish('sum', ({ a, b }) => ({ sum: a + b }));
1126
+
1127
+ // Full route path for custom routes (no auto-prefix)
1128
+ server.publish('/custom/endpoint', () => ({ custom: true }));
917
1129
  });
918
1130
  ```
919
1131
 
@@ -2,15 +2,19 @@ const jsgui = require('jsgui3-client');
2
2
  const { controls, Control, mixins } = jsgui;
3
3
  const Active_HTML_Document = require('../controls/Active_HTML_Document');
4
4
 
5
- class Admin_Page extends Active_HTML_Document {
6
- constructor(spec = {}) {
7
- spec.__type_name = spec.__type_name || 'admin_page';
8
- super(spec);
9
- const { context } = this;
10
-
11
- if (typeof this.body.add_class === 'function') {
12
- this.body.add_class('admin-page');
13
- }
5
+ class Admin_Page extends Active_HTML_Document {
6
+ constructor(spec = {}) {
7
+ spec.__type_name = spec.__type_name || 'admin_page';
8
+ super(spec);
9
+ const { context } = this;
10
+
11
+ this._menu_items = [];
12
+ this._section_labels = Object.create(null);
13
+ this._active_section = 'overview';
14
+
15
+ if (typeof this.body.add_class === 'function') {
16
+ this.body.add_class('admin-page');
17
+ }
14
18
 
15
19
  const compose = () => {
16
20
  // Sidebar
@@ -50,9 +54,9 @@ class Admin_Page extends Active_HTML_Document {
50
54
  top_bar.add(this.page_title);
51
55
 
52
56
  // Content Panel
53
- const content = new controls.div({ context, class: 'admin-content' });
54
- main.add(content);
55
- this.content = content;
57
+ const content_panel = new controls.div({ context, class: 'admin-content' });
58
+ main.add(content_panel);
59
+ this.content_panel = content_panel;
56
60
 
57
61
  // Default content (Overview)
58
62
  this._render_overview();
@@ -63,53 +67,79 @@ class Admin_Page extends Active_HTML_Document {
63
67
  }
64
68
  }
65
69
 
66
- _add_menu_item(label, id, active = false) {
67
- const item = new controls.div({
68
- context: this.context,
69
- class: `menu-item ${active ? 'active' : ''}`
70
- });
71
- item.dom.attributes['data-id'] = id;
72
- item.add(label);
73
- this.menu.add(item);
74
- return item;
75
- }
70
+ _add_menu_item(label, id, active = false) {
71
+ const item = new controls.div({
72
+ context: this.context,
73
+ class: `menu-item ${active ? 'active' : ''}`
74
+ });
75
+ item.dom.attributes['data-id'] = id;
76
+ item.add(label);
77
+ this.menu.add(item);
78
+
79
+ this._section_labels[id] = label;
80
+ this._menu_items.push({
81
+ id,
82
+ label,
83
+ control: item
84
+ });
85
+
86
+ item.on('click', () => {
87
+ this._activate_menu_item(id);
88
+ });
89
+
90
+ return item;
91
+ }
92
+
93
+ _set_control_text(control, text) {
94
+ if (!control) return;
95
+ if (typeof control.clear === 'function') {
96
+ control.clear();
97
+ }
98
+ if (typeof control.add === 'function') {
99
+ control.add(String(text == null ? '' : text));
100
+ }
101
+ }
102
+
103
+ _set_active_menu_item(id) {
104
+ this._menu_items.forEach((menu_item) => {
105
+ if (!menu_item.control) return;
106
+ if (menu_item.id === id) {
107
+ menu_item.control.add_class('active');
108
+ } else {
109
+ menu_item.control.remove_class('active');
110
+ }
111
+ });
112
+ }
113
+
114
+ _activate_menu_item(id) {
115
+ this._active_section = id;
116
+ this._set_active_menu_item(id);
117
+
118
+ const label = this._section_labels[id] || id;
119
+ this._set_control_text(this.page_title, label);
120
+
121
+ // Placeholder navigation logic
122
+ console.log('Navigate to:', id);
123
+ }
76
124
 
77
125
  _render_overview() {
78
- // Clear main content area (this.content is the admin-content div)
79
- if (this.content && this.content.content && typeof this.content.content.clear === 'function') {
80
- this.content.content.clear();
81
- }
126
+ // Clear main content area (content_panel is the admin-content div)
127
+ if (this.content_panel && this.content_panel.content && typeof this.content_panel.content.clear === 'function') {
128
+ this.content_panel.content.clear();
129
+ }
82
130
 
83
131
  const welcome = new controls.div({ context: this.context, class: 'welcome-card' });
84
132
  welcome.add(new controls.h3({ context: this.context }).add('Welcome directly to jsgui3-server Admin'));
85
133
  welcome.add(new controls.p({ context: this.context }).add('Select a resource from the sidebar to inspect.'));
86
- this.content.add(welcome);
134
+ this.content_panel.add(welcome);
87
135
  }
88
136
 
89
- activate() {
90
- if (!this.__active) {
91
- super.activate();
92
-
93
- // Handle menu clicks
94
- const menu_items = document.querySelectorAll('.menu-item');
95
- menu_items.forEach(el => {
96
- el.addEventListener('click', () => {
97
- // Update Active State
98
- menu_items.forEach(i => i.classList.remove('active'));
99
- el.classList.add('active');
100
-
101
- // Update Title
102
- const id = el.getAttribute('data-id');
103
- const label = el.innerText;
104
- document.querySelector('.page-title').innerText = label;
105
-
106
- // Placeholder navigation logic
107
- console.log('Navigate to:', id);
108
- });
109
- });
110
- }
111
- }
112
- }
137
+ activate() {
138
+ if (!this.__active) {
139
+ super.activate();
140
+ }
141
+ }
142
+ }
113
143
 
114
144
  Admin_Page.css = `
115
145
  * { box-sizing: border-box; margin: 0; padding: 0; }