koa-classic-server 1.0.6 → 1.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.
@@ -0,0 +1,26 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Attach by Process ID",
9
+ "processId": "${command:PickProcess}",
10
+ "request": "attach",
11
+ "skipFiles": [
12
+ "<node_internals>/**"
13
+ ],
14
+ "type": "node"
15
+ },
16
+ {
17
+ "type": "node",
18
+ "request": "launch",
19
+ "name": "Launch Program",
20
+ "skipFiles": [
21
+ "<node_internals>/**"
22
+ ],
23
+ "program": "${workspaceFolder}/index.cjs"
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Attach by Process ID",
6
+ "processId": "${command:PickProcess}",
7
+ "request": "attach",
8
+ "skipFiles": [
9
+ "<node_internals>/**"
10
+ ],
11
+ "type": "node"
12
+ },
13
+ {
14
+ "type": "node",
15
+ "request": "launch",
16
+ "name": "Launch Program",
17
+ "skipFiles": [
18
+ "<node_internals>/**"
19
+ ],
20
+ "program": "${workspaceFolder}/index.cjs"
21
+ },
22
+ {
23
+ "name": "Debug Jest Tests",
24
+ "type": "node",
25
+ "request": "launch",
26
+ "runtimeExecutable": "node",
27
+ "runtimeArgs": [
28
+ "--inspect-brk",
29
+ "${workspaceFolder}/node_modules/jest/bin/jest.js",
30
+ "--runInBand"
31
+ ],
32
+ "port": 9229,
33
+ "console": "integratedTerminal",
34
+ "internalConsoleOptions": "neverOpen",
35
+ "skipFiles": [
36
+ "<node_internals>/**"
37
+ ]
38
+ }
39
+ ]
40
+ }
41
+
package/README.md CHANGED
@@ -41,6 +41,10 @@ next import
41
41
  ```js
42
42
  const koaClassicServer = require('koa-classic-server');
43
43
  ```
