tspace-spear 1.2.1 → 1.2.3
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 +36 -4
- package/dist/lib/core/decorators/context.d.ts +91 -0
- package/dist/lib/core/decorators/controller.d.ts +34 -0
- package/dist/lib/core/decorators/headers.d.ts +31 -0
- package/dist/lib/core/decorators/index.d.ts +9 -0
- package/dist/lib/core/decorators/methods.d.ts +82 -0
- package/dist/lib/core/decorators/middleware.d.ts +39 -0
- package/dist/lib/core/decorators/middleware.js.map +1 -1
- package/dist/lib/core/decorators/statusCode.d.ts +26 -0
- package/dist/lib/core/decorators/swagger.d.ts +36 -0
- package/dist/lib/core/server/index.d.ts +302 -0
- package/dist/lib/core/server/index.js +343 -140
- package/dist/lib/core/server/index.js.map +1 -1
- package/dist/lib/core/server/parser-factory.d.ts +32 -0
- package/dist/lib/core/server/parser-factory.js +269 -4
- package/dist/lib/core/server/parser-factory.js.map +1 -1
- package/dist/lib/core/server/router.d.ts +109 -0
- package/dist/lib/core/server/router.js +12 -0
- package/dist/lib/core/server/router.js.map +1 -1
- package/dist/lib/core/types/index.d.ts +248 -0
- package/dist/lib/index.d.ts +11 -0
- package/package.json +24 -10
- package/dist/lib/core/server/radix-router.js +0 -65
- package/dist/lib/core/server/radix-router.js.map +0 -1
- package/dist/tests/benchmark.test.js +0 -145
- package/dist/tests/benchmark.test.js.map +0 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { T } from "../types";
|
|
2
|
+
declare class Router {
|
|
3
|
+
private _routes;
|
|
4
|
+
get routes(): {
|
|
5
|
+
path: string;
|
|
6
|
+
method: T.Method;
|
|
7
|
+
handlers: ((ctx: T.Context, next: T.NextFunction) => any)[];
|
|
8
|
+
}[];
|
|
9
|
+
/**
|
|
10
|
+
* The 'groups' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' methods.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} prefix
|
|
13
|
+
* @param {Router} router
|
|
14
|
+
* @returns {void}
|
|
15
|
+
*/
|
|
16
|
+
groups(prefix: `/${string}`, router: (router: Router) => Router): void;
|
|
17
|
+
/**
|
|
18
|
+
* The 'get' method is used to add the request handler to the router for the 'GET' method.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} path
|
|
21
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
22
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
23
|
+
* @property {Function} next - go to next function
|
|
24
|
+
* @returns {this}
|
|
25
|
+
*/
|
|
26
|
+
get(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
27
|
+
/**
|
|
28
|
+
* The 'post' method is used to add the request handler to the router for the 'POST' method.
|
|
29
|
+
*
|
|
30
|
+
* @param {string} path
|
|
31
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
32
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
33
|
+
* @property {Function} next - go to next function
|
|
34
|
+
* @returns {this}
|
|
35
|
+
*/
|
|
36
|
+
post(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
37
|
+
/**
|
|
38
|
+
* The 'put' method is used to add the request handler to the router for the 'PUT' method.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} path
|
|
41
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
42
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
43
|
+
* @property {Function} next - go to next function
|
|
44
|
+
* @returns {this}
|
|
45
|
+
*/
|
|
46
|
+
put(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
47
|
+
/**
|
|
48
|
+
* The 'patch' method is used to add the request handler to the router for the 'PATCH' method.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} path
|
|
51
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
52
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
53
|
+
* @property {Function} next - go to next function
|
|
54
|
+
* @returns {this}
|
|
55
|
+
*/
|
|
56
|
+
patch(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
57
|
+
/**
|
|
58
|
+
* The 'delete' method is used to add the request handler to the router for the 'DELETE' method.
|
|
59
|
+
*
|
|
60
|
+
* @param {string} path
|
|
61
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
62
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
63
|
+
* @property {Function} next - go to next function
|
|
64
|
+
* @returns {this}
|
|
65
|
+
*/
|
|
66
|
+
delete(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
67
|
+
/**
|
|
68
|
+
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' methods.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} path
|
|
71
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
72
|
+
* @property {object} ctx - context { req , res , query , params , cookies , files , body}
|
|
73
|
+
* @property {function} next - go to next function
|
|
74
|
+
* @returns {this}
|
|
75
|
+
*/
|
|
76
|
+
all(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
77
|
+
/**
|
|
78
|
+
* The 'any' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' methods.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} path
|
|
81
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
82
|
+
* @property {object} ctx - context { req , res , query , params , cookies , files , body}
|
|
83
|
+
* @property {function} next - go to next function
|
|
84
|
+
* @returns {this}
|
|
85
|
+
*/
|
|
86
|
+
any(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
87
|
+
/**
|
|
88
|
+
* The 'head' method is used to add the request handler to the router for the 'HEAD' method.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} path
|
|
91
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
92
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
93
|
+
* @property {Function} next - go to next function
|
|
94
|
+
* @returns {this}
|
|
95
|
+
*/
|
|
96
|
+
head(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
97
|
+
/**
|
|
98
|
+
* The 'options' method is used to add the request handler to the router for the 'OPTIONS' method.
|
|
99
|
+
*
|
|
100
|
+
* @param {string} path
|
|
101
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
102
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
103
|
+
* @property {Function} next - go to next function
|
|
104
|
+
* @returns {this}
|
|
105
|
+
*/
|
|
106
|
+
options(path: `/${string}`, ...handlers: ((ctx: T.Context, next: T.NextFunction) => any)[]): this;
|
|
107
|
+
}
|
|
108
|
+
export { Router };
|
|
109
|
+
export default Router;
|
|
@@ -122,6 +122,18 @@ class Router {
|
|
|
122
122
|
});
|
|
123
123
|
return this;
|
|
124
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* The 'any' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' methods.
|
|
127
|
+
*
|
|
128
|
+
* @param {string} path
|
|
129
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
130
|
+
* @property {object} ctx - context { req , res , query , params , cookies , files , body}
|
|
131
|
+
* @property {function} next - go to next function
|
|
132
|
+
* @returns {this}
|
|
133
|
+
*/
|
|
134
|
+
any(path, ...handlers) {
|
|
135
|
+
return this.all(path, ...handlers);
|
|
136
|
+
}
|
|
125
137
|
/**
|
|
126
138
|
* The 'head' method is used to add the request handler to the router for the 'HEAD' method.
|
|
127
139
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../../src/lib/core/server/router.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../../src/lib/core/server/router.ts"],"names":[],"mappings":";;;AACA,MAAM,MAAM;IAEA,OAAO,GAIT,EAAE,CAAA;IAER,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,OAAO,CAAA;IACvB,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAE,MAAqB,EAAE,MAAoC;QACtE,MAAM,MAAM,GAAI,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC,CAAA;QACpC,KAAI,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,GAAG,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;YAC1D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC5B,CAAC;IACL,CAAC;IAED;;;;;;;;OAQG;IACI,GAAG,CAAC,IAAmB,EAAG,GAAG,QAA+D;QAC/F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,KAAK;YACd,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAED;;;;;;;;OAQG;IACI,IAAI,CAAC,IAAmB,EAAG,GAAG,QAA+D;QAChG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,MAAM;YACf,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAED;;;;;;;;OAQG;IACI,GAAG,CAAC,IAAmB,EAAG,GAAG,QAA+D;QAC/F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,KAAK;YACd,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,IAAmB,EAAG,GAAG,QAA+D;QACjG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,OAAO;YAChB,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAEA;;;;;;;;MAQE;IACI,MAAM,CAAC,IAAmB,EAAG,GAAG,QAA+D;QAClG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,QAAQ;YACjB,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAED;;;;;;;;OAQG;IACI,GAAG,CAAC,IAAmB,EAAG,GAAG,QAA+D;QAC/F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,KAAK;YACd,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAED;;;;;;;;OAQG;IACI,GAAG,CAAC,IAAmB,EAAG,GAAG,QAA+D;QAC/F,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAC,GAAG,QAAQ,CAAC,CAAA;IACrC,CAAC;IAED;;;;;;;;OAQG;IACI,IAAI,CAAC,IAAmB,EAAG,GAAG,QAA+D;QAChG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,MAAM;YACf,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAED;;;;;;;;OAQG;IACI,OAAO,CAAC,IAAmB,EAAG,GAAG,QAA+D;QACnG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,IAAI;YACJ,MAAM,EAAG,SAAS;YAClB,QAAQ;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;CACJ;AAEQ,wBAAM;AACf,kBAAe,MAAM,CAAA"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import http, { IncomingHttpHeaders, IncomingMessage, ServerResponse } from "http";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
type TContext = {
|
|
4
|
+
req: TRequest;
|
|
5
|
+
res: TResponse;
|
|
6
|
+
headers: THeaders;
|
|
7
|
+
query: TQuery;
|
|
8
|
+
params: TParams;
|
|
9
|
+
body: TBody;
|
|
10
|
+
files: TFileUpload;
|
|
11
|
+
cookies: TCookies;
|
|
12
|
+
ip: TIp;
|
|
13
|
+
};
|
|
14
|
+
type TIp = string | null;
|
|
15
|
+
type THeaders<T = IncomingHttpHeaders> = {
|
|
16
|
+
[K in keyof T]: T[K];
|
|
17
|
+
};
|
|
18
|
+
type TQuery<T = Record<string, string | undefined>> = T;
|
|
19
|
+
type TParams<T = Record<string, string | undefined>> = T;
|
|
20
|
+
type TBody<T = Record<string, any>> = T;
|
|
21
|
+
type TCookies<T = Record<string, any>> = T;
|
|
22
|
+
type TFile = {
|
|
23
|
+
size: number;
|
|
24
|
+
sizes: {
|
|
25
|
+
bytes: number;
|
|
26
|
+
kb: number;
|
|
27
|
+
mb: number;
|
|
28
|
+
gb: number;
|
|
29
|
+
};
|
|
30
|
+
tempFilePath: string;
|
|
31
|
+
tempFileName: string;
|
|
32
|
+
mimetype: string;
|
|
33
|
+
extension: string;
|
|
34
|
+
name: string;
|
|
35
|
+
write: (to: string) => Promise<void>;
|
|
36
|
+
remove: () => Promise<void>;
|
|
37
|
+
};
|
|
38
|
+
type TFileUpload = Record<string, TFile[] | undefined>;
|
|
39
|
+
type TNextFunction<T = any> = (err?: Error) => T | Promise<T>;
|
|
40
|
+
type TRequest = IncomingMessage & Partial<any>;
|
|
41
|
+
type THttpResponder = {
|
|
42
|
+
/**200+ */
|
|
43
|
+
ok: (data?: Record<string, any>) => any;
|
|
44
|
+
created: (data?: Record<string, any>) => any;
|
|
45
|
+
accepted: (data?: Record<string, any>) => any;
|
|
46
|
+
/**400+ */
|
|
47
|
+
noContent: (message?: string) => any;
|
|
48
|
+
badRequest: (message?: string) => any;
|
|
49
|
+
unauthorized: (message?: string) => any;
|
|
50
|
+
paymentRequired: (message?: string) => any;
|
|
51
|
+
forbidden: (message?: string) => any;
|
|
52
|
+
unprocessable: (message?: string) => any;
|
|
53
|
+
tooManyRequests: (message?: string) => any;
|
|
54
|
+
notFound: (message?: string) => any;
|
|
55
|
+
/**500+ */
|
|
56
|
+
serverError: (message?: string) => any;
|
|
57
|
+
badGateway: (message?: string) => any;
|
|
58
|
+
unavailable: (message?: string) => any;
|
|
59
|
+
gatewayTimeout: (message?: string) => any;
|
|
60
|
+
/**helper */
|
|
61
|
+
json: (data?: Record<string, any>) => any;
|
|
62
|
+
error: (err: any) => any;
|
|
63
|
+
send: (message: string) => any;
|
|
64
|
+
html: (html: string) => any;
|
|
65
|
+
status: (code: TStatusCode) => {
|
|
66
|
+
json: (data?: Record<string, any>) => any;
|
|
67
|
+
send: (message: string) => any;
|
|
68
|
+
};
|
|
69
|
+
setCookies: (cookies: Record<string, string | {
|
|
70
|
+
value: string;
|
|
71
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
72
|
+
domain?: string;
|
|
73
|
+
secure?: boolean;
|
|
74
|
+
httpOnly?: boolean;
|
|
75
|
+
expires?: Date;
|
|
76
|
+
}>) => any;
|
|
77
|
+
};
|
|
78
|
+
type TStatusCode = 200 | 201 | 202 | 203 | 204 | 300 | 301 | 302 | 303 | 304 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505;
|
|
79
|
+
type TResponse = ServerResponse & THttpResponder;
|
|
80
|
+
type TRouter = {
|
|
81
|
+
method: TMethod;
|
|
82
|
+
path: string;
|
|
83
|
+
handler: string | symbol;
|
|
84
|
+
};
|
|
85
|
+
type TRoute = {
|
|
86
|
+
path: string;
|
|
87
|
+
method: string;
|
|
88
|
+
params: string[];
|
|
89
|
+
};
|
|
90
|
+
type TMethod = 'get' | 'post' | 'patch' | 'put' | 'delete' | 'all' | 'head' | 'options';
|
|
91
|
+
type TMethodInput = Uppercase<TMethod>;
|
|
92
|
+
type Handler = (res: unknown, req: unknown) => void | Promise<void>;
|
|
93
|
+
type UWS = {
|
|
94
|
+
App: () => {
|
|
95
|
+
get: (path: string, handler: Handler) => any;
|
|
96
|
+
post: (path: string, handler: Handler) => any;
|
|
97
|
+
patch: (path: string, handler: Handler) => any;
|
|
98
|
+
put: (path: string, handler: Handler) => any;
|
|
99
|
+
del: (path: string, handler: Handler) => any;
|
|
100
|
+
any: (path: string, handler: Handler) => any;
|
|
101
|
+
options: (path: string, handler: Handler) => any;
|
|
102
|
+
listen: (...args: any[]) => any;
|
|
103
|
+
ws: (path: string, options: {
|
|
104
|
+
open?: (ws: any) => void;
|
|
105
|
+
message?: (ws: any, message: ArrayBuffer, isBinary: boolean) => void;
|
|
106
|
+
close?: (ws: any, code: number, message: ArrayBuffer) => void;
|
|
107
|
+
}) => any;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
type TAdapter = UWS | typeof http;
|
|
111
|
+
type TApplication = {
|
|
112
|
+
controllers?: (new () => any)[] | {
|
|
113
|
+
folder: string;
|
|
114
|
+
name?: RegExp;
|
|
115
|
+
};
|
|
116
|
+
middlewares?: TRequestFunction[] | {
|
|
117
|
+
folder: string;
|
|
118
|
+
name?: RegExp;
|
|
119
|
+
};
|
|
120
|
+
globalPrefix?: string;
|
|
121
|
+
logger?: boolean;
|
|
122
|
+
cluster?: boolean | number;
|
|
123
|
+
adapter?: TAdapter;
|
|
124
|
+
};
|
|
125
|
+
type TRequestFunction = (ctx: TContext, next: TNextFunction) => any;
|
|
126
|
+
type TErrorFunction = (err: Error, ctx: TContext) => any;
|
|
127
|
+
type TSwaggerFormat = "string" | "number" | "integer" | "boolean" | "object" | "array" | "date" | "date-time" | "password" | "int32" | "int64" | "float" | "double" | "byte" | "binary" | "base64" | "email" | "uuid" | "uri" | "hostname" | "ipv4" | "ipv6" | "json" | "xml";
|
|
128
|
+
type TSwaggerType = "string" | "number" | "integer" | "boolean" | "object" | "array" | "date" | "date-time" | "file";
|
|
129
|
+
type TSwaggerDoc = {
|
|
130
|
+
path?: `/${string}`;
|
|
131
|
+
staticUrl?: `${string}`;
|
|
132
|
+
servers?: {
|
|
133
|
+
url: string;
|
|
134
|
+
description?: string;
|
|
135
|
+
}[];
|
|
136
|
+
tags?: string[];
|
|
137
|
+
info?: {
|
|
138
|
+
title?: string;
|
|
139
|
+
description?: string;
|
|
140
|
+
version?: string;
|
|
141
|
+
};
|
|
142
|
+
routes?: {
|
|
143
|
+
path: string;
|
|
144
|
+
method: string;
|
|
145
|
+
params: string[];
|
|
146
|
+
}[];
|
|
147
|
+
specs?: (TSwagger & {
|
|
148
|
+
path: string;
|
|
149
|
+
method: string;
|
|
150
|
+
})[];
|
|
151
|
+
options?: {
|
|
152
|
+
decoratedOnly?: boolean;
|
|
153
|
+
withCredentials?: boolean;
|
|
154
|
+
filter?: boolean;
|
|
155
|
+
docExpansion?: "none" | "list" | "full";
|
|
156
|
+
deepLinking?: boolean;
|
|
157
|
+
displayOperationId?: boolean;
|
|
158
|
+
displayRequestDuration?: boolean;
|
|
159
|
+
layout?: 'BaseLayout' | 'StandaloneLayout';
|
|
160
|
+
};
|
|
161
|
+
responses?: {
|
|
162
|
+
status: number;
|
|
163
|
+
description: string;
|
|
164
|
+
example?: Record<string, any>;
|
|
165
|
+
}[];
|
|
166
|
+
};
|
|
167
|
+
type TSwagger = {
|
|
168
|
+
disabled?: boolean;
|
|
169
|
+
description?: string;
|
|
170
|
+
summary?: string;
|
|
171
|
+
bearerToken?: boolean;
|
|
172
|
+
tags?: string[];
|
|
173
|
+
params?: Record<string, {
|
|
174
|
+
description?: string;
|
|
175
|
+
type?: TSwaggerType;
|
|
176
|
+
example?: any;
|
|
177
|
+
}>;
|
|
178
|
+
query?: Record<string, {
|
|
179
|
+
required?: boolean;
|
|
180
|
+
description?: string;
|
|
181
|
+
type?: TSwaggerType;
|
|
182
|
+
example?: any;
|
|
183
|
+
}>;
|
|
184
|
+
body?: {
|
|
185
|
+
required?: boolean;
|
|
186
|
+
description?: string;
|
|
187
|
+
properties: Record<string, {
|
|
188
|
+
type: TSwaggerType;
|
|
189
|
+
example?: any;
|
|
190
|
+
}>;
|
|
191
|
+
};
|
|
192
|
+
files?: {
|
|
193
|
+
required?: boolean;
|
|
194
|
+
description?: string;
|
|
195
|
+
properties: Record<string, {
|
|
196
|
+
type: TSwaggerType;
|
|
197
|
+
format?: TSwaggerFormat;
|
|
198
|
+
items?: any;
|
|
199
|
+
example?: any;
|
|
200
|
+
}>;
|
|
201
|
+
};
|
|
202
|
+
cookies?: {
|
|
203
|
+
names: string[];
|
|
204
|
+
required?: boolean;
|
|
205
|
+
description?: string;
|
|
206
|
+
};
|
|
207
|
+
responses?: {
|
|
208
|
+
status: number;
|
|
209
|
+
description: string;
|
|
210
|
+
example?: Record<string, any>;
|
|
211
|
+
}[];
|
|
212
|
+
};
|
|
213
|
+
type TWSHandler = {
|
|
214
|
+
connection: (ws: WebSocket) => void | string | Buffer;
|
|
215
|
+
message: (ws: WebSocket, data: WebSocket.Data) => void | string | Buffer;
|
|
216
|
+
close: (ws: WebSocket, code: number, reason: Buffer) => void;
|
|
217
|
+
error: (ws: WebSocket, error: Error) => void;
|
|
218
|
+
};
|
|
219
|
+
export declare namespace T {
|
|
220
|
+
type Adapter = TAdapter;
|
|
221
|
+
type Application = TApplication;
|
|
222
|
+
type NextFunction = TNextFunction;
|
|
223
|
+
type File = TFile;
|
|
224
|
+
type Context = TContext;
|
|
225
|
+
type Router = TRouter;
|
|
226
|
+
type Route = TRoute;
|
|
227
|
+
type Method = TMethod;
|
|
228
|
+
type ErrorFunction = TErrorFunction;
|
|
229
|
+
type HttpStatus = THttpResponder;
|
|
230
|
+
type RequestFunction = TRequestFunction;
|
|
231
|
+
type WebSocketHandler = TWSHandler;
|
|
232
|
+
type StatusCode = TStatusCode;
|
|
233
|
+
type MethodInput = TMethodInput;
|
|
234
|
+
type Response = TResponse;
|
|
235
|
+
type Request = TRequest;
|
|
236
|
+
type FileUpload = TFileUpload;
|
|
237
|
+
type Cookies<T = Record<string, any>> = TCookies<T>;
|
|
238
|
+
type Params<T = Record<string, string>> = TParams<T>;
|
|
239
|
+
type Query<T = Record<string, string>> = TQuery<T>;
|
|
240
|
+
type Body<T = Record<string, any>> = TBody<T>;
|
|
241
|
+
type Headers<T = IncomingHttpHeaders> = THeaders<T>;
|
|
242
|
+
namespace Swagger {
|
|
243
|
+
type Spec = TSwagger;
|
|
244
|
+
type Format = TSwaggerFormat;
|
|
245
|
+
type Doc = TSwaggerDoc;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entry point.
|
|
3
|
+
*
|
|
4
|
+
* @module tspace-spear
|
|
5
|
+
*/
|
|
6
|
+
export * from './core/decorators';
|
|
7
|
+
export * from './core/server/router';
|
|
8
|
+
export * from './core/server';
|
|
9
|
+
export { T } from './core/types';
|
|
10
|
+
import Spear from './core/server';
|
|
11
|
+
export default Spear;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tspace-spear",
|
|
3
|
-
"version": "1.2.
|
|
4
|
-
"description": "tspace-spear is a lightweight API framework for Node.js that
|
|
3
|
+
"version": "1.2.3",
|
|
4
|
+
"description": "tspace-spear is a lightweight, high-performance API framework for Node.js that leverages the native HTTP server and supports uWebSockets.js (C++) for maximum speed and efficiency.",
|
|
5
5
|
"main": "./dist/lib/index.js",
|
|
6
6
|
"types": "./dist/lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -18,7 +18,11 @@
|
|
|
18
18
|
"api",
|
|
19
19
|
"rest api",
|
|
20
20
|
"fast",
|
|
21
|
-
"low overhead"
|
|
21
|
+
"low overhead",
|
|
22
|
+
"http",
|
|
23
|
+
"uWS",
|
|
24
|
+
"uWebSockets",
|
|
25
|
+
"uWebSockets.js"
|
|
22
26
|
],
|
|
23
27
|
"author": "Thanathip (https://github.com/thanathip41)",
|
|
24
28
|
"license": "MIT",
|
|
@@ -31,35 +35,45 @@
|
|
|
31
35
|
"prepare": "npm run build",
|
|
32
36
|
"release": "npm run build && npm publish",
|
|
33
37
|
"beta": "npm run build && npm publish --tag beta",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
38
|
+
"benchmark": "npm run build && ts-node __tests__/benchmark.test.ts",
|
|
39
|
+
"test": "mocha dist/tests/**/0*.test.js",
|
|
40
|
+
"load": "autocannon -c 100 -d 30 -p 10 localhost:3000",
|
|
36
41
|
"docs": "npx docsify-cli serve docs"
|
|
37
42
|
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=14"
|
|
45
|
+
},
|
|
38
46
|
"dependencies": {
|
|
39
47
|
"busboy": "1.6.0",
|
|
40
|
-
"find-my-way": "
|
|
48
|
+
"find-my-way": "8.2.2",
|
|
41
49
|
"mime-types": "2.1.35",
|
|
42
50
|
"on-finished": "2.4.1",
|
|
43
|
-
"reflect-metadata": "0.
|
|
44
|
-
"swagger-ui-dist": "5.32.0"
|
|
51
|
+
"reflect-metadata": "0.2.2",
|
|
52
|
+
"swagger-ui-dist": "5.32.0",
|
|
53
|
+
"ws": "8.19.0"
|
|
45
54
|
},
|
|
46
55
|
"devDependencies": {
|
|
47
56
|
"@types/autocannon": "7.12.5",
|
|
48
57
|
"@types/busboy": "1.5.4",
|
|
58
|
+
"@types/chai": "5.2.3",
|
|
59
|
+
"@types/chai-http": "4.2.4",
|
|
49
60
|
"@types/express": "4.17.21",
|
|
61
|
+
"@types/jest": "30.0.0",
|
|
50
62
|
"@types/mime-types": "2.1.4",
|
|
63
|
+
"@types/mocha": "10.0.10",
|
|
51
64
|
"@types/node": "16.4.0",
|
|
52
65
|
"@types/on-finished": "2.3.4",
|
|
53
66
|
"@types/swagger-ui-dist": "3.30.4",
|
|
54
67
|
"@types/ws": "8.18.1",
|
|
55
68
|
"@types/yargs": "17.0.32",
|
|
56
69
|
"autocannon": "7.15.0",
|
|
70
|
+
"chai": "4.5.0",
|
|
71
|
+
"chai-http": "5.1.2",
|
|
57
72
|
"docsify-cli": "4.4.4",
|
|
58
73
|
"express": "4.19.2",
|
|
59
74
|
"fastify": "4.28.1",
|
|
60
75
|
"ts-node": "10.9.2",
|
|
61
|
-
"typescript": "5.
|
|
62
|
-
"ws": "8.18.3",
|
|
76
|
+
"typescript": "5.9.3",
|
|
63
77
|
"yargs": "17.7.2",
|
|
64
78
|
"zod": "4.3.6"
|
|
65
79
|
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RadixRouter = void 0;
|
|
4
|
-
class RadixNode {
|
|
5
|
-
part;
|
|
6
|
-
children = new Map();
|
|
7
|
-
paramChild;
|
|
8
|
-
handler;
|
|
9
|
-
paramName;
|
|
10
|
-
constructor(part) {
|
|
11
|
-
this.part = part;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
class RadixRouter {
|
|
15
|
-
root = new RadixNode("");
|
|
16
|
-
add(path, handler) {
|
|
17
|
-
const parts = path.split("/").filter(Boolean);
|
|
18
|
-
let node = this.root;
|
|
19
|
-
for (const part of parts) {
|
|
20
|
-
if (part.startsWith(":")) {
|
|
21
|
-
if (!node.paramChild) {
|
|
22
|
-
node.paramChild = new RadixNode(part);
|
|
23
|
-
node.paramChild.paramName = part.slice(1);
|
|
24
|
-
}
|
|
25
|
-
node = node.paramChild;
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
if (!node.children.has(part)) {
|
|
29
|
-
node.children.set(part, new RadixNode(part));
|
|
30
|
-
}
|
|
31
|
-
node = node.children.get(part);
|
|
32
|
-
}
|
|
33
|
-
node.handler = handler;
|
|
34
|
-
}
|
|
35
|
-
lookup(req, res) {
|
|
36
|
-
const url = req.url || "/";
|
|
37
|
-
const path = url.split("?")[0];
|
|
38
|
-
const parts = path.split("/").filter(Boolean);
|
|
39
|
-
let node = this.root;
|
|
40
|
-
const params = {};
|
|
41
|
-
for (const part of parts) {
|
|
42
|
-
const child = node.children.get(part);
|
|
43
|
-
if (child) {
|
|
44
|
-
node = child;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
if (node.paramChild) {
|
|
48
|
-
params[node.paramChild.paramName] = part;
|
|
49
|
-
node = node.paramChild;
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
res.statusCode = 404;
|
|
53
|
-
res.end("Not Found");
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (!node.handler) {
|
|
57
|
-
res.statusCode = 404;
|
|
58
|
-
res.end("Not Found");
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
node.handler(req, res, params);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
exports.RadixRouter = RadixRouter;
|
|
65
|
-
//# sourceMappingURL=radix-router.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"radix-router.js","sourceRoot":"","sources":["../../../../src/lib/core/server/radix-router.ts"],"names":[],"mappings":";;;AAEA,MAAM,SAAS;IAEb,IAAI,CAAQ;IACZ,QAAQ,GAA2B,IAAI,GAAG,EAAE,CAAA;IAC5C,UAAU,CAAY;IACtB,OAAO,CAAU;IACjB,SAAS,CAAS;IAElB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED,MAAa,WAAW;IAEd,IAAI,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC,CAAA;IAEhC,GAAG,CAAC,IAAY,EAAE,OAAgB;QAEhC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAE7C,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QAEpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YAExB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;gBAExB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;oBACpB,IAAI,CAAC,UAAU,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,CAAA;oBACrC,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;iBAC1C;gBAED,IAAI,GAAG,IAAI,CAAC,UAAU,CAAA;gBACtB,SAAQ;aACT;YAED,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;aAC7C;YAED,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAE,CAAA;SAChC;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,MAAM,CAAC,GAAQ,EAAE,GAAQ;QAEvB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAA;QAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAE9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAE7C,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACpB,MAAM,MAAM,GAA0B,EAAE,CAAA;QAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YAExB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAErC,IAAI,KAAK,EAAE;gBACT,IAAI,GAAG,KAAK,CAAA;gBACZ,SAAQ;aACT;YAED,IAAI,IAAI,CAAC,UAAU,EAAE;gBAEnB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,SAAU,CAAC,GAAG,IAAI,CAAA;gBACzC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAA;gBACtB,SAAQ;aACT;YAED,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;YACpB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YACpB,OAAM;SACP;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACjB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;YACpB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YACpB,OAAM;SACP;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;IAChC,CAAC;CACF;AAxED,kCAwEC"}
|