koa-classic-server 3.0.0 → 3.1.0

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 (105) hide show
  1. package/README.md +44 -120
  2. package/index.cjs +236 -21
  3. package/package.json +10 -5
  4. package/.github/workflows/npm-publish.yml +0 -98
  5. package/CLAUDE.md +0 -101
  6. package/__tests__/benchmark-results-baseline-v1.2.0.txt +0 -354
  7. package/__tests__/benchmark-results-optimized-v2.0.0.txt +0 -354
  8. package/__tests__/benchmark-results-v3.0.0.txt +0 -372
  9. package/__tests__/benchmark.js +0 -239
  10. package/__tests__/caching-headers.test.js +0 -556
  11. package/__tests__/compression-fixtures/data.json +0 -1
  12. package/__tests__/compression-fixtures/large.txt +0 -1
  13. package/__tests__/compression-fixtures/small.txt +0 -1
  14. package/__tests__/compression.test.js +0 -284
  15. package/__tests__/customTest/README.md +0 -6
  16. package/__tests__/customTest/loadConfig.util.js +0 -41
  17. package/__tests__/customTest/serversToLoad.util.js +0 -93
  18. package/__tests__/demo-regex-index.js +0 -140
  19. package/__tests__/deprecation-warnings.test.js +0 -105
  20. package/__tests__/directory-sorting-links.test.js +0 -135
  21. package/__tests__/dt-unknown.test.js +0 -635
  22. package/__tests__/ejs.test.js +0 -299
  23. package/__tests__/hidden-fixtures/.dot-dir/inside.txt +0 -1
  24. package/__tests__/hidden-fixtures/.env +0 -2
  25. package/__tests__/hidden-fixtures/.well-known/acme-challenge.txt +0 -1
  26. package/__tests__/hidden-fixtures/config/secrets/password.txt +0 -1
  27. package/__tests__/hidden-fixtures/data.key +0 -1
  28. package/__tests__/hidden-fixtures/file.secret +0 -1
  29. package/__tests__/hidden-fixtures/index.html +0 -1
  30. package/__tests__/hidden-fixtures/normal.txt +0 -1
  31. package/__tests__/hidden-fixtures/subdir/.env +0 -1
  32. package/__tests__/hidden-fixtures/subdir/regular.txt +0 -1
  33. package/__tests__/hidden-option.test.js +0 -407
  34. package/__tests__/hideExtension.test.js +0 -607
  35. package/__tests__/index-option.test.js +0 -449
  36. package/__tests__/index.test.js +0 -345
  37. package/__tests__/listing.test.js +0 -437
  38. package/__tests__/logger.test.js +0 -232
  39. package/__tests__/performance.test.js +0 -370
  40. package/__tests__/publicWwwTest/cartella/sottocartella/ciao.html +0 -11
  41. package/__tests__/publicWwwTest/cartella/sottocartella/provaEjs/testEjs.ejs +0 -11
  42. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome/file con spazio nel nome .txt +0 -1
  43. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome /file con spazio nel nome .txt +0 -1
  44. package/__tests__/publicWwwTest/ejs-templates/complex.ejs +0 -56
  45. package/__tests__/publicWwwTest/ejs-templates/index.ejs +0 -30
  46. package/__tests__/publicWwwTest/ejs-templates/simple.ejs +0 -13
  47. package/__tests__/publicWwwTest/ejs-templates/with-conditional.ejs +0 -28
  48. package/__tests__/publicWwwTest/ejs-templates/with-escaping.ejs +0 -26
  49. package/__tests__/publicWwwTest/ejs-templates/with-loop.ejs +0 -16
  50. package/__tests__/publicWwwTest/hideext-test/about/index.html +0 -1
  51. package/__tests__/publicWwwTest/hideext-test/about.EJS +0 -1
  52. package/__tests__/publicWwwTest/hideext-test/about.ejs +0 -2
  53. package/__tests__/publicWwwTest/hideext-test/blog/articolo.ejs +0 -2
  54. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina +0 -1
  55. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina.ejs +0 -1
  56. package/__tests__/publicWwwTest/hideext-test/file.ejs.bak +0 -1
  57. package/__tests__/publicWwwTest/hideext-test/index.ejs +0 -2
  58. package/__tests__/publicWwwTest/hideext-test/photo.txt +0 -1
  59. package/__tests__/publicWwwTest/hideext-test/sezione/index.ejs +0 -1
  60. package/__tests__/publicWwwTest/hideext-test/style.css +0 -1
  61. package/__tests__/publicWwwTest/ile_vuoto.txt +0 -0
  62. package/__tests__/publicWwwTest/index.html +0 -11
  63. package/__tests__/publicWwwTest/prova file .txt +0 -2
  64. package/__tests__/publicWwwTest/semplicetxt.txt +0 -1
  65. package/__tests__/publicWwwTest/test-page.html +0 -1
  66. package/__tests__/publicWwwTest/test.txt +0 -1
  67. package/__tests__/range-fixtures/sample.txt +0 -1
  68. package/__tests__/range.test.js +0 -223
  69. package/__tests__/security-headers.test.js +0 -165
  70. package/__tests__/security.test.js +0 -322
  71. package/__tests__/server-cache-fixtures/large.txt +0 -1
  72. package/__tests__/server-cache-fixtures/small.txt +0 -1
  73. package/__tests__/server-cache.test.js +0 -594
  74. package/__tests__/setup-benchmark.js +0 -178
  75. package/__tests__/symlink.test.js +0 -441
  76. package/__tests__/template-timeout.test.js +0 -321
  77. package/__tests__/test-regex-quick.js +0 -158
  78. package/__tests__/useOriginalUrl.test.js +0 -213
  79. package/docs/ACTION_PLAN.md +0 -293
  80. package/docs/BENCHMARKS.md +0 -317
  81. package/docs/CHANGELOG.md +0 -880
  82. package/docs/CODE_REVIEW.md +0 -300
  83. package/docs/DEBUG_REPORT.md +0 -593
  84. package/docs/DOCUMENTATION.md +0 -1864
  85. package/docs/EXAMPLES_INDEX_OPTION.md +0 -395
  86. package/docs/FLOW_DIAGRAM.md +0 -954
  87. package/docs/INDEX_OPTION_PRIORITY.md +0 -527
  88. package/docs/OPTIMIZATION_HTTP_CACHING.md +0 -689
  89. package/docs/OPTIMIZATION_ROADMAP_for_V3.md +0 -864
  90. package/docs/PERFORMANCE_ANALYSIS.md +0 -839
  91. package/docs/PERFORMANCE_COMPARISON.md +0 -388
  92. package/docs/noteExports.md +0 -148
  93. package/docs/security_improvement_for_V3.md +0 -421
  94. package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +0 -1734
  95. package/docs/template-engine/esempi-incrementali.js +0 -192
  96. package/docs/template-engine/examples/esempio1-nessun-dato.ejs +0 -12
  97. package/docs/template-engine/examples/esempio2-una-variabile.ejs +0 -11
  98. package/docs/template-engine/examples/esempio3-piu-variabili.ejs +0 -15
  99. package/docs/template-engine/examples/esempio4-condizionale.ejs +0 -18
  100. package/docs/template-engine/examples/esempio5-loop.ejs +0 -18
  101. package/docs/template-engine/examples/index-esempi.html +0 -181
  102. package/docs/template-engine/examples/index.html +0 -40
  103. package/docs/template-engine/examples/test.ejs +0 -64
  104. package/eslint.config.mjs +0 -17
  105. package/jest.config.js +0 -18