44
+ or
45
+ ```js
46
+ import koaClassicServer from "koa-classic-server";
47
+ '''
44
48
 
45
49
  ## API
46
50
 
@@ -0,0 +1,337 @@
1
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // ATTENZIONE QUESTO TEST NON COPRE SE NEL VISUALIZARE IL CONTENUTO DELLE CARTELLE TUTTO VIENE MOSTRATO COME SI DEVE
4
+ // ATTENZIONE MANCA IL TEST PER TESTARE I MOTORI DI RENDERING COME .ejs
5
+ // ERRORI NOTI:
6
+ // 1)QUANDO UNA RISORSA NON VIENE TROVATA IN UNA CARTELLO LO STATO NON È SETTATO SU 404 MA SU 200
7
+ // 2)IL PERCORSO RISERVATO UNZIONA SOLO SE NON VI SONO SPAZI NEL NOME
8
+ // FURURES:
9
+ // A) IMPLEMENTARE UNA ARRAY DI FILE INDEX ,MAGAI DANDO LA POSSIBILITA DI NON DISTINGURE FRA MINUSCOLE EMAIUSCOLE
10
+ //
11
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
12
+
13
+
14
+ const supertest = require('supertest');
15
+ const koaClassicServer = require('../index.cjs');
16
+ const Koa = require('koa');
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const mime = require('mime-types'); //serve alla funzione getFilesRecursivelySync();
20
+ //const {configurations} = require('../customTest/serversToLoad.util'); --> inutile questo serve solo per testari manualmente
21
+
22
+ const rootDir = path.join(__dirname, 'publicWwwTest');
23
+
24
+ // Legge tutti i file ricorsivamente e li memorizza in un array
25
+ const filesAndDirArray = getFilesRecursivelySync(rootDir);
26
+
27
+ // Visualizza l'array risultante
28
+ //console.log(filesAndDirArray);
29
+
30
+ //START option0
31
+
32
+ // Configuriamo le opzioni per koa-classic-server
33
+ const options0 = {
34
+ urlPrefix: '/public', // Il prefisso URL che il middleware dovrà intercettare
35
+ method: ['GET'],// I metodi HTTP ammessi (default 'GET')
36
+ showDirContents: true,// Se mostrare il contenuto della directory in caso di richiesta ad una cartella
37
+ //index: 'index.html', // Nome del file index da cercare all'interno di una directory (se presente)
38
+ };
39
+
40
+ describe(` koaClassicServer options0: ${JSON.stringify(options0)}`, () => {
41
+ let app;
42
+ let server;
43
+
44
+ // Avvia il server prima di eseguire i test
45
+ beforeAll(() => {
46
+ app = new Koa();
47
+ app.use(koaClassicServer(rootDir, options0)); // Monta il middleware
48
+ server = app.listen();// Avvia il server in modo che Supertest possa inviare richieste HTTP
49
+ });
50
+
51
+ test('controllo che se chiamo un percorso che non esiste mi venga restituito l\'errore apropiato ', async () => {
52
+ // Effettua una richiesta GET sull'endpoint configurato (il prefisso)
53
+ const res = await supertest(server).get('/public/percorso_di_una_cartella_o_file_che_non_esiste_fbrojngbornbo/gbrtbbbrbr/tbrbr/rtbrtbrt');
54
+ expect(res.status).toBe(200);
55
+ expect(res.type).toMatch(/text\/html/);// type sta per mimetype .... restituisce text/plain anche se dovrebbe essere text/html
56
+ expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
57
+ });
58
+
59
+ test('controllo che se l\'indirizzo non ricade nel urlPrefix allora debba essere passato al midlware successivo e se non c\'e allora errore 404 not founf', async () => {
60
+ // Effettua una richiesta GET sull'endpoint configurato (il prefisso)
61
+ const res = await supertest(server).get('/percorso al di fuori di url prefix public/gbrtbbbrbr/tbrbr/rtbrtbrt');
62
+ expect(res.status).toBe(404);
63
+ expect(res.type).toMatch("text/plain");// type sta per mimetype .... restituisce text/plain anche se dovrebbe essere text/html
64
+ expect(res.text.replace(/\s/g, '')).toBe("Not Found".replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
65
+ });
66
+
67
+
68
+ // queste rige generaranno test per ogni ile presente nella cartella di test
69
+ const testFnCallbacks = testAllPathByFileList(filesAndDirArray, () => server, options0);//Genera l'array di callback per i test
70
+ testFnCallbacks.forEach(cb => cb());// Esegui ogni callback per registrare il test nello scope del describe
71
+
72
+ afterAll(() => {// Chiude il server dopo aver completato tutti i test
73
+ server.close();
74
+ });
75
+ });
76
+
77
+ //END option0
78
+
79
+ //START option1
80
+ const options1 = {
81
+ method: ['GET'],
82
+ showDirContents: true,
83
+ };
84
+
85
+ describe(` koaClassicServer options1: ${JSON.stringify(options1)}`, () => {
86
+ let app;
87
+ let server;
88
+
89
+ // Avvia il server prima di eseguire i test
90
+ beforeAll(() => {
91
+ app = new Koa();
92
+ app.use(koaClassicServer(rootDir, options1)); // Monta il middleware
93
+ server = app.listen();// Avvia il server in modo che Supertest possa inviare richieste HTTP
94
+ });
95
+
96
+ test('controllo che se chiamo un percorso che non esiste mi venga restituito l\'errore apropiato [ANCHE SENZA URL PREFIX] ', async () => {
97
+ // Effettua una richiesta GET sull'endpoint configurato (il prefisso)
98
+ const res = await supertest(server).get('/BTBg h gh /percorso_di_una_cartella_o_file_che_non_esiste_fbrojngbornbo/gbrtbbbrbr/tbrbr/rtbrtbrt');
99
+ expect(res.status).toBe(200);
100
+ expect(res.type).toMatch(/text\/html/);// type sta per mimetype .... restituisce text/plain anche se dovrebbe essere text/html
101
+ expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
102
+ });
103
+
104
+ const testFnCallbacks = testAllPathByFileList(filesAndDirArray, () => server, options1);//Genera l'array di callback per i test
105
+ testFnCallbacks.forEach(cb => cb());// Esegui ogni callback per registrare il test nello scope del describe
106
+
107
+ afterAll(() => {// Chiude il server dopo aver completato tutti i test
108
+ server.close();
109
+ });
110
+ });
111
+
112
+ //END option1
113
+
114
+ //STASRT option2
115
+ const options2 = {
116
+ method: ['GET'],
117
+ showDirContents: false,
118
+ index: 'index.html',
119
+ };
120
+
121
+ describe(` koaClassicServer options2: ${JSON.stringify(options2)}`, () => {
122
+ let app;
123
+ let server;
124
+
125
+ // Avvia il server prima di eseguire i test
126
+ beforeAll(() => {
127
+ app = new Koa();
128
+ app.use(koaClassicServer(rootDir, options2)); // Monta il middleware
129
+ server = app.listen();// Avvia il server in modo che Supertest possa inviare richieste HTTP
130
+ });
131
+
132
+ const testFnCallbacks = testAllPathByFileList(filesAndDirArray, () => server, options2);//Genera l'array di callback per i test
133
+ testFnCallbacks.forEach(cb => cb());// Esegui ogni callback per registrare il test nello scope del describe
134
+
135
+ afterAll(() => {// Chiude il server dopo aver completato tutti i test
136
+ server.close();
137
+ });
138
+ });
139
+ //END option2
140
+
141
+ //STASRT option3
142
+ const options3 = {
143
+ method: ['GET'],
144
+ showDirContents: false,
145
+ urlsReserved : Array('/percorso_riservato', '/percorso riservato con spazi')
146
+ };
147
+
148
+ describe(` koaClassicServer options2: ${JSON.stringify(options2)}`, () => {
149
+ let app;
150
+ let server;
151
+
152
+ // Avvia il server prima di eseguire i test
153
+ beforeAll(() => {
154
+ app = new Koa();
155
+ app.use(koaClassicServer(rootDir, options3)); // Monta il middleware
156
+ server = app.listen();// Avvia il server in modo che Supertest possa inviare richieste HTTP
157
+ });
158
+
159
+ test('controllo che se l\'indirizzo ricate di un percorso riservato allora venga passato il tutto al midlware successivo e in questo caso errore not ound', async () => {
160
+ // Effettua una richiesta GET sull'endpoint configurato (il prefisso)
161
+ const res = await supertest(server).get('/percorso_riservato/ciao.txt');
162
+ expect(res.status).toBe(404);
163
+ expect(res.type).toMatch("text/plain");// type sta per mimetype .... restituisce text/plain anche se dovrebbe essere text/html
164
+ expect(res.text.replace(/\s/g, '')).toBe("Not Found".replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
165
+ });
166
+
167
+ /* test('lo stesso del precedente ma questa volta il percorso riservato con spazi', async () => {
168
+ // Effettua una richiesta GET sull'endpoint configurato (il prefisso)
169
+ const res = await supertest(server).get('/percorso riservato con spazi/ciao.txt');
170
+ expect(res.status).toBe(404);
171
+ expect(res.type).toMatch("text/plain");// type sta per mimetype .... restituisce text/plain anche se dovrebbe essere text/html
172
+ expect(res.text.replace(/\s/g, '')).toBe("Not Found".replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
173
+ }); */
174
+
175
+
176
+ const testFnCallbacks = testAllPathByFileList(filesAndDirArray, () => server, options2);//Genera l'array di callback per i test
177
+ testFnCallbacks.forEach(cb => cb());// Esegui ogni callback per registrare il test nello scope del describe
178
+
179
+ afterAll(() => {// Chiude il server dopo aver completato tutti i test
180
+ server.close();
181
+ });
182
+ });
183
+ //END option3
184
+
185
+ /* const options0 = {
186
+ // Il prefisso URL che il middleware dovrà intercettare
187
+ urlPrefix: '/public',
188
+ // I metodi HTTP ammessi (default 'GET')
189
+ method: ['GET'],
190
+ // Se mostrare il contenuto della directory in caso di richiesta ad una cartella
191
+ showDirContents: true,
192
+ // Nome del file index da cercare all'interno di una directory (se presente)
193
+ //index: 'index.html',
194
+ }; */
195
+
196
+
197
+
198
+
199
+ // questa funzione serve per leggere ricorsivamente il contenuto di una cartella in modo da leggere il contenuto oferto via __tests__/publicWwwTest e confrontarlo con quello via http
200
+ //in linux anhe le directory sono file quindi mi salvo :)
201
+ function getFilesRecursivelySync(dir) {
202
+ let results = [];
203
+ // Leggiamo il contenuto della directory, ottenendo anche informazioni sui file e le cartelle
204
+ const list = fs.readdirSync(dir, { withFileTypes: true });
205
+
206
+ list.forEach((entry) => {
207
+ const fullPath = path.join(dir, entry.name);
208
+ entry.fullPath = fullPath;
209
+ if (entry.isDirectory()) {
210
+ // Se l'entry è una cartella, la elaboriamo ricorsivamente
211
+ entry.type = 'directory';
212
+ results.push(entry);// inserisco anche la directory stessa nell'elenco
213
+ results = results.concat(getFilesRecursivelySync(fullPath));
214
+ } else if (entry.isFile()) {
215
+ // Se l'entry è un file, lo aggiungiamo all'array dei risultati
216
+ const mimeType = mime.lookup(entry.name) || 'false';//false --> mimetype non riconosciuto , cosi lo trasmette il server , da approfondire
217
+ entry.type = 'file';
218
+ entry.mimeType = mimeType;
219
+ results.push(entry);
220
+ }
221
+ });
222
+
223
+ return results;
224
+ }
225
+
226
+ //ATTENZIONE questa funzione è esattamente identicaa a quella contenuta nel file index.cjs serve per confrontarla e vedere se il risultato combacia
227
+ function requestedUrlNotFound() {
228
+ return `
229
+ <!DOCTYPE html>
230
+ <html>
231
+ <head>
232
+ <meta charset="UTF-8">
233
+ <meta http-equiv="X-UA-Compatible">
234
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
235
+ <title>URL not found</title>
236
+ </head>
237
+ <body>
238
+ <h1>Not Found</h1>
239
+
240
+ <h3>The requested URL was not found on this server.</h3>
241
+
242
+ </body>
243
+ </html>
244
+ `;
245
+ } // function requestedUrlNotFound(){
246
+
247
+ //ATENZIONE per questa funzione guardare la descrizione sotto : per funzionare deve evvere chiamata nel seguente modo :
248
+ // const testFnCallbacks = testAllPathByFileList(filesAndDirArray, () => server, options0);//Genera l'array di callback per i test
249
+ // testFnCallbacks.forEach(cb => cb());// Esegui ogni callback per registrare il test nello scope del describe
250
+
251
+ function testAllPathByFileList(filesAndDirArray, getServer, options) {
252
+ return filesAndDirArray.map((entry, index) => {
253
+ const relativePath = path.relative(rootDir, entry.fullPath);
254
+ // Restituisci una funzione che, se chiamata, definisce un test.
255
+ return () => {
256
+ test(
257
+ `testo l'elemento ${index} (type: ${entry.type}, name: ${entry.name}) con percorso: ${relativePath}`,
258
+ async () => {
259
+ const server = getServer(); // Usa il getter per ottenere il server al momento dell'esecuzione
260
+ const url = path.join(options.urlPrefix || '/', relativePath);
261
+ const res = await supertest(server).get(url);
262
+ expect(res.status).toBe(200);
263
+ // Se l'entry è un file, controlla il contenuto e il MIME type
264
+ if (entry.type === 'file') {
265
+ const content = fs.readFileSync(entry.fullPath, 'utf8');
266
+ expect(res.type).toBe(entry.mimeType);
267
+ expect(res.text).toBe(content);
268
+ } else {//è una directory
269
+ expect(res.type).toBe('text/html');
270
+ expect(res.text).toContain('<!DOCTYPE html>');
271
+ if( options.showDirContents === false ){
272
+ expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
273
+ }
274
+ }
275
+ }
276
+ );
277
+ };
278
+ });
279
+ }
280
+
281
+ /* ATTENZIONE QUESTA FUNZIONE [function testAllPathByFileList] È FATTA IN MANIERA STRANA PER AVER RISOLTO IL PROBLEMA DOPO LUNGA DISCUSSIONE CON CHATGPT
282
+
283
+ Spiegazione
284
+
285
+ Incapsulamento:
286
+ In testAllPathByFileList usiamo map per creare un array in cui ogni elemento è una funzione (callback) che, se invocata, definisce un test usando test().
287
+ Così facendo, non eseguiamo subito test(), ma ne restituiamo la definizione da chiamare in seguito.
288
+
289
+ Uso del Getter:
290
+ Passando () => server come secondo argomento, assicuriamo che al momento dell'esecuzione di ogni callback il server sia già inizializzato.
291
+
292
+ Registrazione dei Test:
293
+ Quando chiamiamo testFnCallbacks.forEach(cb => cb()); nello scope del blocco describe, ogni callback viene invocata e i test vengono definiti correttamente per Jest.
294
+
295
+ Idea di Base
296
+
297
+ Genera un array di callback:
298
+ Crea una funzione che, dato l'array dei file e directory (o dati dinamici), restituisca un array di funzioni. Ogni funzione (callback) quando invocata definirà un test tramite test() ed eseguirà le relative asserzioni con expect().
299
+
300
+ Esegui le callback nello scope del describe:
301
+ All'interno del blocco describe (dove Jest raccoglie i test) iteri sull'array di callback e invochi ciascuna, in modo che i test vengano registrati correttamente. In questo modo, l'errore "Your test suite must contain at least one test" non si verificherà perché i test saranno già stati definiti nello scope globale del describe
302
+
303
+ //END CONSIDERAZIONE IMPORTANTE
304
+ */
305
+
306
+
307
+ /*
308
+ OLD//
309
+
310
+
311
+ function testAllPathByFileList(filesAndDirArray, getServer, options) {
312
+ return filesAndDirArray.map((entry, index) => {
313
+ const relativePath = path.relative(rootDir, entry.fullPath);
314
+ // Restituisci una funzione che, se chiamata, definisce un test.
315
+ return () => {
316
+ test(
317
+ `testo l'elemento ${index} (type: ${entry.type}, name: ${entry.name}) con percorso: ${relativePath}`,
318
+ async () => {
319
+ const server = getServer(); // Usa il getter per ottenere il server al momento dell'esecuzione
320
+ const url = path.join(options.urlPrefix || '/', relativePath);
321
+ const res = await supertest(server).get(url);
322
+ expect(res.status).toBe(200);
323
+ // Se l'entry è un file, controlla il contenuto e il MIME type
324
+ if (entry.type === 'file') {
325
+ const content = fs.readFileSync(entry.fullPath, 'utf8');
326
+ expect(res.type).toBe(entry.mimeType);
327
+ expect(res.text).toBe(content);
328
+ } else {
329
+ expect(res.type).toBe('text/html');
330
+ expect(res.text).toContain('<!DOCTYPE html>');
331
+ }
332
+ }
333
+ );
334
+ };
335
+ });
336
+ }
337
+ */
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+ <h1>hello world</h1>
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+ <h1><%= "hello world" %></h1>
10
+ </body>
11
+ </html>
File without changes
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+ <h1>hello world</h1>
10
+ </body>
11
+ </html>
@@ -0,0 +1,2 @@
1
+
2
+ hello world
@@ -0,0 +1 @@
1
+ hello world
@@ -0,0 +1 @@
1
+ hello world
@@ -0,0 +1,6 @@
1
+ ## questi ile servono per testare manualmente le vari conigurazioni
2
+
3
+ # digitando :
4
+ ### npm run loadConfig
5
+ # potrai sceglire quale configurazione usare per caricare il server e testatarlo la directory puntata è la stessa contenuta nella directory __tests__
6
+ # cioè __tests__/publicWwwTest
@@ -0,0 +1,41 @@
1
+ // questo script permetterà di scegliere la conigurazione con cui lanciare koa-classic-server al ine di essere testato
2
+ // ci sarà una lista interattive di configurazione fra cui scegliere :
3
+
4
+ // chooseCon.js
5
+ const { createServer, configurations } = require('../customTest/serversToLoad.util');
6
+ const inquirer = require('inquirer').default;
7
+
8
+ async function chooseConfiguration() {
9
+ // Costruiamo le scelte dall'array delle configurazioni
10
+ const choices = configurations.map(config => ({
11
+ name: `${config.name}: ${config.description}`,
12
+ value: config.name,
13
+ }));
14
+
15
+ const answers = await inquirer.prompt([
16
+ {
17
+ type: 'list',
18
+ name: 'configName',
19
+ message: 'Seleziona la configurazione da visualizzare:',
20
+ choices: choices,
21
+ },
22
+ ]);
23
+
24
+ return answers.configName;
25
+ }
26
+
27
+ async function main() {
28
+ const configName = await chooseConfiguration();
29
+ const app = createServer(configName);
30
+ const port = process.env.PORT || 3000;
31
+
32
+ app.listen(port, () => {
33
+ console.log(`Server avviato su http://localhost:${port} con configurazione "${configName}"`);
34
+ });
35
+ }
36
+
37
+ main().catch(error => {
38
+ console.error('Errore durante l\'esecuzione:', error);
39
+ process.exit(1);
40
+ });
41
+
@@ -0,0 +1,93 @@
1
+ // quivi sarnno elencato in un array le varie possibili configurzioni di koaClassicServer in modo po sa poterle testare
2
+
3
+ // servers.js
4
+ const Koa = require('koa');
5
+ const koaClassicServer = require('../index.cjs');
6
+ const { join } = require('path');
7
+
8
+ /**
9
+ * Array (o raccolta) delle configurazioni disponibili.
10
+ * Aggiungendo nuovi oggetti qui potrai testare ulteriori configurazioni.
11
+ */
12
+ rootDir = join(__dirname, '../' , '__tests__','publicWwwTest');
13
+ console.log( 'rootDir', rootDir);
14
+ const configurations = [
15
+ {
16
+ name: 'test generico',
17
+ description: ' urlPrefix: \',',
18
+ // Per i test, i file da servire sono quelli della cartella __tests__/publicWwwTest
19
+ rootDir: rootDir,
20
+ options: {
21
+ //urlPrefix: '/',
22
+ method: ['GET'],
23
+ showDirContents: true,
24
+ },
25
+ },
26
+ {
27
+ name: 'test indicando l\'index file ',
28
+ description: "nelle urlPrefix: \'/public\', : //index: 'index.html',",
29
+ // In produzione potresti servire i file dalla cartella "public"
30
+ rootDir: rootDir,
31
+ options: {
32
+ urlPrefix: '/public',
33
+ method: ['GET'],
34
+ showDirContents: true,
35
+ index: 'index.html',
36
+ },
37
+ },
38
+ {
39
+ name: 'test generico',
40
+ description: ' urlPrefix: \'/public\',',
41
+ // Per i test, i file da servire sono quelli della cartella __tests__/publicWwwTest
42
+ rootDir: rootDir,
43
+ options: {
44
+ urlPrefix: '/public',
45
+ method: ['GET'],
46
+ showDirContents: true,
47
+ },
48
+ },
49
+ {
50
+ name: 'test con percorso riservato ',
51
+ description: "urlsReserved : Array('percorso_riservato/', 'percorso riservato con spazi')",
52
+ // Per i test, i file da servire sono quelli della cartella __tests__/publicWwwTest
53
+ rootDir: rootDir,
54
+ options: {
55
+ urlPrefix: '',
56
+ method: ['GET'],
57
+ showDirContents: true,
58
+ urlsReserved : Array('/percorso_riservato', '/percorso riservato con spazi')
59
+ },
60
+ },
61
+ // Puoi aggiungere ulteriori configurazioni qui
62
+ ];
63
+
64
+ /**
65
+ * Cerca e restituisce la configurazione in base al nome.
66
+ * Se non viene trovata, restituisce la prima (default).
67
+ *
68
+ * @param {string} configName - Il nome della configurazione da usare.
69
+ * @returns {object} La configurazione trovata.
70
+ */
71
+ function getConfig(configName) {
72
+ return configurations.find(config => config.name === configName) || configurations[0];
73
+ }
74
+
75
+ /**
76
+ * Crea un'istanza di Koa configurata in base alla configurazione scelta.
77
+ *
78
+ * @param {string} configName - Il nome della configurazione da utilizzare (default: 'default').
79
+ * @returns {Koa} L'istanza dell'applicazione Koa.
80
+ */
81
+ function createServer( configName ) {
82
+ const config = getConfig(configName);
83
+ const app = new Koa();
84
+ console.log('config.options', config.options, 'config.rootDir' , config.rootDir);
85
+ app.use(koaClassicServer(config.rootDir, config.options));
86
+ return app;
87
+ }
88
+
89
+ module.exports = {
90
+ configurations,
91
+ getConfig,
92
+ createServer,
93
+ };
@@ -1,3 +1,4 @@
1
+
1
2
  const { URL } = require("url");
