jsgui3-server 0.0.145 → 0.0.147
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/README.md +16 -0
- package/docs/agent-development-guide.md +92 -9
- package/docs/books/jsgui3-mvvm-fullstack/00-overview.md +17 -0
- package/docs/books/jsgui3-mvvm-fullstack/01-stack-map.md +25 -0
- package/docs/books/jsgui3-mvvm-fullstack/02-control-lifecycle.md +32 -0
- package/docs/books/jsgui3-mvvm-fullstack/03-mvvm-basics.md +57 -0
- package/docs/books/jsgui3-mvvm-fullstack/04-bindings-and-validation.md +51 -0
- package/docs/books/jsgui3-mvvm-fullstack/05-full-stack-example.md +50 -0
- package/docs/books/jsgui3-mvvm-fullstack/06-testing.md +23 -0
- package/docs/books/jsgui3-mvvm-fullstack/07-troubleshooting.md +20 -0
- package/docs/books/jsgui3-mvvm-fullstack/08-agent-playbooks.md +30 -0
- package/docs/books/jsgui3-mvvm-fullstack/README.md +30 -0
- package/docs/comprehensive-documentation.md +145 -34
- package/docs/diagrams/jsgui3-progress-update.svg +181 -0
- package/docs/jsgui3-sass-patterns-book/01-vision-and-goals.md +31 -0
- package/docs/jsgui3-sass-patterns-book/02-stack-map.md +40 -0
- package/docs/jsgui3-sass-patterns-book/03-control-local-sass.md +60 -0
- package/docs/jsgui3-sass-patterns-book/04-extension-and-variants.md +76 -0
- package/docs/jsgui3-sass-patterns-book/05-theming-and-tokens.md +54 -0
- package/docs/jsgui3-sass-patterns-book/06-workspace-overrides.md +45 -0
- package/docs/jsgui3-sass-patterns-book/07-resource-and-bundling.md +46 -0
- package/docs/jsgui3-sass-patterns-book/08-examples.md +62 -0
- package/docs/jsgui3-sass-patterns-book/09-testing-and-adoption.md +27 -0
- package/docs/jsgui3-sass-patterns-book/README.md +23 -0
- package/docs/troubleshooting.md +44 -4
- package/examples/controls/14) window, canvas/client.js +1 -1
- package/examples/controls/14b) window, canvas (improved renderer)/client.js +1 -1
- package/examples/controls/14d) window, canvas globe/client.js +1 -1
- package/examples/controls/14e) window, canvas multithreaded/client.js +1 -1
- package/examples/controls/14f) window, canvas polyglobe/client.js +1 -1
- package/examples/controls/16) window, form container/client.js +254 -0
- package/examples/controls/16) window, form container/server.js +20 -0
- package/examples/controls/17) window, mvvm binding/client.js +530 -0
- package/examples/controls/17) window, mvvm binding/server.js +20 -0
- package/examples/controls/18) window, observable bindRemote/README.md +28 -0
- package/examples/controls/18) window, observable bindRemote/check.js +144 -0
- package/examples/controls/18) window, observable bindRemote/client.js +387 -0
- package/examples/controls/18) window, observable bindRemote/server.js +107 -0
- package/package.json +4 -4
- package/publishers/http-webpage-publisher.js +39 -16
- package/publishers/http-webpageorsite-publisher.js +48 -35
- package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +87 -100
- package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +89 -60
- package/server.js +199 -185
- package/tests/README.md +45 -9
- package/tests/bundlers.test.js +53 -47
- package/tests/examples-controls.e2e.test.js +3 -1
- package/tests/sass-controls.e2e.test.js +123 -9
- package/tests/server-publish-observable.test.js +99 -0
package/README.md
CHANGED
|
@@ -72,6 +72,22 @@ Server.serve({
|
|
|
72
72
|
});
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
### Real-time SSE Streams
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
const { observable } = require('fnl');
|
|
79
|
+
// Create an infinite stream that ticks every second
|
|
80
|
+
const obs = observable(next => {
|
|
81
|
+
setInterval(() => next({ tick: Date.now() }), 1000);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Start server and publish stream
|
|
85
|
+
const server = await Server.serve(MyControl);
|
|
86
|
+
server.publish_observable('/api/stream', obs);
|
|
87
|
+
// Server publishes SSE stream at http://localhost:3000/api/stream
|
|
88
|
+
// Client connects via EventSource or Remote_Observable
|
|
89
|
+
```
|
|
90
|
+
|
|
75
91
|
> **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.
|
|
76
92
|
|
|
77
93
|
## Architecture Overview
|
|
@@ -26,14 +26,97 @@ This document is specifically for AI agents working on the JSGUI3 Server codebas
|
|
|
26
26
|
- Include comprehensive error handling and logging
|
|
27
27
|
- Add JSDoc comments for public APIs
|
|
28
28
|
|
|
29
|
-
### Development Workflow
|
|
30
|
-
1. **Analyze the task** and understand requirements
|
|
31
|
-
2. **Check existing code** for patterns and conventions
|
|
32
|
-
3. **Implement changes** following established patterns
|
|
33
|
-
4. **Test thoroughly** and document any issues found
|
|
34
|
-
5. **Update documentation** including this guide
|
|
35
|
-
|
|
36
|
-
##
|
|
29
|
+
### Development Workflow
|
|
30
|
+
1. **Analyze the task** and understand requirements
|
|
31
|
+
2. **Check existing code** for patterns and conventions
|
|
32
|
+
3. **Implement changes** following established patterns
|
|
33
|
+
4. **Test thoroughly** and document any issues found
|
|
34
|
+
5. **Update documentation** including this guide
|
|
35
|
+
|
|
36
|
+
## Quick Start for AI Agents (Low Thinking Time)
|
|
37
|
+
|
|
38
|
+
Use this section when you need to act fast with minimal deliberation. It is a short, repeatable workflow designed to reduce cognitive overhead.
|
|
39
|
+
|
|
40
|
+
### Fast Lane Checklist (5 Minutes)
|
|
41
|
+
1. **Read the task** and extract the target file, example, or subsystem.
|
|
42
|
+
2. **Locate the target** with `rg` or `rg --files`.
|
|
43
|
+
3. **Open the closest reference doc** from the map below.
|
|
44
|
+
4. **Make a minimal, reversible change** that addresses the task.
|
|
45
|
+
5. **Run the narrowest test** that validates the change.
|
|
46
|
+
6. **Log any gaps** in "Known Issues" below if you find a blocker.
|
|
47
|
+
|
|
48
|
+
### Quick Doc Map
|
|
49
|
+
- **Repo overview**: `README.md`
|
|
50
|
+
- **Testing workflow**: `tests/README.md`
|
|
51
|
+
- **Bundling & assets**: `docs/bundling-system-deep-dive.md`
|
|
52
|
+
- **Server publishing**: `docs/publishers-guide.md`
|
|
53
|
+
- **Troubleshooting**: `docs/troubleshooting.md`
|
|
54
|
+
- **MVVM + full-stack controls**: `docs/books/jsgui3-mvvm-fullstack/README.md`
|
|
55
|
+
- **Agent workflow depth**: `docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md`
|
|
56
|
+
|
|
57
|
+
### Common Task Playbooks
|
|
58
|
+
|
|
59
|
+
#### 1) Fix an Example or Control
|
|
60
|
+
**Goal**: Example renders correctly with expected controls.
|
|
61
|
+
1. Open `examples/.../client.js` and check for `Active_HTML_Document`.
|
|
62
|
+
2. Ensure composition is inside `if (!spec.el)`.
|
|
63
|
+
3. Confirm the control is exported: `controls.Demo_UI = Demo_UI`.
|
|
64
|
+
4. Run the focused test: `node tests/test-runner.js --test=examples-controls.e2e.test.js`.
|
|
65
|
+
5. If the error is render-time, reproduce with `Server_Static_Page_Context`.
|
|
66
|
+
|
|
67
|
+
**Quick probe**:
|
|
68
|
+
```js
|
|
69
|
+
const Server_Static_Page_Context = require('./static-page-context');
|
|
70
|
+
const jsgui = require('./examples/controls/1) window/client.js');
|
|
71
|
+
const Ctrl = jsgui.controls.Demo_UI;
|
|
72
|
+
const ctrl = new Ctrl({ context: new Server_Static_Page_Context() });
|
|
73
|
+
const html = ctrl.all_html_render();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### 2) Investigate a Bundling Failure
|
|
77
|
+
**Goal**: Bundler completes and emits JS/CSS routes.
|
|
78
|
+
1. Find bundler class in `resources/processors/bundlers`.
|
|
79
|
+
2. Verify `complete(...)` is called on success and error paths.
|
|
80
|
+
3. Run: `node tests/test-runner.js --test=bundlers.test.js`.
|
|
81
|
+
4. If compression fails, check `docs/troubleshooting.md`.
|
|
82
|
+
|
|
83
|
+
#### 3) Add or Extend Tests
|
|
84
|
+
**Goal**: Increase coverage without breaking existing flows.
|
|
85
|
+
1. Add new tests under `tests/` with smallest scope.
|
|
86
|
+
2. Use snake_case names and minimal fixtures.
|
|
87
|
+
3. Run only the new test: `node tests/test-runner.js --test=your-test-file.test.js`.
|
|
88
|
+
4. Update `tests/README.md` if workflow changes.
|
|
89
|
+
|
|
90
|
+
#### 4) Update or Add Documentation
|
|
91
|
+
**Goal**: Keep agents and developers aligned on current behavior.
|
|
92
|
+
1. Add short, high-signal sections (avoid large rewrites).
|
|
93
|
+
2. Include commands and file paths.
|
|
94
|
+
3. For broken behavior, add a "Known Issues" entry here.
|
|
95
|
+
|
|
96
|
+
#### 5) MVVM Binding and Full-Stack Control Usage
|
|
97
|
+
**Goal**: Wire data models to controls and serve them end to end.
|
|
98
|
+
1. Build controls under `client.js` using `Active_HTML_Document`.
|
|
99
|
+
2. Compose controls only when `!spec.el`.
|
|
100
|
+
3. Use `this.data.model` and `this.view.data.model` plus `watch` and `computed`.
|
|
101
|
+
4. Render server-side with `Server_Static_Page_Context` for quick validation.
|
|
102
|
+
5. Serve with `Server.serve` and run `examples-controls.e2e.test.js`.
|
|
103
|
+
|
|
104
|
+
### Rapid Triage Checklist (When Tests Fail)
|
|
105
|
+
1. Identify whether the failure is **render**, **bundle**, **runtime**, or **assertion**.
|
|
106
|
+
2. If render: instantiate with `Server_Static_Page_Context`.
|
|
107
|
+
3. If bundle: inspect esbuild logs and `resources/processors/bundlers/...`.
|
|
108
|
+
4. If runtime: open the example in a browser or puppeteer.
|
|
109
|
+
5. If assertion: validate expected output and update fixtures.
|
|
110
|
+
|
|
111
|
+
### Suggested Minimal Command Set
|
|
112
|
+
```bash
|
|
113
|
+
rg -n "needle" path/
|
|
114
|
+
rg --files path/
|
|
115
|
+
node tests/test-runner.js --test=examples-controls.e2e.test.js
|
|
116
|
+
node tests/test-runner.js --test=window-examples.puppeteer.test.js
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Codebase Structure Overview
|
|
37
120
|
|
|
38
121
|
### Core Architecture
|
|
39
122
|
|
|
@@ -487,4 +570,4 @@ If you discover critical issues:
|
|
|
487
570
|
|
|
488
571
|
---
|
|
489
572
|
|
|
490
|
-
**Remember**: This guide is the central place for agents to document broken functionality and implementation gaps. If you find something broken or incomplete, document it here immediately with details about location, impact, and status.
|
|
573
|
+
**Remember**: This guide is the central place for agents to document broken functionality and implementation gaps. If you find something broken or incomplete, document it here immediately with details about location, impact, and status.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Overview
|
|
2
|
+
|
|
3
|
+
JSGUI3 uses a shared control model across server and client. The server renders HTML, bundles JS and CSS, and the client activates controls for interactivity.
|
|
4
|
+
|
|
5
|
+
## Core Ideas
|
|
6
|
+
- Controls are composed on the server, activated in the browser.
|
|
7
|
+
- MVVM is supported via data and view models plus watchers and computed fields.
|
|
8
|
+
- CSS can live alongside controls and is extracted by the bundler.
|
|
9
|
+
|
|
10
|
+
## Minimal Vocabulary
|
|
11
|
+
- **Control**: UI building block.
|
|
12
|
+
- **Active_HTML_Document**: top-level page control for full HTML.
|
|
13
|
+
- **Server_Static_Page_Context**: server-side render context for fast validation.
|
|
14
|
+
- **Publisher**: serves HTML/JS/CSS to the browser.
|
|
15
|
+
|
|
16
|
+
## Quick Win
|
|
17
|
+
If you only need rendering verification, instantiate a control with `Server_Static_Page_Context` and call `all_html_render()`.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Stack Map
|
|
2
|
+
|
|
3
|
+
This chapter gives a quick map of the JSGUI3 stack and the files you touch most often.
|
|
4
|
+
|
|
5
|
+
## Modules
|
|
6
|
+
| Module | Role | Typical Entry |
|
|
7
|
+
| --- | --- | --- |
|
|
8
|
+
| jsgui3-html | core controls and rendering | `controls/` |
|
|
9
|
+
| jsgui3-client | browser activation | `client.js` |
|
|
10
|
+
| jsgui3-server | bundling + publishing | `server.js` |
|
|
11
|
+
|
|
12
|
+
## Key Files
|
|
13
|
+
- `server.js`: main server class, publisher wiring
|
|
14
|
+
- `static-page-context.js`: server render context
|
|
15
|
+
- `controls/Active_HTML_Document.js`: HTML doc wrapper
|
|
16
|
+
- `resources/processors/bundlers/`: JS and CSS bundlers
|
|
17
|
+
- `publishers/http-webpage-publisher.js`: HTML render + static routes
|
|
18
|
+
|
|
19
|
+
## Flow Sketch
|
|
20
|
+
```
|
|
21
|
+
client.js -> JS bundler -> JS/CSS routes -> HTTP_Webpage_Publisher -> browser
|
|
22
|
+
| |
|
|
23
|
+
| +-> CSS extraction from control static css
|
|
24
|
+
+-> Active_HTML_Document render on server
|
|
25
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Control Lifecycle
|
|
2
|
+
|
|
3
|
+
## Compose vs Activate
|
|
4
|
+
- **Compose**: build child controls and layout in the constructor.
|
|
5
|
+
- **Activate**: bind DOM events and runtime logic after client load.
|
|
6
|
+
|
|
7
|
+
## Composition Rule
|
|
8
|
+
Only compose when `!spec.el`. This avoids double composition during client activation.
|
|
9
|
+
|
|
10
|
+
## Minimal Pattern
|
|
11
|
+
```javascript
|
|
12
|
+
class Demo_UI extends Active_HTML_Document {
|
|
13
|
+
constructor(spec = {}) {
|
|
14
|
+
spec.__type_name = spec.__type_name || 'demo_ui';
|
|
15
|
+
super(spec);
|
|
16
|
+
const { context } = this;
|
|
17
|
+
if (!spec.el) {
|
|
18
|
+
const window_ctrl = new controls.Window({ context, title: 'Demo' });
|
|
19
|
+
this.body.add(window_ctrl);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Server Render Quick Check
|
|
26
|
+
```javascript
|
|
27
|
+
const Server_Static_Page_Context = require('./static-page-context');
|
|
28
|
+
const jsgui = require('./examples/controls/1) window/client.js');
|
|
29
|
+
const Demo_UI = jsgui.controls.Demo_UI;
|
|
30
|
+
const demo_ui = new Demo_UI({ context: new Server_Static_Page_Context() });
|
|
31
|
+
const html = demo_ui.all_html_render();
|
|
32
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# MVVM Basics
|
|
2
|
+
|
|
3
|
+
JSGUI3 controls support data and view models. Use `watch` for updates and `computed` for derived values.
|
|
4
|
+
|
|
5
|
+
## Minimal MVVM Skeleton
|
|
6
|
+
```javascript
|
|
7
|
+
const jsgui = require('jsgui3-client');
|
|
8
|
+
const { controls, Control } = jsgui;
|
|
9
|
+
|
|
10
|
+
const set_model_value = (model, name, value) => {
|
|
11
|
+
if (!model) return;
|
|
12
|
+
if (typeof model.set === 'function') {
|
|
13
|
+
model.set(name, value);
|
|
14
|
+
} else {
|
|
15
|
+
model[name] = value;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
class Profile_Panel extends Control {
|
|
20
|
+
constructor(spec = {}) {
|
|
21
|
+
spec.__type_name = spec.__type_name || 'profile_panel';
|
|
22
|
+
super(spec);
|
|
23
|
+
if (!spec.el) {
|
|
24
|
+
const { context } = this;
|
|
25
|
+
const name_input = new controls.Text_Input({ context });
|
|
26
|
+
this.add(name_input);
|
|
27
|
+
this.name_input = name_input;
|
|
28
|
+
}
|
|
29
|
+
this.setup_bindings();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
setup_bindings() {
|
|
33
|
+
const data_model = this.data && this.data.model;
|
|
34
|
+
if (!data_model || !this.name_input) return;
|
|
35
|
+
this.watch(data_model, 'full_name', value => {
|
|
36
|
+
this.name_input.set_value(value || '');
|
|
37
|
+
});
|
|
38
|
+
this.name_input.on('input', () => {
|
|
39
|
+
set_model_value(data_model, 'full_name', this.name_input.get_value());
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Computed Fields
|
|
46
|
+
```javascript
|
|
47
|
+
this.computed(
|
|
48
|
+
view_model,
|
|
49
|
+
['first_name', 'last_name'],
|
|
50
|
+
(first_name, last_name) => {
|
|
51
|
+
const safe_first = (first_name || '').trim();
|
|
52
|
+
const safe_last = (last_name || '').trim();
|
|
53
|
+
return `${safe_first} ${safe_last}`.trim();
|
|
54
|
+
},
|
|
55
|
+
{ propertyName: 'full_name' }
|
|
56
|
+
);
|
|
57
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Bindings and Validation
|
|
2
|
+
|
|
3
|
+
Use `Form_Container` for form layouts and built-in validation messaging. Pair it with `Alert_Banner` for high-level status.
|
|
4
|
+
|
|
5
|
+
## Form_Container Example
|
|
6
|
+
```javascript
|
|
7
|
+
const jsgui = require('jsgui3-client');
|
|
8
|
+
const { controls, Control } = jsgui;
|
|
9
|
+
const Active_HTML_Document = require('jsgui3-server/controls/Active_HTML_Document');
|
|
10
|
+
|
|
11
|
+
const validate_email = value => {
|
|
12
|
+
const trimmed = String(value || '').trim();
|
|
13
|
+
if (!trimmed) return 'Email is required.';
|
|
14
|
+
if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) return 'Enter a valid email.';
|
|
15
|
+
return true;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
class Demo_UI extends Active_HTML_Document {
|
|
19
|
+
constructor(spec = {}) {
|
|
20
|
+
spec.__type_name = spec.__type_name || 'demo_ui';
|
|
21
|
+
super(spec);
|
|
22
|
+
const { context } = this;
|
|
23
|
+
if (!spec.el) {
|
|
24
|
+
const window_ctrl = new controls.Window({ context, title: 'Form Demo' });
|
|
25
|
+
const alert_banner = new controls.Alert_Banner({
|
|
26
|
+
context,
|
|
27
|
+
status: 'info',
|
|
28
|
+
message: 'Complete the form.'
|
|
29
|
+
});
|
|
30
|
+
const form_container = new controls.Form_Container({
|
|
31
|
+
context,
|
|
32
|
+
fields: [
|
|
33
|
+
{ name: 'email', label: 'Email', required: true, validator: validate_email }
|
|
34
|
+
],
|
|
35
|
+
show_status_badge: true
|
|
36
|
+
});
|
|
37
|
+
form_container.on('submit', () => {
|
|
38
|
+
alert_banner.set_status('success');
|
|
39
|
+
alert_banner.set_message('Submitted.');
|
|
40
|
+
});
|
|
41
|
+
form_container.on('invalid', () => {
|
|
42
|
+
alert_banner.set_status('error');
|
|
43
|
+
alert_banner.set_message('Fix errors.');
|
|
44
|
+
});
|
|
45
|
+
window_ctrl.inner.add(alert_banner);
|
|
46
|
+
window_ctrl.inner.add(form_container);
|
|
47
|
+
this.body.add(window_ctrl);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Full-Stack Example
|
|
2
|
+
|
|
3
|
+
This is the minimal end-to-end setup: a control, server entry, and a quick render check.
|
|
4
|
+
|
|
5
|
+
## client.js
|
|
6
|
+
```javascript
|
|
7
|
+
const jsgui = require('jsgui3-client');
|
|
8
|
+
const { controls } = jsgui;
|
|
9
|
+
const Active_HTML_Document = require('jsgui3-server/controls/Active_HTML_Document');
|
|
10
|
+
|
|
11
|
+
class Demo_UI extends Active_HTML_Document {
|
|
12
|
+
constructor(spec = {}) {
|
|
13
|
+
spec.__type_name = spec.__type_name || 'demo_ui';
|
|
14
|
+
super(spec);
|
|
15
|
+
const { context } = this;
|
|
16
|
+
if (!spec.el) {
|
|
17
|
+
const window_ctrl = new controls.Window({
|
|
18
|
+
context,
|
|
19
|
+
title: 'Full Stack Demo',
|
|
20
|
+
pos: [12, 12]
|
|
21
|
+
});
|
|
22
|
+
this.body.add(window_ctrl);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
controls.Demo_UI = Demo_UI;
|
|
28
|
+
module.exports = jsgui;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## server.js
|
|
32
|
+
```javascript
|
|
33
|
+
const Server = require('jsgui3-server');
|
|
34
|
+
const { Demo_UI } = require('./client').controls;
|
|
35
|
+
|
|
36
|
+
Server.serve({
|
|
37
|
+
ctrl: Demo_UI,
|
|
38
|
+
src_path_client_js: require.resolve('./client.js'),
|
|
39
|
+
port: 3000
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Render Check
|
|
44
|
+
```javascript
|
|
45
|
+
const Server_Static_Page_Context = require('jsgui3-server/static-page-context');
|
|
46
|
+
const jsgui = require('./client');
|
|
47
|
+
const Demo_UI = jsgui.controls.Demo_UI;
|
|
48
|
+
const demo_ui = new Demo_UI({ context: new Server_Static_Page_Context() });
|
|
49
|
+
const html = demo_ui.all_html_render();
|
|
50
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
Use the smallest test that validates your change.
|
|
4
|
+
|
|
5
|
+
## Focused Commands
|
|
6
|
+
```bash
|
|
7
|
+
node tests/test-runner.js --test=examples-controls.e2e.test.js
|
|
8
|
+
node tests/test-runner.js --test=window-examples.puppeteer.test.js
|
|
9
|
+
node tests/test-runner.js --test=sass-controls.e2e.test.js
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Server Render Probe
|
|
13
|
+
```javascript
|
|
14
|
+
const Server_Static_Page_Context = require('jsgui3-server/static-page-context');
|
|
15
|
+
const jsgui = require('./client');
|
|
16
|
+
const Demo_UI = jsgui.controls.Demo_UI;
|
|
17
|
+
const demo_ui = new Demo_UI({ context: new Server_Static_Page_Context() });
|
|
18
|
+
const html = demo_ui.all_html_render();
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## When To Expand Coverage
|
|
22
|
+
- Add an e2e test if the change affects bundling or HTML delivery.
|
|
23
|
+
- Add a puppeteer story if the change impacts window interactions.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Render Errors
|
|
4
|
+
- Use `Server_Static_Page_Context` to reproduce server-side render failures.
|
|
5
|
+
- Ensure controls are composed only when `!spec.el`.
|
|
6
|
+
- Check that `jsgui.controls` exports your control.
|
|
7
|
+
|
|
8
|
+
## Bundler Errors
|
|
9
|
+
- Verify bundlers call `complete(...)` on both success and error paths.
|
|
10
|
+
- Confirm `src_path_client_js` points to `client.js`.
|
|
11
|
+
- Review `docs/troubleshooting.md` for known issues.
|
|
12
|
+
|
|
13
|
+
## Missing Controls
|
|
14
|
+
- Confirm the control is exported from `jsgui3-html/controls/controls.js`.
|
|
15
|
+
- Verify `jsgui3-client` is using the linked `jsgui3-html`.
|
|
16
|
+
|
|
17
|
+
## MVVM Binding Not Updating
|
|
18
|
+
- Ensure `this.data.model` and `this.view.data.model` are present.
|
|
19
|
+
- Confirm `watch` and `computed` are wired after composition.
|
|
20
|
+
- Check that input controls use `set_value` and `get_value`.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Agent Playbooks
|
|
2
|
+
|
|
3
|
+
These playbooks are optimized for low thinking time execution.
|
|
4
|
+
|
|
5
|
+
## Playbook: Add a MVVM Binding
|
|
6
|
+
**Goal**: Wire model values to inputs and derived UI.
|
|
7
|
+
1. Confirm `this.data.model` and `this.view.data.model` exist.
|
|
8
|
+
2. Add `watch` handlers for input controls.
|
|
9
|
+
3. Add `computed` fields for derived labels.
|
|
10
|
+
4. Verify with a server render probe.
|
|
11
|
+
|
|
12
|
+
## Playbook: Build a New Control Example
|
|
13
|
+
**Goal**: Add a new example with end-to-end delivery.
|
|
14
|
+
1. Create `examples/.../client.js`.
|
|
15
|
+
2. Extend `Active_HTML_Document` and compose under `!spec.el`.
|
|
16
|
+
3. Export control in `jsgui.controls`.
|
|
17
|
+
4. Add to `tests/examples-controls.e2e.test.js`.
|
|
18
|
+
5. Run the targeted test.
|
|
19
|
+
|
|
20
|
+
## Playbook: Fix a Bundler Failure
|
|
21
|
+
**Goal**: Ensure bundler completes and static routes are available.
|
|
22
|
+
1. Inspect `resources/processors/bundlers/...` for early exits.
|
|
23
|
+
2. Ensure errors call `complete(...)` with a bundle object.
|
|
24
|
+
3. Run `tests/bundlers.test.js`.
|
|
25
|
+
|
|
26
|
+
## Playbook: Improve Full-Stack Control Usage
|
|
27
|
+
**Goal**: Ensure controls render and activate correctly.
|
|
28
|
+
1. Validate `Active_HTML_Document` composition and CSS.
|
|
29
|
+
2. Confirm JS/CSS routes exist via `HTTP_Webpage_Publisher`.
|
|
30
|
+
3. Run the e2e and puppeteer tests.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# JSGUI3 MVVM and Full-Stack Controls Book
|
|
2
|
+
|
|
3
|
+
This book is a fast, focused guide to MVVM binding and end-to-end control delivery in the JSGUI3 stack.
|
|
4
|
+
|
|
5
|
+
## Who This Is For
|
|
6
|
+
- AI agents that need low thinking time workflows.
|
|
7
|
+
- Developers wiring controls across server and client.
|
|
8
|
+
- Anyone troubleshooting binding, rendering, or bundling issues.
|
|
9
|
+
|
|
10
|
+
## How To Read
|
|
11
|
+
- Start with the overview and lifecycle chapters.
|
|
12
|
+
- Use the playbooks for task execution.
|
|
13
|
+
- Jump to testing and troubleshooting as soon as you hit a blocker.
|
|
14
|
+
|
|
15
|
+
## Chapter Index
|
|
16
|
+
1. [Overview](00-overview.md)
|
|
17
|
+
2. [Stack Map](01-stack-map.md)
|
|
18
|
+
3. [Control Lifecycle](02-control-lifecycle.md)
|
|
19
|
+
4. [MVVM Basics](03-mvvm-basics.md)
|
|
20
|
+
5. [Bindings and Validation](04-bindings-and-validation.md)
|
|
21
|
+
6. [Full-Stack Example](05-full-stack-example.md)
|
|
22
|
+
7. [Testing](06-testing.md)
|
|
23
|
+
8. [Troubleshooting](07-troubleshooting.md)
|
|
24
|
+
9. [Agent Playbooks](08-agent-playbooks.md)
|
|
25
|
+
|
|
26
|
+
## Fast Lane Summary
|
|
27
|
+
- Controls live in `client.js` and export to `jsgui.controls`.
|
|
28
|
+
- Compose UI in `constructor` only when `!spec.el`.
|
|
29
|
+
- Use `Server_Static_Page_Context` to validate server-side render quickly.
|
|
30
|
+
- Use `Server.serve` for end-to-end delivery.
|
|
@@ -27,22 +27,24 @@ The server acts as a bridge between server-side JavaScript applications and brow
|
|
|
27
27
|
|
|
28
28
|
## Table of Contents
|
|
29
29
|
|
|
30
|
-
1. [Quick Start](#quick-start)
|
|
31
|
-
2. [
|
|
32
|
-
3. [
|
|
33
|
-
4. [
|
|
34
|
-
5. [
|
|
35
|
-
6. [
|
|
36
|
-
7. [
|
|
37
|
-
8. [
|
|
38
|
-
9. [
|
|
39
|
-
10. [
|
|
40
|
-
11. [
|
|
41
|
-
12. [
|
|
42
|
-
13. [
|
|
43
|
-
14. [
|
|
44
|
-
15. [
|
|
45
|
-
16. [
|
|
30
|
+
1. [Quick Start](#quick-start)
|
|
31
|
+
2. [AI Agent Fast Start](#ai-agent-fast-start)
|
|
32
|
+
3. [Architecture Overview](#architecture-overview)
|
|
33
|
+
4. [Core Components](#core-components)
|
|
34
|
+
5. [Installation and Setup](#installation-and-setup)
|
|
35
|
+
6. [Configuration](#configuration)
|
|
36
|
+
7. [API Reference](#api-reference)
|
|
37
|
+
8. [Examples](#examples)
|
|
38
|
+
9. [Development](#development)
|
|
39
|
+
10. [Troubleshooting](#troubleshooting)
|
|
40
|
+
11. [Deployment & Production](#deployment--production)
|
|
41
|
+
12. [Contributing](#contributing)
|
|
42
|
+
13. [Code Style Guidelines](#code-style-guidelines)
|
|
43
|
+
14. [License](#license)
|
|
44
|
+
15. [Changelog](#changelog)
|
|
45
|
+
16. [Support](#support)
|
|
46
|
+
17. [Roadmap](#roadmap)
|
|
47
|
+
18. [MVVM and Full-Stack Controls](#mvvm-and-full-stack-controls)
|
|
46
48
|
|
|
47
49
|
## Quick Start
|
|
48
50
|
|
|
@@ -97,19 +99,42 @@ Server.serve({
|
|
|
97
99
|
|
|
98
100
|
### With API Endpoints
|
|
99
101
|
|
|
100
|
-
```javascript
|
|
101
|
-
Server.serve({
|
|
102
|
-
ctrl: DashboardControl,
|
|
103
|
-
src_path_client_js: require.resolve('./client.js'),
|
|
104
|
-
api: {
|
|
105
|
-
'metrics': () => ({ users: 1234, revenue: 56789 }),
|
|
106
|
-
'data': async ({ range }) => await fetchAnalytics(range)
|
|
107
|
-
},
|
|
108
|
-
port: 3000
|
|
109
|
-
});
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
##
|
|
102
|
+
```javascript
|
|
103
|
+
Server.serve({
|
|
104
|
+
ctrl: DashboardControl,
|
|
105
|
+
src_path_client_js: require.resolve('./client.js'),
|
|
106
|
+
api: {
|
|
107
|
+
'metrics': () => ({ users: 1234, revenue: 56789 }),
|
|
108
|
+
'data': async ({ range }) => await fetchAnalytics(range)
|
|
109
|
+
},
|
|
110
|
+
port: 3000
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## AI Agent Fast Start
|
|
115
|
+
|
|
116
|
+
This section is a short, task-oriented runway for AI agents that need to act quickly with minimal overhead.
|
|
117
|
+
|
|
118
|
+
**Start here:**
|
|
119
|
+
1. Identify the target subsystem: examples, bundlers, publishers, or controls.
|
|
120
|
+
2. Jump to the focused guide: `docs/books/jsgui3-mvvm-fullstack/README.md`.
|
|
121
|
+
3. Make the smallest change that can pass a targeted test.
|
|
122
|
+
4. Run the narrow test file first, then widen if needed.
|
|
123
|
+
|
|
124
|
+
**Minimal commands:**
|
|
125
|
+
```bash
|
|
126
|
+
rg -n "needle" path/
|
|
127
|
+
rg --files path/
|
|
128
|
+
node tests/test-runner.js --test=examples-controls.e2e.test.js
|
|
129
|
+
node tests/test-runner.js --test=window-examples.puppeteer.test.js
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Known fast checks:**
|
|
133
|
+
- Render server-side quickly with `Server_Static_Page_Context`.
|
|
134
|
+
- Confirm a control is exported under `jsgui.controls`.
|
|
135
|
+
- Ensure composition happens only when `!spec.el`.
|
|
136
|
+
|
|
137
|
+
## Architecture Overview
|
|
113
138
|
|
|
114
139
|
### Core Architecture
|
|
115
140
|
|
|
@@ -212,11 +237,97 @@ JSGUI3 provides a rich set of UI controls:
|
|
|
212
237
|
- **Button**: Interactive button control
|
|
213
238
|
- **Text_Input**: Text input field
|
|
214
239
|
- **Checkbox**: Boolean input control
|
|
215
|
-
- **Date_Picker**: Date selection control
|
|
216
|
-
- **Month_View**: Calendar display
|
|
217
|
-
- **Menu**: Dropdown menu control
|
|
218
|
-
|
|
219
|
-
##
|
|
240
|
+
- **Date_Picker**: Date selection control
|
|
241
|
+
- **Month_View**: Calendar display
|
|
242
|
+
- **Menu**: Dropdown menu control
|
|
243
|
+
|
|
244
|
+
## MVVM and Full-Stack Controls
|
|
245
|
+
|
|
246
|
+
For a complete, step-by-step walkthrough of MVVM binding and full-stack control usage, use:
|
|
247
|
+
`docs/books/jsgui3-mvvm-fullstack/README.md`
|
|
248
|
+
|
|
249
|
+
### Minimal Full-Stack Control Example
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
const jsgui = require('jsgui3-client');
|
|
253
|
+
const { controls } = jsgui;
|
|
254
|
+
const Active_HTML_Document = require('jsgui3-server/controls/Active_HTML_Document');
|
|
255
|
+
|
|
256
|
+
class Demo_UI extends Active_HTML_Document {
|
|
257
|
+
constructor(spec = {}) {
|
|
258
|
+
spec.__type_name = spec.__type_name || 'demo_ui';
|
|
259
|
+
super(spec);
|
|
260
|
+
const { context } = this;
|
|
261
|
+
if (!spec.el) {
|
|
262
|
+
const window_ctrl = new controls.Window({
|
|
263
|
+
context,
|
|
264
|
+
title: 'Hello JSGUI3'
|
|
265
|
+
});
|
|
266
|
+
this.body.add(window_ctrl);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
controls.Demo_UI = Demo_UI;
|
|
272
|
+
module.exports = jsgui;
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
const Server = require('jsgui3-server');
|
|
277
|
+
const { Demo_UI } = require('./client').controls;
|
|
278
|
+
|
|
279
|
+
Server.serve({
|
|
280
|
+
ctrl: Demo_UI,
|
|
281
|
+
src_path_client_js: require.resolve('./client.js'),
|
|
282
|
+
port: 3000
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### MVVM Binding Skeleton
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
const jsgui = require('jsgui3-client');
|
|
290
|
+
const { controls, Control } = jsgui;
|
|
291
|
+
|
|
292
|
+
const set_model_value = (model, name, value) => {
|
|
293
|
+
if (!model) return;
|
|
294
|
+
if (typeof model.set === 'function') {
|
|
295
|
+
model.set(name, value);
|
|
296
|
+
} else {
|
|
297
|
+
model[name] = value;
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
class Profile_Panel extends Control {
|
|
302
|
+
constructor(spec = {}) {
|
|
303
|
+
spec.__type_name = spec.__type_name || 'profile_panel';
|
|
304
|
+
super(spec);
|
|
305
|
+
if (!spec.el) {
|
|
306
|
+
const { context } = this;
|
|
307
|
+
const name_input = new controls.Text_Input({ context });
|
|
308
|
+
this.add(name_input);
|
|
309
|
+
this.name_input = name_input;
|
|
310
|
+
}
|
|
311
|
+
this.setup_bindings();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
setup_bindings() {
|
|
315
|
+
const data_model = this.data && this.data.model;
|
|
316
|
+
if (!data_model || !this.name_input) return;
|
|
317
|
+
this.watch(data_model, 'full_name', value => {
|
|
318
|
+
this.name_input.set_value(value || '');
|
|
319
|
+
});
|
|
320
|
+
this.name_input.on('input', () => {
|
|
321
|
+
set_model_value(data_model, 'full_name', this.name_input.get_value());
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
controls.Profile_Panel = Profile_Panel;
|
|
327
|
+
module.exports = jsgui;
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Installation and Setup
|
|
220
331
|
|
|
221
332
|
### Prerequisites
|
|
222
333
|
|