@@ -1,299 +0,0 @@
1
- const Koa = require('koa');
2
- const koaClassicServer = require('../index.cjs');
3
- const supertest = require('supertest');
4
- const path = require('path');
5
- const fs = require('fs');
6
- const ejs = require('ejs');
7
-
8
- describe('EJS Template Engine Integration Tests', () => {
9
- let app;
10
- let server;
11
- let request;
12
-
13
- beforeAll(() => {
14
- app = new Koa();
15
-
16
- const rootDir = path.join(__dirname, 'publicWwwTest');
17
-
18
- // Configure koaClassicServer with EJS template support
19
- app.use(
20
- koaClassicServer(rootDir, {
21
- method: ['GET'],
22
- dirListing: { enabled: true },
23
- template: {
24
- ext: ['ejs'],
25
- render: async (ctx, next, filePath) => {
26
- // Read the template file
27
- const templateContent = await fs.promises.readFile(filePath, 'utf-8');
28
-
29
- // Prepare data for different templates
30
- const data = getTemplateData(filePath);
31
-
32
- // Render with EJS
33
- const html = ejs.render(templateContent, data);
34
-
35
- ctx.type = 'text/html';
36
- ctx.body = html;
37
- }
38
- }
39
- })
40
- );
41
-
42
- server = app.listen();
43
- request = supertest(server);
44
- });
45
-
46
- afterAll(() => {
47
- if (server) {
48
- server.close();
49
- }
50
- });
51
-
52
- // Helper function to provide data for each template
53
- function getTemplateData(filePath) {
54
- const basename = path.basename(filePath, '.ejs');
55
-
56
- const dataMap = {
57
- 'simple': {
58
- title: 'Simple EJS Test',
59
- heading: 'Hello from EJS',
60
- message: 'This is a simple template test',
61
- timestamp: '2025-11-18'
62
- },
63
- 'with-loop': {
64
- items: [
65
- { name: 'Item 1', value: 100 },
66
- { name: 'Item 2', value: 200 },
67
- { name: 'Item 3', value: 300 }
68
- ]
69
- },
70
- 'with-conditional': {
71
- isLoggedIn: true,
72
- username: 'TestUser',
73
- role: 'admin',
74
- notifications: 5
75
- },
76
- 'with-escaping': {
77
- userInput: '<script>alert("XSS")</script>',
78
- htmlContent: '<strong>Bold text</strong>',
79
- safeText: 'Plain & safe text',
80
- allowedHtml: '<em>Emphasized text</em>'
81
- },
82
- 'complex': {
83
- pageTitle: 'E-Commerce Products',
84
- user: {
85
- name: 'Mario Rossi'
86
- },
87
- products: [
88
- {
89
- id: 1,
90
- name: 'Laptop',
91
- description: 'High-performance laptop',
92
- price: 999.99,
93
- discount: 10,
94
- inStock: true
95
- },
96
- {
97
- id: 2,
98
- name: 'Mouse',
99
- description: 'Wireless mouse',
100
- price: 29.99,
101
- discount: 0,
102
- inStock: true
103
- },
104
- {
105
- id: 3,
106
- name: 'Keyboard',
107
- description: 'Mechanical keyboard',
108
- price: 149.99,
109
- discount: 15,
110
- inStock: false
111
- }
112
- ]
113
- },
114
- 'testEjs': {
115
- // For the existing test file
116
- }
117
- };
118
-
119
- return dataMap[basename] || {};
120
- }
121
-
122
- describe('Simple Template - simple.ejs', () => {
123
- test('Should render simple template with variables', async () => {
124
- const response = await request.get('/ejs-templates/simple.ejs');
125
-
126
- expect(response.status).toBe(200);
127
- expect(response.type).toBe('text/html');
128
- expect(response.text).toContain('Simple EJS Test');
129
- expect(response.text).toContain('Hello from EJS');
130
- expect(response.text).toContain('This is a simple template test');
131
- expect(response.text).toContain('2025-11-18');
132
- });
133
- });
134
-
135
- describe('Loop Template - with-loop.ejs', () => {
136
- test('Should render template with forEach loop', async () => {
137
- const response = await request.get('/ejs-templates/with-loop.ejs');
138
-
139
- expect(response.status).toBe(200);
140
- expect(response.text).toContain('Lista di Items');
141
- expect(response.text).toContain('Item 1 - 100');
142
- expect(response.text).toContain('Item 2 - 200');
143
- expect(response.text).toContain('Item 3 - 300');
144
- expect(response.text).toContain('Totale items: 3');
145
- expect(response.text).toContain('data-index="0"');
146
- expect(response.text).toContain('data-index="1"');
147
- expect(response.text).toContain('data-index="2"');
148
- });
149
- });
150
-
151
- describe('Conditional Template - with-conditional.ejs', () => {
152
- test('Should render template with if/else conditionals (logged in)', async () => {
153
- const response = await request.get('/ejs-templates/with-conditional.ejs');
154
-
155
- expect(response.status).toBe(200);
156
- expect(response.text).toContain('Benvenuto, TestUser!');
157
- expect(response.text).toContain('Ruolo: admin');
158
- expect(response.text).toContain('Hai 5 nuove notifiche');
159
- // Should NOT contain guest panel
160
- expect(response.text).not.toContain('Benvenuto, ospite!');
161
- });
162
- });
163
-
164
- describe('Escaping Template - with-escaping.ejs', () => {
165
- test('Should properly escape HTML in <%= %> tags', async () => {
166
- const response = await request.get('/ejs-templates/with-escaping.ejs');
167
-
168
- expect(response.status).toBe(200);
169
-
170
- // HTML should be escaped (safe)
171
- // Note: EJS uses &#34; instead of &quot; for quotes
172
- expect(response.text).toContain('&lt;script&gt;alert(&#34;XSS&#34;)&lt;/script&gt;');
173
-
174
- // HTML should NOT be escaped (unsafe - unescaped output)
175
- expect(response.text).toContain('<strong>Bold text</strong>');
176
-
177
- // Safe text with & should be escaped
178
- expect(response.text).toContain('Plain &amp; safe text');
179
-
180
- // Allowed HTML should be rendered
181
- expect(response.text).toContain('<em>Emphasized text</em>');
182
- });
183
-
184
- test('Should protect against XSS attacks', async () => {
185
- const response = await request.get('/ejs-templates/with-escaping.ejs');
186
-
187
- // The escaped section should not contain executable script tags
188
- const escapedSection = response.text.match(/<div class="escaped">[\s\S]*?<\/div>/)[0];
189
- expect(escapedSection).not.toContain('<script>');
190
- expect(escapedSection).toContain('&lt;script&gt;');
191
- });
192
- });
193
-
194
- describe('Complex Template - complex.ejs', () => {
195
- test('Should render complex template with all features', async () => {
196
- const response = await request.get('/ejs-templates/complex.ejs');
197
-
198
- expect(response.status).toBe(200);
199
-
200
- // Page title
201
- expect(response.text).toContain('E-Commerce Products');
202
-
203
- // User greeting
204
- expect(response.text).toContain('Ciao, Mario Rossi!');
205
-
206
- // Products list
207
- expect(response.text).toContain('Laptop');
208
- expect(response.text).toContain('High-performance laptop');
209
- expect(response.text).toContain('€999.99');
210
-
211
- // Discount calculation
212
- expect(response.text).toContain('Sconto: 10%');
213
- expect(response.text).toContain('€899.99'); // 999.99 - 10%
214
-
215
- // Mouse without discount
216
- expect(response.text).toContain('Mouse');
217
- expect(response.text).toContain('€29.99');
218
-
219
- // Keyboard out of stock
220
- expect(response.text).toContain('Keyboard');
221
- expect(response.text).toContain('Non disponibile');
222
-
223
- // Total count
224
- expect(response.text).toContain('Totale prodotti: 3');
225
- });
226
-
227
- test('Should have correct product data attributes', async () => {
228
- const response = await request.get('/ejs-templates/complex.ejs');
229
-
230
- expect(response.text).toContain('data-id="1"');
231
- expect(response.text).toContain('data-id="2"');
232
- expect(response.text).toContain('data-id="3"');
233
- });
234
-
235
- test('Should show "Add to cart" button only for in-stock items', async () => {
236
- const response = await request.get('/ejs-templates/complex.ejs');
237
-
238
- // Count "Aggiungi al carrello" buttons - should be 2 (Laptop and Mouse)
239
- const buttonMatches = response.text.match(/Aggiungi al carrello/g);
240
- expect(buttonMatches).toHaveLength(2);
241
-
242
- // Count "Non disponibile" - should be 1 (Keyboard)
243
- const outOfStockMatches = response.text.match(/Non disponibile/g);
244
- expect(outOfStockMatches).toHaveLength(1);
245
- });
246
- });
247
-
248
- describe('Index Template - index.ejs', () => {
249
- test('Should render index page with links', async () => {
250
- const response = await request.get('/ejs-templates/index.ejs');
251
-
252
- expect(response.status).toBe(200);
253
- expect(response.text).toContain('Test Templates EJS');
254
- expect(response.text).toContain('simple.ejs');
255
- expect(response.text).toContain('with-loop.ejs');
256
- expect(response.text).toContain('with-conditional.ejs');
257
- expect(response.text).toContain('with-escaping.ejs');
258
- expect(response.text).toContain('complex.ejs');
259
- });
260
- });
261
-
262
- describe('Existing EJS file - testEjs.ejs', () => {
263
- test('Should render existing testEjs.ejs file', async () => {
264
- const response = await request.get('/cartella/sottocartella/provaEjs/testEjs.ejs');
265
-
266
- expect(response.status).toBe(200);
267
- expect(response.type).toBe('text/html');
268
- expect(response.text).toContain('<h1>hello world</h1>');
269
- });
270
- });
271
-
272
- describe('Error Handling', () => {
273
- test('Should return 404 for non-existent .ejs file', async () => {
274
- const response = await request.get('/ejs-templates/non-existent.ejs');
275
-
276
- expect(response.status).toBe(404);
277
- });
278
- });
279
-
280
- describe('Performance', () => {
281
- test('Should render complex template in reasonable time', async () => {
282
- const start = Date.now();
283
- const response = await request.get('/ejs-templates/complex.ejs');
284
- const duration = Date.now() - start;
285
-
286
- expect(response.status).toBe(200);
287
- expect(duration).toBeLessThan(100); // Should render in less than 100ms
288
- });
289
-
290
- test('Should render simple template very quickly', async () => {
291
- const start = Date.now();
292
- const response = await request.get('/ejs-templates/simple.ejs');
293
- const duration = Date.now() - start;
294
-
295
- expect(response.status).toBe(200);
296
- expect(duration).toBeLessThan(50); // Should render in less than 50ms
297
- });
298
- });
299
- });
@@ -1 +0,0 @@
1
- dot dir file
@@ -1,2 +0,0 @@
1
- SECRET_KEY=mysecretvalue
2
- DB_PASSWORD=hidden123
@@ -1 +0,0 @@
1
- key data
@@ -1 +0,0 @@
1
- secret data
@@ -1 +0,0 @@
1
- regular
@@ -1 +0,0 @@
1
- normal
@@ -1 +0,0 @@
1
- NESTED_SECRET=nestedvalue
@@ -1 +0,0 @@
1
- regular in subdir