@radatek/microserver 3.0.6 → 3.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/microserver.d.ts +20 -14
- package/microserver.js +39 -24
- package/package.json +1 -1
package/microserver.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MicroServer
|
|
3
|
-
* @version 3.0.
|
|
3
|
+
* @version 3.0.7
|
|
4
4
|
* @package @radatek/microserver
|
|
5
5
|
* @copyright Darius Kisonas 2022
|
|
6
6
|
* @license MIT
|
|
@@ -44,7 +44,6 @@ export declare abstract class Plugin {
|
|
|
44
44
|
priority?: number;
|
|
45
45
|
handler?(req: ServerRequest, res: ServerResponse, next: Function): Promise<string | object | void> | string | object | void;
|
|
46
46
|
routes?(): Promise<RoutesSet | void> | RoutesSet | void;
|
|
47
|
-
constructor();
|
|
48
47
|
}
|
|
49
48
|
interface PluginClass {
|
|
50
49
|
new (options: any, server: MicroServer): Plugin;
|
|
@@ -86,6 +85,7 @@ export declare class ServerRequest<T = any> extends http.IncomingMessage {
|
|
|
86
85
|
rawBody: Buffer[];
|
|
87
86
|
/** Request raw body size */
|
|
88
87
|
rawBodySize: number;
|
|
88
|
+
protected constructor(res: http.ServerResponse, server: MicroServer);
|
|
89
89
|
/** Extend http.IncomingMessage */
|
|
90
90
|
static extend(req: http.IncomingMessage, res: http.ServerResponse, server: MicroServer): ServerRequest;
|
|
91
91
|
/** Check if request is ready */
|
|
@@ -114,6 +114,7 @@ export declare class ServerResponse<T = any> extends http.ServerResponse {
|
|
|
114
114
|
readonly req: ServerRequest<T>;
|
|
115
115
|
/** Should response be json */
|
|
116
116
|
isJson: boolean;
|
|
117
|
+
protected constructor(server: MicroServer);
|
|
117
118
|
/** Extends http.ServerResponse */
|
|
118
119
|
static extend(res: http.ServerResponse): void;
|
|
119
120
|
/** Send error reponse */
|
|
@@ -162,7 +163,7 @@ export interface MicroServerConfig extends ListenConfig {
|
|
|
162
163
|
/** extra options for plugins */
|
|
163
164
|
[key: string]: any;
|
|
164
165
|
}
|
|
165
|
-
interface MicroServerEvents {
|
|
166
|
+
export interface MicroServerEvents {
|
|
166
167
|
ready: () => void;
|
|
167
168
|
close: () => void;
|
|
168
169
|
listen: (port: number, address: string, server: http.Server) => void;
|
|
@@ -258,6 +259,7 @@ export interface CorsOptions {
|
|
|
258
259
|
/** Max age */
|
|
259
260
|
maxAge?: number;
|
|
260
261
|
}
|
|
262
|
+
/** CORS plugin. Config may be: true - allow all, string - allow specific origin, or CorsOptions */
|
|
261
263
|
export declare class CorsPlugin extends Plugin {
|
|
262
264
|
priority: number;
|
|
263
265
|
name: string;
|
|
@@ -265,6 +267,7 @@ export declare class CorsPlugin extends Plugin {
|
|
|
265
267
|
constructor(options?: CorsOptions | string | true);
|
|
266
268
|
handler?(req: ServerRequest, res: ServerResponse, next: Function): Promise<string | object | void> | string | object | void;
|
|
267
269
|
}
|
|
270
|
+
/** Methods plugin to support OPTIONS method, and restrict allowed methods. Configuration is comma separated string */
|
|
268
271
|
export declare class MethodsPlugin extends Plugin {
|
|
269
272
|
priority: number;
|
|
270
273
|
name: string;
|
|
@@ -274,6 +277,7 @@ export declare class MethodsPlugin extends Plugin {
|
|
|
274
277
|
export interface BodyOptions {
|
|
275
278
|
maxBodySize?: number;
|
|
276
279
|
}
|
|
280
|
+
/** Body parser plugin */
|
|
277
281
|
export declare class BodyPlugin extends Plugin {
|
|
278
282
|
priority: number;
|
|
279
283
|
name: string;
|
|
@@ -291,6 +295,7 @@ export interface UploadFile {
|
|
|
291
295
|
size: number;
|
|
292
296
|
filePath?: string;
|
|
293
297
|
}
|
|
298
|
+
/** Upload plugin, At least uploadDir option is required */
|
|
294
299
|
export declare class UploadPlugin extends Plugin {
|
|
295
300
|
priority: number;
|
|
296
301
|
name: string;
|
|
@@ -321,7 +326,7 @@ interface WebSocketEvents {
|
|
|
321
326
|
message: (data: string | Buffer | ArrayBuffer | Blob) => void;
|
|
322
327
|
open: () => void;
|
|
323
328
|
}
|
|
324
|
-
/** WebSocket class */
|
|
329
|
+
/** WebSocket class used in upgrade handler */
|
|
325
330
|
export declare class WebSocket extends EventEmitter {
|
|
326
331
|
ready: boolean;
|
|
327
332
|
constructor(req: ServerRequest, options?: WebSocketOptions);
|
|
@@ -339,6 +344,7 @@ export declare class WebSocket extends EventEmitter {
|
|
|
339
344
|
off<K extends keyof WebSocketEvents>(event: K, listener: WebSocketEvents[K]): this;
|
|
340
345
|
removeListener<K extends keyof WebSocketEvents>(event: K, listener: WebSocketEvents[K]): this;
|
|
341
346
|
}
|
|
347
|
+
/** WebSocket plugin to support `WEBSOCKET /url` routes */
|
|
342
348
|
export declare class WebSocketPlugin extends Plugin {
|
|
343
349
|
name: string;
|
|
344
350
|
constructor(options?: any, server?: MicroServer);
|
|
@@ -385,6 +391,8 @@ export interface StaticFilesOptions {
|
|
|
385
391
|
maxAge?: number;
|
|
386
392
|
/** static errors file for status code, '*' - default */
|
|
387
393
|
errors?: Record<string, string>;
|
|
394
|
+
/** check precompressed file */
|
|
395
|
+
precompressedGzip?: boolean;
|
|
388
396
|
}
|
|
389
397
|
export interface ServeFileOptions {
|
|
390
398
|
/** path */
|
|
@@ -406,11 +414,7 @@ export interface ServeFileOptions {
|
|
|
406
414
|
/** stat */
|
|
407
415
|
stats?: fs.Stats;
|
|
408
416
|
}
|
|
409
|
-
/**
|
|
410
|
-
* Static files middleware plugin
|
|
411
|
-
* Usage: server.use('static', '/public')
|
|
412
|
-
* Usage: server.use('static', { root: 'public', path: '/static' })
|
|
413
|
-
*/
|
|
417
|
+
/** Static files plugin. At least must be path to public folder as string or StaticFilesOptions */
|
|
414
418
|
export declare class StaticFilesPlugin extends Plugin {
|
|
415
419
|
priority: number;
|
|
416
420
|
/** Default mime types */
|
|
@@ -439,6 +443,7 @@ export declare class StaticFilesPlugin extends Plugin {
|
|
|
439
443
|
maxAge?: number;
|
|
440
444
|
prefix: string;
|
|
441
445
|
errors?: Record<string, string>;
|
|
446
|
+
checkPrecompressedGzip?: boolean;
|
|
442
447
|
constructor(options?: StaticFilesOptions | string, server?: MicroServer);
|
|
443
448
|
/** Default static files handler */
|
|
444
449
|
handler(req: ServerRequest, res: ServerResponse, next: Function): any;
|
|
@@ -462,9 +467,9 @@ export interface ProxyOptions {
|
|
|
462
467
|
[key: string]: boolean;
|
|
463
468
|
};
|
|
464
469
|
}
|
|
470
|
+
/** Reverse proxy plugin, At least remote url as string or in ProxyOptions is required */
|
|
465
471
|
export declare class ProxyPlugin extends Plugin {
|
|
466
472
|
priority: number;
|
|
467
|
-
name: string;
|
|
468
473
|
/** Default valid headers */
|
|
469
474
|
static validHeaders: {
|
|
470
475
|
[key: string]: boolean;
|
|
@@ -610,6 +615,7 @@ export declare class AuthPlugin extends Plugin {
|
|
|
610
615
|
/** Authentication middleware */
|
|
611
616
|
handler(req: ServerRequest, res: ServerResponse, next: Function): Promise<any>;
|
|
612
617
|
}
|
|
618
|
+
/** Load standard plugins with predefined configs: MethodsPlugin, CorsPlugin, TrustProxyPlugin, BodyPlugin, AuthPlugin, StaticFilesPlugin */
|
|
613
619
|
export declare class StandardPlugins extends Plugin {
|
|
614
620
|
constructor(options?: any, server?: MicroServer);
|
|
615
621
|
}
|
|
@@ -706,7 +712,7 @@ export declare class FileStore {
|
|
|
706
712
|
observe(data: object, cb: (data: object, key: string, value: any) => void): object;
|
|
707
713
|
}
|
|
708
714
|
/** Model validation options */
|
|
709
|
-
interface ModelContextOptions {
|
|
715
|
+
export interface ModelContextOptions {
|
|
710
716
|
/** User info */
|
|
711
717
|
user?: UserInfo;
|
|
712
718
|
/** Request params */
|
|
@@ -725,12 +731,12 @@ interface ModelContextOptions {
|
|
|
725
731
|
projection?: Record<string, 0 | 1 | true | false>;
|
|
726
732
|
}
|
|
727
733
|
/** Model field validation options */
|
|
728
|
-
interface ModelValidateFieldOptions extends ModelContextOptions {
|
|
734
|
+
export interface ModelValidateFieldOptions extends ModelContextOptions {
|
|
729
735
|
name: string;
|
|
730
736
|
field: ResolvedFieldSchema;
|
|
731
737
|
model: Model<any>;
|
|
732
738
|
}
|
|
733
|
-
|
|
739
|
+
interface ModelCallbackFunc {
|
|
734
740
|
(options: any): any;
|
|
735
741
|
}
|
|
736
742
|
type ModelBasicCtorType = typeof String | typeof Number | typeof Boolean | typeof Date;
|
|
@@ -764,7 +770,7 @@ export interface ModelFieldSchema {
|
|
|
764
770
|
/** Regex validation or 'email', 'url', 'date', 'time', 'date-time' */
|
|
765
771
|
format?: string;
|
|
766
772
|
}
|
|
767
|
-
interface ResolvedFieldSchema {
|
|
773
|
+
export interface ResolvedFieldSchema {
|
|
768
774
|
type: string;
|
|
769
775
|
model?: Model<any>;
|
|
770
776
|
primaryKey?: boolean;
|
package/microserver.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MicroServer
|
|
3
|
-
* @version 3.0.
|
|
3
|
+
* @version 3.0.7
|
|
4
4
|
* @package @radatek/microserver
|
|
5
5
|
* @copyright Darius Kisonas 2022
|
|
6
6
|
* @license MIT
|
|
@@ -77,7 +77,6 @@ function deferPromise(cb) {
|
|
|
77
77
|
export class Plugin {
|
|
78
78
|
name;
|
|
79
79
|
priority;
|
|
80
|
-
constructor() { }
|
|
81
80
|
}
|
|
82
81
|
// #region ServerRequest/ServerResponse
|
|
83
82
|
/** Extended http.IncomingMessage */
|
|
@@ -120,7 +119,6 @@ export class ServerRequest extends http.IncomingMessage {
|
|
|
120
119
|
_body;
|
|
121
120
|
// @internal
|
|
122
121
|
_isReady;
|
|
123
|
-
// @internal
|
|
124
122
|
constructor(res, server) {
|
|
125
123
|
super(new net.Socket());
|
|
126
124
|
ServerRequest.extend(this, res, server);
|
|
@@ -215,7 +213,6 @@ export class ServerRequest extends http.IncomingMessage {
|
|
|
215
213
|
export class ServerResponse extends http.ServerResponse {
|
|
216
214
|
/** Should response be json */
|
|
217
215
|
isJson;
|
|
218
|
-
// @internal
|
|
219
216
|
constructor(server) {
|
|
220
217
|
super(new http.IncomingMessage(new net.Socket()));
|
|
221
218
|
ServerRequest.extend(this.req, this, server);
|
|
@@ -816,6 +813,7 @@ class RouterItem {
|
|
|
816
813
|
// @internal
|
|
817
814
|
_last;
|
|
818
815
|
}
|
|
816
|
+
/** Router plugin */
|
|
819
817
|
class RouterPlugin extends Plugin {
|
|
820
818
|
priority = 100;
|
|
821
819
|
name = 'router';
|
|
@@ -947,6 +945,7 @@ class RouterPlugin extends Plugin {
|
|
|
947
945
|
this.walk(this._getStack(req.pathname, ['hook', method, '*']), req, res, next);
|
|
948
946
|
}
|
|
949
947
|
}
|
|
948
|
+
/** CORS plugin. Config may be: true - allow all, string - allow specific origin, or CorsOptions */
|
|
950
949
|
export class CorsPlugin extends Plugin {
|
|
951
950
|
priority = -100;
|
|
952
951
|
name = 'cors';
|
|
@@ -980,6 +979,7 @@ export class CorsPlugin extends Plugin {
|
|
|
980
979
|
}
|
|
981
980
|
// #enregion CorsPlugin
|
|
982
981
|
// #region MethodsPlugin
|
|
982
|
+
/** Methods plugin to support OPTIONS method, and restrict allowed methods. Configuration is comma separated string */
|
|
983
983
|
export class MethodsPlugin extends Plugin {
|
|
984
984
|
priority = -90;
|
|
985
985
|
name = 'methods';
|
|
@@ -1006,6 +1006,7 @@ export class MethodsPlugin extends Plugin {
|
|
|
1006
1006
|
return next();
|
|
1007
1007
|
}
|
|
1008
1008
|
}
|
|
1009
|
+
/** Body parser plugin */
|
|
1009
1010
|
export class BodyPlugin extends Plugin {
|
|
1010
1011
|
priority = -80;
|
|
1011
1012
|
name = 'body';
|
|
@@ -1061,6 +1062,7 @@ export class BodyPlugin extends Plugin {
|
|
|
1061
1062
|
});
|
|
1062
1063
|
}
|
|
1063
1064
|
}
|
|
1065
|
+
/** Upload plugin, At least uploadDir option is required */
|
|
1064
1066
|
export class UploadPlugin extends Plugin {
|
|
1065
1067
|
priority = -70;
|
|
1066
1068
|
name = 'upload';
|
|
@@ -1194,7 +1196,7 @@ export class UploadPlugin extends Plugin {
|
|
|
1194
1196
|
}
|
|
1195
1197
|
const EMPTY_BUFFER = Buffer.alloc(0);
|
|
1196
1198
|
const DEFLATE_TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
|
|
1197
|
-
/** WebSocket class */
|
|
1199
|
+
/** WebSocket class used in upgrade handler */
|
|
1198
1200
|
export class WebSocket extends EventEmitter {
|
|
1199
1201
|
// @internal
|
|
1200
1202
|
_socket;
|
|
@@ -1464,6 +1466,7 @@ export class WebSocket extends EventEmitter {
|
|
|
1464
1466
|
this._socket.write(frame, () => this._socket.write(data, cb));
|
|
1465
1467
|
}
|
|
1466
1468
|
}
|
|
1469
|
+
/** WebSocket plugin to support `WEBSOCKET /url` routes */
|
|
1467
1470
|
export class WebSocketPlugin extends Plugin {
|
|
1468
1471
|
name = 'websocket';
|
|
1469
1472
|
// @internal
|
|
@@ -1483,8 +1486,6 @@ export class WebSocketPlugin extends Plugin {
|
|
|
1483
1486
|
}
|
|
1484
1487
|
upgradeHandler(server, req, socket, head) {
|
|
1485
1488
|
const host = req.headers.host || '';
|
|
1486
|
-
const vhostPlugin = server.getPlugin('vhost');
|
|
1487
|
-
const vserver = vhostPlugin?.vhosts?.[host] || server;
|
|
1488
1489
|
const res = {
|
|
1489
1490
|
req,
|
|
1490
1491
|
get headersSent() {
|
|
@@ -1539,7 +1540,7 @@ export class WebSocketPlugin extends Plugin {
|
|
|
1539
1540
|
if (req.method !== 'GET' || req.headers.upgrade?.toLowerCase() !== 'websocket')
|
|
1540
1541
|
return res.error(400);
|
|
1541
1542
|
req.method = 'WEBSOCKET';
|
|
1542
|
-
|
|
1543
|
+
server.handler(req, res);
|
|
1543
1544
|
}
|
|
1544
1545
|
}
|
|
1545
1546
|
// #endregion WebSocket
|
|
@@ -1618,13 +1619,7 @@ export class VHostPlugin extends Plugin {
|
|
|
1618
1619
|
}
|
|
1619
1620
|
}
|
|
1620
1621
|
const etagPrefix = crypto.randomBytes(4).toString('hex');
|
|
1621
|
-
|
|
1622
|
-
//TODO: add unknown file extension handler
|
|
1623
|
-
/**
|
|
1624
|
-
* Static files middleware plugin
|
|
1625
|
-
* Usage: server.use('static', '/public')
|
|
1626
|
-
* Usage: server.use('static', { root: 'public', path: '/static' })
|
|
1627
|
-
*/
|
|
1622
|
+
/** Static files plugin. At least must be path to public folder as string or StaticFilesOptions */
|
|
1628
1623
|
export class StaticFilesPlugin extends Plugin {
|
|
1629
1624
|
priority = 110;
|
|
1630
1625
|
/** Default mime types */
|
|
@@ -1668,6 +1663,7 @@ export class StaticFilesPlugin extends Plugin {
|
|
|
1668
1663
|
maxAge;
|
|
1669
1664
|
prefix;
|
|
1670
1665
|
errors;
|
|
1666
|
+
checkPrecompressedGzip;
|
|
1671
1667
|
constructor(options, server) {
|
|
1672
1668
|
super();
|
|
1673
1669
|
if (!options)
|
|
@@ -1683,8 +1679,8 @@ export class StaticFilesPlugin extends Plugin {
|
|
|
1683
1679
|
this.etag = options.etag !== false;
|
|
1684
1680
|
this.maxAge = options.maxAge;
|
|
1685
1681
|
this.errors = options.errors;
|
|
1682
|
+
this.checkPrecompressedGzip = options.precompressedGzip;
|
|
1686
1683
|
this.prefix = ('/' + (options.path?.replace(/^[.\/]*/, '') || '').replace(/\/$/, '')).replace(/\/$/, '');
|
|
1687
|
-
const defSend = ServerResponse.prototype.send;
|
|
1688
1684
|
if (server && !server.getPlugin('static')) {
|
|
1689
1685
|
this.name = 'static'; // only first plugin instance is registered as
|
|
1690
1686
|
const defSend = ServerResponse.prototype.send;
|
|
@@ -1744,11 +1740,27 @@ export class StaticFilesPlugin extends Plugin {
|
|
|
1744
1740
|
req.filename = filename;
|
|
1745
1741
|
return handler.call(this, req, res, next);
|
|
1746
1742
|
}
|
|
1747
|
-
this.
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1743
|
+
if (this.checkPrecompressedGzip && (req.headers['accept-encoding'] || '').includes('gzip')) {
|
|
1744
|
+
const gzipped = filename + '.gz';
|
|
1745
|
+
fs.stat(gzipped, (err, statsGz) => {
|
|
1746
|
+
if (!err && statsGz.isFile()) {
|
|
1747
|
+
res.setHeader('Content-Encoding', 'gzip');
|
|
1748
|
+
filename = gzipped;
|
|
1749
|
+
stats = statsGz;
|
|
1750
|
+
}
|
|
1751
|
+
this.serveFile(req, res, {
|
|
1752
|
+
path: filename,
|
|
1753
|
+
mimeType,
|
|
1754
|
+
stats
|
|
1755
|
+
});
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
else
|
|
1759
|
+
this.serveFile(req, res, {
|
|
1760
|
+
path: filename,
|
|
1761
|
+
mimeType,
|
|
1762
|
+
stats
|
|
1763
|
+
});
|
|
1752
1764
|
});
|
|
1753
1765
|
}
|
|
1754
1766
|
/** Send static file */
|
|
@@ -1802,9 +1814,9 @@ export class StaticFilesPlugin extends Plugin {
|
|
|
1802
1814
|
statRes(null, options.stats);
|
|
1803
1815
|
}
|
|
1804
1816
|
}
|
|
1817
|
+
/** Reverse proxy plugin, At least remote url as string or in ProxyOptions is required */
|
|
1805
1818
|
export class ProxyPlugin extends Plugin {
|
|
1806
1819
|
priority = 120;
|
|
1807
|
-
name = 'proxy';
|
|
1808
1820
|
/** Default valid headers */
|
|
1809
1821
|
static validHeaders = {
|
|
1810
1822
|
authorization: true,
|
|
@@ -1838,6 +1850,8 @@ export class ProxyPlugin extends Plugin {
|
|
|
1838
1850
|
options = { remote: options };
|
|
1839
1851
|
if (!options.remote)
|
|
1840
1852
|
throw new Error('Invalid param');
|
|
1853
|
+
if (server && !server.getPlugin('proxy'))
|
|
1854
|
+
this.name = 'proxy';
|
|
1841
1855
|
this.remoteUrl = new URL(options.remote);
|
|
1842
1856
|
this.regex = options.match ? new RegExp(options.match) : undefined;
|
|
1843
1857
|
this.headers = options.headers;
|
|
@@ -2278,6 +2292,7 @@ export class AuthPlugin extends Plugin {
|
|
|
2278
2292
|
}
|
|
2279
2293
|
}
|
|
2280
2294
|
// #endregion AuthPlugin
|
|
2295
|
+
/** Load standard plugins with predefined configs: MethodsPlugin, CorsPlugin, TrustProxyPlugin, BodyPlugin, AuthPlugin, StaticFilesPlugin */
|
|
2281
2296
|
export class StandardPlugins extends Plugin {
|
|
2282
2297
|
constructor(options, server) {
|
|
2283
2298
|
super();
|
|
@@ -2293,9 +2308,9 @@ export class StandardPlugins extends Plugin {
|
|
|
2293
2308
|
use(MethodsPlugin);
|
|
2294
2309
|
use(CorsPlugin, 'cors');
|
|
2295
2310
|
use(TrustProxyPlugin, 'trustproxy');
|
|
2311
|
+
use(AuthPlugin, 'auth');
|
|
2296
2312
|
use(BodyPlugin);
|
|
2297
2313
|
use(StaticFilesPlugin, 'static');
|
|
2298
|
-
use(AuthPlugin, 'auth');
|
|
2299
2314
|
}
|
|
2300
2315
|
}
|
|
2301
2316
|
/**
|
|
@@ -2763,7 +2778,7 @@ export class Models {
|
|
|
2763
2778
|
}
|
|
2764
2779
|
export class Model {
|
|
2765
2780
|
static collections = new ModelCollectionsInternal();
|
|
2766
|
-
static models =
|
|
2781
|
+
static models = new Models();
|
|
2767
2782
|
static set db(db) {
|
|
2768
2783
|
this.collections.db = db;
|
|
2769
2784
|
}
|