jsgui3-server 0.0.150 → 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/.github/instructions/copilot.instructions.md +1 -0
- package/AGENTS.md +2 -0
- package/README.md +89 -13
- package/admin-ui/v1/controls/admin_shell.js +702 -669
- package/admin-ui/v1/server.js +14 -1
- package/docs/api-reference.md +504 -306
- package/docs/books/creating-a-new-admin-ui/README.md +20 -20
- 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/comprehensive-documentation.md +220 -220
- package/docs/configuration-reference.md +281 -204
- package/docs/middleware-guide.md +236 -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/docs/system-architecture.md +24 -18
- 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/compression.js +217 -0
- package/middleware/index.js +15 -0
- package/middleware/json-body.js +126 -0
- package/module.js +3 -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 +756 -18
- package/server.js +502 -123
- 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
package/docs/swagger.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# Swagger / OpenAPI Documentation
|
|
2
|
+
|
|
3
|
+
jsgui3-server includes **built-in, zero-dependency** Swagger / OpenAPI 3.0.3 support. Every API you define — whether through `Server.serve()` or `server.publish()` — is automatically documented and browsable via an interactive Swagger UI.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
const Server = require('jsgui3-server/server');
|
|
9
|
+
|
|
10
|
+
Server.serve({
|
|
11
|
+
port: 8080,
|
|
12
|
+
api: {
|
|
13
|
+
'users/list': {
|
|
14
|
+
handler: listUsers,
|
|
15
|
+
method: 'POST',
|
|
16
|
+
summary: 'List all users',
|
|
17
|
+
tags: ['Users']
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Open your browser:
|
|
24
|
+
|
|
25
|
+
| URL | Purpose |
|
|
26
|
+
|-----|---------|
|
|
27
|
+
| `http://localhost:8080/api/docs` | Interactive Swagger UI |
|
|
28
|
+
| `http://localhost:8080/api/openapi.json` | Raw OpenAPI 3.0 spec (JSON) |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
The `swagger` option controls whether the routes are registered:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
Server.serve({
|
|
38
|
+
swagger: true, // Always enable (default in dev)
|
|
39
|
+
swagger: false, // Always disable (default in production)
|
|
40
|
+
// swagger omitted → auto (enabled when NODE_ENV !== 'production')
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
You can also pass an object for fine-grained control:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
Server.serve({
|
|
48
|
+
swagger: {
|
|
49
|
+
title: 'My Service API',
|
|
50
|
+
version: '2.0.0',
|
|
51
|
+
description: 'Custom description for the spec info block'
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Environment-Based Defaults
|
|
57
|
+
|
|
58
|
+
| `NODE_ENV` | `swagger` omitted | `swagger: true` | `swagger: false` |
|
|
59
|
+
|--------------|-------------------|-----------------|------------------|
|
|
60
|
+
| development | ✅ enabled | ✅ enabled | ❌ disabled |
|
|
61
|
+
| production | ❌ disabled | ✅ enabled | ❌ disabled |
|
|
62
|
+
| *(unset)* | ✅ enabled | ✅ enabled | ❌ disabled |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Defining API Metadata
|
|
67
|
+
|
|
68
|
+
### Declarative API (recommended)
|
|
69
|
+
|
|
70
|
+
Pass metadata directly in the `api` option of `Server.serve()`:
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
Server.serve({
|
|
74
|
+
port: 8080,
|
|
75
|
+
api: {
|
|
76
|
+
'products/search': {
|
|
77
|
+
handler: searchProducts,
|
|
78
|
+
method: 'POST',
|
|
79
|
+
summary: 'Search products',
|
|
80
|
+
description: 'Full-text search across the product catalog.',
|
|
81
|
+
tags: ['Products', 'Search'],
|
|
82
|
+
params: {
|
|
83
|
+
query: { type: 'string', description: 'Search query', required: true },
|
|
84
|
+
page: { type: 'integer', description: 'Page number', default: 1 },
|
|
85
|
+
page_size: { type: 'integer', description: 'Results per page', default: 25 },
|
|
86
|
+
sort: { type: 'string', description: 'Sort field', enum: ['name', 'price', 'date'] }
|
|
87
|
+
},
|
|
88
|
+
returns: {
|
|
89
|
+
rows: { type: 'array', items: { type: 'object' } },
|
|
90
|
+
total_count: { type: 'integer', description: 'Total matching results' },
|
|
91
|
+
page: { type: 'integer' }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Imperative API
|
|
99
|
+
|
|
100
|
+
Use `server.publish()` with a `meta` object:
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
const server = new Server({ website: false });
|
|
104
|
+
|
|
105
|
+
server.publish('users/create', createUser, {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
summary: 'Create a new user',
|
|
108
|
+
description: 'Creates a user account and returns the user object.',
|
|
109
|
+
tags: ['Users'],
|
|
110
|
+
params: {
|
|
111
|
+
name: { type: 'string', required: true, description: 'Full name' },
|
|
112
|
+
email: { type: 'string', required: true, description: 'Email address' }
|
|
113
|
+
},
|
|
114
|
+
returns: {
|
|
115
|
+
id: { type: 'integer', description: 'New user ID' },
|
|
116
|
+
name: { type: 'string' },
|
|
117
|
+
email: { type: 'string' }
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Register swagger routes after all publish() calls:
|
|
122
|
+
server._register_swagger_routes({ title: 'User Service' });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Metadata Reference
|
|
128
|
+
|
|
129
|
+
All metadata fields are **optional**. Endpoints without metadata still produce a valid (minimal) Swagger entry.
|
|
130
|
+
|
|
131
|
+
### Endpoint Metadata Fields
|
|
132
|
+
|
|
133
|
+
| Field | Type | Default | Purpose |
|
|
134
|
+
|----------------------|----------|-----------------|---------|
|
|
135
|
+
| `method` | string | `'POST'` | HTTP method (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) |
|
|
136
|
+
| `summary` | string | — | One-line summary shown in Swagger UI operation list |
|
|
137
|
+
| `description` | string | — | Multi-line Markdown description for expanded view |
|
|
138
|
+
| `tags` | string[] | auto-detected | Grouping tags (auto-detected from route if omitted) |
|
|
139
|
+
| `params` | Object | — | Request body schema (see schema format below) |
|
|
140
|
+
| `returns` | Object | — | Response body schema (see schema format below) |
|
|
141
|
+
| `deprecated` | boolean | `false` | Strike-through in Swagger UI |
|
|
142
|
+
| `operationId` | string | auto-generated | Unique operation identifier |
|
|
143
|
+
| `response_description`| string | `'Successful response'` | Custom 200 response description |
|
|
144
|
+
| `schema` | Object | — | Alternative to `params` (from Function_Publisher) |
|
|
145
|
+
|
|
146
|
+
### Schema Format
|
|
147
|
+
|
|
148
|
+
The `params` and `returns` objects use a simple `{key: definition}` format:
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
{
|
|
152
|
+
field_name: {
|
|
153
|
+
type: 'string', // 'string' | 'integer' | 'number' | 'boolean' | 'array' | 'object'
|
|
154
|
+
description: '...', // Human-readable description
|
|
155
|
+
default: 'value', // Default value
|
|
156
|
+
required: true, // Whether the field is required
|
|
157
|
+
enum: ['a', 'b'], // Allowed values
|
|
158
|
+
items: { type: '...' } // For type: 'array' — describes each item
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
This simple format is automatically converted to OpenAPI Schema Objects by the spec generator.
|
|
164
|
+
|
|
165
|
+
You can also pass raw OpenAPI schemas if you need more control:
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
{
|
|
169
|
+
type: 'object',
|
|
170
|
+
properties: {
|
|
171
|
+
name: { type: 'string' },
|
|
172
|
+
age: { type: 'integer' }
|
|
173
|
+
},
|
|
174
|
+
required: ['name']
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Tag Auto-Detection
|
|
179
|
+
|
|
180
|
+
When an endpoint has no explicit `tags`, a tag is automatically derived from the route path:
|
|
181
|
+
|
|
182
|
+
| Route | Auto-Tag |
|
|
183
|
+
|-------|----------|
|
|
184
|
+
| `/api/users/list` | `users` |
|
|
185
|
+
| `/api/data/products` | `data` |
|
|
186
|
+
| `/api/admin/v1/status` | `admin` |
|
|
187
|
+
| `/health` | `health` |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Architecture
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
Server.serve({ api: {...} })
|
|
195
|
+
│
|
|
196
|
+
├── serve-factory.js ─── normalises endpoints
|
|
197
|
+
│ │ preserves summary, tags, params, returns
|
|
198
|
+
│ ▼
|
|
199
|
+
├── server.publish(name, fn, meta)
|
|
200
|
+
│ │
|
|
201
|
+
│ ├── Function_Publisher ─── stores api_meta
|
|
202
|
+
│ └── _api_registry[] ─── indexed for OpenAPI
|
|
203
|
+
│
|
|
204
|
+
└── _register_swagger_routes()
|
|
205
|
+
│
|
|
206
|
+
└── Swagger_Publisher (extends HTTP_Publisher)
|
|
207
|
+
│
|
|
208
|
+
├── /api/openapi.json ─── openapi.js generates spec
|
|
209
|
+
│ walks _api_registry + function_publishers
|
|
210
|
+
│ converts params/returns → OpenAPI schemas
|
|
211
|
+
│
|
|
212
|
+
└── /api/docs ─── swagger-ui.js generates HTML
|
|
213
|
+
loads Swagger UI from CDN
|
|
214
|
+
dark theme matching jsgui3
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Source Files
|
|
218
|
+
|
|
219
|
+
| File | Purpose |
|
|
220
|
+
|------|---------|
|
|
221
|
+
| `publishers/swagger-publisher.js` | `Swagger_Publisher` class (extends `HTTP_Publisher`) |
|
|
222
|
+
| `openapi.js` | OpenAPI 3.0.3 spec generator (zero dependencies) |
|
|
223
|
+
| `publishers/swagger-ui.js` | HTML page generator (CDN-based Swagger UI) |
|
|
224
|
+
| `publishers/http-function-publisher.js` | Stores `api_meta` on publisher instances |
|
|
225
|
+
| `publishers/Publishers.js` | Registry — includes `'swagger'` entry |
|
|
226
|
+
| `server.js` | `publish()` + `_register_swagger_routes()` |
|
|
227
|
+
| `serve-factory.js` | Metadata flow + auto-registration |
|
|
228
|
+
| `tests/openapi.test.js` | 14 tests across 5 suites |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Customisation
|
|
233
|
+
|
|
234
|
+
### Title and Version
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
Server.serve({
|
|
238
|
+
swagger: { title: 'My API', version: '2.0.0' }
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Manual Registration
|
|
243
|
+
|
|
244
|
+
For servers created with `new Server(...)` directly:
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
const server = new Server({ website: false });
|
|
248
|
+
// ... server.publish() calls ...
|
|
249
|
+
server._register_swagger_routes({
|
|
250
|
+
title: 'My API',
|
|
251
|
+
version: '3.0.0',
|
|
252
|
+
description: 'API for my service'
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Standalone Publisher
|
|
257
|
+
|
|
258
|
+
You can also create a `Swagger_Publisher` independently and attach it
|
|
259
|
+
to any server with access to the router:
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
const Swagger_Publisher = require('jsgui3-server/publishers/swagger-publisher');
|
|
263
|
+
|
|
264
|
+
const swagger = new Swagger_Publisher({
|
|
265
|
+
server: my_server,
|
|
266
|
+
title: 'My API',
|
|
267
|
+
version: '3.0.0'
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
my_server.server_router.set_route('/api/openapi.json', swagger, swagger.handle_http.bind(swagger));
|
|
271
|
+
my_server.server_router.set_route('/api/docs', swagger, swagger.handle_http.bind(swagger));
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The publisher is also available in the `Publishers` registry:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
const Publishers = require('jsgui3-server/publishers/Publishers');
|
|
278
|
+
const Swagger_Publisher = Publishers.swagger;
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Disabling in Production
|
|
282
|
+
|
|
283
|
+
Swagger is automatically disabled when `NODE_ENV=production`. To force it on:
|
|
284
|
+
|
|
285
|
+
```js
|
|
286
|
+
Server.serve({ swagger: true });
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## How It Works Internally
|
|
292
|
+
|
|
293
|
+
1. **Endpoint registration** — `server.publish()` creates a `Function_Publisher` and adds an entry to `server._api_registry` with the full metadata.
|
|
294
|
+
|
|
295
|
+
2. **Metadata normalisation** — `serve-factory.js` preserves `summary`, `tags`, `params`, `returns`, and `schema` from the declarative API definition and passes them through to `publish()`.
|
|
296
|
+
|
|
297
|
+
3. **Spec generation** — When `/api/openapi.json` is requested, `openapi.js` walks the `_api_registry` and `function_publishers` arrays, converts the simple schema format to OpenAPI Schema Objects, and assembles a complete OpenAPI 3.0.3 document.
|
|
298
|
+
|
|
299
|
+
4. **Swagger UI** — When `/api/docs` is requested, a pre-generated HTML page is served that loads Swagger UI from the unpkg CDN and points it at `/api/openapi.json`.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Testing
|
|
304
|
+
|
|
305
|
+
Run the test suite:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
node --test tests/openapi.test.js
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
This runs 14 tests across 5 suites:
|
|
312
|
+
- **simple_schema_to_openapi** — schema conversion edge cases
|
|
313
|
+
- **generate_openapi_spec** — spec structure, minimal metadata, route filtering
|
|
314
|
+
- **collect_api_entries** — deduplication across data sources
|
|
315
|
+
- **generate_swagger_html** — HTML output and CDN links
|
|
316
|
+
- **Swagger routes integration** — end-to-end HTTP tests with a real server
|
|
@@ -32,29 +32,29 @@ JSGUI3 Server is a Node.js-based web framework that serves modern JavaScript GUI
|
|
|
32
32
|
|
|
33
33
|
**Purpose:** Handles conversion of various content types to HTTP responses.
|
|
34
34
|
|
|
35
|
-
**Key Publishers:**
|
|
36
|
-
- `HTTP_Webpage_Publisher`: Serves bundled JSGUI3 controls as complete web pages
|
|
37
|
-
- `HTTP_Website_Publisher`: Manages multi-page websites
|
|
38
|
-
- `HTTP_Function_Publisher`: Exposes JavaScript functions as REST API endpoints
|
|
39
|
-
- `HTTP_Observable_Publisher`: Streams observable-backed SSE
|
|
40
|
-
- `HTTP_SSE_Publisher`: General-purpose SSE fan-out publisher
|
|
41
|
-
- `HTTP_CSS_Publisher`: Serves CSS stylesheets
|
|
42
|
-
- `HTTP_JS_Publisher`: Serves JavaScript bundles
|
|
43
|
-
- `HTTP_Image_Publisher`: Handles image file serving
|
|
35
|
+
**Key Publishers:**
|
|
36
|
+
- `HTTP_Webpage_Publisher`: Serves bundled JSGUI3 controls as complete web pages
|
|
37
|
+
- `HTTP_Website_Publisher`: Manages multi-page websites
|
|
38
|
+
- `HTTP_Function_Publisher`: Exposes JavaScript functions as REST API endpoints
|
|
39
|
+
- `HTTP_Observable_Publisher`: Streams observable-backed SSE
|
|
40
|
+
- `HTTP_SSE_Publisher`: General-purpose SSE fan-out publisher
|
|
41
|
+
- `HTTP_CSS_Publisher`: Serves CSS stylesheets
|
|
42
|
+
- `HTTP_JS_Publisher`: Serves JavaScript bundles
|
|
43
|
+
- `HTTP_Image_Publisher`: Handles image file serving
|
|
44
44
|
|
|
45
45
|
### 3. Resource Management Layer
|
|
46
46
|
**Directory:** `resources/`
|
|
47
47
|
|
|
48
48
|
**Purpose:** Provides abstractions for accessing different types of data and functionality.
|
|
49
49
|
|
|
50
|
-
**Key Resources:**
|
|
51
|
-
- `Server_Resource_Pool`: Manages collections of resources with lifecycle management
|
|
52
|
-
- `Process_Resource`: Local process resource (`direct` default, optional `pm2`)
|
|
53
|
-
- `Remote_Process_Resource`: HTTP-controlled remote process resource
|
|
54
|
-
- `Website_Resource`: Wraps website objects for server integration
|
|
55
|
-
- `File_System_Resource`: Provides file system access
|
|
56
|
-
- `Data_Resource`: Handles data storage and retrieval
|
|
57
|
-
- `Local_Server_Info_Resource`: Provides server environment information
|
|
50
|
+
**Key Resources:**
|
|
51
|
+
- `Server_Resource_Pool`: Manages collections of resources with lifecycle management
|
|
52
|
+
- `Process_Resource`: Local process resource (`direct` default, optional `pm2`)
|
|
53
|
+
- `Remote_Process_Resource`: HTTP-controlled remote process resource
|
|
54
|
+
- `Website_Resource`: Wraps website objects for server integration
|
|
55
|
+
- `File_System_Resource`: Provides file system access
|
|
56
|
+
- `Data_Resource`: Handles data storage and retrieval
|
|
57
|
+
- `Local_Server_Info_Resource`: Provides server environment information
|
|
58
58
|
|
|
59
59
|
### 4. Processing Layer
|
|
60
60
|
**Directory:** `resources/processors/`
|
|
@@ -105,6 +105,8 @@ Client Request
|
|
|
105
105
|
↓
|
|
106
106
|
HTTP Server (Node.js http/https)
|
|
107
107
|
↓
|
|
108
|
+
Middleware Pipeline (server.use) ← gzip/deflate/brotli, CORS, logging, etc.
|
|
109
|
+
↓
|
|
108
110
|
Server Router
|
|
109
111
|
↓
|
|
110
112
|
Resource Pool
|
|
@@ -118,6 +120,10 @@ Content Processing/Bundling
|
|
|
118
120
|
HTTP Response
|
|
119
121
|
```
|
|
120
122
|
|
|
123
|
+
Middleware functions registered via `server.use(fn)` execute in order before
|
|
124
|
+
the router. If no middleware is registered, the router is called directly
|
|
125
|
+
with zero overhead. See [Middleware Guide](middleware-guide.md) for details.
|
|
126
|
+
|
|
121
127
|
### Component Serving Flow
|
|
122
128
|
|
|
123
129
|
```
|
|
@@ -276,4 +282,4 @@ Add new processing pipelines for assets and data.
|
|
|
276
282
|
|
|
277
283
|
---
|
|
278
284
|
|
|
279
|
-
This architecture document provides the foundation for understanding how JSGUI3 Server components work together. For detailed implementation of specific components, refer to their individual documentation files.
|
|
285
|
+
This architecture document provides the foundation for understanding how JSGUI3 Server components work together. For detailed implementation of specific components, refer to their individual documentation files.
|
|
@@ -105,9 +105,14 @@ if (require.main === module) {
|
|
|
105
105
|
throw err;
|
|
106
106
|
} else {
|
|
107
107
|
// Should have build it by now...
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
console.log('server started');
|
|
110
|
+
server.print_endpoints({
|
|
111
|
+
prefix: 'active endpoint'
|
|
112
|
+
});
|
|
110
113
|
}
|
|
114
|
+
}, {
|
|
115
|
+
on_port_conflict: 'auto-loopback'
|
|
111
116
|
});
|
|
112
117
|
})
|
|
113
118
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const jsgui = require('./client');
|
|
4
|
+
const { UserProfileEditor } = jsgui.controls;
|
|
5
|
+
|
|
6
|
+
let pass = 0, fail = 0;
|
|
7
|
+
function check(label, ok) {
|
|
8
|
+
if (ok) { console.log(` ✅ ${label}`); pass++; }
|
|
9
|
+
else { console.log(` ❌ ${label}`); fail++; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
console.log('\n═══ MVVM & Declarative API Check ═══\n');
|
|
13
|
+
|
|
14
|
+
// ── 1. Construction & Model Initialisation ──────────────────────────
|
|
15
|
+
const editor = new UserProfileEditor({
|
|
16
|
+
first_name: 'John',
|
|
17
|
+
last_name: 'Smith',
|
|
18
|
+
is_active: true
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
check('Control instantiated', !!editor);
|
|
22
|
+
check('Has data.model layer', !!editor.data && !!editor.data.model);
|
|
23
|
+
check('Has view.data.model layer', !!editor.view && !!editor.view.data && !!editor.view.data.model);
|
|
24
|
+
|
|
25
|
+
// ── 2. Raw Model Values ─────────────────────────────────────────────
|
|
26
|
+
check('first_name stored correctly', editor.data.model.get('first_name').value === 'John');
|
|
27
|
+
check('last_name stored correctly', editor.data.model.get('last_name').value === 'Smith');
|
|
28
|
+
check('is_active stored correctly', editor.data.model.get('is_active').value === true);
|
|
29
|
+
|
|
30
|
+
// ── 3. Computed Properties ──────────────────────────────────────────
|
|
31
|
+
const fullName = editor.data.model.get('full_name').value;
|
|
32
|
+
check('Computed full_name = "John Smith"', fullName === 'John Smith');
|
|
33
|
+
|
|
34
|
+
const statusText = editor.data.model.get('status_text').value;
|
|
35
|
+
check('Computed status_text = "Active Account"', statusText === 'Active Account');
|
|
36
|
+
|
|
37
|
+
// ── 4. Server-Side HTML Rendering ───────────────────────────────────
|
|
38
|
+
const html = editor.all_html_render();
|
|
39
|
+
check('HTML renders without throwing', typeof html === 'string' && html.length > 0);
|
|
40
|
+
check('HTML has .profile-card wrapper', html.includes('profile-card'));
|
|
41
|
+
check('HTML has active-state class', html.includes('active-state'));
|
|
42
|
+
check('HTML has profile-header section', html.includes('profile-header'));
|
|
43
|
+
check('HTML has profile-body section', html.includes('profile-body'));
|
|
44
|
+
check('HTML has profile-footer section', html.includes('profile-footer'));
|
|
45
|
+
check('HTML has Toggle Status button', html.includes('Toggle Status'));
|
|
46
|
+
check('HTML has Save Profile button', html.includes('Save Profile'));
|
|
47
|
+
check('HTML has input elements for bind-value', html.includes('<input'));
|
|
48
|
+
check('HTML has First Name label', html.includes('First Name:'));
|
|
49
|
+
check('HTML has Last Name label', html.includes('Last Name:'));
|
|
50
|
+
// Note: bind-text content (e.g. "John Smith") is injected client-side
|
|
51
|
+
// during activation. SSR renders the structure; bind-text populates at runtime.
|
|
52
|
+
|
|
53
|
+
// ── 5. Model Mutation: Update first_name ─────────────────────────────
|
|
54
|
+
editor.data.model.set('first_name', 'Alice');
|
|
55
|
+
const updatedFullName = editor.data.model.get('full_name').value;
|
|
56
|
+
check('Computed full_name updates to "Alice Smith"', updatedFullName === 'Alice Smith');
|
|
57
|
+
|
|
58
|
+
// ── 6. Model Mutation: toggleStatus() ────────────────────────────────
|
|
59
|
+
editor.toggleStatus();
|
|
60
|
+
check('is_active toggled to false', editor.data.model.get('is_active').value === false);
|
|
61
|
+
check('Computed status_text = "Suspended Account"', editor.data.model.get('status_text').value === 'Suspended Account');
|
|
62
|
+
|
|
63
|
+
// ── 7. Toggle back ──────────────────────────────────────────────────
|
|
64
|
+
editor.toggleStatus();
|
|
65
|
+
check('is_active toggled back to true', editor.data.model.get('is_active').value === true);
|
|
66
|
+
check('Computed status_text back to "Active Account"', editor.data.model.get('status_text').value === 'Active Account');
|
|
67
|
+
|
|
68
|
+
// ── 8. Edge cases ───────────────────────────────────────────────────
|
|
69
|
+
editor.data.model.set('first_name', '');
|
|
70
|
+
check('Computed full_name with empty first = "Smith"', editor.data.model.get('full_name').value === 'Smith');
|
|
71
|
+
|
|
72
|
+
editor.data.model.set('last_name', '');
|
|
73
|
+
check('Computed full_name with both empty = ""', editor.data.model.get('full_name').value === '');
|
|
74
|
+
|
|
75
|
+
editor.data.model.set('first_name', 'Solo');
|
|
76
|
+
check('Computed full_name with empty last = "Solo"', editor.data.model.get('full_name').value === 'Solo');
|
|
77
|
+
|
|
78
|
+
// ── 9. CSS static property ──────────────────────────────────────────
|
|
79
|
+
check('UserProfileEditor.css defined', typeof UserProfileEditor.css === 'string' && UserProfileEditor.css.length > 100);
|
|
80
|
+
check('CSS contains .profile-card rule', UserProfileEditor.css.includes('.profile-card'));
|
|
81
|
+
check('CSS contains .active-state rule', UserProfileEditor.css.includes('.active-state'));
|
|
82
|
+
check('CSS contains .inactive-state rule', UserProfileEditor.css.includes('.inactive-state'));
|
|
83
|
+
|
|
84
|
+
// ── Verdict ─────────────────────────────────────────────────────────
|
|
85
|
+
console.log('\n═══════════════════════════════════════════');
|
|
86
|
+
console.log(`RESULTS: ${pass} passed, ${fail} failed`);
|
|
87
|
+
if (fail === 0) {
|
|
88
|
+
console.log('\n✅ VERDICT: All MVVM & Declarative API checks passed!');
|
|
89
|
+
} else {
|
|
90
|
+
console.log('\n⚠️ VERDICT: Some checks failed — review results above');
|
|
91
|
+
}
|
|
92
|
+
console.log('═══════════════════════════════════════════\n');
|
|
93
|
+
|
|
94
|
+
process.exit(fail > 0 ? 1 : 0);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[jsgui3-html] DEPRECATED: "FormField" is deprecated. Use "Form_Field" instead. This will be removed in v1.0.0.
|
|
2
|
+
[jsgui3-html] DEPRECATED: "PropertyEditor" is deprecated. Use "Property_Editor" instead. This will be removed in v1.0.0.
|
|
3
|
+
|
|
4
|
+
═══ MVVM Declarative API Check ═══
|
|
5
|
+
|
|
6
|
+
✅ Control initialized
|
|
7
|
+
❌ Computed full_name working (John Smith)
|
|
8
|
+
❌ Computed status_text working (Active Account)
|
|
9
|
+
✅ HTML rendered without throwing
|
|
10
|
+
❌ HTML contains full_name
|
|
11
|
+
✅ HTML contains active-state class
|
|
12
|
+
❌ HTML contains status_text
|
|
13
|
+
❌ Computed dependency updates successfully when first_name changes
|
|
14
|
+
❌ Re-rendered HTML reflects new name
|
|
15
|
+
❌ Status is now inactive via toggleStatus()
|
|
16
|
+
❌ Status text updated automatically
|
|
17
|
+
❌ HTML reflects inactive-state class
|
|
18
|
+
❌ HTML reflects Suspended Account text
|
|
19
|
+
|
|
20
|
+
═══════════════════════════════════════════
|
|
21
|
+
RESULTS: 3 passed, 10 failed
|
|
22
|
+
|
|
23
|
+
⚠️ VERDICT: Some checks failed — review results above
|
|
24
|
+
═══════════════════════════════════════════
|
|
25
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[jsgui3-html] DEPRECATED: "FormField" is deprecated. Use "Form_Field" instead. This will be removed in v1.0.0.
|
|
2
|
+
[jsgui3-html] DEPRECATED: "PropertyEditor" is deprecated. Use "Property_Editor" instead. This will be removed in v1.0.0.
|
|
3
|
+
|
|
4
|
+
═══ MVVM Declarative API Check ═══
|
|
5
|
+
|
|
6
|
+
✅ Control initialized
|
|
7
|
+
--- Debug fullName: [38;5;129mJohn Smith[0m
|
|
8
|
+
❌ Computed full_name working (John Smith)
|
|
9
|
+
--- Debug statusText: [38;5;129mActive Account[0m
|
|
10
|
+
❌ Computed status_text working (Active Account)
|
|
11
|
+
✅ HTML rendered without throwing
|
|
12
|
+
❌ HTML contains full_name
|
|
13
|
+
✅ HTML contains active-state class
|
|
14
|
+
❌ HTML contains status_text
|
|
15
|
+
❌ Computed dependency updates successfully when first_name changes
|
|
16
|
+
❌ Re-rendered HTML reflects new name
|
|
17
|
+
❌ Status is now inactive via toggleStatus()
|
|
18
|
+
❌ Status text updated automatically
|
|
19
|
+
❌ HTML reflects inactive-state class
|
|
20
|
+
❌ HTML reflects Suspended Account text
|
|
21
|
+
|
|
22
|
+
═══════════════════════════════════════════
|
|
23
|
+
RESULTS: 3 passed, 10 failed
|
|
24
|
+
|
|
25
|
+
⚠️ VERDICT: Some checks failed — review results above
|
|
26
|
+
═══════════════════════════════════════════
|
|
27
|
+
|