jsgui3-server 0.0.151 → 0.0.152
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/admin-ui/v1/controls/admin_shell.js +33 -0
- package/admin-ui/v1/server.js +14 -1
- package/docs/api-reference.md +120 -2
- package/docs/books/website-design/01-introduction.md +73 -0
- package/docs/books/website-design/02-current-state.md +195 -0
- package/docs/books/website-design/03-base-class.md +181 -0
- package/docs/books/website-design/04-webpage.md +307 -0
- package/docs/books/website-design/05-website.md +456 -0
- package/docs/books/website-design/06-pages-storage.md +170 -0
- package/docs/books/website-design/07-api-layer.md +285 -0
- package/docs/books/website-design/08-server-integration.md +271 -0
- package/docs/books/website-design/09-cross-agent-review.md +190 -0
- package/docs/books/website-design/10-open-questions.md +196 -0
- package/docs/books/website-design/11-converged-recommendation.md +205 -0
- package/docs/books/website-design/12-content-model.md +395 -0
- package/docs/books/website-design/13-webpage-module-spec.md +404 -0
- package/docs/books/website-design/14-website-module-spec.md +541 -0
- package/docs/books/website-design/15-multi-repo-plan.md +275 -0
- package/docs/books/website-design/16-minimal-first.md +203 -0
- package/docs/books/website-design/17-implementation-report-codex.md +81 -0
- package/docs/books/website-design/README.md +43 -0
- package/docs/configuration-reference.md +54 -0
- package/docs/proposals/jsgui3-website-and-webpage-design-jsgui3-server-support.md +257 -0
- package/docs/proposals/jsgui3-website-and-webpage-design-review.md +73 -0
- package/docs/proposals/jsgui3-website-and-webpage-design.md +732 -0
- package/docs/swagger.md +316 -0
- package/examples/controls/1) window/server.js +6 -1
- package/examples/controls/21) mvvm and declarative api/check.js +94 -0
- package/examples/controls/21) mvvm and declarative api/check_output.txt +25 -0
- package/examples/controls/21) mvvm and declarative api/check_output_2.txt +27 -0
- package/examples/controls/21) mvvm and declarative api/client.js +241 -0
- declarative api/e2e-screenshot-1-name-change.png +0 -0
- declarative api/e2e-screenshot-2-toggled.png +0 -0
- declarative api/e2e-screenshot-3-final.png +0 -0
- declarative api/e2e-screenshot-final.png +0 -0
- package/examples/controls/21) mvvm and declarative api/e2e-test.js +175 -0
- package/examples/controls/21) mvvm and declarative api/out.html +1 -0
- package/examples/controls/21) mvvm and declarative api/page_out.html +1 -0
- package/examples/controls/21) mvvm and declarative api/server.js +18 -0
- package/examples/data-views/01) query-endpoint/server.js +61 -0
- package/labs/website-design/001-base-class-overhead/check.js +162 -0
- package/labs/website-design/002-pages-storage/check.js +244 -0
- package/labs/website-design/002-pages-storage/results.txt +0 -0
- package/labs/website-design/003-type-detection/check.js +193 -0
- package/labs/website-design/003-type-detection/results.txt +0 -0
- package/labs/website-design/004-two-stage-validation/check.js +314 -0
- package/labs/website-design/004-two-stage-validation/results.txt +0 -0
- package/labs/website-design/005-normalize-input/check.js +303 -0
- package/labs/website-design/006-serve-website-spike/check.js +290 -0
- package/labs/website-design/README.md +34 -0
- package/labs/website-design/manifest.json +68 -0
- package/labs/website-design/run-all.js +60 -0
- package/middleware/json-body.js +126 -0
- package/openapi.js +474 -0
- package/package.json +11 -8
- package/publishers/Publishers.js +6 -5
- package/publishers/http-function-publisher.js +135 -126
- package/publishers/http-webpage-publisher.js +89 -11
- package/publishers/query-publisher.js +116 -0
- package/publishers/swagger-publisher.js +203 -0
- package/publishers/swagger-ui.js +578 -0
- package/resources/adapters/array-adapter.js +143 -0
- package/resources/query-resource.js +131 -0
- package/serve-factory.js +728 -18
- package/server.js +421 -103
- package/tests/README.md +23 -1
- package/tests/admin-ui-jsgui-controls.test.js +16 -1
- package/tests/helpers/playwright-e2e-harness.js +326 -0
- package/tests/openapi.test.js +319 -0
- package/tests/playwright-smoke.test.js +134 -0
- package/tests/publish-enhancements.test.js +673 -0
- package/tests/query-publisher.test.js +430 -0
- package/tests/quick-json-body-test.js +169 -0
- package/tests/serve.test.js +425 -122
- package/tests/swagger-publisher.test.js +1076 -0
- package/tests/test-runner.js +1 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Chapter 9: Cross-Agent Review
|
|
2
|
+
|
|
3
|
+
An OpenAI o3 agent was given the original proposals document and asked to review it and contribute to the design discussion. This chapter presents their findings and discusses the responses.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Review Process
|
|
8
|
+
|
|
9
|
+
The agent was asked to do two things:
|
|
10
|
+
|
|
11
|
+
1. **Review the proposals** — identify Best and Worst ideas (5 Best, 5 Worst)
|
|
12
|
+
2. **Contribute to the design** — propose new ideas or refinements, then write a separate server-support document
|
|
13
|
+
|
|
14
|
+
The results were two documents:
|
|
15
|
+
- `jsgui3-website-and-webpage-design-review.md` — the review
|
|
16
|
+
- `jsgui3-website-and-webpage-design-jsgui3-server-support.md` — a detailed server integration proposal
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Best Ideas (Their Assessment)
|
|
21
|
+
|
|
22
|
+
### 1. "Keeping Website/Webpage optional to jsgui3-server"
|
|
23
|
+
|
|
24
|
+
They identified this as the strongest architectural choice. The reasoning: it preserves low-friction serving for simple cases while allowing richer abstractions for apps that want them.
|
|
25
|
+
|
|
26
|
+
**Response**: Agreed completely. This is a hard constraint, not just a design preference. The server's `Server.serve(MyCtrl)` one-liner is one of its best features and must not be complicated.
|
|
27
|
+
|
|
28
|
+
### 2. "Making inspectability a first-class goal"
|
|
29
|
+
|
|
30
|
+
They praised `toJSON()` and metadata exposure for admin tooling, diagnostics, docs generation, and tests.
|
|
31
|
+
|
|
32
|
+
**Response**: Agreed. The admin UI already introspects the resource pool and router. Having structured `toJSON()` on Website/Webpage gives it a stable contract to display.
|
|
33
|
+
|
|
34
|
+
### 3. "Supporting multiple page input shapes"
|
|
35
|
+
|
|
36
|
+
Both array and object-map formats were called "pragmatic."
|
|
37
|
+
|
|
38
|
+
**Response**: Agreed. This is about meeting users where they are, not forcing one format.
|
|
39
|
+
|
|
40
|
+
### 4. "Calling out the API.js export bug"
|
|
41
|
+
|
|
42
|
+
Good proposal hygiene — the design document is grounded in reality and identifies hard runtime blockers.
|
|
43
|
+
|
|
44
|
+
**Response**: The bug (`MediaSourceHandle.exports` instead of `module.exports`) would crash on any `require('./API')` call. Including it prevents someone from trying to use the existing code and being confused.
|
|
45
|
+
|
|
46
|
+
### 5. "The open-question section is high quality"
|
|
47
|
+
|
|
48
|
+
They noted it addresses exactly the unknowns that matter for primitives.
|
|
49
|
+
|
|
50
|
+
**Response**: Agreed. Design documents should be honest about what they don't know.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Worst Ideas (Their Assessment)
|
|
55
|
+
|
|
56
|
+
### 1. "Leaning on `Collection` internals (`pages._arr`)"
|
|
57
|
+
|
|
58
|
+
Called the weakest technical direction. Bakes internal details into public behavior, increases fragility.
|
|
59
|
+
|
|
60
|
+
**Response**: **Strongly agree.** The current `http-website-publisher.js` accesses `website.pages._arr` directly. This is an implementation detail of Collection that shouldn't appear in any public interface. Chapter 6 discusses alternatives; Map with method-based access is the cleaner direction.
|
|
61
|
+
|
|
62
|
+
### 2. "Using `Evented_Class` as a default Webpage model"
|
|
63
|
+
|
|
64
|
+
Called "over-engineered for current needs." Adds boilerplate, coupling, and cognitive load before there's a concrete consumer.
|
|
65
|
+
|
|
66
|
+
**Response**: **Partially disagree.** The reviewer is right that per-field change events are premature. But extending `Evented_Class` as a base class is essentially free — it adds `.on()` and `.raise()` without requiring their use. In an ecosystem where nearly everything extends `Evented_Class`, *not* using it is the choice that needs justification. The counter-argument is detailed in Chapter 3.
|
|
67
|
+
|
|
68
|
+
The key insight the reviewer missed: extending `Evented_Class` does not mean firing events on every property change. You can extend it and only raise events for meaningful lifecycle moments like `'page-added'` or `'ready'`.
|
|
69
|
+
|
|
70
|
+
### 3. "Hard-coupling primitives to jsgui3-html"
|
|
71
|
+
|
|
72
|
+
Called unnecessary dependency weight that limits reuse.
|
|
73
|
+
|
|
74
|
+
**Response**: **Partially disagree.** Both modules will depend on `jsgui3-html` — this is a stated requirement, not a design choice. The page `content` *is* a jsgui3-html control constructor. The question isn't whether to depend on jsgui3-html but how deeply: just importing `Evented_Class` (light coupling) vs. using Collection, tof, obext, etc. (deep coupling).
|
|
75
|
+
|
|
76
|
+
That said, the reviewer's principle is sound: keep the dependency surface as small as possible even within a required dependency.
|
|
77
|
+
|
|
78
|
+
### 4. "`instanceof` as a core integration strategy"
|
|
79
|
+
|
|
80
|
+
Called brittle across duplicated installs/workspaces.
|
|
81
|
+
|
|
82
|
+
**Response**: **Agree.** This is a real issue in the jsgui3 ecosystem, where packages are often `npm link`ed during development. Two copies of `jsgui3-website` would break `instanceof`. Chapter 8 discusses alternatives including duck typing and Symbol-based type markers.
|
|
83
|
+
|
|
84
|
+
### 5. "Defaulting page `path` to `'/'`"
|
|
85
|
+
|
|
86
|
+
Can silently mask configuration mistakes in multi-page scenarios.
|
|
87
|
+
|
|
88
|
+
**Response**: **Agree.** Two pages both defaulting to `/` would silently collide. The proposals in Chapter 4 do not default `path`, making it explicitly required.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Their Design Contributions
|
|
93
|
+
|
|
94
|
+
### 1. Layered model: core primitives + server adapter
|
|
95
|
+
|
|
96
|
+
**Idea**: Keep primitives lightweight. Put all server-specific logic in jsgui3-server.
|
|
97
|
+
|
|
98
|
+
**Response**: Correct architectural separation. The primitives define *what*, the server decides *how*. The Webpage shouldn't know about Express, HTTP, or bundling.
|
|
99
|
+
|
|
100
|
+
### 2. Strict minimal contract for primitives
|
|
101
|
+
|
|
102
|
+
**Idea**: Explicitly define what properties each primitive has and stick to it.
|
|
103
|
+
|
|
104
|
+
**Response**: Agreed, with nuance. The contract should be clear, but extensibility should be preserved. Unknown spec properties shouldn't crash the constructor.
|
|
105
|
+
|
|
106
|
+
### 3. Map semantics with stable methods
|
|
107
|
+
|
|
108
|
+
**Idea**: Use `add_page`, `get_page`, `has_page`, `remove_page`, `list_pages` — never expose storage internals.
|
|
109
|
+
|
|
110
|
+
**Response**: Agreed. This is the recommendation in Chapter 6 (Map option) and is implemented in Chapter 5, approaches B and C.
|
|
111
|
+
|
|
112
|
+
### 4. Separate endpoint declaration from server publishing
|
|
113
|
+
|
|
114
|
+
**Idea**: `Website_API` stores definitions; the server publishes them.
|
|
115
|
+
|
|
116
|
+
**Response**: Agreed. This is the central principle in Chapter 7. The naming discussion (declare/define/register vs. publish) addresses exactly this.
|
|
117
|
+
|
|
118
|
+
### 5. Normalize and validate early
|
|
119
|
+
|
|
120
|
+
**Idea**: Route normalization, duplicate detection, and handler checks at construction time.
|
|
121
|
+
|
|
122
|
+
**Response**: Agreed but with limits. Validation in the constructor catches errors early but can be annoying during development when building objects incrementally. The `finalize()` lifecycle model (discussed in Chapter 4, Approach C) offers a compromise: be permissive during construction, validate at finalization.
|
|
123
|
+
|
|
124
|
+
### 6. Lifecycle semantics instead of full reactivity
|
|
125
|
+
|
|
126
|
+
**Idea**: A simple `finalize()` model — mutable during composition, read-mostly after publish.
|
|
127
|
+
|
|
128
|
+
**Response**: This is the review's most original contribution. It solves the event-system complexity problem without losing safety. The idea is explored in Chapter 4, Approach C.
|
|
129
|
+
|
|
130
|
+
### 7. Formal `toJSON()` introspection contract
|
|
131
|
+
|
|
132
|
+
**Idea**: Keep serialization deterministic and tool-friendly.
|
|
133
|
+
|
|
134
|
+
**Response**: Agreed. All approaches in Chapters 4 and 5 include `toJSON()`.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Their Server Support Document
|
|
139
|
+
|
|
140
|
+
The OpenAI agent produced a separate, detailed server-integration proposal. Key contributions:
|
|
141
|
+
|
|
142
|
+
### The Normalized Manifest
|
|
143
|
+
|
|
144
|
+
The document's best idea. Instead of publishers each handling different input formats, a normalization step produces a standard `normalized_website_manifest` that all publishers consume. This includes:
|
|
145
|
+
|
|
146
|
+
- `normalized_page_manifest` — per-page with render_mode, cache_policy, assets, etc.
|
|
147
|
+
- `normalized_api_manifest` — per-endpoint with method, auth, rate_limit, tags
|
|
148
|
+
- `normalized_website_manifest` — site-level with base_path, policies, combined pages and API
|
|
149
|
+
|
|
150
|
+
**Response**: Architecturally excellent. This is the right pattern. The concern is scope — the proposed manifests include many fields (`rate_limit`, `route_priority`, `cache_policy`) that don't have consumers yet. Starting with a minimal manifest and growing it is more pragmatic.
|
|
151
|
+
|
|
152
|
+
### File-by-file changes
|
|
153
|
+
|
|
154
|
+
The document maps out changes to `serve-factory.js`, all three publishers, `server.js`, and the wrapper modules. It also proposes five new helper modules.
|
|
155
|
+
|
|
156
|
+
**Response**: The analysis is thorough. The recommendation to start with fewer helper files (one `normalize.js` rather than five) is more practical for a first pass.
|
|
157
|
+
|
|
158
|
+
### Delivery phases
|
|
159
|
+
|
|
160
|
+
Four phases: normalization → publisher modernization → metadata completeness → admin surface.
|
|
161
|
+
|
|
162
|
+
**Response**: Well-ordered. Each phase delivers independently useful value. The first phase (normalization + compatibility) is the right starting point.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Points of Convergence
|
|
167
|
+
|
|
168
|
+
Both agents (and the conversation so far) converge on:
|
|
169
|
+
|
|
170
|
+
1. Website/Webpage must be optional to the server
|
|
171
|
+
2. Map-based page storage with method-based API (no `_arr`)
|
|
172
|
+
3. Server should use capability checks, not `instanceof`
|
|
173
|
+
4. `toJSON()` for introspection
|
|
174
|
+
5. Accept multiple input formats (array, object-map, instances)
|
|
175
|
+
6. API endpoints should carry metadata beyond just name+handler
|
|
176
|
+
|
|
177
|
+
## Points of Disagreement
|
|
178
|
+
|
|
179
|
+
| Topic | This author | OpenAI reviewer |
|
|
180
|
+
|-------|-------------|-----------------|
|
|
181
|
+
| `Evented_Class` as base | Yes — ecosystem norm, free capability | No — over-engineered |
|
|
182
|
+
| `jsgui3-html` dependency | Required (stated constraint) | Unnecessary weight |
|
|
183
|
+
| When to validate | At construction or finalize | Always at construction |
|
|
184
|
+
| Number of new helper files | Start with 1 | Start with 5 |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Synthesis Forward
|
|
189
|
+
|
|
190
|
+
Chapter 11 captures the current convergence from this chapter: keep primitives optional, use normalized server manifests, avoid storage internals leakage, and ship in phased increments with strict backward compatibility.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Chapter 10: Open Questions
|
|
2
|
+
|
|
3
|
+
These are design decisions that remain unresolved. Each one could go in multiple directions, and the right choice depends on how these modules will actually be used.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Should Webpage manage client-side JS paths?
|
|
8
|
+
|
|
9
|
+
Today, `serve-factory.js` resolves client-side JavaScript paths (`src_path_client_js`). The page just says "my content is this control" and the server figures out what to bundle.
|
|
10
|
+
|
|
11
|
+
**Option A**: Webpage has a `client_js` property that points to the entry file:
|
|
12
|
+
```js
|
|
13
|
+
new Webpage({
|
|
14
|
+
content: MyCtrl,
|
|
15
|
+
client_js: './client/main.js'
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Option B**: The server infers the bundle path from the content control, as it does today.
|
|
20
|
+
|
|
21
|
+
**Option C**: Both — `client_js` is optional, and if provided, overrides the server's inference.
|
|
22
|
+
|
|
23
|
+
**The tension**: If the Webpage knows its client-side JS path, it becomes more self-contained (good for static site generation, good for admin display). But if it doesn't, the server retains full control over bundling (simpler, less to coordinate).
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. Static vs. dynamic pages — who decides?
|
|
28
|
+
|
|
29
|
+
A static page serves the same HTML to every request. A dynamic page generates HTML per-request (SSR). Today, all pages are effectively static — bundled once, served forever.
|
|
30
|
+
|
|
31
|
+
**Option A**: Page declares its render mode:
|
|
32
|
+
```js
|
|
33
|
+
new Webpage({ path: '/profile', content: Profile, render_mode: 'dynamic' });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Option B**: Server decides based on the content type (function = dynamic, instance = static).
|
|
37
|
+
|
|
38
|
+
**Option C**: Server decides, but page can opt in:
|
|
39
|
+
```js
|
|
40
|
+
new Webpage({ path: '/profile', content: Profile, dynamic: true });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**The tension**: Render mode has huge server implications (static pre-render vs. per-request handler). Should the page author decide this, or should the server operator? A page author might not understand the performance implications.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. Can these modules be used without jsgui3-server?
|
|
48
|
+
|
|
49
|
+
Potential non-server use cases:
|
|
50
|
+
- **Static site generator** — iterate pages, render each to an HTML file
|
|
51
|
+
- **Sitemap generator** — iterate pages, output XML
|
|
52
|
+
- **Documentation tool** — display the website structure
|
|
53
|
+
- **Testing** — assert that a website has the right pages/endpoints
|
|
54
|
+
|
|
55
|
+
If the answer is "yes, these should work standalone," it pushes toward keeping them dependency-light and not assuming a server context. If the answer is "they're primarily for jsgui3-server," more coupling is acceptable.
|
|
56
|
+
|
|
57
|
+
**Current position**: Both packages will depend on `jsgui3-html` (for `Evented_Class`), but nothing from `jsgui3-server`. This makes standalone use possible.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 4. Page ordering
|
|
62
|
+
|
|
63
|
+
Does the order of pages matter?
|
|
64
|
+
|
|
65
|
+
**Yes**: Navigation menus, sitemaps, breadcrumbs all have a natural order. If pages are in a Map, insertion order is preserved — but is that the intended display order?
|
|
66
|
+
|
|
67
|
+
**No**: Pages are identified by path, not position. A navigation component would use explicit ordering, not page insertion order.
|
|
68
|
+
|
|
69
|
+
**Maybe**: An optional `order` or `nav_index` property could let pages opt into ordered display:
|
|
70
|
+
```js
|
|
71
|
+
new Webpage({ path: '/about', title: 'About', nav_index: 2 });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This doesn't need to be decided now, but the data structure choice (Map preserves order; plain objects have less predictable iteration) has implications.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 5. Nested routes
|
|
79
|
+
|
|
80
|
+
Should a Website support hierarchical page grouping?
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
/docs
|
|
84
|
+
/docs/getting-started
|
|
85
|
+
/docs/api
|
|
86
|
+
/docs/api/server
|
|
87
|
+
/docs/api/server/serve
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Option A**: Flat list — all pages are siblings. The path hierarchy is implicit in the path strings. Navigation code parses paths to build trees.
|
|
91
|
+
|
|
92
|
+
**Option B**: Page groups — pages can have child pages:
|
|
93
|
+
```js
|
|
94
|
+
site.add_page({
|
|
95
|
+
path: '/docs',
|
|
96
|
+
content: DocsIndex,
|
|
97
|
+
children: [
|
|
98
|
+
{ path: '/docs/getting-started', content: GettingStarted },
|
|
99
|
+
{ path: '/docs/api', content: ApiDocs }
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Option C**: Separate concept — a `Route_Group` or `Page_Group` class that wraps related pages.
|
|
105
|
+
|
|
106
|
+
**The pragmatic answer**: Start flat. If path hierarchy matters, it can be derived from path strings. Adding a formal grouping mechanism before there's a concrete use case for it adds complexity without clear benefit.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 6. Multiple websites on one server
|
|
111
|
+
|
|
112
|
+
Can a single `jsgui3-server` serve multiple websites?
|
|
113
|
+
|
|
114
|
+
Today, `server.js` uses `Website_Group` (a Collection) which implies yes. But the implementation is skeletal. If this is a real requirement, it affects how websites declare their `base_path` and how the server routes between them.
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
Server.serve({
|
|
118
|
+
websites: [
|
|
119
|
+
new Website({ name: 'main', base_path: '/', pages: [...] }),
|
|
120
|
+
new Website({ name: 'admin', base_path: '/admin', pages: [...] })
|
|
121
|
+
]
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
This might be over-engineering. The more common pattern is one server, one website, multiple pages.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 7. Hot reloading and live updates
|
|
130
|
+
|
|
131
|
+
If a Website raises `'page-added'` events, could the server react to runtime page additions?
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
const site = new Website({ pages: [...] });
|
|
135
|
+
Server.serve(site);
|
|
136
|
+
|
|
137
|
+
// Later:
|
|
138
|
+
site.add_page({ path: '/new', content: NewPage });
|
|
139
|
+
// → server automatically adds the route?
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
This would be powerful for development workflows (add a page, see it immediately without restarting). But it requires publisher support for incremental bundling and route registration. The `finalize()` lifecycle model from Chapter 4 explicitly prevents this by design.
|
|
143
|
+
|
|
144
|
+
**The safe answer**: Don't support it initially. Build for "define site → serve it" as a one-shot workflow. If hot reloading becomes important, `Evented_Class` as the base makes it possible later — the events are there, the server just needs to listen.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 8. Error boundaries
|
|
149
|
+
|
|
150
|
+
When a page's content control throws during rendering, what happens?
|
|
151
|
+
|
|
152
|
+
**Option A**: The server catches it and shows an error page (500).
|
|
153
|
+
**Option B**: The Website has an `error_page` property for a custom error control.
|
|
154
|
+
**Option C**: Each page has its own error boundary.
|
|
155
|
+
|
|
156
|
+
This is entirely a server concern and probably shouldn't be in the Website/Webpage API at all. But it's worth noting because the proposals don't mention it.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 9. The `server` property in Website
|
|
161
|
+
|
|
162
|
+
The current `Website.js` stores `this.server` from the spec:
|
|
163
|
+
```js
|
|
164
|
+
this.api = new API({ server: this.server });
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Should the new Website know about its server?
|
|
168
|
+
|
|
169
|
+
**No**: The Website is an abstract definition. It shouldn't know *how* it's being served. The server consumes the Website, not the other way around.
|
|
170
|
+
|
|
171
|
+
**Yes**: Some use cases (publishing, URL generation) require knowing the server's hostname, port, or base URL. The Website could hold this as metadata.
|
|
172
|
+
|
|
173
|
+
**Compromise**: Don't store a server reference. If the Website needs deployment context, that's provided at serve-time by the server, not stored in the definition.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 10. What to implement first
|
|
178
|
+
|
|
179
|
+
Given everything discussed in this book, what's the minimum viable Website + Webpage that would be useful?
|
|
180
|
+
|
|
181
|
+
**Suggested first pass**:
|
|
182
|
+
|
|
183
|
+
1. `Webpage` extending `Evented_Class` with explicit properties (Chapter 4, Approach B)
|
|
184
|
+
2. `Website` using Map-based pages and structured API (Chapter 5, Approach B)
|
|
185
|
+
3. Fix the API.js export bug (Chapter 2)
|
|
186
|
+
4. Ship as 0.0.9 of both packages
|
|
187
|
+
5. Add Website detection to `serve-factory.js` (Chapter 8, minimal approach)
|
|
188
|
+
6. Test with an example that creates a Website and serves it
|
|
189
|
+
|
|
190
|
+
Everything else — normalization layers, publisher refactoring, admin integration, lifecycle finalization — can follow once the basics work.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Note on Chapter 11
|
|
195
|
+
|
|
196
|
+
Chapter 11 (`11-converged-recommendation.md`) provides an updated synthesis and phased plan that refines this first-pass list into a more explicit baseline contract and delivery sequence.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Chapter 11: Converged Recommendation
|
|
2
|
+
|
|
3
|
+
This chapter turns the debate from previous chapters into a concrete baseline that can be implemented incrementally.
|
|
4
|
+
|
|
5
|
+
The goal is not to "win" every design argument. The goal is to define a stable, useful first version that keeps `jsgui3-server` backward-compatible while unlocking richer website/webpage primitives.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 11.1 Decision Summary
|
|
10
|
+
|
|
11
|
+
| Area | Recommended baseline | Why |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Base class | `Evented_Class` with plain property assignment | Ecosystem-consistent, low overhead, no per-property event boilerplate |
|
|
14
|
+
| Webpage contract | Explicit known fields + `toJSON()` + lightweight validation | Improves introspection and catches common mistakes early |
|
|
15
|
+
| Website pages storage | Internal `Map` keyed by normalized path | O(1) lookup, duplicate detection, insertion-order preserved |
|
|
16
|
+
| Website API layer | Structured endpoint registry (Map-backed) with metadata | Supports docs/admin/auth/method semantics without server coupling |
|
|
17
|
+
| Server input handling | Normalize all input shapes into one internal manifest | Keeps publishers simple and removes shape-specific branching |
|
|
18
|
+
| Type detection | Capability checks with optional explicit marker | Avoids brittle `instanceof` behavior in linked/workspace installs |
|
|
19
|
+
| Lifecycle | Optional `finalize()` boundary, not full reactive mutation system | Safer publishing without heavy event complexity |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 11.2 Minimal Stable Primitive Contract
|
|
24
|
+
|
|
25
|
+
The first stable release should guarantee this contract.
|
|
26
|
+
|
|
27
|
+
### `Webpage`
|
|
28
|
+
|
|
29
|
+
Required:
|
|
30
|
+
|
|
31
|
+
1. `path` (string, normalized to leading slash)
|
|
32
|
+
2. `ctrl` (control constructor / renderer)
|
|
33
|
+
|
|
34
|
+
Recommended:
|
|
35
|
+
|
|
36
|
+
1. `name`
|
|
37
|
+
2. `title`
|
|
38
|
+
3. `content` (structured content/i18n data, optional)
|
|
39
|
+
4. `meta`
|
|
40
|
+
5. `scripts`
|
|
41
|
+
6. `stylesheets`
|
|
42
|
+
7. `render_mode` (`static` or `dynamic`) — see [Chapter 4 discussion](04-webpage.md)
|
|
43
|
+
8. `toJSON()` for deterministic introspection
|
|
44
|
+
|
|
45
|
+
Compatibility during migration:
|
|
46
|
+
|
|
47
|
+
1. Accept legacy `content: Function` as an alias for `ctrl`.
|
|
48
|
+
2. Normalize to `ctrl` internally so server/publisher code has one renderer field.
|
|
49
|
+
|
|
50
|
+
### `Website`
|
|
51
|
+
|
|
52
|
+
Required:
|
|
53
|
+
|
|
54
|
+
1. page registry (`add_page`, `get_page`, `has_page`, `remove_page`, `pages`, `routes`)
|
|
55
|
+
2. API registry (`add_endpoint`/`define_endpoint`, `get_endpoint`, `api_endpoints`)
|
|
56
|
+
|
|
57
|
+
Recommended:
|
|
58
|
+
|
|
59
|
+
1. `name`
|
|
60
|
+
2. `meta`
|
|
61
|
+
3. `assets`
|
|
62
|
+
4. `base_path`
|
|
63
|
+
5. `toJSON()` summary for admin/tooling
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 11.3 Server Integration Baseline
|
|
68
|
+
|
|
69
|
+
`jsgui3-server` should treat Website/Webpage support as additive and normalize all inputs.
|
|
70
|
+
|
|
71
|
+
### Input forms to support
|
|
72
|
+
|
|
73
|
+
1. `Server.serve(MyCtrl)`
|
|
74
|
+
2. `Server.serve({ pages: {...}, api: {...} })`
|
|
75
|
+
3. `Server.serve(new Webpage(...))`
|
|
76
|
+
4. `Server.serve(new Website(...))`
|
|
77
|
+
5. shape-compatible plain objects for page/site definitions
|
|
78
|
+
|
|
79
|
+
### Internal flow
|
|
80
|
+
|
|
81
|
+
1. Detect and normalize input into `normalized_website_manifest`
|
|
82
|
+
2. Validate normalized routes/endpoints
|
|
83
|
+
3. Build static and dynamic page route registrations
|
|
84
|
+
4. Publish API endpoints with method/path metadata
|
|
85
|
+
5. Expose publication summary for introspection/admin
|
|
86
|
+
|
|
87
|
+
This keeps the publisher pipeline focused on serving, not on input parsing.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 11.4 Validation Policy
|
|
92
|
+
|
|
93
|
+
Use two-stage validation.
|
|
94
|
+
|
|
95
|
+
Construction-time lightweight validation:
|
|
96
|
+
|
|
97
|
+
1. route is string-like
|
|
98
|
+
2. handler/content types are sane
|
|
99
|
+
3. obvious shape errors fail fast
|
|
100
|
+
|
|
101
|
+
Publish-time strict validation:
|
|
102
|
+
|
|
103
|
+
1. duplicate routes
|
|
104
|
+
2. invalid HTTP methods
|
|
105
|
+
3. unresolved assets
|
|
106
|
+
4. unsupported render modes
|
|
107
|
+
|
|
108
|
+
This avoids over-strict constructors while still giving strong safety before serving.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 11.5 Backward Compatibility Rules
|
|
113
|
+
|
|
114
|
+
These rules should hold through the migration.
|
|
115
|
+
|
|
116
|
+
1. Existing `Server.serve(...)` signatures continue to work unchanged.
|
|
117
|
+
2. Existing `api: { name: fn }` remains valid.
|
|
118
|
+
3. Existing control-first one-liner remains first-class.
|
|
119
|
+
4. New Website/Webpage primitives are optional convenience, not mandatory API layers.
|
|
120
|
+
5. Deprecations, if any, should be warning-only for at least one minor cycle.
|
|
121
|
+
|
|
122
|
+
Field migration rule:
|
|
123
|
+
|
|
124
|
+
1. `Webpage.ctrl` is the canonical renderer field.
|
|
125
|
+
2. Legacy `Webpage.content` used as a renderer remains accepted as input during migration.
|
|
126
|
+
3. Server normalization maps both shapes into one internal manifest (`ctrl` canonical, structured content separate).
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 11.6 Non-Goals for the First Release
|
|
131
|
+
|
|
132
|
+
To keep scope controlled, do not block first release on:
|
|
133
|
+
|
|
134
|
+
1. runtime hot-add/remove page re-publication
|
|
135
|
+
2. nested page-tree abstractions
|
|
136
|
+
3. full OpenAPI generation
|
|
137
|
+
4. advanced per-route auth/rate-limit engines
|
|
138
|
+
5. multi-website orchestration features
|
|
139
|
+
|
|
140
|
+
These can be layered in after stable primitive/server interoperability is proven.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 11.7 Suggested Phased Delivery
|
|
145
|
+
|
|
146
|
+
1. **Phase A: Primitive stabilization**
|
|
147
|
+
Finalize `Webpage` and `Website` contracts, including `toJSON()` and minimal validation.
|
|
148
|
+
|
|
149
|
+
2. **Phase B: Server normalization layer**
|
|
150
|
+
Add `normalize_serve_input` + manifest conversion in `serve-factory.js`.
|
|
151
|
+
|
|
152
|
+
3. **Phase C: Publisher alignment**
|
|
153
|
+
Refactor publishers to consume normalized manifests and remove `._arr`/`instanceof` coupling.
|
|
154
|
+
|
|
155
|
+
4. **Phase D: Tooling/admin surfacing**
|
|
156
|
+
Expose website manifest and publication summary in admin APIs/UI.
|
|
157
|
+
|
|
158
|
+
Each phase should ship with targeted tests and can be released independently.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 11.8 Recommended First Implementation Target
|
|
163
|
+
|
|
164
|
+
A pragmatic first milestone:
|
|
165
|
+
|
|
166
|
+
1. Webpage with explicit fields + `toJSON()` + path normalization
|
|
167
|
+
2. Website with Map-backed page registry + structured API endpoint registry
|
|
168
|
+
3. Server normalization for Website/Webpage inputs
|
|
169
|
+
4. Route conflict detection and clear error messages
|
|
170
|
+
5. No regressions for legacy `Server.serve` usage
|
|
171
|
+
|
|
172
|
+
If this milestone is stable, the architecture is validated and later enhancements become straightforward rather than speculative.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 11.9 Acceptance Criteria for the Milestone
|
|
177
|
+
|
|
178
|
+
1. A `Website` with at least two pages serves both routes correctly.
|
|
179
|
+
2. A `Webpage` passed directly to `Server.serve(...)` serves at its declared path.
|
|
180
|
+
3. Duplicate page paths fail with a deterministic, actionable error.
|
|
181
|
+
4. API endpoint metadata (`method`, `path`) is preserved through normalization and publication.
|
|
182
|
+
5. Legacy usage (`Server.serve(MyCtrl)`, `Server.serve({ pages, api })`) still passes existing tests.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 11.10 Forward References
|
|
187
|
+
|
|
188
|
+
The following chapters expand this recommendation into full implementation blueprints:
|
|
189
|
+
|
|
190
|
+
- **[Chapter 12](12-content-model.md)**: Defines the content model — how Webpage holds text strings, structured data, and i18n translations
|
|
191
|
+
- **[Chapter 13](13-webpage-module-spec.md)**: Complete module specification for `jsgui3-webpage` (constructor, every method, validation, test plan)
|
|
192
|
+
- **[Chapter 14](14-website-module-spec.md)**: Complete module specification for `jsgui3-website` (page registry, API registry, finalize cascade)
|
|
193
|
+
- **[Chapter 15](15-multi-repo-plan.md)**: Multi-repo implementation coordination (dependency graph, phased delivery, version pinning)
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 11.11 Version Track Alignment
|
|
198
|
+
|
|
199
|
+
To avoid ambiguity across later chapters:
|
|
200
|
+
|
|
201
|
+
1. **v0.1.x** is the minimal-first track from Chapter 16 (small surface, fast adoption).
|
|
202
|
+
2. **v0.3.x** is the full-spec target from Chapters 13 and 14 (lifecycle, introspection, i18n helpers, richer API).
|
|
203
|
+
3. Chapter 15 coordinates both tracks as one migration path, not competing plans.
|
|
204
|
+
|
|
205
|
+
**Current status (Feb 2026)**: Codex implemented the full spec (see [Ch.17](17-implementation-report-codex.md)). Implementation exists in repo source but packages have not yet been published to npm (still v0.0.8 on registry). Server integration (`normalize_serve_input`, `website_manifest`) is live in `serve-factory.js`.
|