2
3
  const fs = require("fs");
3
4
  const mime = require("mime-types");
@@ -6,7 +7,7 @@ const { error } = require("console");
6
7
 
7
8
  // è la funzione che avierà il server rootDir = cartella dei file statici, UrlPrefix = prefisso del path dove guardare es localhost:3000\views
8
9
  // questa funzione deve restituire un midlware
9
- module.exports = function koaClassicServer(
10
+ module.exports = function koaClassicServer(
10
11
  rootDir,
11
12
  opts = {}
12
13
 
@@ -270,4 +271,4 @@ module.exports = function koaClassicServer(
270
271
  return toReturn;
271
272
  } // function show_dir( dir ){
272
273
  }; // return (ctx, next) => {
273
- };
274
+ };
package/index.mjs ADDED
@@ -0,0 +1,9 @@
1
+
2
+ // index.js (ESM)
3
+ // index.esm.js
4
+
5
+ // Importa il modulo principale (anche se è scritto in CommonJS)
6
+ // Node gestirà l'interoperabilità e restituirà il valore presente in module.exports.
7
+ import koaClassicServer from './index.cjs';
8
+ export default koaClassicServer;
9
+
package/noteExports.md ADDED
@@ -0,0 +1,148 @@
1
+
2
+ ## versione corta
3
+ Utilizzare Conditional Exports in package.json
4
+
5
+ Con Node.js (versione 12.20+, 14+ o successive) puoi sfruttare il campo exports nel file package.json per indicare percorsi diversi a seconda del metodo di importazione:
6
+
7
+ Esempio di package.json:
8
+
9
+ {
10
+ "name": "mia-libreria",
11
+ "version": "1.0.0",
12
+ "main": "./index.cjs", // entry point per CommonJS
13
+ "exports": {
14
+ "import": "./index.js", // entry point per ESM
15
+ "require": "./index.cjs" // entry point per CommonJS
16
+ }
17
+ }
18
+
19
+ Con questa configurazione, puoi scrivere la logica principale in un file (ad esempio lib/koaClassicServer.js) e poi creare due entry point:
20
+
21
+ Per ESM (index.js)
22
+
23
+ // index.js
24
+ export { default } from './lib/koaClassicServer.js';
25
+
26
+ Per CommonJS (index.cjs)
27
+
28
+ // index.cjs
29
+ module.exports = require('./lib/koaClassicServer.js').default;
30
+
31
+ In questo modo gli utenti potranno importare il modulo in ESM:
32
+
33
+ import koaClassicServer from "mia-libreria";
34
+
35
+ oppure in CommonJS:
36
+
37
+ const koaClassicServer = require("mia-libreria");
38
+
39
+
40
+
41
+ ## versione lunga
42
+
43
+ l'uso dei Conditional Exports nel file package.json, è un meccanismo introdotto nelle versioni moderne di Node.js (dalla 12.20 in poi, con supporto stabile a partire dalla 14) che ti permette di specificare percorsi di ingresso diversi a seconda di come il modulo viene importato:
44
+
45
+ ESM (quando usi import ... from 'modulo')
46
+ CommonJS (quando usi require('modulo'))
47
+
48
+ Questo approccio ti consente di mantenere una singola distribuzione del tuo modulo, fornendo però due "versioni" compatibili in base al sistema di moduli utilizzato dall'ambiente dell'utente.
49
+ Struttura di Base del package.json
50
+
51
+ Ecco un esempio di configurazione:
52
+
53
+ {
54
+ "name": "mia-libreria",
55
+ "version": "1.0.0",
56
+ "main": "./index.cjs",
57
+ "exports": {
58
+ "import": "./index.js",
59
+ "require": "./index.cjs"
60
+ }
61
+ }
62
+
63
+ Spiegazione dei campi principali:
64
+
65
+ main:
66
+ Tradizionalmente questo campo specifica il file di ingresso per i moduli CommonJS. Anche se non è obbligatorio se usi il campo exports, è buona pratica inserirlo per mantenere la compatibilità con strumenti o ambienti che non supportano ancora i conditional exports.
67
+
68
+ exports:
69
+ Questo campo permette di definire in modo esplicito quali file (o percorsi) devono essere utilizzati quando il modulo viene importato, in base al contesto. In questo esempio, abbiamo due condizioni:
70
+ "import": "./index.js": Quando il modulo viene importato in un contesto ECMAScript (ESM), Node.js userà il file index.js.
71
+ "require": "./index.cjs": Quando il modulo viene importato tramite CommonJS (require()), verrà usato il file index.cjs.
72
+
73
+ Strutturare il Modulo per Supportare Entrambi gli Stili
74
+
75
+ Supponiamo di avere una struttura simile a questa:
76
+
77
+ mia-libreria/
78
+ ├── lib/
79
+ │ └── koaClassicServer.js
80
+ ├── index.js // Entry point per ESM
81
+ ├── index.cjs // Entry point per CommonJS
82
+ └── package.json
83
+
84
+ 1. File lib/koaClassicServer.js (la logica principale)
85
+
86
+ Scrivi qui il tuo modulo in sintassi moderna (ESM). Ad esempio:
87
+
88
+ // lib/koaClassicServer.js
89
+ export default function koaClassicServer(rootDir, opts = {}) {
90
+ // ... implementazione del middleware
91
+ }
92
+
93
+ 2. File index.js (entry point per ESM)
94
+
95
+ Questo file importa il modulo principale e lo re-esporta:
96
+
97
+ // index.js (ESM)
98
+ export { default } from './lib/koaClassicServer.js';
99
+
100
+ 3. File index.cjs (entry point per CommonJS)
101
+
102
+ In questo file, importa il modulo in modo compatibile con CommonJS e lo esporta:
103
+
104
+ // index.cjs (CommonJS)
105
+ module.exports = require('./lib/koaClassicServer.js').default;
106
+
107
+ Come Funziona in Pratica
108
+
109
+ Utilizzando ESM:
110
+
111
+ Se un utente importa il modulo in un file ESM:
112
+
113
+ import koaClassicServer from 'mia-libreria';
114
+
115
+ Node.js guarderà il campo exports nel package.json e, vedendo la chiave "import", caricherà il file index.js che esporta il modulo definito in koaClassicServer.js.
116
+
117
+ Utilizzando CommonJS:
118
+
119
+ Se invece un utente importa il modulo in un file CommonJS:
120
+
121
+ const koaClassicServer = require('mia-libreria');
122
+
123
+ Node.js, vedendo la chiave "require" nel campo exports, caricherà il file index.cjs che esporta correttamente il modulo.
124
+
125
+ Vantaggi di Questo Approccio
126
+
127
+ Compatibilità Doppia:
128
+ Permette agli utenti di utilizzare il modulo indipendentemente dal sistema di moduli scelto.
129
+
130
+ Manutenzione Centralizzata:
131
+ La logica principale è scritta in un solo file (koaClassicServer.js), riducendo la duplicazione del codice.
132
+
133
+ Supporto ai Nuovi Standard:
134
+ Utilizzando i conditional exports, ti prepari per il futuro, dove i moduli ESM diventeranno lo standard principale.
135
+
136
+ Controllo Esplicito dell'Interfaccia:
137
+ Il campo exports consente di definire in modo esplicito e sicuro quali file devono essere esposti agli utenti del modulo, evitando accessi accidentali a file interni non destinati alla pubblicazione.
138
+
139
+ Considerazioni Finali
140
+
141
+ Versione di Node.js:
142
+ Assicurati che i tuoi utenti utilizzino una versione di Node.js che supporti i conditional exports (Node 14+ è consigliato).
143
+
144
+ Compatibilità con Strumenti di Build:
145
+ Se utilizzi strumenti di build o bundler, verifica che siano configurati per gestire correttamente il campo exports.
146
+
147
+ Utilizzando i Conditional Exports nel package.json potrai distribuire il tuo modulo in modo elegante e compatibile con entrambi gli stili di moduli, offrendo un'esperienza di utilizzo migliore agli sviluppatori che lo importeranno.
148
+
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "koa-classic-server",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "a server in style Apache 2",
5
- "main": "index.js",
5
+ "main": "index.cjs",
6
+ "exports": {
7
+ "import": "./index.mjs",
8
+ "require": "./index.cjs"
9
+ },
6
10
  "scripts": {
7
- "start": "node index.js",
8
- "test": "jest"
11
+ "start": "node index.cjs",
12
+ "test": "jest",
13
+ "loadConfig": "node ./customTest/loadConfig.util.js"
9
14
  },
