jsgui3-server 0.0.138 → 0.0.140
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/AGENTS.md +87 -0
- package/README.md +12 -0
- package/docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md +19 -0
- package/docs/advanced-usage-examples.md +1360 -0
- package/docs/agent-development-guide.md +386 -0
- package/docs/api-reference.md +916 -0
- package/docs/broken-functionality-tracker.md +285 -0
- package/docs/bundling-system-deep-dive.md +525 -0
- package/docs/cli-reference.md +393 -0
- package/docs/comprehensive-documentation.md +1403 -0
- package/docs/configuration-reference.md +808 -0
- package/docs/controls-development.md +859 -0
- package/docs/documentation-review/CURRENT_REVIEW.md +95 -0
- package/docs/function-publishers-json-apis.md +847 -0
- package/docs/getting-started-with-json.md +518 -0
- package/docs/minification-compression-sourcemaps-status.md +482 -0
- package/docs/minification-compression-sourcemaps-test-results.md +205 -0
- package/docs/publishers-guide.md +313 -0
- package/docs/resources-guide.md +615 -0
- package/docs/serve-helpers.md +406 -0
- package/docs/simple-server-api-design.md +13 -0
- package/docs/system-architecture.md +275 -0
- package/docs/troubleshooting.md +698 -0
- package/examples/json/README.md +115 -0
- package/examples/json/basic-api/README.md +345 -0
- package/examples/json/basic-api/server.js +199 -0
- package/examples/json/simple-api/README.md +125 -0
- package/examples/json/simple-api/diagnostic-report.json +73 -0
- package/examples/json/simple-api/diagnostic-test.js +433 -0
- package/examples/json/simple-api/server-debug.md +58 -0
- package/examples/json/simple-api/server.js +91 -0
- package/examples/json/simple-api/test.js +215 -0
- package/http/responders/static/Static_Route_HTTP_Responder.js +1 -2
- package/package.json +19 -8
- package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +65 -12
- package/publishers/helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer.js +6 -1
- package/publishers/http-function-publisher.js +59 -38
- package/publishers/http-webpage-publisher.js +48 -1
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +38 -146
- package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +54 -5
- package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +36 -4
- package/serve-factory.js +36 -9
- package/server.js +10 -4
- package/test-report.json +0 -0
- package/tests/README.md +250 -0
- package/tests/assigners.test.js +316 -0
- package/tests/bundlers.test.js +329 -0
- package/tests/configuration-validation.test.js +530 -0
- package/tests/content-analysis.test.js +641 -0
- package/tests/end-to-end.test.js +496 -0
- package/tests/error-handling.test.js +746 -0
- package/tests/performance.test.js +653 -0
- package/tests/publishers.test.js +395 -0
- package/tests/temp_invalid.js +7 -0
- package/tests/temp_invalid_utf8.js +1 -0
- package/tests/temp_malformed.js +10 -0
- package/tests/test-runner.js +261 -0
|
@@ -23,7 +23,54 @@ class HTTP_Webpage_Publisher extends HTTP_Webpageorsite_Publisher {
|
|
|
23
23
|
return webpage;
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
// Store bundler configuration for passing to preparers
|
|
28
|
+
this.bundler_config = spec.bundler || {};
|
|
29
|
+
|
|
30
|
+
// Add input validation for bundler configuration
|
|
31
|
+
if (spec.bundler !== undefined && typeof spec.bundler !== 'object') {
|
|
32
|
+
throw new Error('bundler must be an object');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Add input validation for compression settings
|
|
36
|
+
if (this.bundler_config.compression) {
|
|
37
|
+
const compression = this.bundler_config.compression;
|
|
38
|
+
if (compression.enabled !== undefined && typeof compression.enabled !== 'boolean') {
|
|
39
|
+
throw new Error('bundler.compression.enabled must be a boolean');
|
|
40
|
+
}
|
|
41
|
+
if (compression.algorithms && !Array.isArray(compression.algorithms)) {
|
|
42
|
+
throw new Error('bundler.compression.algorithms must be an array');
|
|
43
|
+
}
|
|
44
|
+
if (compression.algorithms) {
|
|
45
|
+
const validAlgorithms = ['gzip', 'br'];
|
|
46
|
+
for (const alg of compression.algorithms) {
|
|
47
|
+
if (!validAlgorithms.includes(alg)) {
|
|
48
|
+
throw new Error(`Invalid compression algorithm: ${alg}. Must be one of: ${validAlgorithms.join(', ')}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (compression.threshold !== undefined && (typeof compression.threshold !== 'number' || compression.threshold < 0)) {
|
|
53
|
+
throw new Error('bundler.compression.threshold must be a non-negative number');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Add input validation for minification settings
|
|
58
|
+
if (this.bundler_config.minify) {
|
|
59
|
+
const minify = this.bundler_config.minify;
|
|
60
|
+
if (minify.level !== undefined && typeof minify.level !== 'string') {
|
|
61
|
+
throw new Error('bundler.minify.level must be a string');
|
|
62
|
+
}
|
|
63
|
+
if (minify.level !== undefined) {
|
|
64
|
+
const validLevels = ['conservative', 'normal', 'aggressive'];
|
|
65
|
+
if (!validLevels.includes(minify.level)) {
|
|
66
|
+
throw new Error(`Invalid minification level: ${minify.level}. Must be one of: ${validLevels.join(', ')}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.static_routes_responses_webpage_bundle_preparer = new Static_Routes_Responses_Webpage_Bundle_Preparer({
|
|
72
|
+
bundler_config: this.bundler_config
|
|
73
|
+
});
|
|
27
74
|
(async() => {
|
|
28
75
|
const res_get_ready = await this.get_ready();
|
|
29
76
|
this.raise('ready', res_get_ready);
|
|
@@ -18,16 +18,20 @@ const CSS_And_JS_From_JS_String_Extractor = require('../../../extractors/js/css_
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
21
|
-
constructor(spec) {
|
|
21
|
+
constructor(spec = {}) {
|
|
22
22
|
super(spec);
|
|
23
23
|
|
|
24
24
|
if (spec.debug !== undefined) this.debug = spec.debug;
|
|
25
25
|
|
|
26
|
+
// Store bundler configuration
|
|
27
|
+
this.bundler_config = spec.bundler || {};
|
|
28
|
+
|
|
26
29
|
//this.css_extractor = new CSS_Extractor();
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
this.non_minifying_bundler = new Core_JS_Non_Minifying_Bundler_Using_ESBuild({
|
|
30
|
-
debug: this.debug
|
|
33
|
+
debug: this.debug,
|
|
34
|
+
sourcemaps: this.bundler_config.sourcemaps
|
|
31
35
|
});
|
|
32
36
|
|
|
33
37
|
|
|
@@ -35,20 +39,27 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
35
39
|
|
|
36
40
|
|
|
37
41
|
// Probably don't use that minifying bundler in debug mode.
|
|
38
|
-
this.minifying_js_single_file_bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild(
|
|
42
|
+
this.minifying_js_single_file_bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
|
|
43
|
+
minify: this.bundler_config.minify
|
|
44
|
+
});
|
|
39
45
|
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
bundle(js_file_path) {
|
|
43
49
|
const {non_minifying_bundler, css_and_js_from_js_string_extractor, minifying_js_single_file_bundler} = this;
|
|
44
50
|
|
|
51
|
+
// Validate input
|
|
52
|
+
if (typeof js_file_path !== 'string' || js_file_path.trim() === '') {
|
|
53
|
+
throw new Error('bundle() expects a valid file path string');
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
// Maybe this should get them positioned absolutely when removed from the grid?
|
|
46
57
|
// But then what about the space they leave?
|
|
47
58
|
|
|
48
59
|
// This is just a simple principle demo though.
|
|
49
60
|
// Maybe want a simple and explicit option to change behaviour like I specify.
|
|
50
61
|
|
|
51
|
-
|
|
62
|
+
|
|
52
63
|
|
|
53
64
|
const res_obs = obs(async(next, complete, error) => {
|
|
54
65
|
|
|
@@ -78,30 +89,22 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
78
89
|
const {css, js} = res_extract_css_and_js_from_js;
|
|
79
90
|
|
|
80
91
|
if (this.debug) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// Don't minify the js.
|
|
85
|
-
|
|
86
|
-
// Make res bundle items that include the CSS and the non-minified JS.
|
|
87
|
-
|
|
88
|
-
// Including the source map would be better still.
|
|
92
|
+
// Generate source maps for CSS-free JS
|
|
93
|
+
const css_free_bundle_result = await non_minifying_bundler.bundle_js_string(js);
|
|
94
|
+
const css_free_bundle_item = css_free_bundle_result[0]._arr[0];
|
|
89
95
|
|
|
90
96
|
const res_bundle = new Bundle();
|
|
91
|
-
// Add the non-minified JS (as a bundle item object)
|
|
92
|
-
|
|
93
97
|
const o_js_bundle_item = {
|
|
94
98
|
type: 'JavaScript',
|
|
95
|
-
extension: '
|
|
96
|
-
text:
|
|
99
|
+
extension: 'js',
|
|
100
|
+
text: css_free_bundle_item.text
|
|
97
101
|
}
|
|
98
|
-
res_bundle.
|
|
102
|
+
res_bundle.push(o_js_bundle_item);
|
|
99
103
|
const o_css_bundle_item = {
|
|
100
104
|
type: 'CSS',
|
|
101
105
|
extension: 'css',
|
|
102
106
|
text: css
|
|
103
107
|
}
|
|
104
|
-
|
|
105
108
|
res_bundle.push(o_css_bundle_item);
|
|
106
109
|
next(res_bundle);
|
|
107
110
|
complete(res_bundle);
|
|
@@ -112,125 +115,30 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
112
115
|
|
|
113
116
|
|
|
114
117
|
|
|
115
|
-
|
|
116
118
|
} else {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
119
|
+
// Generate source maps for CSS-free JS and minify
|
|
120
|
+
const css_free_bundle_result = await non_minifying_bundler.bundle_js_string(js);
|
|
121
|
+
const css_free_bundle_item = css_free_bundle_result[0]._arr[0];
|
|
122
|
+
const minified_js = await minifying_js_single_file_bundler.bundle(css_free_bundle_item.text);
|
|
120
123
|
|
|
121
124
|
//console.log('minified_js', minified_js);
|
|
122
125
|
//console.log('minified_js.length', minified_js.length);
|
|
123
126
|
|
|
124
127
|
// it's an array....
|
|
125
128
|
|
|
126
|
-
if (is_array(minified_js)) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// Though merging / concating bundles will be fine too.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const minified_js_bundle_collection = minified_js[0];
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const o_css_bundle_item = {
|
|
141
|
-
type: 'CSS',
|
|
142
|
-
extension: 'css',
|
|
143
|
-
text: css
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
minified_js_bundle_collection.push(o_css_bundle_item);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// Maybe will provide the class / class instance that processes CSS or SASS/SCSS / whatever else.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
// Could add the extracted CSS here.
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
next(minified_js_bundle_collection);
|
|
158
|
-
|
|
159
|
-
// But create a CSS bundle item...
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// And also the CSS...
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
complete(minified_js_bundle_collection);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const unneeded_looking_into_the_js_bundle = () => {
|
|
176
|
-
if (minified_js_bundle_collection._arr) {
|
|
177
|
-
|
|
178
|
-
if (minified_js_bundle_collection._arr.length === 1) {
|
|
179
|
-
|
|
180
|
-
const minified_js_bundle_item = minified_js_bundle_collection._arr[0];
|
|
181
|
-
console.log('minified_js_bundle_item', minified_js_bundle_item);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (minified_js_bundle_item.type === 'JavaScript') {
|
|
185
|
-
|
|
186
|
-
//const str_minified_js = minified_js_bundle_item.text;
|
|
187
|
-
|
|
188
|
-
//const res =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
} else {
|
|
195
|
-
|
|
196
|
-
console.trace();
|
|
197
|
-
throw 'NYI';
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// Could even check it's js here...?
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
console.trace();
|
|
206
|
-
throw 'NYI';
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
} else {
|
|
210
|
-
console.trace();
|
|
211
|
-
throw 'NYI';
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
} else {
|
|
215
|
-
|
|
216
|
-
console.trace();
|
|
217
|
-
throw 'NYI';
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
} else {
|
|
226
|
-
console.trace();
|
|
227
|
-
throw 'stop';
|
|
129
|
+
if (is_array(minified_js) && minified_js.length === 1) {
|
|
130
|
+
const minified_bundle = minified_js[0];
|
|
131
|
+
const o_css_bundle_item = {
|
|
132
|
+
type: 'CSS',
|
|
133
|
+
extension: 'css',
|
|
134
|
+
text: css
|
|
228
135
|
}
|
|
229
|
-
|
|
136
|
+
minified_bundle.push(o_css_bundle_item);
|
|
137
|
+
next(minified_bundle);
|
|
138
|
+
complete(minified_bundle);
|
|
230
139
|
} else {
|
|
231
|
-
|
|
232
140
|
console.trace();
|
|
233
|
-
throw '
|
|
141
|
+
throw 'Unexpected minified JS structure';
|
|
234
142
|
}
|
|
235
143
|
|
|
236
144
|
|
|
@@ -240,12 +148,8 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
240
148
|
|
|
241
149
|
|
|
242
150
|
|
|
243
|
-
|
|
244
|
-
|
|
245
151
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
152
|
+
|
|
249
153
|
//console.trace();
|
|
250
154
|
//throw 'stop';
|
|
251
155
|
|
|
@@ -259,13 +163,11 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
259
163
|
|
|
260
164
|
|
|
261
165
|
|
|
262
|
-
|
|
263
166
|
// Maybe that will be a Ready_To_Serve_Static_Bundle
|
|
264
167
|
|
|
265
168
|
|
|
266
169
|
|
|
267
170
|
|
|
268
|
-
|
|
269
171
|
// Though it needs to provide (a bundle of?) both JS and CSS.
|
|
270
172
|
// Better to use a standard bundle class (collection) to transfer these objects.
|
|
271
173
|
|
|
@@ -291,17 +193,6 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
291
193
|
|
|
292
194
|
|
|
293
195
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
196
|
//console.log('res_extract_css_and_js_from_js', res_extract_css_and_js_from_js);
|
|
306
197
|
|
|
307
198
|
//console.trace();
|
|
@@ -372,7 +263,6 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
372
263
|
|
|
373
264
|
|
|
374
265
|
|
|
375
|
-
|
|
376
266
|
});
|
|
377
267
|
return res_obs;
|
|
378
268
|
|
|
@@ -382,8 +272,10 @@ class Advanced_JS_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
|
382
272
|
|
|
383
273
|
}
|
|
384
274
|
|
|
275
|
+
|
|
385
276
|
|
|
386
277
|
|
|
387
278
|
}
|
|
388
279
|
|
|
280
|
+
|
|
389
281
|
module.exports = Advanced_JS_Bundler_Using_ESBuild;
|
package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js
CHANGED
|
@@ -14,11 +14,13 @@ const Bundler_Using_ESBuild = require('./Bundler_Using_ESBuild');
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class Core_JS_Non_Minifying_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
17
|
-
constructor(spec) {
|
|
17
|
+
constructor(spec = {}) {
|
|
18
18
|
super(spec);
|
|
19
19
|
|
|
20
20
|
if (spec.debug !== undefined) this.debug = spec.debug;
|
|
21
21
|
|
|
22
|
+
// Store sourcemap configuration
|
|
23
|
+
this.sourcemap_config = spec.sourcemaps || {};
|
|
22
24
|
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -42,11 +44,56 @@ class Core_JS_Non_Minifying_Bundler_Using_ESBuild extends Bundler_Using_ESBuild
|
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
|
|
47
|
+
bundle_js_string(js_string) {
|
|
48
|
+
const res_obs = obs(async(next, complete, error) => {
|
|
49
|
+
const o_build = {
|
|
50
|
+
stdin: {
|
|
51
|
+
contents: js_string,
|
|
52
|
+
resolveDir: process.cwd()
|
|
53
|
+
},
|
|
54
|
+
bundle: true,
|
|
55
|
+
treeShaking: true,
|
|
56
|
+
write: false,
|
|
57
|
+
// Remove outdir since we're keeping in memory
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Configure sourcemaps based on configuration
|
|
61
|
+
const sourcemapsEnabled = this.sourcemap_config.enabled !== false; // Default: true in debug, false in production
|
|
62
|
+
if (sourcemapsEnabled && (this.debug || this.sourcemap_config.includeInProduction)) {
|
|
63
|
+
o_build.sourcemap = this.sourcemap_config.format || 'inline';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let result = await esbuild.build(o_build);
|
|
67
|
+
|
|
68
|
+
if (result.outputFiles.length === 1) {
|
|
69
|
+
const output_file = result.outputFiles[0];
|
|
70
|
+
const res_bundle = new Bundle();
|
|
71
|
+
const o_bundle_item = {
|
|
72
|
+
type: 'JavaScript',
|
|
73
|
+
extension: 'js',
|
|
74
|
+
text: output_file.text
|
|
75
|
+
}
|
|
76
|
+
res_bundle.push(o_bundle_item);
|
|
77
|
+
next(res_bundle);
|
|
78
|
+
complete();
|
|
79
|
+
} else {
|
|
80
|
+
console.trace();
|
|
81
|
+
throw 'NYI';
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return res_obs;
|
|
85
|
+
}
|
|
86
|
+
|
|
45
87
|
bundle(js_file_path) {
|
|
46
88
|
|
|
47
89
|
|
|
48
90
|
const res_obs = obs(async(next, complete, error) => {
|
|
49
91
|
|
|
92
|
+
// Validate input
|
|
93
|
+
if (typeof js_file_path !== 'string' || js_file_path.trim() === '') {
|
|
94
|
+
throw new Error('bundle() expects a valid file path string');
|
|
95
|
+
}
|
|
96
|
+
|
|
50
97
|
//console.log('Core_JS_Bundler_Using_ESBuild bundle js_file_path:', js_file_path);
|
|
51
98
|
|
|
52
99
|
// Looks like we need better linking build options....
|
|
@@ -57,7 +104,7 @@ class Core_JS_Non_Minifying_Bundler_Using_ESBuild extends Bundler_Using_ESBuild
|
|
|
57
104
|
|
|
58
105
|
//format: 'iife',
|
|
59
106
|
bundle: true,
|
|
60
|
-
|
|
107
|
+
|
|
61
108
|
// Possibly no minification here....
|
|
62
109
|
// Want to use non-minified or only partially minified version to separate the JS and the CSS.
|
|
63
110
|
|
|
@@ -65,11 +112,13 @@ class Core_JS_Non_Minifying_Bundler_Using_ESBuild extends Bundler_Using_ESBuild
|
|
|
65
112
|
|
|
66
113
|
//sourcemap: 'external',
|
|
67
114
|
write: false,
|
|
68
|
-
outdir
|
|
115
|
+
// Remove outdir since we're keeping in memory
|
|
69
116
|
}
|
|
70
117
|
|
|
71
|
-
|
|
72
|
-
|
|
118
|
+
// Configure sourcemaps based on configuration
|
|
119
|
+
const sourcemapsEnabled = this.sourcemap_config.enabled !== false; // Default: true in debug, false in production
|
|
120
|
+
if (sourcemapsEnabled && (this.debug || this.sourcemap_config.includeInProduction)) {
|
|
121
|
+
o_build.sourcemap = this.sourcemap_config.format || 'inline';
|
|
73
122
|
}
|
|
74
123
|
|
|
75
124
|
|
|
@@ -16,8 +16,11 @@ const Bundler_Using_ESBuild = require('./Bundler_Using_ESBuild');
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class Core_JS_Single_File_Minifying_Bundler_Using_ESBuild extends Bundler_Using_ESBuild {
|
|
19
|
-
constructor(spec) {
|
|
19
|
+
constructor(spec = {}) {
|
|
20
20
|
super(spec);
|
|
21
|
+
|
|
22
|
+
// Store minification configuration
|
|
23
|
+
this.minify_config = spec.minify || this.get_default_minify_config();
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
// And the options....
|
|
@@ -30,10 +33,35 @@ class Core_JS_Single_File_Minifying_Bundler_Using_ESBuild extends Bundler_Using_
|
|
|
30
33
|
// Core_JS_Non_Minifying_Bundler_Using_ESBuild for example....
|
|
31
34
|
|
|
32
35
|
// Really specific class names for specific functionality to call reqlly quickly and interchange really quickly.
|
|
33
|
-
|
|
36
|
+
|
|
34
37
|
// Probably use the non-minifying bundler, and then use a minifier afterwards.
|
|
35
38
|
// And here the minifier is ESBuild, as is the bundler.
|
|
36
39
|
|
|
40
|
+
get_minify_options() {
|
|
41
|
+
const level = this.minify_config.level || 'normal';
|
|
42
|
+
const enabled = this.minify_config.enabled !== false; // Default: true
|
|
43
|
+
|
|
44
|
+
if (!enabled) {
|
|
45
|
+
return false; // Disable minification
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const baseOptions = {
|
|
49
|
+
conservative: { mangle: false, compress: { sequences: false } },
|
|
50
|
+
normal: { mangle: true, compress: true },
|
|
51
|
+
aggressive: { mangle: true, compress: { drop_console: true, drop_debugger: true } }
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const options = { ...baseOptions[level], ...this.minify_config.options };
|
|
55
|
+
return options;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get_default_minify_config() {
|
|
59
|
+
return {
|
|
60
|
+
enabled: true,
|
|
61
|
+
level: 'normal'
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
37
65
|
|
|
38
66
|
|
|
39
67
|
|
|
@@ -43,6 +71,10 @@ class Core_JS_Single_File_Minifying_Bundler_Using_ESBuild extends Bundler_Using_
|
|
|
43
71
|
bundle(str_js) {
|
|
44
72
|
|
|
45
73
|
|
|
74
|
+
// Validate input
|
|
75
|
+
if (typeof str_js !== 'string') {
|
|
76
|
+
throw new Error('bundle() expects a string parameter');
|
|
77
|
+
}
|
|
46
78
|
const res_obs = obs(async(next, complete, error) => {
|
|
47
79
|
|
|
48
80
|
|
|
@@ -60,7 +92,7 @@ class Core_JS_Single_File_Minifying_Bundler_Using_ESBuild extends Bundler_Using_
|
|
|
60
92
|
//sourcefile: 'imaginary-file.js',
|
|
61
93
|
//loader: 'ts',
|
|
62
94
|
},
|
|
63
|
-
|
|
95
|
+
bundle: true,
|
|
64
96
|
|
|
65
97
|
// Possibly no minification here....
|
|
66
98
|
// Want to use non-minified or only partially minified version to separate the JS and the CSS.
|
|
@@ -71,7 +103,7 @@ class Core_JS_Single_File_Minifying_Bundler_Using_ESBuild extends Bundler_Using_
|
|
|
71
103
|
|
|
72
104
|
//sourcemap: 'external',
|
|
73
105
|
write: false,
|
|
74
|
-
outdir
|
|
106
|
+
// Remove outdir since we're keeping in memory
|
|
75
107
|
})
|
|
76
108
|
//console.log('result.outputFiles:\n\n');
|
|
77
109
|
for (let out of result.outputFiles) {
|
package/serve-factory.js
CHANGED
|
@@ -144,6 +144,9 @@ module.exports = (Server) => {
|
|
|
144
144
|
};
|
|
145
145
|
if (typeof serve_options.ctrl === 'function') {
|
|
146
146
|
server_spec.Ctrl = serve_options.ctrl;
|
|
147
|
+
} else if (serve_options.api && typeof serve_options.api === 'object') {
|
|
148
|
+
// API-only server: explicitly disable website setup
|
|
149
|
+
server_spec.website = false;
|
|
147
150
|
}
|
|
148
151
|
if (root_client_path) {
|
|
149
152
|
server_spec.src_path_client_js = root_client_path;
|
|
@@ -153,7 +156,7 @@ module.exports = (Server) => {
|
|
|
153
156
|
if (host) {
|
|
154
157
|
server_instance.allowed_addresses = Array.isArray(host) ? host : [host];
|
|
155
158
|
}
|
|
156
|
-
|
|
159
|
+
|
|
157
160
|
const settle = (resolver, value) => {
|
|
158
161
|
if (callback) {
|
|
159
162
|
try {
|
|
@@ -164,9 +167,9 @@ module.exports = (Server) => {
|
|
|
164
167
|
}
|
|
165
168
|
return resolver(value);
|
|
166
169
|
};
|
|
167
|
-
|
|
170
|
+
|
|
168
171
|
let has_started = false;
|
|
169
|
-
|
|
172
|
+
|
|
170
173
|
const extra_page_promises = additional_pages.map(([route, cfg]) => prepare_webpage_route(server_instance, route, cfg, {
|
|
171
174
|
caller_dir,
|
|
172
175
|
debug: debug_enabled
|
|
@@ -177,41 +180,65 @@ module.exports = (Server) => {
|
|
|
177
180
|
debug: debug_enabled
|
|
178
181
|
}));
|
|
179
182
|
}
|
|
180
|
-
|
|
183
|
+
|
|
181
184
|
if (serve_options.api && typeof serve_options.api === 'object') {
|
|
185
|
+
console.log('🔍 DEBUG: Setting up API routes');
|
|
182
186
|
for (const [name, handler] of Object.entries(serve_options.api)) {
|
|
183
187
|
if (typeof handler === 'function') {
|
|
188
|
+
console.log(`🔍 DEBUG: Publishing API route: ${name}`);
|
|
184
189
|
server_instance.publish(name, handler);
|
|
185
190
|
}
|
|
186
191
|
}
|
|
192
|
+
console.log('🔍 DEBUG: API routes setup complete');
|
|
187
193
|
}
|
|
188
|
-
|
|
194
|
+
|
|
189
195
|
return new Promise((resolve, reject) => {
|
|
190
196
|
const start_server = () => {
|
|
191
197
|
if (has_started) return;
|
|
192
198
|
has_started = true;
|
|
199
|
+
console.log('🔍 DEBUG: Calling server_instance.start()');
|
|
193
200
|
server_instance.start(port, (err) => {
|
|
194
|
-
if (err)
|
|
201
|
+
if (err) {
|
|
202
|
+
console.log('🔍 DEBUG: server_instance.start() failed:', err);
|
|
203
|
+
return settle(reject, err);
|
|
204
|
+
}
|
|
205
|
+
console.log('🔍 DEBUG: server_instance.start() succeeded');
|
|
195
206
|
const message = host ? `Serving on http://${Array.isArray(host) ? host[0] : host}:${port || 0}/` : `Serving on port ${port || 0} (all IPv4 interfaces)`;
|
|
196
207
|
console.log(message);
|
|
197
208
|
console.log('Server ready');
|
|
198
209
|
settle(resolve, server_instance);
|
|
199
210
|
});
|
|
200
211
|
};
|
|
201
|
-
|
|
212
|
+
|
|
213
|
+
console.log('🔍 DEBUG: Setting up ready event listener');
|
|
202
214
|
server_instance.on('ready', () => {
|
|
215
|
+
console.log('🔍 DEBUG: Ready event fired');
|
|
203
216
|
Promise.allSettled(extra_page_promises).then(results => {
|
|
204
217
|
const rejected_entry = results.find(result => result.status === 'rejected');
|
|
205
218
|
if (rejected_entry) {
|
|
219
|
+
console.log('🔍 DEBUG: Extra page promise rejected:', rejected_entry.reason);
|
|
206
220
|
return settle(reject, rejected_entry.reason);
|
|
207
221
|
}
|
|
222
|
+
console.log('🔍 DEBUG: All extra page promises resolved, calling start_server()');
|
|
208
223
|
start_server();
|
|
209
|
-
}).catch(err =>
|
|
224
|
+
}).catch(err => {
|
|
225
|
+
console.log('🔍 DEBUG: Extra page promises error:', err);
|
|
226
|
+
settle(reject, err);
|
|
227
|
+
});
|
|
210
228
|
});
|
|
211
|
-
|
|
229
|
+
|
|
230
|
+
// For API-only servers, trigger ready immediately after API setup
|
|
231
|
+
if (serve_options.api && typeof serve_options.api === 'object' && !serve_options.ctrl) {
|
|
232
|
+
console.log('🔍 DEBUG: API-only server detected, triggering ready event');
|
|
233
|
+
server_instance.raise('ready');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
console.log('🔍 DEBUG: Setting up fallback timeout');
|
|
212
237
|
setTimeout(() => {
|
|
213
238
|
// Fallback in case ready event never fires (should not happen, but guard just in case)
|
|
239
|
+
console.log('🔍 DEBUG: Fallback timeout triggered, has_started:', has_started);
|
|
214
240
|
if (!has_started) {
|
|
241
|
+
console.log('🔍 DEBUG: Calling start_server() from fallback');
|
|
215
242
|
start_server();
|
|
216
243
|
}
|
|
217
244
|
}, 2000).unref?.();
|
package/server.js
CHANGED
|
@@ -85,7 +85,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
85
85
|
const opts_webpage = {
|
|
86
86
|
'name': this.name || 'Website'
|
|
87
87
|
};
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
if (Ctrl) {
|
|
90
90
|
|
|
91
91
|
|
|
@@ -102,7 +102,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
102
102
|
|
|
103
103
|
if (disk_path_client_js) opts_wp_publisher.src_path_client_js = disk_path_client_js;
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
|
|
107
107
|
// HTTP_Webpage_Publisher probably needs to build the JavaScript. Possibly other assets too.
|
|
108
108
|
const wp_publisher = new HTTP_Webpage_Publisher(opts_wp_publisher);
|
|
@@ -125,7 +125,8 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
125
125
|
|
|
126
126
|
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
|
|
129
|
+
|
|
129
130
|
//console.trace();
|
|
130
131
|
//throw 'stop';
|
|
131
132
|
|
|
@@ -145,6 +146,12 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
145
146
|
|
|
146
147
|
|
|
147
148
|
} else {
|
|
149
|
+
// Check if this is an API-only server (no website needed)
|
|
150
|
+
if (spec.website === false) {
|
|
151
|
+
// API-only server: emit ready immediately after router setup
|
|
152
|
+
this.raise('ready');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
148
155
|
|
|
149
156
|
// Ahhh the web page publisher may be used instead of the website publisher.
|
|
150
157
|
// See about making use of relevant shared abstractions.
|
|
@@ -173,7 +180,6 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
173
180
|
});
|
|
174
181
|
}
|
|
175
182
|
|
|
176
|
-
|
|
177
183
|
|
|
178
184
|
Object.defineProperty(this, 'router', { get: () => server_router })
|
|
179
185
|
}
|
package/test-report.json
ADDED
|
File without changes
|