jsgui3-server 0.0.147 → 0.0.149
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/workflows/control-scan-manifest-check.yml +31 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-071799b982906680f5fd699d.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-07352945ad5c92654fcb8b65.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-138a601fadb6191ea314c6fd.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-171f6c381c2cadf2e9fa7087.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-1d973388156b84a04373fac9.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-20e117bc8a10d2cd16234bbe.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-2b028a82b0e5efddba42425f.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-4518556cd5c7e059e82b22b8.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-5bac1aa0f213902f718ed74f.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-5f9996ac7822caf777d92f56.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-60a92c702e65fd9cf748e3ec.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-6164c1f8f738995c541895d2.js +44 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-6718a85eb9e5aa782dd47a05.js +45 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-69e280f14e37aee76a1d4675.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-7570d1b030d44b111ed59c4c.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-7798c9bbd55e510d5039f936.js +42 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-78cd511ea1ef18ecb03d1be5.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-7d482e0b95bcb5e3c543118b.js +43 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-80e9476d1127c55b40fdb36f.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-810ced55d5320a3088a05b13.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-8423565f1a40e329afc8c6cf.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-900bef783b8cee36506ec282.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-a1a37aff6416fdad74040ddf.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-ad48d5e8eda40f175b4df090.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-aec5a2d963015528c9099462.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-af9d34e0f1722fab9e28c269.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-b818e4015e2f1fe86280b5ab.js +41 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-bcb2541adc70b7aba61768c5.js +44 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-bfe89d2c78ed44f95ed7dd73.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-c06f04806a1e688e1187110c.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-c3f3adf904f585afc544b96a.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-d45acb873e1d8e32d5e60f2e.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-db06f132533706f4a0163b8c.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-f660f40d78b135fc8560a862.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-f9dee4ec18a96e09bee06bae.js +39 -0
- package/README.md +85 -3
- package/admin-ui/client.js +213 -0
- package/admin-ui/server.js +104 -0
- package/client/controls/auto-observable.js +207 -0
- package/dev-status.svg +139 -0
- package/docs/api-reference.md +301 -43
- package/docs/books/admin-ui/01-introduction.md +32 -0
- package/docs/books/admin-ui/02-architecture.md +92 -0
- package/docs/books/admin-ui/03-controls.md +194 -0
- package/docs/books/admin-ui/04-implementation-plan.md +62 -0
- package/docs/books/admin-ui/README.md +26 -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/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/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/examples/controls/15) window, observable SSE/server.js +6 -1
- package/examples/controls/19) window, auto observable ui/client.js +125 -0
- package/examples/controls/19) window, auto observable ui/server.js +73 -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 +11 -4
- package/package.json +14 -4
- 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-observable-publisher.js +8 -0
- package/publishers/http-sse-publisher.js +341 -0
- package/publishers/http-webpage-publisher.js +13 -3
- package/publishers/http-webpageorsite-publisher.js +18 -0
- package/resources/process-resource.js +950 -0
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +164 -46
- 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 +441 -259
- package/server.js +161 -16
- package/tests/README.md +66 -4
- 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 +13 -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
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const jsgui = require('./client');
|
|
2
|
+
const { Admin_Page } = jsgui.controls;
|
|
3
|
+
const { each } = jsgui;
|
|
4
|
+
|
|
5
|
+
class Admin_Module {
|
|
6
|
+
constructor(server) {
|
|
7
|
+
this.server = server;
|
|
8
|
+
this.setup_routes();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
setup_routes() {
|
|
12
|
+
const { server } = this;
|
|
13
|
+
|
|
14
|
+
// 1. Main Admin Page Route
|
|
15
|
+
// Using a custom Website_Resource for the admin app
|
|
16
|
+
// We register Admin_Page as the content control
|
|
17
|
+
|
|
18
|
+
// Manual route setup to render the page
|
|
19
|
+
// (Similar to how examples work, but integrated)
|
|
20
|
+
|
|
21
|
+
// We'll expose a 'setup' method that the main server calls
|
|
22
|
+
// Or we can attach directly if we have access to the router
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Called by the main server to attach admin functionality
|
|
26
|
+
attach_to_router(router) {
|
|
27
|
+
console.log('[Admin_Module] Attaching /admin routes...');
|
|
28
|
+
|
|
29
|
+
// API: List Resources
|
|
30
|
+
// GET /api/admin/resources
|
|
31
|
+
router.set_route('/api/admin/resources', (req, res) => {
|
|
32
|
+
const resources_data = this.get_resources_tree();
|
|
33
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
34
|
+
res.end(JSON.stringify(resources_data));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// API: List Observables
|
|
38
|
+
// GET /api/admin/observables
|
|
39
|
+
router.set_route('/api/admin/observables', (req, res) => {
|
|
40
|
+
const observables = this.get_observables_list();
|
|
41
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
42
|
+
res.end(JSON.stringify(observables));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get_resources_tree() {
|
|
47
|
+
const pool = this.server.resource_pool;
|
|
48
|
+
const tree = {
|
|
49
|
+
name: 'Root',
|
|
50
|
+
type: 'pool',
|
|
51
|
+
children: []
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (pool && pool.resources) {
|
|
55
|
+
// Need to iterate pool resources safely
|
|
56
|
+
// resource_pool.resources is likely a Collection or array
|
|
57
|
+
const resources = pool.resources._arr || []; // Assuming Data_Structures.Collection
|
|
58
|
+
|
|
59
|
+
resources.forEach(res => {
|
|
60
|
+
tree.children.push({
|
|
61
|
+
name: res.name || 'Unnamed Resource',
|
|
62
|
+
type: res.constructor.name
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return tree;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get_observables_list() {
|
|
70
|
+
// We need a way to track all published observables
|
|
71
|
+
// Ideally, HTTP_Observable_Publisher instances are stored in the resource pool or a specific list
|
|
72
|
+
|
|
73
|
+
// For now, we'll scan the router for observable publishers
|
|
74
|
+
// This relies on the server exposing its router/routes map
|
|
75
|
+
const observables = [];
|
|
76
|
+
|
|
77
|
+
// Implementation detail: server.router doesn't expose a simple list of routes easily in standard Router
|
|
78
|
+
// We might need to track them when publish_observable is called.
|
|
79
|
+
// But we can look at server.resource_pool for publishers
|
|
80
|
+
|
|
81
|
+
const pool = this.server.resource_pool;
|
|
82
|
+
if (pool && pool.resources) {
|
|
83
|
+
const resources = pool.resources._arr || [];
|
|
84
|
+
resources.forEach(res => {
|
|
85
|
+
// Check if it's an observable publisher
|
|
86
|
+
// Robust check: does it have 'obs' property and handle_http?
|
|
87
|
+
// Or check constructor name if available
|
|
88
|
+
if (res.constructor.name === 'Observable_Publisher' || (res.obs && res.handle_http)) {
|
|
89
|
+
observables.push({
|
|
90
|
+
name: res.name || 'Observable',
|
|
91
|
+
route: '?', // Route might not be stored on the resource itself, but on the router
|
|
92
|
+
schema: res.schema,
|
|
93
|
+
status: res.is_paused ? 'paused' : 'active',
|
|
94
|
+
connections: res.active_sse_connections ? res.active_sse_connections.size : 0
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return observables;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = Admin_Module;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
const jsgui = require('jsgui3-client');
|
|
2
|
+
const { Control, controls } = jsgui;
|
|
3
|
+
|
|
4
|
+
class Auto_Observable_UI extends Control {
|
|
5
|
+
constructor(spec = {}) {
|
|
6
|
+
spec.__type_name = spec.__type_name || 'auto_observable_ui';
|
|
7
|
+
super(spec);
|
|
8
|
+
this.add_class('auto-observable-ui');
|
|
9
|
+
|
|
10
|
+
this.url = spec.url;
|
|
11
|
+
this.obs = spec.obs;
|
|
12
|
+
|
|
13
|
+
// Container for the dynamic content
|
|
14
|
+
this.content_container = new controls.div({
|
|
15
|
+
context: this.context,
|
|
16
|
+
class: 'content-container'
|
|
17
|
+
});
|
|
18
|
+
this.add(this.content_container);
|
|
19
|
+
|
|
20
|
+
// Status indicator
|
|
21
|
+
this.status_indicator = new controls.div({
|
|
22
|
+
context: this.context,
|
|
23
|
+
class: 'status-indicator status-connecting'
|
|
24
|
+
});
|
|
25
|
+
this.add(this.status_indicator);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
activate() {
|
|
29
|
+
if (!this.__active) {
|
|
30
|
+
super.activate();
|
|
31
|
+
this._connect();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_connect() {
|
|
36
|
+
let obs = this.obs;
|
|
37
|
+
if (!obs && this.url) {
|
|
38
|
+
obs = new jsgui.Remote_Observable({ url: this.url });
|
|
39
|
+
this.obs = obs;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!obs) return;
|
|
43
|
+
|
|
44
|
+
obs.on('connect', () => {
|
|
45
|
+
this.status_indicator.remove_class('status-connecting');
|
|
46
|
+
this.status_indicator.add_class('status-connected');
|
|
47
|
+
this.status_indicator.dom.innerText = 'Connected';
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
obs.on('schema', (schema) => {
|
|
51
|
+
console.log('Schema received:', schema);
|
|
52
|
+
this._build_ui_from_schema(schema);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
obs.on('next', (data) => {
|
|
56
|
+
// If we haven't received a schema yet, maybe infer it or just display raw?
|
|
57
|
+
// For now, if we built the UI, we update it.
|
|
58
|
+
if (this._update_handler) {
|
|
59
|
+
this._update_handler(data);
|
|
60
|
+
} else if (!this._ui_built) {
|
|
61
|
+
// Infer simple schema if not provided?
|
|
62
|
+
// Or just show raw JSON
|
|
63
|
+
this._build_default_ui(data);
|
|
64
|
+
this._ui_built = true;
|
|
65
|
+
if (this._update_handler) this._update_handler(data);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
obs.on('error', (err) => {
|
|
70
|
+
this.status_indicator.add_class('status-error');
|
|
71
|
+
this.status_indicator.dom.innerText = 'Error: ' + err.message;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
obs.connect();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_build_ui_from_schema(schema) {
|
|
78
|
+
if (this._ui_built) return; // Don't rebuild for now
|
|
79
|
+
this._ui_built = true;
|
|
80
|
+
|
|
81
|
+
this.content_container.content.clear();
|
|
82
|
+
|
|
83
|
+
const type = schema.type || (schema.output_type ? schema.output_type : 'unknown');
|
|
84
|
+
|
|
85
|
+
if (type === 'int' || type === 'number') {
|
|
86
|
+
this._build_number_ui(schema);
|
|
87
|
+
} else if (type === 'text' || type === 'log') {
|
|
88
|
+
this._build_log_ui(schema);
|
|
89
|
+
} else if (type === 'percentage' || (type === 'number' && schema.min !== undefined && schema.max !== undefined)) {
|
|
90
|
+
this._build_gauge_ui(schema);
|
|
91
|
+
} else {
|
|
92
|
+
this._build_json_ui(schema);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_build_default_ui(first_data) {
|
|
97
|
+
if (typeof first_data === 'number') {
|
|
98
|
+
this._build_number_ui({ type: 'number' });
|
|
99
|
+
} else if (typeof first_data === 'string') {
|
|
100
|
+
this._build_log_ui({ type: 'text' });
|
|
101
|
+
} else {
|
|
102
|
+
this._build_json_ui({ type: 'object' });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_build_number_ui(schema) {
|
|
107
|
+
const val_div = new controls.div({
|
|
108
|
+
context: this.context,
|
|
109
|
+
class: 'value-display number-display'
|
|
110
|
+
});
|
|
111
|
+
this.content_container.add(val_div);
|
|
112
|
+
|
|
113
|
+
const label = new controls.h3({ context: this.context });
|
|
114
|
+
label.add(schema.name || 'Value');
|
|
115
|
+
val_div.add(label);
|
|
116
|
+
|
|
117
|
+
const value_text = new controls.div({ context: this.context, class: 'value-text' });
|
|
118
|
+
value_text.add('--');
|
|
119
|
+
val_div.add(value_text);
|
|
120
|
+
|
|
121
|
+
this._update_handler = (data) => {
|
|
122
|
+
let val = data;
|
|
123
|
+
if (typeof data === 'object' && data.value !== undefined) val = data.value;
|
|
124
|
+
value_text.dom.innerText = String(val);
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
_build_log_ui(schema) {
|
|
129
|
+
const log_container = new controls.div({
|
|
130
|
+
context: this.context,
|
|
131
|
+
class: 'value-display log-display'
|
|
132
|
+
});
|
|
133
|
+
this.content_container.add(log_container);
|
|
134
|
+
|
|
135
|
+
const label = new controls.h3({ context: this.context });
|
|
136
|
+
label.add(schema.name || 'Log');
|
|
137
|
+
log_container.add(label);
|
|
138
|
+
|
|
139
|
+
const log_area = new controls.div({ context: this.context, class: 'log-area' });
|
|
140
|
+
log_container.add(log_area);
|
|
141
|
+
|
|
142
|
+
this._update_handler = (data) => {
|
|
143
|
+
const entry = document.createElement('div');
|
|
144
|
+
entry.className = 'log-entry';
|
|
145
|
+
let msg = data;
|
|
146
|
+
if (typeof data === 'object') msg = data.message || JSON.stringify(data);
|
|
147
|
+
|
|
148
|
+
entry.innerText = `[${new Date().toLocaleTimeString()}] ${msg}`;
|
|
149
|
+
log_area.dom.appendChild(entry);
|
|
150
|
+
log_area.dom.scrollTop = log_area.dom.scrollHeight;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_build_gauge_ui(schema) {
|
|
155
|
+
// Simple progress bar for now
|
|
156
|
+
const container = new controls.div({
|
|
157
|
+
context: this.context,
|
|
158
|
+
class: 'value-display gauge-display'
|
|
159
|
+
});
|
|
160
|
+
this.content_container.add(container);
|
|
161
|
+
|
|
162
|
+
const label = new controls.h3({ context: this.context });
|
|
163
|
+
label.add(schema.name || 'Gauge');
|
|
164
|
+
container.add(label);
|
|
165
|
+
|
|
166
|
+
const bar_bg = new controls.div({ context: this.context, class: 'progress-bg' });
|
|
167
|
+
const bar_fill = new controls.div({ context: this.context, class: 'progress-fill' });
|
|
168
|
+
bar_bg.add(bar_fill);
|
|
169
|
+
container.add(bar_bg);
|
|
170
|
+
|
|
171
|
+
const value_text = new controls.div({ context: this.context, class: 'value-text-small' });
|
|
172
|
+
container.add(value_text);
|
|
173
|
+
|
|
174
|
+
const min = schema.min || 0;
|
|
175
|
+
const max = schema.max || 100;
|
|
176
|
+
|
|
177
|
+
this._update_handler = (data) => {
|
|
178
|
+
let val = data;
|
|
179
|
+
if (typeof data === 'object' && data.value !== undefined) val = data.value;
|
|
180
|
+
|
|
181
|
+
const pct = Math.max(0, Math.min(100, ((val - min) / (max - min)) * 100));
|
|
182
|
+
bar_fill.dom.style.width = pct + '%';
|
|
183
|
+
value_text.dom.innerText = `${val} / ${max}`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
_build_json_ui(schema) {
|
|
188
|
+
const container = new controls.div({
|
|
189
|
+
context: this.context,
|
|
190
|
+
class: 'value-display json-display'
|
|
191
|
+
});
|
|
192
|
+
this.content_container.add(container);
|
|
193
|
+
|
|
194
|
+
const label = new controls.h3({ context: this.context });
|
|
195
|
+
label.add(schema.name || 'Data');
|
|
196
|
+
container.add(label);
|
|
197
|
+
|
|
198
|
+
const pre = new controls.pre({ context: this.context });
|
|
199
|
+
container.add(pre);
|
|
200
|
+
|
|
201
|
+
this._update_handler = (data) => {
|
|
202
|
+
pre.dom.innerText = JSON.stringify(data, null, 2);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = Auto_Observable_UI;
|
package/dev-status.svg
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 850" style="background:#1e1e2e; font-family: 'Segoe UI', sans-serif; color: #cdd6f4;">
|
|
2
|
+
<!-- Definitions for gradients and shadows -->
|
|
3
|
+
<defs>
|
|
4
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
+
<feDropShadow dx="3" dy="3" stdDeviation="4" flood-color="#000000" flood-opacity="0.5"/>
|
|
6
|
+
</filter>
|
|
7
|
+
<linearGradient id="grad-server" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
8
|
+
<stop offset="0%" style="stop-color:#313244;stop-opacity:1" />
|
|
9
|
+
<stop offset="100%" style="stop-color:#45475a;stop-opacity:1" />
|
|
10
|
+
</linearGradient>
|
|
11
|
+
<linearGradient id="grad-client" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
12
|
+
<stop offset="0%" style="stop-color:#181825;stop-opacity:1" />
|
|
13
|
+
<stop offset="100%" style="stop-color:#1e1e2e;stop-opacity:1" />
|
|
14
|
+
</linearGradient>
|
|
15
|
+
<linearGradient id="grad-success" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
16
|
+
<stop offset="0%" style="stop-color:#a6e3a1;stop-opacity:0.2" />
|
|
17
|
+
<stop offset="100%" style="stop-color:#a6e3a1;stop-opacity:0.1" />
|
|
18
|
+
</linearGradient>
|
|
19
|
+
<marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
20
|
+
<path d="M0,0 L0,6 L9,3 z" fill="#89b4fa" />
|
|
21
|
+
</marker>
|
|
22
|
+
</defs>
|
|
23
|
+
|
|
24
|
+
<!-- Title -->
|
|
25
|
+
<text x="50" y="50" fill="#cdd6f4" font-size="32" font-weight="bold">jsgui3-server: Dev Status & Architecture</text>
|
|
26
|
+
<text x="50" y="80" fill="#a6adc8" font-size="16">Admin UI • Auto-Observables • Defensive Programming • Server Lifecycle</text>
|
|
27
|
+
|
|
28
|
+
<!-- Areas -->
|
|
29
|
+
<rect x="50" y="110" width="500" height="700" rx="15" fill="url(#grad-server)" stroke="#585b70" stroke-width="2" />
|
|
30
|
+
<text x="70" y="140" fill="#fab387" font-size="24" font-weight="bold">Server Side (Node.js)</text>
|
|
31
|
+
|
|
32
|
+
<rect x="650" y="110" width="500" height="700" rx="15" fill="url(#grad-client)" stroke="#585b70" stroke-width="2" />
|
|
33
|
+
<text x="670" y="140" fill="#89b4fa" font-size="24" font-weight="bold">Client Side (Browser)</text>
|
|
34
|
+
|
|
35
|
+
<!-- Server Components -->
|
|
36
|
+
|
|
37
|
+
<!-- Server Lifecycle Box -->
|
|
38
|
+
<g transform="translate(80, 180)">
|
|
39
|
+
<rect width="440" height="140" rx="8" fill="#313244" stroke="#f38ba8" stroke-width="2" stroke-dasharray="5,5" filter="url(#shadow)" />
|
|
40
|
+
<text x="15" y="30" fill="#f38ba8" font-size="18" font-weight="bold">Lifecycle Fixes</text>
|
|
41
|
+
|
|
42
|
+
<g transform="translate(20, 50)">
|
|
43
|
+
<circle cx="10" cy="10" r="5" fill="#f38ba8" />
|
|
44
|
+
<text x="25" y="15" fill="#cdd6f4" font-size="14">1. _started Guard (Prevents double start)</text>
|
|
45
|
+
</g>
|
|
46
|
+
<g transform="translate(20, 80)">
|
|
47
|
+
<circle cx="10" cy="10" r="5" fill="#f38ba8" />
|
|
48
|
+
<text x="25" y="15" fill="#cdd6f4" font-size="14">2. Split Events: 'ready' vs 'listening'</text>
|
|
49
|
+
</g>
|
|
50
|
+
<g transform="translate(20, 110)">
|
|
51
|
+
<text x="25" y="15" fill="#a6adc8" font-size="12" font-style="italic">Fixed EADDRINUSE crash root cause</text>
|
|
52
|
+
</g>
|
|
53
|
+
</g>
|
|
54
|
+
|
|
55
|
+
<!-- Admin Module -->
|
|
56
|
+
<g transform="translate(80, 350)">
|
|
57
|
+
<rect width="200" height="120" rx="8" fill="#45475a" stroke="#89b4fa" stroke-width="2" filter="url(#shadow)" />
|
|
58
|
+
<text x="50" y="30" fill="#89b4fa" font-size="18" font-weight="bold">Admin_Module</text>
|
|
59
|
+
<line x1="10" y1="40" x2="190" y2="40" stroke="#585b70" />
|
|
60
|
+
<text x="15" y="65" fill="#cdd6f4" font-size="14">GET /api/admin/resources</text>
|
|
61
|
+
<text x="15" y="90" fill="#cdd6f4" font-size="14">GET /api/admin/observables</text>
|
|
62
|
+
</g>
|
|
63
|
+
|
|
64
|
+
<!-- Publishers -->
|
|
65
|
+
<g transform="translate(320, 350)">
|
|
66
|
+
<rect width="200" height="120" rx="8" fill="#45475a" stroke="#a6e3a1" stroke-width="2" filter="url(#shadow)" />
|
|
67
|
+
<text x="30" y="30" fill="#a6e3a1" font-size="18" font-weight="bold">Publishers</text>
|
|
68
|
+
<line x1="10" y1="40" x2="190" y2="40" stroke="#585b70" />
|
|
69
|
+
<text x="15" y="65" fill="#cdd6f4" font-size="14">HTTP_Webpage_Publisher</text>
|
|
70
|
+
<text x="15" y="90" fill="#cdd6f4" font-size="14">HTTP_Observable_Publisher</text>
|
|
71
|
+
</g>
|
|
72
|
+
|
|
73
|
+
<!-- Defensive Layers -->
|
|
74
|
+
<g transform="translate(80, 500)">
|
|
75
|
+
<rect width="440" height="100" rx="8" fill="url(#grad-success)" stroke="#a6e3a1" stroke-width="1" />
|
|
76
|
+
<text x="15" y="30" fill="#a6e3a1" font-size="18" font-weight="bold">Defensive Coding Layers</text>
|
|
77
|
+
<text x="20" y="60" fill="#cdd6f4" font-size="14">• Resource_Pool.add(undefined) → Warn & Return</text>
|
|
78
|
+
<text x="20" y="80" fill="#cdd6f4" font-size="14">• Bundler Failures → Fallback Empty Bundle</text>
|
|
79
|
+
</g>
|
|
80
|
+
|
|
81
|
+
<!-- Bundler -->
|
|
82
|
+
<g transform="translate(80, 630)">
|
|
83
|
+
<rect width="440" height="60" rx="8" fill="#313244" stroke="#fab387" stroke-width="2" />
|
|
84
|
+
<text x="15" y="35" fill="#fab387" font-size="18" font-weight="bold">Bundler (esbuild)</text>
|
|
85
|
+
<text x="180" y="35" fill="#cdd6f4" font-size="14">Fixed: npm link jsgui3-html</text>
|
|
86
|
+
</g>
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
<!-- Client Components -->
|
|
90
|
+
|
|
91
|
+
<!-- Admin Page -->
|
|
92
|
+
<g transform="translate(680, 250)">
|
|
93
|
+
<rect width="440" height="180" rx="8" fill="#313244" stroke="#89b4fa" stroke-width="2" filter="url(#shadow)" />
|
|
94
|
+
<text x="15" y="30" fill="#89b4fa" font-size="18" font-weight="bold">Admin_Page (Client)</text>
|
|
95
|
+
<line x1="10" y1="40" x2="430" y2="40" stroke="#585b70" />
|
|
96
|
+
|
|
97
|
+
<!-- Child Controls -->
|
|
98
|
+
<g transform="translate(20, 60)">
|
|
99
|
+
<rect width="180" height="40" rx="4" fill="#45475a" stroke="#cba6f7" stroke-width="1" />
|
|
100
|
+
<text x="35" y="25" fill="#cba6f7" font-size="14">Resource_List</text>
|
|
101
|
+
</g>
|
|
102
|
+
|
|
103
|
+
<g transform="translate(220, 60)">
|
|
104
|
+
<rect width="180" height="40" rx="4" fill="#45475a" stroke="#cba6f7" stroke-width="1" />
|
|
105
|
+
<text x="25" y="25" fill="#cba6f7" font-size="14">Observables_List</text>
|
|
106
|
+
</g>
|
|
107
|
+
|
|
108
|
+
<g transform="translate(120, 120)">
|
|
109
|
+
<rect width="200" height="40" rx="4" fill="#45475a" stroke="#f9e2af" stroke-width="1" />
|
|
110
|
+
<text x="30" y="25" fill="#f9e2af" font-size="14">Auto_Observable_UI</text>
|
|
111
|
+
</g>
|
|
112
|
+
</g>
|
|
113
|
+
|
|
114
|
+
<!-- Data Flow Arrows -->
|
|
115
|
+
|
|
116
|
+
<!-- Route Info -->
|
|
117
|
+
<path d="M 280 410 L 680 300" stroke="#89b4fa" stroke-width="2" stroke-dasharray="5,5" fill="none" marker-end="url(#arrow)" />
|
|
118
|
+
<rect x="420" y="330" width="120" height="25" rx="4" fill="#1e1e2e" stroke="#89b4fa" />
|
|
119
|
+
<text x="430" y="347" fill="#89b4fa" font-size="12">JSON Data</text>
|
|
120
|
+
|
|
121
|
+
<!-- Observable Stream -->
|
|
122
|
+
<path d="M 430 470 L 800 390" stroke="#a6e3a1" stroke-width="2" fill="none" marker-end="url(#arrow)" />
|
|
123
|
+
<rect x="560" y="440" width="100" height="25" rx="4" fill="#1e1e2e" stroke="#a6e3a1" />
|
|
124
|
+
<text x="575" y="457" fill="#a6e3a1" font-size="12">SSE Steam</text>
|
|
125
|
+
|
|
126
|
+
<!-- Legend -->
|
|
127
|
+
<g transform="translate(900, 750)">
|
|
128
|
+
<text x="0" y="0" fill="#a6adc8" font-size="14" font-weight="bold">Legend</text>
|
|
129
|
+
<rect x="0" y="10" width="15" height="15" fill="#313244" stroke="#f38ba8" />
|
|
130
|
+
<text x="25" y="23" fill="#cdd6f4" font-size="12">Lifecycle Code</text>
|
|
131
|
+
|
|
132
|
+
<rect x="0" y="35" width="15" height="15" fill="#313244" stroke="#89b4fa" />
|
|
133
|
+
<text x="25" y="48" fill="#cdd6f4" font-size="12">UI / Route Component</text>
|
|
134
|
+
|
|
135
|
+
<rect x="0" y="60" width="15" height="15" fill="#313244" stroke="#a6e3a1" />
|
|
136
|
+
<text x="25" y="73" fill="#cdd6f4" font-size="12">Observable / Defensive</text>
|
|
137
|
+
</g>
|
|
138
|
+
|
|
139
|
+
</svg>
|