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.
Files changed (57) hide show
  1. package/AGENTS.md +87 -0
  2. package/README.md +12 -0
  3. package/docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md +19 -0
  4. package/docs/advanced-usage-examples.md +1360 -0
  5. package/docs/agent-development-guide.md +386 -0
  6. package/docs/api-reference.md +916 -0
  7. package/docs/broken-functionality-tracker.md +285 -0
  8. package/docs/bundling-system-deep-dive.md +525 -0
  9. package/docs/cli-reference.md +393 -0
  10. package/docs/comprehensive-documentation.md +1403 -0
  11. package/docs/configuration-reference.md +808 -0
  12. package/docs/controls-development.md +859 -0
  13. package/docs/documentation-review/CURRENT_REVIEW.md +95 -0
  14. package/docs/function-publishers-json-apis.md +847 -0
  15. package/docs/getting-started-with-json.md +518 -0
  16. package/docs/minification-compression-sourcemaps-status.md +482 -0
  17. package/docs/minification-compression-sourcemaps-test-results.md +205 -0
  18. package/docs/publishers-guide.md +313 -0
  19. package/docs/resources-guide.md +615 -0
  20. package/docs/serve-helpers.md +406 -0
  21. package/docs/simple-server-api-design.md +13 -0
  22. package/docs/system-architecture.md +275 -0
  23. package/docs/troubleshooting.md +698 -0
  24. package/examples/json/README.md +115 -0
  25. package/examples/json/basic-api/README.md +345 -0
  26. package/examples/json/basic-api/server.js +199 -0
  27. package/examples/json/simple-api/README.md +125 -0
  28. package/examples/json/simple-api/diagnostic-report.json +73 -0
  29. package/examples/json/simple-api/diagnostic-test.js +433 -0
  30. package/examples/json/simple-api/server-debug.md +58 -0
  31. package/examples/json/simple-api/server.js +91 -0
  32. package/examples/json/simple-api/test.js +215 -0
  33. package/http/responders/static/Static_Route_HTTP_Responder.js +1 -2
  34. package/package.json +19 -8
  35. package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +65 -12
  36. package/publishers/helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer.js +6 -1
  37. package/publishers/http-function-publisher.js +59 -38
  38. package/publishers/http-webpage-publisher.js +48 -1
  39. package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +38 -146
  40. package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +54 -5
  41. package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +36 -4
  42. package/serve-factory.js +36 -9
  43. package/server.js +10 -4
  44. package/test-report.json +0 -0
  45. package/tests/README.md +250 -0
  46. package/tests/assigners.test.js +316 -0
  47. package/tests/bundlers.test.js +329 -0
  48. package/tests/configuration-validation.test.js +530 -0
  49. package/tests/content-analysis.test.js +641 -0
  50. package/tests/end-to-end.test.js +496 -0
  51. package/tests/error-handling.test.js +746 -0
  52. package/tests/performance.test.js +653 -0
  53. package/tests/publishers.test.js +395 -0
  54. package/tests/temp_invalid.js +7 -0
  55. package/tests/temp_invalid_utf8.js +1 -0
  56. package/tests/temp_malformed.js +10 -0
  57. package/tests/test-runner.js +261 -0
