mikroserve 0.0.6 → 0.0.7
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/README.md +6 -1
- package/lib/MikroServe.d.mts +7 -6
- package/lib/MikroServe.d.ts +7 -6
- package/lib/MikroServe.js +65 -21
- package/lib/MikroServe.mjs +2 -3
- package/lib/Router.d.mts +5 -3
- package/lib/Router.d.ts +5 -3
- package/lib/{chunk-E3RGQ7QF.mjs → chunk-J2WPHNMW.mjs} +61 -16
- package/lib/{chunk-NSHBEU32.mjs → chunk-JJX5XRNB.mjs} +6 -4
- package/lib/index.d.mts +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +65 -21
- package/lib/index.mjs +2 -3
- package/lib/interfaces/index.d.mts +19 -4
- package/lib/interfaces/index.d.ts +19 -4
- package/lib/utils/configDefaults.d.mts +3 -0
- package/lib/utils/configDefaults.d.ts +3 -0
- package/lib/utils/configDefaults.js +6 -8
- package/lib/utils/configDefaults.mjs +1 -2
- package/package.json +2 -2
- package/lib/chunk-6HESV5Q6.mjs +0 -9
- package/lib/utils/getTruthyValue.d.mts +0 -6
- package/lib/utils/getTruthyValue.d.ts +0 -6
- package/lib/utils/getTruthyValue.js +0 -33
- package/lib/utils/getTruthyValue.mjs +0 -6
package/README.md
CHANGED
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
**Minimalistic, ready-to-use API, built on Node.js primitives**.
|
|
4
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/mikroserve)
|
|
6
|
+
|
|
7
|
+
[](https://bundlephobia.com/package/mikroserve)
|
|
8
|
+
|
|
5
9
|

|
|
6
|
-
|
|
10
|
+
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
12
|
|
|
8
13
|
---
|
|
9
14
|
|
package/lib/MikroServe.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { MikroServeOptions, Middleware, RouteHandler, ServerType } from './interfaces/index.mjs';
|
|
2
|
+
import 'node:http';
|
|
3
|
+
import 'node:http2';
|
|
4
|
+
import 'node:https';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @description MikroServe manages HTTP server operations with routing.
|
|
@@ -44,11 +45,11 @@ declare class MikroServe {
|
|
|
44
45
|
/**
|
|
45
46
|
* @description Creates an HTTP/HTTPS server, sets up graceful shutdown, and starts listening.
|
|
46
47
|
*/
|
|
47
|
-
start():
|
|
48
|
+
start(): ServerType;
|
|
48
49
|
/**
|
|
49
50
|
* @description Creates and configures a server instance without starting it.
|
|
50
51
|
*/
|
|
51
|
-
createServer():
|
|
52
|
+
createServer(): ServerType;
|
|
52
53
|
/**
|
|
53
54
|
* @description Rate limiting middleware.
|
|
54
55
|
*/
|
|
@@ -80,7 +81,7 @@ declare class MikroServe {
|
|
|
80
81
|
/**
|
|
81
82
|
* @description Sets up graceful shutdown handlers for a server.
|
|
82
83
|
*/
|
|
83
|
-
setupGracefulShutdown(server:
|
|
84
|
+
setupGracefulShutdown(server: ServerType): void;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
export { MikroServe };
|
package/lib/MikroServe.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { MikroServeOptions, Middleware, RouteHandler, ServerType } from './interfaces/index.js';
|
|
2
|
+
import 'node:http';
|
|
3
|
+
import 'node:http2';
|
|
4
|
+
import 'node:https';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @description MikroServe manages HTTP server operations with routing.
|
|
@@ -44,11 +45,11 @@ declare class MikroServe {
|
|
|
44
45
|
/**
|
|
45
46
|
* @description Creates an HTTP/HTTPS server, sets up graceful shutdown, and starts listening.
|
|
46
47
|
*/
|
|
47
|
-
start():
|
|
48
|
+
start(): ServerType;
|
|
48
49
|
/**
|
|
49
50
|
* @description Creates and configures a server instance without starting it.
|
|
50
51
|
*/
|
|
51
|
-
createServer():
|
|
52
|
+
createServer(): ServerType;
|
|
52
53
|
/**
|
|
53
54
|
* @description Rate limiting middleware.
|
|
54
55
|
*/
|
|
@@ -80,7 +81,7 @@ declare class MikroServe {
|
|
|
80
81
|
/**
|
|
81
82
|
* @description Sets up graceful shutdown handlers for a server.
|
|
82
83
|
*/
|
|
83
|
-
setupGracefulShutdown(server:
|
|
84
|
+
setupGracefulShutdown(server: ServerType): void;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
export { MikroServe };
|
package/lib/MikroServe.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(MikroServe_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(MikroServe_exports);
|
|
36
36
|
var import_node_fs = require("fs");
|
|
37
37
|
var import_node_http = __toESM(require("http"));
|
|
38
|
+
var import_node_http2 = __toESM(require("http2"));
|
|
38
39
|
var import_node_https = __toESM(require("https"));
|
|
39
40
|
var import_mikroconf = require("mikroconf");
|
|
40
41
|
|
|
@@ -281,18 +282,13 @@ var Router = class {
|
|
|
281
282
|
}
|
|
282
283
|
};
|
|
283
284
|
|
|
284
|
-
// src/utils/getTruthyValue.ts
|
|
285
|
-
function getTruthyValue(value) {
|
|
286
|
-
if (value === "true" || value === true) return true;
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
285
|
// src/utils/configDefaults.ts
|
|
291
286
|
var configDefaults = () => {
|
|
292
287
|
return {
|
|
293
288
|
port: Number(process.env.PORT) || 3e3,
|
|
294
289
|
host: process.env.HOST || "0.0.0.0",
|
|
295
290
|
useHttps: false,
|
|
291
|
+
useHttp2: false,
|
|
296
292
|
sslCert: "",
|
|
297
293
|
sslKey: "",
|
|
298
294
|
sslCa: "",
|
|
@@ -304,6 +300,10 @@ var configDefaults = () => {
|
|
|
304
300
|
allowedDomains: ["*"]
|
|
305
301
|
};
|
|
306
302
|
};
|
|
303
|
+
function getTruthyValue(value) {
|
|
304
|
+
if (value === "true" || value === true) return true;
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
307
|
|
|
308
308
|
// src/MikroServe.ts
|
|
309
309
|
var MikroServe = class {
|
|
@@ -322,6 +322,7 @@ var MikroServe = class {
|
|
|
322
322
|
{ flag: "--port", path: "port", defaultValue: defaults.port },
|
|
323
323
|
{ flag: "--host", path: "host", defaultValue: defaults.host },
|
|
324
324
|
{ flag: "--https", path: "useHttps", defaultValue: defaults.useHttps, isFlag: true },
|
|
325
|
+
{ flag: "--http2", path: "useHttp2", defaultValue: defaults.useHttp2, isFlag: true },
|
|
325
326
|
{ flag: "--cert", path: "sslCert", defaultValue: defaults.sslCert },
|
|
326
327
|
{ flag: "--key", path: "sslKey", defaultValue: defaults.sslKey },
|
|
327
328
|
{ flag: "--ca", path: "sslCa", defaultValue: defaults.sslCa },
|
|
@@ -423,7 +424,22 @@ var MikroServe = class {
|
|
|
423
424
|
*/
|
|
424
425
|
createServer() {
|
|
425
426
|
const boundRequestHandler = this.requestHandler.bind(this);
|
|
426
|
-
if (this.config.
|
|
427
|
+
if (this.config.useHttp2) {
|
|
428
|
+
if (!this.config.sslCert || !this.config.sslKey)
|
|
429
|
+
throw new Error("SSL certificate and key paths are required when useHttp2 is true");
|
|
430
|
+
try {
|
|
431
|
+
const httpsOptions = {
|
|
432
|
+
key: (0, import_node_fs.readFileSync)(this.config.sslKey),
|
|
433
|
+
cert: (0, import_node_fs.readFileSync)(this.config.sslCert),
|
|
434
|
+
...this.config.sslCa ? { ca: (0, import_node_fs.readFileSync)(this.config.sslCa) } : {}
|
|
435
|
+
};
|
|
436
|
+
return import_node_http2.default.createSecureServer(httpsOptions, boundRequestHandler);
|
|
437
|
+
} catch (error) {
|
|
438
|
+
if (error.message.includes("key values mismatch"))
|
|
439
|
+
throw new Error(`SSL certificate and key do not match: ${error.message}`);
|
|
440
|
+
throw error;
|
|
441
|
+
}
|
|
442
|
+
} else if (this.config.useHttps) {
|
|
427
443
|
if (!this.config.sslCert || !this.config.sslKey)
|
|
428
444
|
throw new Error("SSL certificate and key paths are required when useHttps is true");
|
|
429
445
|
try {
|
|
@@ -477,8 +493,14 @@ var MikroServe = class {
|
|
|
477
493
|
this.setSecurityHeaders(res, this.config.useHttps);
|
|
478
494
|
if (isDebug) console.log(`${method} ${url}`);
|
|
479
495
|
if (req.method === "OPTIONS") {
|
|
480
|
-
res.
|
|
481
|
-
|
|
496
|
+
if (res instanceof import_node_http.default.ServerResponse) {
|
|
497
|
+
res.statusCode = 204;
|
|
498
|
+
res.end();
|
|
499
|
+
} else {
|
|
500
|
+
const h2Res = res;
|
|
501
|
+
h2Res.writeHead(204);
|
|
502
|
+
h2Res.end();
|
|
503
|
+
}
|
|
482
504
|
return;
|
|
483
505
|
}
|
|
484
506
|
try {
|
|
@@ -603,14 +625,25 @@ var MikroServe = class {
|
|
|
603
625
|
* @description Set security headers.
|
|
604
626
|
*/
|
|
605
627
|
setSecurityHeaders(res, isHttps = false) {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
"Content-Security-Policy",
|
|
610
|
-
"
|
|
611
|
-
|
|
612
|
-
if (isHttps
|
|
613
|
-
|
|
628
|
+
const securityHeaders = {
|
|
629
|
+
"X-Content-Type-Options": "nosniff",
|
|
630
|
+
"X-Frame-Options": "DENY",
|
|
631
|
+
"Content-Security-Policy": "default-src 'self'; script-src 'self'; object-src 'none'",
|
|
632
|
+
"X-XSS-Protection": "1; mode=block"
|
|
633
|
+
};
|
|
634
|
+
if (isHttps || this.config.useHttp2) {
|
|
635
|
+
securityHeaders["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";
|
|
636
|
+
}
|
|
637
|
+
if (res instanceof import_node_http.default.ServerResponse) {
|
|
638
|
+
Object.entries(securityHeaders).forEach(([name, value]) => {
|
|
639
|
+
res.setHeader(name, value);
|
|
640
|
+
});
|
|
641
|
+
} else {
|
|
642
|
+
const h2Res = res;
|
|
643
|
+
Object.entries(securityHeaders).forEach(([name, value]) => {
|
|
644
|
+
h2Res.setHeader(name, value);
|
|
645
|
+
});
|
|
646
|
+
}
|
|
614
647
|
}
|
|
615
648
|
/**
|
|
616
649
|
* @description Sends a response with appropriate headers.
|
|
@@ -619,10 +652,21 @@ var MikroServe = class {
|
|
|
619
652
|
const headers = {
|
|
620
653
|
...response.headers || {}
|
|
621
654
|
};
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
655
|
+
const hasWriteHead = (res2) => {
|
|
656
|
+
return typeof res2.writeHead === "function" && typeof res2.end === "function";
|
|
657
|
+
};
|
|
658
|
+
if (hasWriteHead(res)) {
|
|
659
|
+
res.writeHead(response.statusCode, headers);
|
|
660
|
+
if (response.body === null || response.body === void 0) res.end();
|
|
661
|
+
else if (typeof response.body === "string") res.end(response.body);
|
|
662
|
+
else res.end(JSON.stringify(response.body));
|
|
663
|
+
} else {
|
|
664
|
+
console.warn("Unexpected response object type without writeHead/end methods");
|
|
665
|
+
res.writeHead?.(response.statusCode, headers);
|
|
666
|
+
if (response.body === null || response.body === void 0) res.end?.();
|
|
667
|
+
else if (typeof response.body === "string") res.end?.(response.body);
|
|
668
|
+
else res.end?.(JSON.stringify(response.body));
|
|
669
|
+
}
|
|
626
670
|
}
|
|
627
671
|
/**
|
|
628
672
|
* @description Sets up graceful shutdown handlers for a server.
|
package/lib/MikroServe.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MikroServe
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-J2WPHNMW.mjs";
|
|
4
4
|
import "./chunk-ZFBBESGU.mjs";
|
|
5
5
|
import "./chunk-KJT4SET2.mjs";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-6HESV5Q6.mjs";
|
|
6
|
+
import "./chunk-JJX5XRNB.mjs";
|
|
8
7
|
export {
|
|
9
8
|
MikroServe
|
|
10
9
|
};
|
package/lib/Router.d.mts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { Middleware, RouteHandler, Route, RequestType, ResponseType, HandlerResponse } from './interfaces/index.mjs';
|
|
2
|
+
import 'node:http';
|
|
3
|
+
import 'node:http2';
|
|
4
|
+
import 'node:https';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Router class to manage routes and middleware
|
|
@@ -54,7 +56,7 @@ declare class Router {
|
|
|
54
56
|
/**
|
|
55
57
|
* Handle a request and find the matching route
|
|
56
58
|
*/
|
|
57
|
-
handle(req:
|
|
59
|
+
handle(req: RequestType, res: ResponseType): Promise<HandlerResponse | null>;
|
|
58
60
|
/**
|
|
59
61
|
* Execute middleware chain and final handler
|
|
60
62
|
*/
|
package/lib/Router.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { Middleware, RouteHandler, Route, RequestType, ResponseType, HandlerResponse } from './interfaces/index.js';
|
|
2
|
+
import 'node:http';
|
|
3
|
+
import 'node:http2';
|
|
4
|
+
import 'node:https';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Router class to manage routes and middleware
|
|
@@ -54,7 +56,7 @@ declare class Router {
|
|
|
54
56
|
/**
|
|
55
57
|
* Handle a request and find the matching route
|
|
56
58
|
*/
|
|
57
|
-
handle(req:
|
|
59
|
+
handle(req: RequestType, res: ResponseType): Promise<HandlerResponse | null>;
|
|
58
60
|
/**
|
|
59
61
|
* Execute middleware chain and final handler
|
|
60
62
|
*/
|
|
@@ -6,11 +6,12 @@ import {
|
|
|
6
6
|
} from "./chunk-KJT4SET2.mjs";
|
|
7
7
|
import {
|
|
8
8
|
configDefaults
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-JJX5XRNB.mjs";
|
|
10
10
|
|
|
11
11
|
// src/MikroServe.ts
|
|
12
12
|
import { readFileSync } from "node:fs";
|
|
13
13
|
import http from "node:http";
|
|
14
|
+
import http2 from "node:http2";
|
|
14
15
|
import https from "node:https";
|
|
15
16
|
import { MikroConf, parsers } from "mikroconf";
|
|
16
17
|
var MikroServe = class {
|
|
@@ -29,6 +30,7 @@ var MikroServe = class {
|
|
|
29
30
|
{ flag: "--port", path: "port", defaultValue: defaults.port },
|
|
30
31
|
{ flag: "--host", path: "host", defaultValue: defaults.host },
|
|
31
32
|
{ flag: "--https", path: "useHttps", defaultValue: defaults.useHttps, isFlag: true },
|
|
33
|
+
{ flag: "--http2", path: "useHttp2", defaultValue: defaults.useHttp2, isFlag: true },
|
|
32
34
|
{ flag: "--cert", path: "sslCert", defaultValue: defaults.sslCert },
|
|
33
35
|
{ flag: "--key", path: "sslKey", defaultValue: defaults.sslKey },
|
|
34
36
|
{ flag: "--ca", path: "sslCa", defaultValue: defaults.sslCa },
|
|
@@ -130,7 +132,22 @@ var MikroServe = class {
|
|
|
130
132
|
*/
|
|
131
133
|
createServer() {
|
|
132
134
|
const boundRequestHandler = this.requestHandler.bind(this);
|
|
133
|
-
if (this.config.
|
|
135
|
+
if (this.config.useHttp2) {
|
|
136
|
+
if (!this.config.sslCert || !this.config.sslKey)
|
|
137
|
+
throw new Error("SSL certificate and key paths are required when useHttp2 is true");
|
|
138
|
+
try {
|
|
139
|
+
const httpsOptions = {
|
|
140
|
+
key: readFileSync(this.config.sslKey),
|
|
141
|
+
cert: readFileSync(this.config.sslCert),
|
|
142
|
+
...this.config.sslCa ? { ca: readFileSync(this.config.sslCa) } : {}
|
|
143
|
+
};
|
|
144
|
+
return http2.createSecureServer(httpsOptions, boundRequestHandler);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (error.message.includes("key values mismatch"))
|
|
147
|
+
throw new Error(`SSL certificate and key do not match: ${error.message}`);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
} else if (this.config.useHttps) {
|
|
134
151
|
if (!this.config.sslCert || !this.config.sslKey)
|
|
135
152
|
throw new Error("SSL certificate and key paths are required when useHttps is true");
|
|
136
153
|
try {
|
|
@@ -184,8 +201,14 @@ var MikroServe = class {
|
|
|
184
201
|
this.setSecurityHeaders(res, this.config.useHttps);
|
|
185
202
|
if (isDebug) console.log(`${method} ${url}`);
|
|
186
203
|
if (req.method === "OPTIONS") {
|
|
187
|
-
res.
|
|
188
|
-
|
|
204
|
+
if (res instanceof http.ServerResponse) {
|
|
205
|
+
res.statusCode = 204;
|
|
206
|
+
res.end();
|
|
207
|
+
} else {
|
|
208
|
+
const h2Res = res;
|
|
209
|
+
h2Res.writeHead(204);
|
|
210
|
+
h2Res.end();
|
|
211
|
+
}
|
|
189
212
|
return;
|
|
190
213
|
}
|
|
191
214
|
try {
|
|
@@ -310,14 +333,25 @@ var MikroServe = class {
|
|
|
310
333
|
* @description Set security headers.
|
|
311
334
|
*/
|
|
312
335
|
setSecurityHeaders(res, isHttps = false) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
"Content-Security-Policy",
|
|
317
|
-
"
|
|
318
|
-
|
|
319
|
-
if (isHttps
|
|
320
|
-
|
|
336
|
+
const securityHeaders = {
|
|
337
|
+
"X-Content-Type-Options": "nosniff",
|
|
338
|
+
"X-Frame-Options": "DENY",
|
|
339
|
+
"Content-Security-Policy": "default-src 'self'; script-src 'self'; object-src 'none'",
|
|
340
|
+
"X-XSS-Protection": "1; mode=block"
|
|
341
|
+
};
|
|
342
|
+
if (isHttps || this.config.useHttp2) {
|
|
343
|
+
securityHeaders["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";
|
|
344
|
+
}
|
|
345
|
+
if (res instanceof http.ServerResponse) {
|
|
346
|
+
Object.entries(securityHeaders).forEach(([name, value]) => {
|
|
347
|
+
res.setHeader(name, value);
|
|
348
|
+
});
|
|
349
|
+
} else {
|
|
350
|
+
const h2Res = res;
|
|
351
|
+
Object.entries(securityHeaders).forEach(([name, value]) => {
|
|
352
|
+
h2Res.setHeader(name, value);
|
|
353
|
+
});
|
|
354
|
+
}
|
|
321
355
|
}
|
|
322
356
|
/**
|
|
323
357
|
* @description Sends a response with appropriate headers.
|
|
@@ -326,10 +360,21 @@ var MikroServe = class {
|
|
|
326
360
|
const headers = {
|
|
327
361
|
...response.headers || {}
|
|
328
362
|
};
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
363
|
+
const hasWriteHead = (res2) => {
|
|
364
|
+
return typeof res2.writeHead === "function" && typeof res2.end === "function";
|
|
365
|
+
};
|
|
366
|
+
if (hasWriteHead(res)) {
|
|
367
|
+
res.writeHead(response.statusCode, headers);
|
|
368
|
+
if (response.body === null || response.body === void 0) res.end();
|
|
369
|
+
else if (typeof response.body === "string") res.end(response.body);
|
|
370
|
+
else res.end(JSON.stringify(response.body));
|
|
371
|
+
} else {
|
|
372
|
+
console.warn("Unexpected response object type without writeHead/end methods");
|
|
373
|
+
res.writeHead?.(response.statusCode, headers);
|
|
374
|
+
if (response.body === null || response.body === void 0) res.end?.();
|
|
375
|
+
else if (typeof response.body === "string") res.end?.(response.body);
|
|
376
|
+
else res.end?.(JSON.stringify(response.body));
|
|
377
|
+
}
|
|
333
378
|
}
|
|
334
379
|
/**
|
|
335
380
|
* @description Sets up graceful shutdown handlers for a server.
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getTruthyValue
|
|
3
|
-
} from "./chunk-6HESV5Q6.mjs";
|
|
4
|
-
|
|
5
1
|
// src/utils/configDefaults.ts
|
|
6
2
|
var configDefaults = () => {
|
|
7
3
|
return {
|
|
8
4
|
port: Number(process.env.PORT) || 3e3,
|
|
9
5
|
host: process.env.HOST || "0.0.0.0",
|
|
10
6
|
useHttps: false,
|
|
7
|
+
useHttp2: false,
|
|
11
8
|
sslCert: "",
|
|
12
9
|
sslKey: "",
|
|
13
10
|
sslCa: "",
|
|
@@ -25,6 +22,7 @@ var getDefaultConfig = () => {
|
|
|
25
22
|
port: defaults.port,
|
|
26
23
|
host: defaults.host,
|
|
27
24
|
useHttps: defaults.useHttps,
|
|
25
|
+
useHttp2: defaults.useHttp2,
|
|
28
26
|
sslCert: defaults.sslCert,
|
|
29
27
|
sslKey: defaults.sslKey,
|
|
30
28
|
sslCa: defaults.sslCa,
|
|
@@ -36,6 +34,10 @@ var getDefaultConfig = () => {
|
|
|
36
34
|
allowedDomains: defaults.allowedDomains
|
|
37
35
|
};
|
|
38
36
|
};
|
|
37
|
+
function getTruthyValue(value) {
|
|
38
|
+
if (value === "true" || value === true) return true;
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
39
41
|
|
|
40
42
|
export {
|
|
41
43
|
configDefaults,
|
package/lib/index.d.mts
CHANGED
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -37,6 +37,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
37
37
|
// src/MikroServe.ts
|
|
38
38
|
var import_node_fs = require("fs");
|
|
39
39
|
var import_node_http = __toESM(require("http"));
|
|
40
|
+
var import_node_http2 = __toESM(require("http2"));
|
|
40
41
|
var import_node_https = __toESM(require("https"));
|
|
41
42
|
var import_mikroconf = require("mikroconf");
|
|
42
43
|
|
|
@@ -283,18 +284,13 @@ var Router = class {
|
|
|
283
284
|
}
|
|
284
285
|
};
|
|
285
286
|
|
|
286
|
-
// src/utils/getTruthyValue.ts
|
|
287
|
-
function getTruthyValue(value) {
|
|
288
|
-
if (value === "true" || value === true) return true;
|
|
289
|
-
return false;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
287
|
// src/utils/configDefaults.ts
|
|
293
288
|
var configDefaults = () => {
|
|
294
289
|
return {
|
|
295
290
|
port: Number(process.env.PORT) || 3e3,
|
|
296
291
|
host: process.env.HOST || "0.0.0.0",
|
|
297
292
|
useHttps: false,
|
|
293
|
+
useHttp2: false,
|
|
298
294
|
sslCert: "",
|
|
299
295
|
sslKey: "",
|
|
300
296
|
sslCa: "",
|
|
@@ -306,6 +302,10 @@ var configDefaults = () => {
|
|
|
306
302
|
allowedDomains: ["*"]
|
|
307
303
|
};
|
|
308
304
|
};
|
|
305
|
+
function getTruthyValue(value) {
|
|
306
|
+
if (value === "true" || value === true) return true;
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
309
|
|
|
310
310
|
// src/MikroServe.ts
|
|
311
311
|
var MikroServe = class {
|
|
@@ -324,6 +324,7 @@ var MikroServe = class {
|
|
|
324
324
|
{ flag: "--port", path: "port", defaultValue: defaults.port },
|
|
325
325
|
{ flag: "--host", path: "host", defaultValue: defaults.host },
|
|
326
326
|
{ flag: "--https", path: "useHttps", defaultValue: defaults.useHttps, isFlag: true },
|
|
327
|
+
{ flag: "--http2", path: "useHttp2", defaultValue: defaults.useHttp2, isFlag: true },
|
|
327
328
|
{ flag: "--cert", path: "sslCert", defaultValue: defaults.sslCert },
|
|
328
329
|
{ flag: "--key", path: "sslKey", defaultValue: defaults.sslKey },
|
|
329
330
|
{ flag: "--ca", path: "sslCa", defaultValue: defaults.sslCa },
|
|
@@ -425,7 +426,22 @@ var MikroServe = class {
|
|
|
425
426
|
*/
|
|
426
427
|
createServer() {
|
|
427
428
|
const boundRequestHandler = this.requestHandler.bind(this);
|
|
428
|
-
if (this.config.
|
|
429
|
+
if (this.config.useHttp2) {
|
|
430
|
+
if (!this.config.sslCert || !this.config.sslKey)
|
|
431
|
+
throw new Error("SSL certificate and key paths are required when useHttp2 is true");
|
|
432
|
+
try {
|
|
433
|
+
const httpsOptions = {
|
|
434
|
+
key: (0, import_node_fs.readFileSync)(this.config.sslKey),
|
|
435
|
+
cert: (0, import_node_fs.readFileSync)(this.config.sslCert),
|
|
436
|
+
...this.config.sslCa ? { ca: (0, import_node_fs.readFileSync)(this.config.sslCa) } : {}
|
|
437
|
+
};
|
|
438
|
+
return import_node_http2.default.createSecureServer(httpsOptions, boundRequestHandler);
|
|
439
|
+
} catch (error) {
|
|
440
|
+
if (error.message.includes("key values mismatch"))
|
|
441
|
+
throw new Error(`SSL certificate and key do not match: ${error.message}`);
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
} else if (this.config.useHttps) {
|
|
429
445
|
if (!this.config.sslCert || !this.config.sslKey)
|
|
430
446
|
throw new Error("SSL certificate and key paths are required when useHttps is true");
|
|
431
447
|
try {
|
|
@@ -479,8 +495,14 @@ var MikroServe = class {
|
|
|
479
495
|
this.setSecurityHeaders(res, this.config.useHttps);
|
|
480
496
|
if (isDebug) console.log(`${method} ${url}`);
|
|
481
497
|
if (req.method === "OPTIONS") {
|
|
482
|
-
res.
|
|
483
|
-
|
|
498
|
+
if (res instanceof import_node_http.default.ServerResponse) {
|
|
499
|
+
res.statusCode = 204;
|
|
500
|
+
res.end();
|
|
501
|
+
} else {
|
|
502
|
+
const h2Res = res;
|
|
503
|
+
h2Res.writeHead(204);
|
|
504
|
+
h2Res.end();
|
|
505
|
+
}
|
|
484
506
|
return;
|
|
485
507
|
}
|
|
486
508
|
try {
|
|
@@ -605,14 +627,25 @@ var MikroServe = class {
|
|
|
605
627
|
* @description Set security headers.
|
|
606
628
|
*/
|
|
607
629
|
setSecurityHeaders(res, isHttps = false) {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
"Content-Security-Policy",
|
|
612
|
-
"
|
|
613
|
-
|
|
614
|
-
if (isHttps
|
|
615
|
-
|
|
630
|
+
const securityHeaders = {
|
|
631
|
+
"X-Content-Type-Options": "nosniff",
|
|
632
|
+
"X-Frame-Options": "DENY",
|
|
633
|
+
"Content-Security-Policy": "default-src 'self'; script-src 'self'; object-src 'none'",
|
|
634
|
+
"X-XSS-Protection": "1; mode=block"
|
|
635
|
+
};
|
|
636
|
+
if (isHttps || this.config.useHttp2) {
|
|
637
|
+
securityHeaders["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";
|
|
638
|
+
}
|
|
639
|
+
if (res instanceof import_node_http.default.ServerResponse) {
|
|
640
|
+
Object.entries(securityHeaders).forEach(([name, value]) => {
|
|
641
|
+
res.setHeader(name, value);
|
|
642
|
+
});
|
|
643
|
+
} else {
|
|
644
|
+
const h2Res = res;
|
|
645
|
+
Object.entries(securityHeaders).forEach(([name, value]) => {
|
|
646
|
+
h2Res.setHeader(name, value);
|
|
647
|
+
});
|
|
648
|
+
}
|
|
616
649
|
}
|
|
617
650
|
/**
|
|
618
651
|
* @description Sends a response with appropriate headers.
|
|
@@ -621,10 +654,21 @@ var MikroServe = class {
|
|
|
621
654
|
const headers = {
|
|
622
655
|
...response.headers || {}
|
|
623
656
|
};
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
657
|
+
const hasWriteHead = (res2) => {
|
|
658
|
+
return typeof res2.writeHead === "function" && typeof res2.end === "function";
|
|
659
|
+
};
|
|
660
|
+
if (hasWriteHead(res)) {
|
|
661
|
+
res.writeHead(response.statusCode, headers);
|
|
662
|
+
if (response.body === null || response.body === void 0) res.end();
|
|
663
|
+
else if (typeof response.body === "string") res.end(response.body);
|
|
664
|
+
else res.end(JSON.stringify(response.body));
|
|
665
|
+
} else {
|
|
666
|
+
console.warn("Unexpected response object type without writeHead/end methods");
|
|
667
|
+
res.writeHead?.(response.statusCode, headers);
|
|
668
|
+
if (response.body === null || response.body === void 0) res.end?.();
|
|
669
|
+
else if (typeof response.body === "string") res.end?.(response.body);
|
|
670
|
+
else res.end?.(JSON.stringify(response.body));
|
|
671
|
+
}
|
|
628
672
|
}
|
|
629
673
|
/**
|
|
630
674
|
* @description Sets up graceful shutdown handlers for a server.
|
package/lib/index.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MikroServe
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-J2WPHNMW.mjs";
|
|
4
4
|
import "./chunk-ZFBBESGU.mjs";
|
|
5
5
|
import "./chunk-KJT4SET2.mjs";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-6HESV5Q6.mjs";
|
|
6
|
+
import "./chunk-JJX5XRNB.mjs";
|
|
8
7
|
export {
|
|
9
8
|
MikroServe
|
|
10
9
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
|
+
import http2 from 'node:http2';
|
|
3
|
+
import https from 'node:https';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* @description Server configuration options.
|
|
@@ -21,6 +23,11 @@ type MikroServeConfiguration = {
|
|
|
21
23
|
* @default false
|
|
22
24
|
*/
|
|
23
25
|
useHttps: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Should the server use HTTP2?
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
useHttp2: boolean;
|
|
24
31
|
/**
|
|
25
32
|
* The path to the SSL certificate.
|
|
26
33
|
* @default '''
|
|
@@ -82,12 +89,12 @@ interface ResponseHelpers {
|
|
|
82
89
|
* @description Context object passed to route handlers.
|
|
83
90
|
*/
|
|
84
91
|
interface Context extends ResponseHelpers {
|
|
85
|
-
req: http.IncomingMessage;
|
|
86
|
-
res: http.ServerResponse;
|
|
92
|
+
req: http.IncomingMessage | http2.Http2ServerRequest;
|
|
93
|
+
res: http.ServerResponse | http2.Http2ServerResponse;
|
|
87
94
|
params: Record<string, string>;
|
|
88
95
|
query: Record<string, string>;
|
|
89
96
|
body: any;
|
|
90
|
-
headers: http.IncomingHttpHeaders;
|
|
97
|
+
headers: http.IncomingHttpHeaders | http2.IncomingHttpHeaders;
|
|
91
98
|
path: string;
|
|
92
99
|
state: Record<string, any>;
|
|
93
100
|
}
|
|
@@ -124,5 +131,13 @@ interface PathPattern {
|
|
|
124
131
|
pattern: RegExp;
|
|
125
132
|
paramNames: string[];
|
|
126
133
|
}
|
|
134
|
+
type ServerType = http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer;
|
|
135
|
+
type RequestType = http.IncomingMessage | http2.Http2ServerRequest;
|
|
136
|
+
type ResponseType = http.ServerResponse | http2.Http2ServerResponse | {
|
|
137
|
+
setHeader: (name: string, value: string) => void;
|
|
138
|
+
getHeaders?: () => Record<string, string | string[] | number>;
|
|
139
|
+
writeHead: (statusCode: number, headers: Record<string, string | string[] | number>) => void;
|
|
140
|
+
statusCode?: number;
|
|
141
|
+
};
|
|
127
142
|
|
|
128
|
-
export type { Context, HandlerResponse, Middleware, MikroServeConfiguration, MikroServeOptions, PathPattern, ResponseHelpers, Route, RouteHandler };
|
|
143
|
+
export type { Context, HandlerResponse, Middleware, MikroServeConfiguration, MikroServeOptions, PathPattern, RequestType, ResponseHelpers, ResponseType, Route, RouteHandler, ServerType };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
|
+
import http2 from 'node:http2';
|
|
3
|
+
import https from 'node:https';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* @description Server configuration options.
|
|
@@ -21,6 +23,11 @@ type MikroServeConfiguration = {
|
|
|
21
23
|
* @default false
|
|
22
24
|
*/
|
|
23
25
|
useHttps: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Should the server use HTTP2?
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
useHttp2: boolean;
|
|
24
31
|
/**
|
|
25
32
|
* The path to the SSL certificate.
|
|
26
33
|
* @default '''
|
|
@@ -82,12 +89,12 @@ interface ResponseHelpers {
|
|
|
82
89
|
* @description Context object passed to route handlers.
|
|
83
90
|
*/
|
|
84
91
|
interface Context extends ResponseHelpers {
|
|
85
|
-
req: http.IncomingMessage;
|
|
86
|
-
res: http.ServerResponse;
|
|
92
|
+
req: http.IncomingMessage | http2.Http2ServerRequest;
|
|
93
|
+
res: http.ServerResponse | http2.Http2ServerResponse;
|
|
87
94
|
params: Record<string, string>;
|
|
88
95
|
query: Record<string, string>;
|
|
89
96
|
body: any;
|
|
90
|
-
headers: http.IncomingHttpHeaders;
|
|
97
|
+
headers: http.IncomingHttpHeaders | http2.IncomingHttpHeaders;
|
|
91
98
|
path: string;
|
|
92
99
|
state: Record<string, any>;
|
|
93
100
|
}
|
|
@@ -124,5 +131,13 @@ interface PathPattern {
|
|
|
124
131
|
pattern: RegExp;
|
|
125
132
|
paramNames: string[];
|
|
126
133
|
}
|
|
134
|
+
type ServerType = http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer;
|
|
135
|
+
type RequestType = http.IncomingMessage | http2.Http2ServerRequest;
|
|
136
|
+
type ResponseType = http.ServerResponse | http2.Http2ServerResponse | {
|
|
137
|
+
setHeader: (name: string, value: string) => void;
|
|
138
|
+
getHeaders?: () => Record<string, string | string[] | number>;
|
|
139
|
+
writeHead: (statusCode: number, headers: Record<string, string | string[] | number>) => void;
|
|
140
|
+
statusCode?: number;
|
|
141
|
+
};
|
|
127
142
|
|
|
128
|
-
export type { Context, HandlerResponse, Middleware, MikroServeConfiguration, MikroServeOptions, PathPattern, ResponseHelpers, Route, RouteHandler };
|
|
143
|
+
export type { Context, HandlerResponse, Middleware, MikroServeConfiguration, MikroServeOptions, PathPattern, RequestType, ResponseHelpers, ResponseType, Route, RouteHandler, ServerType };
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { MikroServeConfiguration } from '../interfaces/index.mjs';
|
|
2
2
|
import 'node:http';
|
|
3
|
+
import 'node:http2';
|
|
4
|
+
import 'node:https';
|
|
3
5
|
|
|
4
6
|
declare const configDefaults: () => MikroServeConfiguration;
|
|
5
7
|
declare const getDefaultConfig: () => {
|
|
6
8
|
port: number;
|
|
7
9
|
host: string;
|
|
8
10
|
useHttps: boolean;
|
|
11
|
+
useHttp2: boolean;
|
|
9
12
|
sslCert: string;
|
|
10
13
|
sslKey: string;
|
|
11
14
|
sslCa: string;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { MikroServeConfiguration } from '../interfaces/index.js';
|
|
2
2
|
import 'node:http';
|
|
3
|
+
import 'node:http2';
|
|
4
|
+
import 'node:https';
|
|
3
5
|
|
|
4
6
|
declare const configDefaults: () => MikroServeConfiguration;
|
|
5
7
|
declare const getDefaultConfig: () => {
|
|
6
8
|
port: number;
|
|
7
9
|
host: string;
|
|
8
10
|
useHttps: boolean;
|
|
11
|
+
useHttp2: boolean;
|
|
9
12
|
sslCert: string;
|
|
10
13
|
sslKey: string;
|
|
11
14
|
sslCa: string;
|
|
@@ -24,19 +24,12 @@ __export(configDefaults_exports, {
|
|
|
24
24
|
getDefaultConfig: () => getDefaultConfig
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(configDefaults_exports);
|
|
27
|
-
|
|
28
|
-
// src/utils/getTruthyValue.ts
|
|
29
|
-
function getTruthyValue(value) {
|
|
30
|
-
if (value === "true" || value === true) return true;
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// src/utils/configDefaults.ts
|
|
35
27
|
var configDefaults = () => {
|
|
36
28
|
return {
|
|
37
29
|
port: Number(process.env.PORT) || 3e3,
|
|
38
30
|
host: process.env.HOST || "0.0.0.0",
|
|
39
31
|
useHttps: false,
|
|
32
|
+
useHttp2: false,
|
|
40
33
|
sslCert: "",
|
|
41
34
|
sslKey: "",
|
|
42
35
|
sslCa: "",
|
|
@@ -54,6 +47,7 @@ var getDefaultConfig = () => {
|
|
|
54
47
|
port: defaults.port,
|
|
55
48
|
host: defaults.host,
|
|
56
49
|
useHttps: defaults.useHttps,
|
|
50
|
+
useHttp2: defaults.useHttp2,
|
|
57
51
|
sslCert: defaults.sslCert,
|
|
58
52
|
sslKey: defaults.sslKey,
|
|
59
53
|
sslCa: defaults.sslCa,
|
|
@@ -65,6 +59,10 @@ var getDefaultConfig = () => {
|
|
|
65
59
|
allowedDomains: defaults.allowedDomains
|
|
66
60
|
};
|
|
67
61
|
};
|
|
62
|
+
function getTruthyValue(value) {
|
|
63
|
+
if (value === "true" || value === true) return true;
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
68
66
|
// Annotate the CommonJS export names for ESM import in node:
|
|
69
67
|
0 && (module.exports = {
|
|
70
68
|
configDefaults,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mikroserve",
|
|
3
3
|
"description": "Minimalistic, ready-to-use API, built on Node.js primitives.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.7",
|
|
5
5
|
"author": "Mikael Vesavuori",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -61,6 +61,6 @@
|
|
|
61
61
|
"vitest": "2"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"mikroconf": "
|
|
64
|
+
"mikroconf": "latest"
|
|
65
65
|
}
|
|
66
66
|
}
|
package/lib/chunk-6HESV5Q6.mjs
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/utils/getTruthyValue.ts
|
|
21
|
-
var getTruthyValue_exports = {};
|
|
22
|
-
__export(getTruthyValue_exports, {
|
|
23
|
-
getTruthyValue: () => getTruthyValue
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(getTruthyValue_exports);
|
|
26
|
-
function getTruthyValue(value) {
|
|
27
|
-
if (value === "true" || value === true) return true;
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
31
|
-
0 && (module.exports = {
|
|
32
|
-
getTruthyValue
|
|
33
|
-
});
|