kempo-server 1.4.3 → 1.4.6
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/.github/copilot-instructions.md +96 -96
- package/.github/workflows/publish-npm.yml +45 -0
- package/README.md +650 -650
- package/builtinMiddleware.js +136 -136
- package/defaultConfig.js +129 -129
- package/docs/.config.json +5 -5
- package/docs/.config.json.example +19 -19
- package/docs/api/user/[id]/GET.js +15 -15
- package/docs/api/user/[id]/[info]/DELETE.js +12 -12
- package/docs/api/user/[id]/[info]/GET.js +17 -17
- package/docs/api/user/[id]/[info]/POST.js +18 -18
- package/docs/api/user/[id]/[info]/PUT.js +19 -19
- package/docs/configuration.html +119 -119
- package/docs/examples.html +201 -201
- package/docs/getting-started.html +72 -72
- package/docs/index.html +81 -81
- package/docs/manifest.json +87 -87
- package/docs/middleware.html +147 -147
- package/docs/request-response.html +95 -95
- package/docs/routing.html +77 -77
- package/example-middleware.js +23 -23
- package/example.config.json +50 -50
- package/findFile.js +138 -138
- package/getFiles.js +72 -72
- package/getFlags.js +34 -34
- package/index.js +47 -47
- package/middlewareRunner.js +25 -25
- package/package.json +10 -6
- package/requestWrapper.js +87 -87
- package/responseWrapper.js +204 -204
- package/router.js +285 -285
- package/serveFile.js +71 -71
- package/tests/builtinMiddleware-cors.node-test.js +17 -17
- package/tests/builtinMiddleware.node-test.js +74 -74
- package/tests/defaultConfig.node-test.js +13 -13
- package/tests/example-middleware.node-test.js +31 -31
- package/tests/findFile.node-test.js +46 -46
- package/tests/getFiles.node-test.js +25 -25
- package/tests/getFlags.node-test.js +30 -30
- package/tests/index.node-test.js +23 -23
- package/tests/middlewareRunner.node-test.js +18 -18
- package/tests/requestWrapper.node-test.js +51 -51
- package/tests/responseWrapper.node-test.js +74 -74
- package/tests/router-middleware.node-test.js +46 -46
- package/tests/router.node-test.js +88 -88
- package/tests/serveFile.node-test.js +52 -52
- package/tests/test-utils.js +106 -106
package/index.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import http from 'http';
|
|
3
|
-
import router from './router.js';
|
|
4
|
-
import getFlags from './getFlags.js';
|
|
5
|
-
|
|
6
|
-
const flags = getFlags(process.argv.slice(2), {
|
|
7
|
-
port: 3000,
|
|
8
|
-
logging: 2,
|
|
9
|
-
root: './',
|
|
10
|
-
scan: false
|
|
11
|
-
}, {
|
|
12
|
-
p: 'port',
|
|
13
|
-
l: 'logging',
|
|
14
|
-
r: 'root',
|
|
15
|
-
s: 'scan'
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
if(typeof(flags.logging) === 'string'){
|
|
19
|
-
switch(flags.logging.toLowerCase()) {
|
|
20
|
-
case 'silent':
|
|
21
|
-
flags.logging = 0;
|
|
22
|
-
break;
|
|
23
|
-
case 'minimal':
|
|
24
|
-
flags.logging = 1;
|
|
25
|
-
break;
|
|
26
|
-
case 'verbose':
|
|
27
|
-
flags.logging = 3;
|
|
28
|
-
break;
|
|
29
|
-
case 'debug':
|
|
30
|
-
flags.logging = 4;
|
|
31
|
-
break;
|
|
32
|
-
default:
|
|
33
|
-
flags.logging = 2;
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const log = (message, level = 2) => {
|
|
39
|
-
if(level <= flags.logging){
|
|
40
|
-
console.log(message);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const server = http.createServer(await router(flags, log));
|
|
45
|
-
server.listen(flags.port);
|
|
46
|
-
log(`Server started at: http://localhost:${flags.port}`);
|
|
47
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import http from 'http';
|
|
3
|
+
import router from './router.js';
|
|
4
|
+
import getFlags from './getFlags.js';
|
|
5
|
+
|
|
6
|
+
const flags = getFlags(process.argv.slice(2), {
|
|
7
|
+
port: 3000,
|
|
8
|
+
logging: 2,
|
|
9
|
+
root: './',
|
|
10
|
+
scan: false
|
|
11
|
+
}, {
|
|
12
|
+
p: 'port',
|
|
13
|
+
l: 'logging',
|
|
14
|
+
r: 'root',
|
|
15
|
+
s: 'scan'
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
if(typeof(flags.logging) === 'string'){
|
|
19
|
+
switch(flags.logging.toLowerCase()) {
|
|
20
|
+
case 'silent':
|
|
21
|
+
flags.logging = 0;
|
|
22
|
+
break;
|
|
23
|
+
case 'minimal':
|
|
24
|
+
flags.logging = 1;
|
|
25
|
+
break;
|
|
26
|
+
case 'verbose':
|
|
27
|
+
flags.logging = 3;
|
|
28
|
+
break;
|
|
29
|
+
case 'debug':
|
|
30
|
+
flags.logging = 4;
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
flags.logging = 2;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const log = (message, level = 2) => {
|
|
39
|
+
if(level <= flags.logging){
|
|
40
|
+
console.log(message);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const server = http.createServer(await router(flags, log));
|
|
45
|
+
server.listen(flags.port);
|
|
46
|
+
log(`Server started at: http://localhost:${flags.port}`);
|
|
47
|
+
|
package/middlewareRunner.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
// Middleware runner for Kempo Server
|
|
2
|
-
export default class MiddlewareRunner {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.middlewares = [];
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
use(middleware) {
|
|
8
|
-
this.middlewares.push(middleware);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async run(req, res, finalHandler) {
|
|
12
|
-
let index = 0;
|
|
13
|
-
|
|
14
|
-
const next = async () => {
|
|
15
|
-
if (index >= this.middlewares.length) {
|
|
16
|
-
return await finalHandler();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const middleware = this.middlewares[index++];
|
|
20
|
-
await middleware(req, res, next);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
await next();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
1
|
+
// Middleware runner for Kempo Server
|
|
2
|
+
export default class MiddlewareRunner {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.middlewares = [];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
use(middleware) {
|
|
8
|
+
this.middlewares.push(middleware);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async run(req, res, finalHandler) {
|
|
12
|
+
let index = 0;
|
|
13
|
+
|
|
14
|
+
const next = async () => {
|
|
15
|
+
if (index >= this.middlewares.length) {
|
|
16
|
+
return await finalHandler();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const middleware = this.middlewares[index++];
|
|
20
|
+
await middleware(req, res, next);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
await next();
|
|
24
|
+
}
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kempo-server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.6",
|
|
5
5
|
"description": "A lightweight, zero-dependency, file based routing server.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"kempo-server": "./index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
"start": "node index.js -r ./docs",
|
|
12
|
+
"tests": "npx kempo-test",
|
|
13
|
+
"tests:gui": "npx kempo-test --gui",
|
|
14
|
+
"tests:browser": "npx kempo-test -b",
|
|
15
|
+
"tests:node": "npx kempo-test -n"
|
|
16
16
|
},
|
|
17
17
|
"author": "",
|
|
18
18
|
"license": "ISC",
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"essentialcss": "^2.0.1",
|
|
21
21
|
"kempo-testing-framework": "^1.2.3"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/dustinpoissant/kempo-server"
|
|
22
26
|
}
|
|
23
27
|
}
|
package/requestWrapper.js
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import { URL } from 'url';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates an enhanced request object with Express-like functionality
|
|
5
|
-
* @param {IncomingMessage} request - The original Node.js request object
|
|
6
|
-
* @param {Object} params - Route parameters from dynamic routes
|
|
7
|
-
* @returns {Object} Enhanced request object
|
|
8
|
-
*/
|
|
9
|
-
export function createRequestWrapper(request, params = {}) {
|
|
10
|
-
// Parse URL to extract query parameters
|
|
11
|
-
const url = new URL(request.url, `http://${request.headers.host || 'localhost'}`);
|
|
12
|
-
const query = Object.fromEntries(url.searchParams);
|
|
13
|
-
|
|
14
|
-
// Create the enhanced request object
|
|
15
|
-
const enhancedRequest = {
|
|
16
|
-
// Original request properties and methods
|
|
17
|
-
...request,
|
|
18
|
-
method: request.method,
|
|
19
|
-
url: request.url,
|
|
20
|
-
headers: request.headers,
|
|
21
|
-
|
|
22
|
-
// Enhanced properties
|
|
23
|
-
params,
|
|
24
|
-
query,
|
|
25
|
-
path: url.pathname,
|
|
26
|
-
|
|
27
|
-
// Body parsing methods
|
|
28
|
-
async body() {
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
let body = '';
|
|
31
|
-
|
|
32
|
-
request.on('data', chunk => {
|
|
33
|
-
body += chunk.toString();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
request.on('end', () => {
|
|
37
|
-
resolve(body);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
request.on('error', reject);
|
|
41
|
-
});
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
async json() {
|
|
45
|
-
try {
|
|
46
|
-
const body = await this.body();
|
|
47
|
-
return JSON.parse(body);
|
|
48
|
-
} catch (error) {
|
|
49
|
-
throw new Error('Invalid JSON in request body');
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
async text() {
|
|
54
|
-
return this.body();
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
async buffer() {
|
|
58
|
-
return new Promise((resolve, reject) => {
|
|
59
|
-
const chunks = [];
|
|
60
|
-
|
|
61
|
-
request.on('data', chunk => {
|
|
62
|
-
chunks.push(chunk);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
request.on('end', () => {
|
|
66
|
-
resolve(Buffer.concat(chunks));
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
request.on('error', reject);
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
// Utility methods
|
|
74
|
-
get(headerName) {
|
|
75
|
-
return request.headers[headerName.toLowerCase()];
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
is(type) {
|
|
79
|
-
const contentType = this.get('content-type') || '';
|
|
80
|
-
return contentType.includes(type);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
return enhancedRequest;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export default createRequestWrapper;
|
|
1
|
+
import { URL } from 'url';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates an enhanced request object with Express-like functionality
|
|
5
|
+
* @param {IncomingMessage} request - The original Node.js request object
|
|
6
|
+
* @param {Object} params - Route parameters from dynamic routes
|
|
7
|
+
* @returns {Object} Enhanced request object
|
|
8
|
+
*/
|
|
9
|
+
export function createRequestWrapper(request, params = {}) {
|
|
10
|
+
// Parse URL to extract query parameters
|
|
11
|
+
const url = new URL(request.url, `http://${request.headers.host || 'localhost'}`);
|
|
12
|
+
const query = Object.fromEntries(url.searchParams);
|
|
13
|
+
|
|
14
|
+
// Create the enhanced request object
|
|
15
|
+
const enhancedRequest = {
|
|
16
|
+
// Original request properties and methods
|
|
17
|
+
...request,
|
|
18
|
+
method: request.method,
|
|
19
|
+
url: request.url,
|
|
20
|
+
headers: request.headers,
|
|
21
|
+
|
|
22
|
+
// Enhanced properties
|
|
23
|
+
params,
|
|
24
|
+
query,
|
|
25
|
+
path: url.pathname,
|
|
26
|
+
|
|
27
|
+
// Body parsing methods
|
|
28
|
+
async body() {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
let body = '';
|
|
31
|
+
|
|
32
|
+
request.on('data', chunk => {
|
|
33
|
+
body += chunk.toString();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
request.on('end', () => {
|
|
37
|
+
resolve(body);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
request.on('error', reject);
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
async json() {
|
|
45
|
+
try {
|
|
46
|
+
const body = await this.body();
|
|
47
|
+
return JSON.parse(body);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
throw new Error('Invalid JSON in request body');
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
async text() {
|
|
54
|
+
return this.body();
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
async buffer() {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const chunks = [];
|
|
60
|
+
|
|
61
|
+
request.on('data', chunk => {
|
|
62
|
+
chunks.push(chunk);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
request.on('end', () => {
|
|
66
|
+
resolve(Buffer.concat(chunks));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
request.on('error', reject);
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// Utility methods
|
|
74
|
+
get(headerName) {
|
|
75
|
+
return request.headers[headerName.toLowerCase()];
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
is(type) {
|
|
79
|
+
const contentType = this.get('content-type') || '';
|
|
80
|
+
return contentType.includes(type);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return enhancedRequest;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default createRequestWrapper;
|