jsgui3-server 0.0.147 → 0.0.148
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/admin-ui/client.js +213 -0
- package/admin-ui/server.js +104 -0
- package/client/controls/auto-observable.js +207 -0
- package/docs/books/admin-ui/01-introduction.md +32 -0
- package/docs/books/admin-ui/02-architecture.md +92 -0
- package/docs/books/admin-ui/03-controls.md +194 -0
- package/docs/books/admin-ui/04-implementation-plan.md +62 -0
- package/docs/books/admin-ui/README.md +26 -0
- package/examples/controls/19) window, auto observable ui/client.js +125 -0
- package/examples/controls/19) window, auto observable ui/server.js +64 -0
- package/package.json +3 -3
- package/publishers/http-observable-publisher.js +8 -0
- package/publishers/http-webpage-publisher.js +13 -3
- package/publishers/http-webpageorsite-publisher.js +18 -0
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +54 -32
- package/server.js +72 -3
|
@@ -5,17 +5,17 @@ const Core_JS_Non_Minifying_Bundler_Using_ESBuild = require('./Core_JS_Non_Minif
|
|
|
5
5
|
const Bundler_Using_ESBuild = require('./Bundler_Using_ESBuild');
|
|
6
6
|
const {is_array} = require('lang-tools');
|
|
7
7
|
|
|
8
|
-
const Core_JS_Single_File_Minifying_Bundler_Using_ESBuild = require('./Core_JS_Single_File_Minifying_Bundler_Using_ESBuild');
|
|
8
|
+
const Core_JS_Single_File_Minifying_Bundler_Using_ESBuild = require('./Core_JS_Single_File_Minifying_Bundler_Using_ESBuild');
|
|
9
9
|
|
|
10
10
|
//const CSS_Extractor = require('./_Old_CSS_Extractor');
|
|
11
11
|
|
|
12
12
|
// Use a different CSS extractor.
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
const Bundle = require('../../bundle');
|
|
16
|
-
|
|
17
|
-
const CSS_And_JS_From_JS_String_Extractor = require('../../../extractors/js/css_and_js/CSS_And_JS_From_JS_String_Extractor');
|
|
18
|
-
const {compile_styles} = require('../../style-bundler');
|
|
15
|
+
const Bundle = require('../../bundle');
|
|
16
|
+
|
|
17
|
+
const CSS_And_JS_From_JS_String_Extractor = require('../../../extractors/js/css_and_js/CSS_And_JS_From_JS_String_Extractor');
|
|
18
|
+
const {compile_styles} = require('../../style-bundler');
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
@@ -24,10 +24,10 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
24
24
|
|
|
25
25
|
if (spec.debug !== undefined) this.debug = spec.debug;
|
|
26
26
|
|
|
27
|
-
// Store bundler configuration
|
|
28
|
-
this.bundler_config = spec.bundler || {};
|
|
29
|
-
const style_config = spec.style || this.bundler_config.style || {};
|
|
30
|
-
this.style_config = Object.assign({debug: this.debug === true}, style_config);
|
|
27
|
+
// Store bundler configuration
|
|
28
|
+
this.bundler_config = spec.bundler || {};
|
|
29
|
+
const style_config = spec.style || this.bundler_config.style || {};
|
|
30
|
+
this.style_config = Object.assign({debug: this.debug === true}, style_config);
|
|
31
31
|
|
|
32
32
|
//this.css_extractor = new CSS_Extractor();
|
|
33
33
|
|
|
@@ -49,7 +49,7 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
bundle(js_file_path) {
|
|
52
|
-
const {non_minifying_bundler, css_and_js_from_js_string_extractor, minifying_js_single_file_bundler, style_config} = this;
|
|
52
|
+
const {non_minifying_bundler, css_and_js_from_js_string_extractor, minifying_js_single_file_bundler, style_config} = this;
|
|
53
53
|
|
|
54
54
|
// Validate input
|
|
55
55
|
if (typeof js_file_path !== 'string' || js_file_path.trim() === '') {
|
|
@@ -66,6 +66,7 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
66
66
|
|
|
67
67
|
const res_obs = obs(async(next, complete, error) => {
|
|
68
68
|
|
|
69
|
+
try {
|
|
69
70
|
//console.log('Advanced_JS_Bundler_Using_ESBuild bundle js_file_path:', js_file_path);
|
|
70
71
|
|
|
71
72
|
const res_nmb = await non_minifying_bundler.bundle(js_file_path);
|
|
@@ -88,17 +89,17 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
88
89
|
const {text} = bundle_item;
|
|
89
90
|
// Then use the css and js from js extractor.
|
|
90
91
|
|
|
91
|
-
const res_extract_styles_and_js = await css_and_js_from_js_string_extractor.extract(text);
|
|
92
|
-
const {
|
|
93
|
-
css = '',
|
|
94
|
-
scss = '',
|
|
95
|
-
sass = '',
|
|
96
|
-
style_segments = [],
|
|
97
|
-
js = text
|
|
98
|
-
} = res_extract_styles_and_js || {};
|
|
99
|
-
|
|
100
|
-
const style_bundle = compile_styles({css, scss, sass, style_segments}, style_config);
|
|
101
|
-
const compiled_css = style_bundle.css || '';
|
|
92
|
+
const res_extract_styles_and_js = await css_and_js_from_js_string_extractor.extract(text);
|
|
93
|
+
const {
|
|
94
|
+
css = '',
|
|
95
|
+
scss = '',
|
|
96
|
+
sass = '',
|
|
97
|
+
style_segments = [],
|
|
98
|
+
js = text
|
|
99
|
+
} = res_extract_styles_and_js || {};
|
|
100
|
+
|
|
101
|
+
const style_bundle = compile_styles({css, scss, sass, style_segments}, style_config);
|
|
102
|
+
const compiled_css = style_bundle.css || '';
|
|
102
103
|
|
|
103
104
|
if (this.debug) {
|
|
104
105
|
// Generate source maps for CSS-free JS
|
|
@@ -112,11 +113,11 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
112
113
|
text: css_free_bundle_item.text
|
|
113
114
|
}
|
|
114
115
|
res_bundle.push(o_js_bundle_item);
|
|
115
|
-
const o_css_bundle_item = {
|
|
116
|
-
type: 'CSS',
|
|
117
|
-
extension: 'css',
|
|
118
|
-
text: compiled_css
|
|
119
|
-
}
|
|
116
|
+
const o_css_bundle_item = {
|
|
117
|
+
type: 'CSS',
|
|
118
|
+
extension: 'css',
|
|
119
|
+
text: compiled_css
|
|
120
|
+
}
|
|
120
121
|
res_bundle.push(o_css_bundle_item);
|
|
121
122
|
next(res_bundle);
|
|
122
123
|
complete(res_bundle);
|
|
@@ -140,11 +141,11 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
140
141
|
|
|
141
142
|
if (is_array(minified_js) && minified_js.length === 1) {
|
|
142
143
|
const minified_bundle = minified_js[0];
|
|
143
|
-
const o_css_bundle_item = {
|
|
144
|
-
type: 'CSS',
|
|
145
|
-
extension: 'css',
|
|
146
|
-
text: compiled_css
|
|
147
|
-
}
|
|
144
|
+
const o_css_bundle_item = {
|
|
145
|
+
type: 'CSS',
|
|
146
|
+
extension: 'css',
|
|
147
|
+
text: compiled_css
|
|
148
|
+
}
|
|
148
149
|
minified_bundle.push(o_css_bundle_item);
|
|
149
150
|
next(minified_bundle);
|
|
150
151
|
complete(minified_bundle);
|
|
@@ -241,6 +242,27 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
241
242
|
// Need to use a non minifying bundler (first).
|
|
242
243
|
|
|
243
244
|
|
|
245
|
+
} catch (bundleError) {
|
|
246
|
+
// Defensive programming: Log error but don't crash the server
|
|
247
|
+
console.error('[Advanced_JS_Bundler_Using_ESBuild] Bundling failed:', bundleError.message || bundleError);
|
|
248
|
+
console.error('[Advanced_JS_Bundler_Using_ESBuild] Returning empty bundle to allow server startup.');
|
|
249
|
+
|
|
250
|
+
// Return an empty bundle so the server can continue
|
|
251
|
+
const fallback_bundle = new Bundle();
|
|
252
|
+
fallback_bundle.push({
|
|
253
|
+
type: 'JavaScript',
|
|
254
|
+
extension: 'js',
|
|
255
|
+
text: '/* Bundling failed - see server logs */'
|
|
256
|
+
});
|
|
257
|
+
fallback_bundle.push({
|
|
258
|
+
type: 'CSS',
|
|
259
|
+
extension: 'css',
|
|
260
|
+
text: '/* Bundling failed - see server logs */'
|
|
261
|
+
});
|
|
262
|
+
next(fallback_bundle);
|
|
263
|
+
complete(fallback_bundle);
|
|
264
|
+
}
|
|
265
|
+
|
|
244
266
|
const _old_code = async() => {
|
|
245
267
|
|
|
246
268
|
const css_extractor_res = await css_extractor.separate_css_and_js(js_file_path)
|
|
@@ -290,4 +312,4 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
290
312
|
}
|
|
291
313
|
|
|
292
314
|
|
|
293
|
-
module.exports = Advanced_JS_Bundler_Using_ESBuild;
|
|
315
|
+
module.exports = Advanced_JS_Bundler_Using_ESBuild;
|
package/server.js
CHANGED
|
@@ -75,6 +75,63 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
75
75
|
});
|
|
76
76
|
resource_pool.add(server_router);
|
|
77
77
|
this.https_options = spec.https_options || undefined;
|
|
78
|
+
|
|
79
|
+
// Admin Module Setup
|
|
80
|
+
// Admin Module Setup
|
|
81
|
+
const Admin_Module = require('./admin-ui/server');
|
|
82
|
+
this.admin = new Admin_Module(this);
|
|
83
|
+
this.admin.attach_to_router(server_router);
|
|
84
|
+
|
|
85
|
+
// Register Admin Page Route
|
|
86
|
+
let Admin_Page_Control;
|
|
87
|
+
try {
|
|
88
|
+
console.log('DEBUG: Attempting to load Admin_Page_Control...');
|
|
89
|
+
Admin_Page_Control = require('./admin-ui/client').controls.Admin_Page;
|
|
90
|
+
console.log('DEBUG: Admin_Page_Control type:', typeof Admin_Page_Control);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
console.warn('DEBUG: Failed to load Admin_Page_Control', e);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (Admin_Page_Control) {
|
|
96
|
+
console.log('DEBUG: Creating Admin Webpage...');
|
|
97
|
+
const admin_app = new Webpage({
|
|
98
|
+
content: Admin_Page_Control,
|
|
99
|
+
title: 'jsgui3 Admin'
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const HTTP_Webpage_Publisher = require('./publishers/http-webpage-publisher');
|
|
103
|
+
console.log('DEBUG: Creating Admin Publisher...');
|
|
104
|
+
const admin_publisher = new HTTP_Webpage_Publisher({
|
|
105
|
+
name: 'Admin_Publisher',
|
|
106
|
+
webpage: admin_app,
|
|
107
|
+
//src_path_client_js: require('path').join(__dirname, 'admin-ui/client.js')
|
|
108
|
+
});
|
|
109
|
+
// Fix for Resource_Pool.add(undefined) error
|
|
110
|
+
admin_publisher.name = 'Admin_Publisher';
|
|
111
|
+
|
|
112
|
+
admin_publisher.on('ready', (res_ready) => {
|
|
113
|
+
if (res_ready._arr) {
|
|
114
|
+
for (const bundle_item of res_ready._arr) {
|
|
115
|
+
const { route } = bundle_item;
|
|
116
|
+
const Static_Route_HTTP_Responder = require('./http/responders/static/Static_Route_HTTP_Responder');
|
|
117
|
+
const responder = new Static_Route_HTTP_Responder(bundle_item);
|
|
118
|
+
server_router.set_route(route, responder, responder.handle_http);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
server_router.set_route('/admin', admin_publisher, admin_publisher.handle_http);
|
|
124
|
+
console.log('DEBUG: Adding admin_publisher to pool:', !!admin_publisher);
|
|
125
|
+
if (admin_publisher) {
|
|
126
|
+
resource_pool.add(admin_publisher);
|
|
127
|
+
} else {
|
|
128
|
+
console.error('DEBUG: admin_publisher is undefined!');
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
console.warn('Skipping /admin route registration due to missing control.');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
78
135
|
if (spec.routes) {
|
|
79
136
|
throw 'NYI - will use Website class rather than Website_Resource here'
|
|
80
137
|
each(spec.routes, (app_spec, route) => {
|
|
@@ -145,8 +202,12 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
145
202
|
'name': 'Website_Resource - Single Webpage',
|
|
146
203
|
'webpage': wp_app
|
|
147
204
|
});
|
|
148
|
-
|
|
149
|
-
|
|
205
|
+
console.log('DEBUG: Adding ws_resource to pool:', !!ws_resource);
|
|
206
|
+
if (ws_resource) {
|
|
207
|
+
resource_pool.add(ws_resource);
|
|
208
|
+
} else {
|
|
209
|
+
console.error('DEBUG: ws_resource is undefined!');
|
|
210
|
+
}
|
|
150
211
|
this.raise('ready');
|
|
151
212
|
});
|
|
152
213
|
|
|
@@ -227,6 +288,14 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
227
288
|
return this.resource_pool.resource_names;
|
|
228
289
|
}
|
|
229
290
|
'start'(port, callback, fnProcessRequest) {
|
|
291
|
+
// Guard against double-start which causes EADDRINUSE
|
|
292
|
+
if (this._started) {
|
|
293
|
+
console.warn('Server.start() called but server already started. Ignoring duplicate call.');
|
|
294
|
+
if (callback) callback(null, true);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
this._started = true;
|
|
298
|
+
|
|
230
299
|
if (tof(port) !== 'number') {
|
|
231
300
|
console.log('Invalid port:', port);
|
|
232
301
|
console.trace();
|
|
@@ -274,7 +343,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
274
343
|
if (started_count > 0) {
|
|
275
344
|
if (!ready_raised) {
|
|
276
345
|
console.log('Server ready');
|
|
277
|
-
this.raise('
|
|
346
|
+
this.raise('listening'); // Changed from 'ready' to avoid double-fire
|
|
278
347
|
ready_raised = true;
|
|
279
348
|
}
|
|
280
349
|
if (callback) callback(null, true);
|