@@ -0,0 +1,653 @@
1
+ const assert = require('assert');
2
+ const { describe, it, before, after } = require('mocha');
3
+ const fs = require('fs').promises;
4
+ const path = require('path');
5
+
6
+ // Import classes for performance testing
7
+ const Core_JS_Non_Minifying_Bundler_Using_ESBuild = require('../resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild');
8
+ const Core_JS_Single_File_Minifying_Bundler_Using_ESBuild = require('../resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild');
9
+ const Advanced_JS_Bundler_Using_ESBuild = require('../resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild');
10
+ const Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner = require('../publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner');
11
+ const Server = require('../server');
12
+
13
+ describe('Performance Tests', function() {
14
+ this.timeout(60000); // Allow longer timeout for performance tests
15
+
16
+ let testJsFile;
17
+ let largeJsContent;
18
+ let mediumJsContent;
19
+ let smallJsContent;
20
+
21
+ before(async function() {
22
+ // Create test files of different sizes
23
+ smallJsContent = `
24
+ function smallTest() {
25
+ return "small";
26
+ }
27
+ console.log(smallTest());
28
+ `;
29
+
30
+ mediumJsContent = `
31
+ // Medium-sized JavaScript file
32
+ const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
33
+
34
+ function processData(arr) {
35
+ return arr.map(x => x * 2)
36
+ .filter(x => x > 10)
37
+ .reduce((sum, x) => sum + x, 0);
38
+ }
39
+
40
+ class DataProcessor {
41
+ constructor(data) {
42
+ this.data = data;
43
+ }
44
+
45
+ process() {
46
+ return processData(this.data);
47
+ }
48
+
49
+ getStatistics() {
50
+ return {
51
+ count: this.data.length,
52
+ sum: this.data.reduce((a, b) => a + b, 0),
53
+ average: this.data.reduce((a, b) => a + b, 0) / this.data.length
54
+ };
55
+ }
56
+ }
57
+
58
+ const processor = new DataProcessor(data);
59
+ console.log('Result:', processor.process());
60
+ console.log('Stats:', processor.getStatistics());
61
+ `;
62
+
63
+ largeJsContent = `
64
+ // Large JavaScript file for performance testing
65
+ const largeArray = [];
66
+ for (let i = 0; i < 10000; i++) {
67
+ largeArray.push({
68
+ id: i,
69
+ name: \`Item \${i}\`,
70
+ value: Math.random(),
71
+ nested: {
72
+ prop1: \`Nested \${i}\`,
73
+ prop2: i * 2,
74
+ prop3: {
75
+ deep: \`Deep nested \${i}\`,
76
+ deeper: {
77
+ value: i * i
78
+ }
79
+ }
80
+ }
81
+ });
82
+ }
83
+
84
+ function processLargeArray(arr) {
85
+ return arr
86
+ .filter(item => item.value > 0.5)
87
+ .map(item => ({
88
+ ...item,
89
+ processed: true,
90
+ computed: item.nested.prop2 * item.nested.prop3.deeper.value
91
+ }))
92
+ .sort((a, b) => b.computed - a.computed)
93
+ .slice(0, 100);
94
+ }
95
+
96
+ function createLargeString() {
97
+ let str = '';
98
+ for (let i = 0; i < 1000; i++) {
99
+ str += \`Line \${i}: This is a test string that will be repeated many times to create a large file. \`;
100
+ str += \`Additional content to make this even larger. \${i * i} \${Math.random()} \`;
101
+ }
102
+ return str;
103
+ }
104
+
105
+ const largeString = createLargeString();
106
+ const processedData = processLargeArray(largeArray);
107
+
108
+ console.log('Large array length:', largeArray.length);
109
+ console.log('Processed data length:', processedData.length);
110
+ console.log('Large string length:', largeString.length);
111
+ console.log('Sample processed item:', processedData[0]);
112
+ `;
113
+
114
+ // Create temporary file
115
+ testJsFile = path.join(__dirname, 'temp_performance_test.js');
116
+ await fs.writeFile(testJsFile, largeJsContent);
117
+ });
118
+
119
+ after(async function() {
120
+ // Clean up
121
+ try {
122
+ await fs.unlink(testJsFile);
123
+ } catch (err) {
124
+ // Ignore if file doesn't exist
125
+ }
126
+ });
127
+
128
+ describe('Bundling Performance Benchmarks', function() {
129
+ it('should measure bundling performance across different file sizes', async function() {
130
+ const testCases = [
131
+ { name: 'Small', content: smallJsContent },
132
+ { name: 'Medium', content: mediumJsContent },
133
+ { name: 'Large', content: largeJsContent }
134
+ ];
135
+
136
+ const bundler = new Core_JS_Non_Minifying_Bundler_Using_ESBuild();
137
+ const results = {};
138
+
139
+ for (const testCase of testCases) {
140
+ const startTime = Date.now();
141
+ const result = await bundler.bundle_js_string(testCase.content);
142
+ const endTime = Date.now();
143
+
144
+ const bundle = result[0];
145
+ const bundledContent = bundle._arr[0].text;
146
+
147
+ results[testCase.name] = {
148
+ inputSize: testCase.content.length,
149
+ outputSize: bundledContent.length,
150
+ duration: endTime - startTime,
151
+ throughput: testCase.content.length / ((endTime - startTime) / 1000) // bytes per second
152
+ };
153
+ }
154
+
155
+ // Log results
156
+ console.log('Bundling Performance Results:');
157
+ Object.entries(results).forEach(([name, result]) => {
158
+ console.log(`${name}: ${result.duration}ms, ${result.inputSize} → ${result.outputSize} bytes, ${(result.throughput / 1024).toFixed(2)} KB/s`);
159
+ });
160
+
161
+ // Performance assertions
162
+ assert(results.Small.duration < 1000, 'Small file should bundle quickly');
163
+ assert(results.Medium.duration < 2000, 'Medium file should bundle reasonably quickly');
164
+ assert(results.Large.duration < 10000, 'Large file should bundle within reasonable time');
165
+
166
+ // Throughput should be reasonable
167
+ assert(results.Small.throughput > 1000, 'Should have reasonable throughput');
168
+ });
169
+
170
+ it('should compare minification performance at different levels', async function() {
171
+ const levels = ['conservative', 'normal', 'aggressive'];
172
+ const results = {};
173
+
174
+ for (const level of levels) {
175
+ const bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
176
+ minify: { level, enabled: true }
177
+ });
178
+
179
+ const startTime = Date.now();
180
+ const result = await bundler.bundle(largeJsContent);
181
+ const endTime = Date.now();
182
+
183
+ const bundle = result[0];
184
+ const minifiedContent = bundle._arr[0].text;
185
+
186
+ results[level] = {
187
+ duration: endTime - startTime,
188
+ inputSize: largeJsContent.length,
189
+ outputSize: minifiedContent.length,
190
+ compressionRatio: minifiedContent.length / largeJsContent.length
191
+ };
192
+ }
193
+
194
+ // Log results
195
+ console.log('Minification Performance Results:');
196
+ Object.entries(results).forEach(([level, result]) => {
197
+ console.log(`${level}: ${result.duration}ms, ${result.inputSize} → ${result.outputSize} bytes (${(result.compressionRatio * 100).toFixed(1)}%)`);
198
+ });
199
+
200
+ // Performance should be reasonable
201
+ Object.values(results).forEach(result => {
202
+ assert(result.duration < 15000, 'Minification should complete within reasonable time');
203
+ assert(result.compressionRatio < 1, 'Minification should reduce size');
204
+ });
205
+ });
206
+
207
+ it('should benchmark advanced bundling with CSS extraction', async function() {
208
+ const bundler = new Advanced_JS_Bundler_Using_ESBuild({
209
+ debug: false,
210
+ bundler: {
211
+ minify: { enabled: true, level: 'normal' }
212
+ }
213
+ });
214
+
215
+ const startTime = Date.now();
216
+ try {
217
+ const result = await bundler.bundle(testJsFile);
218
+ const endTime = Date.now();
219
+
220
+ const duration = endTime - startTime;
221
+ const bundle = result[0];
222
+ const jsItem = bundle._arr.find(item => item.type === 'JavaScript');
223
+ const cssItem = bundle._arr.find(item => item.type === 'CSS');
224
+
225
+ console.log(`Advanced bundling: ${duration}ms`);
226
+ console.log(`JS: ${largeJsContent.length} → ${jsItem.text.length} bytes`);
227
+ if (cssItem) {
228
+ console.log(`CSS extracted: ${cssItem.text.length} bytes`);
229
+ }
230
+
231
+ assert(duration < 20000, 'Advanced bundling should complete within reasonable time');
232
+ assert(jsItem, 'Should produce JavaScript bundle');
233
+ } catch (error) {
234
+ console.log(`Advanced bundling failed: ${error.message}`);
235
+ // Skip this test if advanced bundling fails
236
+ this.skip();
237
+ }
238
+ });
239
+
240
+ it('should measure concurrent bundling performance', async function() {
241
+ const bundler = new Core_JS_Non_Minifying_Bundler_Using_ESBuild();
242
+ const concurrentBundles = 5;
243
+
244
+ const startTime = Date.now();
245
+ const promises = [];
246
+
247
+ for (let i = 0; i < concurrentBundles; i++) {
248
+ promises.push(bundler.bundle_js_string(mediumJsContent));
249
+ }
250
+
251
+ await Promise.all(promises);
252
+ const endTime = Date.now();
253
+
254
+ const totalDuration = endTime - startTime;
255
+ const avgDuration = totalDuration / concurrentBundles;
256
+
257
+ console.log(`Concurrent bundling (${concurrentBundles} bundles): ${totalDuration}ms total, ${avgDuration.toFixed(2)}ms average`);
258
+
259
+ assert(totalDuration < 10000, 'Concurrent bundling should be efficient');
260
+ assert(avgDuration < 3000, 'Average bundling time should be reasonable');
261
+ });
262
+ });
263
+
264
+ describe('Compression Performance Benchmarks', function() {
265
+ let testItems;
266
+
267
+ beforeEach(function() {
268
+ // Create test items of different sizes and types
269
+ testItems = [
270
+ {
271
+ type: 'Small HTML',
272
+ extension: 'html',
273
+ text: '<!DOCTYPE html><html><body><h1>Small</h1></body></html>',
274
+ response_buffers: {}
275
+ },
276
+ {
277
+ type: 'Medium HTML',
278
+ extension: 'html',
279
+ text: '<!DOCTYPE html><html><head><title>Medium</title></head><body><h1>Medium</h1><p>' + 'Content '.repeat(500) + '</p></body></html>',
280
+ response_buffers: {}
281
+ },
282
+ {
283
+ type: 'Large HTML',
284
+ extension: 'html',
285
+ text: '<!DOCTYPE html><html><head><title>Large</title></head><body><h1>Large</h1><p>' + 'Content '.repeat(2000) + '</p></body></html>',
286
+ response_buffers: {}
287
+ },
288
+ {
289
+ type: 'JavaScript',
290
+ extension: 'js',
291
+ text: largeJsContent,
292
+ response_buffers: {}
293
+ }
294
+ ];
295
+
296
+ // Initialize identity buffers
297
+ testItems.forEach(item => {
298
+ item.response_buffers.identity = Buffer.from(item.text, 'utf8');
299
+ });
300
+ });
301
+
302
+ it('should benchmark gzip compression performance', async function() {
303
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
304
+ compression: {
305
+ enabled: true,
306
+ algorithms: ['gzip'],
307
+ gzip: { level: 6 }
308
+ }
309
+ });
310
+
311
+ const startTime = Date.now();
312
+ await assigner.assign(testItems);
313
+ const endTime = Date.now();
314
+
315
+ const duration = endTime - startTime;
316
+
317
+ console.log(`Gzip compression performance: ${duration}ms for ${testItems.length} items`);
318
+
319
+ // Calculate total sizes
320
+ const totalOriginal = testItems.reduce((sum, item) => sum + item.response_buffers.identity.length, 0);
321
+ const totalCompressed = testItems.reduce((sum, item) => item.response_buffers.gzip ? sum + item.response_buffers.gzip.length : sum, 0);
322
+ const avgCompressionRatio = totalCompressed / totalOriginal;
323
+
324
+ console.log(`Total: ${totalOriginal} → ${totalCompressed} bytes (${(avgCompressionRatio * 100).toFixed(1)}%)`);
325
+
326
+ assert(duration < 5000, 'Gzip compression should be fast');
327
+ assert(avgCompressionRatio < 0.8, 'Should achieve reasonable compression');
328
+ });
329
+
330
+ it('should benchmark brotli compression performance', async function() {
331
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
332
+ compression: {
333
+ enabled: true,
334
+ algorithms: ['br'],
335
+ brotli: { quality: 6 }
336
+ }
337
+ });
338
+
339
+ const startTime = Date.now();
340
+ await assigner.assign(testItems);
341
+ const endTime = Date.now();
342
+
343
+ const duration = endTime - startTime;
344
+
345
+ console.log(`Brotli compression performance: ${duration}ms for ${testItems.length} items`);
346
+
347
+ // Calculate total sizes
348
+ const totalOriginal = testItems.reduce((sum, item) => sum + item.response_buffers.identity.length, 0);
349
+ const totalCompressed = testItems.reduce((sum, item) => item.response_buffers.br ? sum + item.response_buffers.br.length : sum, 0);
350
+ const avgCompressionRatio = totalCompressed / totalOriginal;
351
+
352
+ console.log(`Total: ${totalOriginal} → ${totalCompressed} bytes (${(avgCompressionRatio * 100).toFixed(1)}%)`);
353
+
354
+ assert(duration < 10000, 'Brotli compression should complete reasonably quickly');
355
+ assert(avgCompressionRatio < 0.8, 'Should achieve good compression');
356
+ });
357
+
358
+ it('should compare gzip vs brotli performance', async function() {
359
+ const gzipAssigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
360
+ compression: {
361
+ enabled: true,
362
+ algorithms: ['gzip']
363
+ }
364
+ });
365
+
366
+ const brotliAssigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
367
+ compression: {
368
+ enabled: true,
369
+ algorithms: ['br']
370
+ }
371
+ });
372
+
373
+ // Test gzip
374
+ const gzipStart = Date.now();
375
+ await gzipAssigner.assign(testItems);
376
+ const gzipEnd = Date.now();
377
+
378
+ // Test brotli
379
+ const brotliStart = Date.now();
380
+ await brotliAssigner.assign(testItems);
381
+ const brotliEnd = Date.now();
382
+
383
+ const gzipDuration = gzipEnd - gzipStart;
384
+ const brotliDuration = brotliEnd - brotliStart;
385
+
386
+ console.log(`Gzip: ${gzipDuration}ms, Brotli: ${brotliDuration}ms`);
387
+
388
+ // Calculate compression ratios
389
+ const totalOriginal = testItems.reduce((sum, item) => sum + item.response_buffers.identity.length, 0);
390
+ const gzipTotal = testItems.reduce((sum, item) => item.response_buffers.gzip ? sum + item.response_buffers.gzip.length : sum, 0);
391
+ const brotliTotal = testItems.reduce((sum, item) => item.response_buffers.br ? sum + item.response_buffers.br.length : sum, 0);
392
+
393
+ console.log(`Gzip ratio: ${(gzipTotal / totalOriginal * 100).toFixed(1)}%`);
394
+ console.log(`Brotli ratio: ${(brotliTotal / totalOriginal * 100).toFixed(1)}%`);
395
+
396
+ // Brotli typically takes longer but compresses better
397
+ assert(gzipDuration > 0 && brotliDuration > 0, 'Both algorithms should take some time');
398
+ });
399
+
400
+ it('should test compression threshold performance impact', async function() {
401
+ const thresholds = [0, 512, 2048, 8192]; // Different threshold sizes
402
+ const results = {};
403
+
404
+ for (const threshold of thresholds) {
405
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
406
+ compression: {
407
+ enabled: true,
408
+ algorithms: ['gzip'],
409
+ threshold: threshold
410
+ }
411
+ });
412
+
413
+ const startTime = Date.now();
414
+ await assigner.assign(testItems);
415
+ const endTime = Date.now();
416
+
417
+ const compressedCount = testItems.filter(item => item.response_buffers.gzip).length;
418
+
419
+ results[threshold] = {
420
+ duration: endTime - startTime,
421
+ compressedCount: compressedCount,
422
+ totalItems: testItems.length
423
+ };
424
+ }
425
+
426
+ console.log('Compression threshold performance:');
427
+ Object.entries(results).forEach(([threshold, result]) => {
428
+ console.log(`Threshold ${threshold}: ${result.duration}ms, ${result.compressedCount}/${result.totalItems} compressed`);
429
+ });
430
+
431
+ // Lower thresholds should result in more compression
432
+ assert(results[0].compressedCount >= results[8192].compressedCount,
433
+ 'Lower threshold should compress more items');
434
+ });
435
+ });
436
+
437
+ describe('End-to-End Server Performance', function() {
438
+ let server;
439
+ let serverPort = 3002;
440
+
441
+ after(async function() {
442
+ if (server) {
443
+ await server.stop();
444
+ }
445
+ });
446
+
447
+ it('should measure server startup performance', async function() {
448
+ const startTime = Date.now();
449
+
450
+ server = new Server();
451
+ try {
452
+ await server.serve({
453
+ ctrl: class TestControl {
454
+ all_html_render() {
455
+ return Promise.resolve(`<!DOCTYPE html>
456
+ <html>
457
+ <head><title>Test</title></head>
458
+ <body><h1>Test Control</h1></body>
459
+ </html>`);
460
+ }
461
+ },
462
+ port: serverPort,
463
+ debug: false,
464
+ bundler: {
465
+ minify: { enabled: true },
466
+ compression: { enabled: true }
467
+ }
468
+ });
469
+
470
+ const endTime = Date.now();
471
+ const startupTime = endTime - startTime;
472
+
473
+ console.log(`Server startup time: ${startupTime}ms`);
474
+
475
+ assert(startupTime < 10000, 'Server should start within reasonable time');
476
+
477
+ // Clean up
478
+ await server.stop();
479
+ server = null;
480
+ } catch (error) {
481
+ console.log(`Server startup failed: ${error.message}`);
482
+ // Skip this test if server startup fails
483
+ this.skip();
484
+ }
485
+ });
486
+
487
+ it('should benchmark response times for different configurations', async function() {
488
+ const configurations = [
489
+ { name: 'No compression', compression: false, minify: false },
490
+ { name: 'Gzip only', compression: { enabled: true, algorithms: ['gzip'] }, minify: false },
491
+ { name: 'Brotli only', compression: { enabled: true, algorithms: ['br'] }, minify: false },
492
+ { name: 'Full optimization', compression: { enabled: true, algorithms: ['gzip', 'br'] }, minify: true }
493
+ ];
494
+
495
+ const results = {};
496
+
497
+ for (const config of configurations) {
498
+ server = new Server();
499
+ try {
500
+ await server.serve({
501
+ ctrl: class TestControl {
502
+ all_html_render() {
503
+ return Promise.resolve(`<!DOCTYPE html>
504
+ <html>
505
+ <head><title>Test</title></head>
506
+ <body>
507
+ <h1>Test Control</h1>
508
+ <script>
509
+ // Large script to test compression
510
+ const data = [];
511
+ for (let i = 0; i < 1000; i++) {
512
+ data.push({ id: i, value: Math.random(), name: 'Item' + i });
513
+ }
514
+ console.log('Data loaded:', data.length);
515
+ </script>
516
+ </body>
517
+ </html>`);
518
+ }
519
+ },
520
+ port: serverPort,
521
+ debug: false,
522
+ bundler: {
523
+ minify: config.minify ? { enabled: true, level: 'normal' } : { enabled: false },
524
+ compression: config.compression
525
+ }
526
+ });
527
+
528
+ // Wait for server to be ready
529
+ await new Promise(resolve => setTimeout(resolve, 1000));
530
+
531
+ // Measure response time
532
+ const responseStart = Date.now();
533
+ const response = await makeRequest(`http://localhost:${serverPort}/`, {
534
+ 'Accept-Encoding': config.name.includes('Gzip') ? 'gzip' :
535
+ config.name.includes('Brotli') ? 'br' : 'identity'
536
+ });
537
+ const responseEnd = Date.now();
538
+
539
+ results[config.name] = {
540
+ responseTime: responseEnd - responseStart,
541
+ statusCode: response.statusCode,
542
+ contentLength: response.body.length,
543
+ contentEncoding: response.headers['content-encoding']
544
+ };
545
+
546
+ await server.stop();
547
+ server = null;
548
+ } catch (error) {
549
+ console.log(`Configuration ${config.name} failed: ${error.message}`);
550
+ results[config.name] = { error: error.message };
551
+ if (server) {
552
+ try {
553
+ await server.stop();
554
+ } catch (e) {
555
+ // Ignore cleanup errors
556
+ }
557
+ server = null;
558
+ }
559
+ }
560
+ }
561
+
562
+ console.log('Server response performance:');
563
+ Object.entries(results).forEach(([name, result]) => {
564
+ if (result.error) {
565
+ console.log(`${name}: Failed - ${result.error}`);
566
+ } else {
567
+ console.log(`${name}: ${result.responseTime}ms, ${result.contentLength} bytes, encoding: ${result.contentEncoding || 'none'}`);
568
+ }
569
+ });
570
+
571
+ // Check successful responses
572
+ const successfulResults = Object.values(results).filter(result => !result.error);
573
+ successfulResults.forEach(result => {
574
+ assert.strictEqual(result.statusCode, 200, 'Successful responses should have status 200');
575
+ assert(result.responseTime < 5000, 'Successful responses should be reasonably fast');
576
+ });
577
+ });
578
+ });
579
+
580
+ describe('Memory Usage Analysis', function() {
581
+ it('should monitor memory usage during bundling operations', async function() {
582
+ const bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
583
+ minify: { enabled: true, level: 'aggressive' }
584
+ });
585
+
586
+ const initialMemory = process.memoryUsage();
587
+
588
+ // Perform multiple bundling operations
589
+ for (let i = 0; i < 10; i++) {
590
+ await bundler.bundle(largeJsContent);
591
+ }
592
+
593
+ const finalMemory = process.memoryUsage();
594
+
595
+ const memoryIncrease = {
596
+ rss: finalMemory.rss - initialMemory.rss,
597
+ heapUsed: finalMemory.heapUsed - initialMemory.heapUsed,
598
+ heapTotal: finalMemory.heapTotal - initialMemory.heapTotal
599
+ };
600
+
601
+ console.log('Memory usage after bundling operations:');
602
+ console.log(`RSS: ${memoryIncrease.rss / 1024 / 1024} MB`);
603
+ console.log(`Heap Used: ${memoryIncrease.heapUsed / 1024 / 1024} MB`);
604
+ console.log(`Heap Total: ${memoryIncrease.heapTotal / 1024 / 1024} MB`);
605
+
606
+ // Memory usage should be reasonable
607
+ assert(memoryIncrease.heapUsed < 50 * 1024 * 1024, 'Memory usage should be reasonable (< 50MB increase)');
608
+ });
609
+ });
610
+ });
611
+
612
+ // Helper function for HTTP requests (simplified version for performance tests)
613
+ function makeRequest(url, headers = {}) {
614
+ return new Promise((resolve, reject) => {
615
+ const http = require('http');
616
+ const parsedUrl = new URL(url);
617
+
618
+ const options = {
619
+ hostname: parsedUrl.hostname,
620
+ port: parsedUrl.port,
621
+ path: parsedUrl.pathname,
622
+ method: 'GET',
623
+ headers: {
624
+ 'User-Agent': 'JSGUI3-Performance-Test/1.0',
625
+ ...headers
626
+ }
627
+ };
628
+
629
+ const req = http.request(options, (res) => {
630
+ let body = Buffer.alloc(0);
631
+
632
+ res.on('data', (chunk) => {
633
+ body = Buffer.concat([body, chunk]);
634
+ });
635
+
636
+ res.on('end', () => {
637
+ resolve({
638
+ statusCode: res.statusCode,
639
+ headers: res.headers,
640
+ body: body
641
+ });
642
+ });
643
+ });
644
+
645
+ req.on('error', reject);
646
+ req.setTimeout(10000, () => {
647
+ req.destroy();
648
+ reject(new Error('Request timeout'));
649
+ });
650
+
651
+ req.end();
652
+ });
653
+ }