10
15
  "keywords": [
11
16
  "file",
@@ -14,8 +19,11 @@
14
19
  "author": "Italo Paesano",
15
20
  "license": "MIT",
16
21
  "dependencies": {
17
- "jest": "^29.4.2",
18
- "koa": "^2.13.4",
19
- "supertest": "^6.3.3"
22
+ "koa": "^2.13.4"
23
+ },
24
+ "devDependencies": {
25
+ "inquirer": "^12.4.1",
26
+ "jest": "^29.7.0",
27
+ "supertest": "^7.0.0"
20
28
  }
21
29
  }
package/index.test.js DELETED
@@ -1,63 +0,0 @@
1
- //const request = require('supertest');
2
- //const Koa = require('koa');
3
- const classicServer = require('koa-classic-server');
4
-
5
- const testDir = __dirname + '/test' ;
6
-
7
- const fakeApp = classicServer( testDir );
8
-
9
- const fakeCtx = {
10
- method: 'GET',
11
- href: 'http://localhost:3000/', // da controllare
12
- body: '',
13
- response: {}
14
- }
15
-
16
- const fakeNext = () => {};
17
-
18
- ///console.log(fakeApp( fakeCtx, fakeNext));
19
-
20
- test('prima prova', () => {
21
- fakeApp( fakeCtx, fakeNext).then((result) => {
22
- console.log('resuuultttttt',result);
23
- expect( result ).not.toBe(3);
24
- })//)).not.toBe(3);
25
- });
26
-
27
- /* const app = new Koa();
28
- app.use(classicServer( __dirname + '/test'));
29
-
30
- const server = app.listen();
31
-
32
- request(server)
33
- .get('/')
34
- .expect('Content-Type', 'text/html')
35
- //.expect('Content-Length', '15')
36
- .expect(200)
37
- .end(function(err, res) {
38
- if (err) throw err;
39
- }); */
40
-
41
-
42
-
43
- /* describe('koa-classic-server', () => {
44
- let app;
45
-
46
- beforeEach(() => {
47
- app = new Koa();
48
- app.use(classicServer());
49
- });
50
-
51
- it('should return Hello World!', async () => {
52
- const res = await request(app.callback()).get('/');
53
- expect(res.status).toBe(200);
54
- expect(res.text).toBe('Hello World!');
55
- });
56
-
57
- it('should return 404 for invalid route', async () => {
58
- const res = await request(app.callback()).get('/invalid');
59
- expect(res.status).toBe(404);
60
- expect(res.text).toBe('Not Found');
61
- });
62
- });
63
- */