skyguard-js 1.2.0 → 1.2.2
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 +9 -462
- package/dist/app.d.ts +34 -10
- package/dist/app.js +59 -27
- package/dist/crypto/hasher.js +2 -1
- package/dist/crypto/jwt.js +2 -1
- package/dist/http/context.d.ts +115 -0
- package/dist/http/context.js +147 -0
- package/dist/http/httpAdapter.d.ts +4 -4
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +3 -1
- package/dist/http/logger.d.ts +10 -1
- package/dist/http/logger.js +44 -8
- package/dist/http/nodeNativeHttp.d.ts +6 -5
- package/dist/http/nodeNativeHttp.js +13 -6
- package/dist/http/request.d.ts +4 -0
- package/dist/http/request.js +12 -4
- package/dist/http/response.d.ts +21 -2
- package/dist/http/response.js +30 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -2
- package/dist/middlewares/cors.d.ts +10 -4
- package/dist/middlewares/cors.js +35 -18
- package/dist/middlewares/csrf.js +33 -33
- package/dist/middlewares/index.d.ts +1 -1
- package/dist/middlewares/rateLimiter.d.ts +58 -6
- package/dist/middlewares/rateLimiter.js +149 -40
- package/dist/middlewares/session.js +4 -4
- package/dist/routing/routeResolveFunc.d.ts +10 -0
- package/dist/routing/routeResolveFunc.js +21 -0
- package/dist/routing/router.d.ts +16 -10
- package/dist/routing/router.js +32 -25
- package/dist/routing/routerGroup.d.ts +10 -5
- package/dist/routing/routerGroup.js +11 -10
- package/dist/sessions/databaseSessionStorage.d.ts +52 -0
- package/dist/sessions/databaseSessionStorage.js +166 -0
- package/dist/sessions/fileSessionStorage.js +1 -1
- package/dist/sessions/index.d.ts +1 -0
- package/dist/sessions/index.js +3 -1
- package/dist/sessions/memorySessionStorage.js +1 -1
- package/dist/storage/storage.d.ts +3 -3
- package/dist/storage/storage.js +7 -7
- package/dist/storage/types.d.ts +5 -5
- package/dist/storage/uploader.d.ts +9 -9
- package/dist/storage/uploader.js +62 -62
- package/dist/types/index.d.ts +11 -10
- package/dist/validators/rules/bigIntRule.d.ts +0 -6
- package/dist/validators/rules/bigIntRule.js +0 -24
- package/dist/validators/validationRule.js +1 -1
- package/dist/validators/validationSchema.js +8 -8
- package/package.json +2 -2
- package/dist/helpers/http.d.ts +0 -95
- package/dist/helpers/http.js +0 -112
package/dist/app.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createApp =
|
|
3
|
+
exports.createApp = void 0;
|
|
4
4
|
const routing_1 = require("./routing");
|
|
5
|
+
const routeResolveFunc_1 = require("./routing/routeResolveFunc");
|
|
5
6
|
const http_1 = require("./http");
|
|
6
7
|
const validationException_1 = require("./exceptions/validationException");
|
|
7
8
|
const node_path_1 = require("node:path");
|
|
9
|
+
const node_fs_1 = require("node:fs");
|
|
8
10
|
const fileStaticHandler_1 = require("./static/fileStaticHandler");
|
|
9
11
|
const node_http_1 = require("node:http");
|
|
10
12
|
const httpExceptions_1 = require("./exceptions/httpExceptions");
|
|
@@ -35,6 +37,10 @@ class App {
|
|
|
35
37
|
staticFileHandler = null;
|
|
36
38
|
/** View engine for rendering templates (optional) */
|
|
37
39
|
viewEngine;
|
|
40
|
+
/** Logger configuration */
|
|
41
|
+
loggerOptions = {
|
|
42
|
+
format: "dev",
|
|
43
|
+
};
|
|
38
44
|
/**
|
|
39
45
|
* Bootstraps and configures the application.
|
|
40
46
|
*
|
|
@@ -66,15 +72,15 @@ class App {
|
|
|
66
72
|
*/
|
|
67
73
|
async handle(adapter) {
|
|
68
74
|
try {
|
|
69
|
-
const
|
|
70
|
-
if (this.staticFileHandler &&
|
|
71
|
-
const staticResponse = await this.staticFileHandler.tryServeFile(
|
|
75
|
+
const context = await adapter.getContext();
|
|
76
|
+
if (this.staticFileHandler && context.req.method === http_1.HttpMethods.get) {
|
|
77
|
+
const staticResponse = await this.staticFileHandler.tryServeFile(context.req.url);
|
|
72
78
|
if (staticResponse) {
|
|
73
79
|
adapter.sendResponse(staticResponse);
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
|
-
const response = await this.router.resolve(
|
|
83
|
+
const response = await this.router.resolve(context);
|
|
78
84
|
adapter.sendResponse(response);
|
|
79
85
|
}
|
|
80
86
|
catch (error) {
|
|
@@ -142,14 +148,40 @@ class App {
|
|
|
142
148
|
*
|
|
143
149
|
* @param port - TCP port to listen on
|
|
144
150
|
*/
|
|
145
|
-
run(port, callback, hostname = "
|
|
151
|
+
run(port = 3000, callback, hostname = "localhost") {
|
|
146
152
|
(0, node_http_1.createServer)((req, res) => {
|
|
147
|
-
const adapter = new http_1.NodeHttpAdapter(req, res);
|
|
153
|
+
const adapter = new http_1.NodeHttpAdapter(req, res, this.loggerOptions);
|
|
148
154
|
void this.handle(adapter);
|
|
149
155
|
}).listen(port, hostname, () => {
|
|
150
|
-
callback
|
|
156
|
+
if (callback)
|
|
157
|
+
callback();
|
|
151
158
|
});
|
|
152
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Configures HTTP request logger output format and optional file output.
|
|
162
|
+
*
|
|
163
|
+
* Supported formats are inspired by morgan:
|
|
164
|
+
* - "combined"
|
|
165
|
+
* - "common"
|
|
166
|
+
* - "dev"
|
|
167
|
+
* - "short"
|
|
168
|
+
* - "tiny"
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* app.logger("common");
|
|
172
|
+
* app.logger("combined", "./logs/http.log");
|
|
173
|
+
*/
|
|
174
|
+
logger(format = "dev", filePath) {
|
|
175
|
+
this.loggerOptions = {
|
|
176
|
+
...this.loggerOptions,
|
|
177
|
+
format,
|
|
178
|
+
};
|
|
179
|
+
if (filePath) {
|
|
180
|
+
this.loggerOptions.fileStream = (0, node_fs_1.createWriteStream)(filePath, {
|
|
181
|
+
flags: "a",
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
153
185
|
/**
|
|
154
186
|
* Sets a global prefix for all routes.
|
|
155
187
|
*
|
|
@@ -162,25 +194,25 @@ class App {
|
|
|
162
194
|
setPrefix(prefix) {
|
|
163
195
|
this.router.setPrefix(prefix);
|
|
164
196
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.router.get(path,
|
|
197
|
+
get(path, handlerOrMiddlewares, handler) {
|
|
198
|
+
const { action, middlewares } = (0, routeResolveFunc_1.normalizeRouteArgs)(handlerOrMiddlewares, handler);
|
|
199
|
+
this.router.get(path, middlewares, action);
|
|
168
200
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
this.router.post(path,
|
|
201
|
+
post(path, handlerOrMiddlewares, handler) {
|
|
202
|
+
const { action, middlewares } = (0, routeResolveFunc_1.normalizeRouteArgs)(handlerOrMiddlewares, handler);
|
|
203
|
+
this.router.post(path, middlewares, action);
|
|
172
204
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this.router.put(path,
|
|
205
|
+
put(path, handlerOrMiddlewares, handler) {
|
|
206
|
+
const { action, middlewares } = (0, routeResolveFunc_1.normalizeRouteArgs)(handlerOrMiddlewares, handler);
|
|
207
|
+
this.router.put(path, middlewares, action);
|
|
176
208
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
this.router.patch(path,
|
|
209
|
+
patch(path, handlerOrMiddlewares, handler) {
|
|
210
|
+
const { action, middlewares } = (0, routeResolveFunc_1.normalizeRouteArgs)(handlerOrMiddlewares, handler);
|
|
211
|
+
this.router.patch(path, middlewares, action);
|
|
180
212
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.router.delete(path,
|
|
213
|
+
delete(path, handlerOrMiddlewares, handler) {
|
|
214
|
+
const { action, middlewares } = (0, routeResolveFunc_1.normalizeRouteArgs)(handlerOrMiddlewares, handler);
|
|
215
|
+
this.router.delete(path, middlewares, action);
|
|
184
216
|
}
|
|
185
217
|
/**
|
|
186
218
|
* Registers global middlewares.
|
|
@@ -188,9 +220,9 @@ class App {
|
|
|
188
220
|
* These are executed for every route.
|
|
189
221
|
*
|
|
190
222
|
* @example
|
|
191
|
-
* const auth = async (
|
|
192
|
-
* console.log(
|
|
193
|
-
* return await next(
|
|
223
|
+
* const auth = async (context, next) => {
|
|
224
|
+
* console.log(context.headers);
|
|
225
|
+
* return await next(context);
|
|
194
226
|
* }
|
|
195
227
|
*
|
|
196
228
|
* app.middlewares(auth);
|
|
@@ -222,6 +254,7 @@ class App {
|
|
|
222
254
|
}
|
|
223
255
|
if (error instanceof validationException_1.ValidationException) {
|
|
224
256
|
adapter.sendResponse(http_1.Response.json({
|
|
257
|
+
message: "Validation Error",
|
|
225
258
|
errors: error.getErrorsByField(),
|
|
226
259
|
}).setStatusCode(400));
|
|
227
260
|
return;
|
|
@@ -234,7 +267,6 @@ class App {
|
|
|
234
267
|
console.error(error);
|
|
235
268
|
}
|
|
236
269
|
}
|
|
237
|
-
exports.App = App;
|
|
238
270
|
const createApp = () => {
|
|
239
271
|
return App.bootstrap();
|
|
240
272
|
};
|
package/dist/crypto/hasher.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Hasher = void 0;
|
|
4
|
+
const container_1 = require("../container/container");
|
|
4
5
|
const node_crypto_1 = require("node:crypto");
|
|
5
6
|
const node_util_1 = require("node:util");
|
|
6
7
|
/**
|
|
@@ -257,4 +258,4 @@ class HasherCrypto {
|
|
|
257
258
|
* - scrypt is intentionally expensive; concurrency is bounded in batch methods to help prevent
|
|
258
259
|
* resource exhaustion (especially relevant in containers and small instances).
|
|
259
260
|
*/
|
|
260
|
-
exports.Hasher =
|
|
261
|
+
exports.Hasher = container_1.Container.singleton(HasherCrypto);
|
package/dist/crypto/jwt.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.JWT = void 0;
|
|
4
|
+
const container_1 = require("../container/container");
|
|
4
5
|
const baseException_1 = require("../exceptions/baseException");
|
|
5
6
|
const node_crypto_1 = require("node:crypto");
|
|
6
7
|
class JWTGeneratorException extends baseException_1.BaseException {
|
|
@@ -308,4 +309,4 @@ class Jwt {
|
|
|
308
309
|
* - Expiration handling is **strict**: `verify()` expects `exp` to exist and be in the future.
|
|
309
310
|
* - Input parsing is defensive: malformed tokens or unsupported algorithms yield `null` on verify/decode.
|
|
310
311
|
*/
|
|
311
|
-
exports.JWT =
|
|
312
|
+
exports.JWT = container_1.Container.singleton(Jwt);
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { IncomingHttpHeaders } from "node:http";
|
|
2
|
+
import { Request } from "./request";
|
|
3
|
+
import { Response } from "./response";
|
|
4
|
+
import { Readable } from "node:stream";
|
|
5
|
+
import { Session } from "../sessions";
|
|
6
|
+
/**
|
|
7
|
+
* Unified HTTP context shared by middleware and route handlers.
|
|
8
|
+
*
|
|
9
|
+
* This object wraps the current {@link Request} and exposes convenient
|
|
10
|
+
* read-only accessors (`headers`, `body`, `params`, etc.) plus response
|
|
11
|
+
* builder helpers (`json`, `text`, `redirect`, `stream`, `download`).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* app.get("/users/{id}", context => {
|
|
15
|
+
* return context.json({
|
|
16
|
+
* id: context.params.id,
|
|
17
|
+
* ip: context.remoteAddress,
|
|
18
|
+
* });
|
|
19
|
+
* });
|
|
20
|
+
*/
|
|
21
|
+
export declare class Context {
|
|
22
|
+
private readonly _req;
|
|
23
|
+
/**
|
|
24
|
+
* @param _req - Current request wrapper instance.
|
|
25
|
+
*/
|
|
26
|
+
constructor(_req: Request);
|
|
27
|
+
/**
|
|
28
|
+
* Returns a new empty response instance.
|
|
29
|
+
*
|
|
30
|
+
* Useful when constructing a response manually.
|
|
31
|
+
*/
|
|
32
|
+
get res(): Response;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the underlying request object.
|
|
35
|
+
*/
|
|
36
|
+
get req(): Request;
|
|
37
|
+
/**
|
|
38
|
+
* Returns incoming request headers.
|
|
39
|
+
*/
|
|
40
|
+
get headers(): IncomingHttpHeaders;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the socket peer IP address when available.
|
|
43
|
+
*/
|
|
44
|
+
get remoteAddress(): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Returns parsed request body.
|
|
47
|
+
*/
|
|
48
|
+
get body(): Record<string, any>;
|
|
49
|
+
/**
|
|
50
|
+
* Returns route path parameters.
|
|
51
|
+
*/
|
|
52
|
+
get params(): Record<string, any>;
|
|
53
|
+
/**
|
|
54
|
+
* Returns parsed query string values.
|
|
55
|
+
*/
|
|
56
|
+
get query(): Record<string, any>;
|
|
57
|
+
/**
|
|
58
|
+
* Returns parsed request cookies.
|
|
59
|
+
*/
|
|
60
|
+
get cookies(): Record<string, string>;
|
|
61
|
+
/**
|
|
62
|
+
* Returns request session wrapper.
|
|
63
|
+
*/
|
|
64
|
+
get session(): Session;
|
|
65
|
+
/**
|
|
66
|
+
* Creates a JSON response.
|
|
67
|
+
*
|
|
68
|
+
* @param data - Serializable payload.
|
|
69
|
+
*/
|
|
70
|
+
json(data: unknown): Response;
|
|
71
|
+
/**
|
|
72
|
+
* Creates a plain-text response.
|
|
73
|
+
*
|
|
74
|
+
* @param data - Text payload.
|
|
75
|
+
*/
|
|
76
|
+
text(data: string): Response;
|
|
77
|
+
/**
|
|
78
|
+
* Creates an HTTP redirect response (302 by default).
|
|
79
|
+
*
|
|
80
|
+
* @param url - Redirect target URL.
|
|
81
|
+
*/
|
|
82
|
+
redirect(url: string): Response;
|
|
83
|
+
/**
|
|
84
|
+
* Creates a streaming response.
|
|
85
|
+
*
|
|
86
|
+
* @param stream - Readable stream body.
|
|
87
|
+
* @param headers - Optional extra headers.
|
|
88
|
+
*/
|
|
89
|
+
stream(stream: Readable, headers?: Record<string, string>): Response;
|
|
90
|
+
/**
|
|
91
|
+
* Creates a download response from a filesystem path.
|
|
92
|
+
*
|
|
93
|
+
* @param path - File path.
|
|
94
|
+
* @param filename - Optional download filename.
|
|
95
|
+
* @param headers - Optional additional headers.
|
|
96
|
+
*/
|
|
97
|
+
download(path: string, filename?: string, headers?: Record<string, string>): Promise<Response>;
|
|
98
|
+
/**
|
|
99
|
+
* Renders a configured template with optional params.
|
|
100
|
+
*
|
|
101
|
+
* @param data - Template source or identifier depending on view engine setup.
|
|
102
|
+
* @param params - Template context values.
|
|
103
|
+
*/
|
|
104
|
+
render(data: string, params?: Record<string, unknown>): Promise<Response>;
|
|
105
|
+
/**
|
|
106
|
+
* Sends a file for inline display.
|
|
107
|
+
*
|
|
108
|
+
* @param filePath - File path to send.
|
|
109
|
+
* @param options - Optional root and headers.
|
|
110
|
+
*/
|
|
111
|
+
sendFile(filePath: string, options: {
|
|
112
|
+
headers?: Record<string, string>;
|
|
113
|
+
root?: string;
|
|
114
|
+
}): Promise<Response>;
|
|
115
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Context = void 0;
|
|
4
|
+
const response_1 = require("./response");
|
|
5
|
+
/**
|
|
6
|
+
* Unified HTTP context shared by middleware and route handlers.
|
|
7
|
+
*
|
|
8
|
+
* This object wraps the current {@link Request} and exposes convenient
|
|
9
|
+
* read-only accessors (`headers`, `body`, `params`, etc.) plus response
|
|
10
|
+
* builder helpers (`json`, `text`, `redirect`, `stream`, `download`).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* app.get("/users/{id}", context => {
|
|
14
|
+
* return context.json({
|
|
15
|
+
* id: context.params.id,
|
|
16
|
+
* ip: context.remoteAddress,
|
|
17
|
+
* });
|
|
18
|
+
* });
|
|
19
|
+
*/
|
|
20
|
+
class Context {
|
|
21
|
+
_req;
|
|
22
|
+
/**
|
|
23
|
+
* @param _req - Current request wrapper instance.
|
|
24
|
+
*/
|
|
25
|
+
constructor(_req) {
|
|
26
|
+
this._req = _req;
|
|
27
|
+
this._req = _req;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns a new empty response instance.
|
|
31
|
+
*
|
|
32
|
+
* Useful when constructing a response manually.
|
|
33
|
+
*/
|
|
34
|
+
get res() {
|
|
35
|
+
return new response_1.Response();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns the underlying request object.
|
|
39
|
+
*/
|
|
40
|
+
get req() {
|
|
41
|
+
return this._req;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns incoming request headers.
|
|
45
|
+
*/
|
|
46
|
+
get headers() {
|
|
47
|
+
return this._req.headers;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns the socket peer IP address when available.
|
|
51
|
+
*/
|
|
52
|
+
get remoteAddress() {
|
|
53
|
+
return this._req.remoteAddress;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns parsed request body.
|
|
57
|
+
*/
|
|
58
|
+
get body() {
|
|
59
|
+
return this._req.body;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns route path parameters.
|
|
63
|
+
*/
|
|
64
|
+
get params() {
|
|
65
|
+
return this._req.params;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns parsed query string values.
|
|
69
|
+
*/
|
|
70
|
+
get query() {
|
|
71
|
+
return this._req.query;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns parsed request cookies.
|
|
75
|
+
*/
|
|
76
|
+
get cookies() {
|
|
77
|
+
return this._req.cookies;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns request session wrapper.
|
|
81
|
+
*/
|
|
82
|
+
get session() {
|
|
83
|
+
return this._req.session;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a JSON response.
|
|
87
|
+
*
|
|
88
|
+
* @param data - Serializable payload.
|
|
89
|
+
*/
|
|
90
|
+
json(data) {
|
|
91
|
+
return response_1.Response.json(data);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Creates a plain-text response.
|
|
95
|
+
*
|
|
96
|
+
* @param data - Text payload.
|
|
97
|
+
*/
|
|
98
|
+
text(data) {
|
|
99
|
+
return response_1.Response.text(data);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Creates an HTTP redirect response (302 by default).
|
|
103
|
+
*
|
|
104
|
+
* @param url - Redirect target URL.
|
|
105
|
+
*/
|
|
106
|
+
redirect(url) {
|
|
107
|
+
return response_1.Response.redirect(url);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Creates a streaming response.
|
|
111
|
+
*
|
|
112
|
+
* @param stream - Readable stream body.
|
|
113
|
+
* @param headers - Optional extra headers.
|
|
114
|
+
*/
|
|
115
|
+
stream(stream, headers) {
|
|
116
|
+
return response_1.Response.stream(stream, headers);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Creates a download response from a filesystem path.
|
|
120
|
+
*
|
|
121
|
+
* @param path - File path.
|
|
122
|
+
* @param filename - Optional download filename.
|
|
123
|
+
* @param headers - Optional additional headers.
|
|
124
|
+
*/
|
|
125
|
+
async download(path, filename, headers) {
|
|
126
|
+
return await response_1.Response.download(path, filename, headers);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Renders a configured template with optional params.
|
|
130
|
+
*
|
|
131
|
+
* @param data - Template source or identifier depending on view engine setup.
|
|
132
|
+
* @param params - Template context values.
|
|
133
|
+
*/
|
|
134
|
+
async render(data, params) {
|
|
135
|
+
return await response_1.Response.render(data, params);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Sends a file for inline display.
|
|
139
|
+
*
|
|
140
|
+
* @param filePath - File path to send.
|
|
141
|
+
* @param options - Optional root and headers.
|
|
142
|
+
*/
|
|
143
|
+
async sendFile(filePath, options) {
|
|
144
|
+
return await response_1.Response.sendFile(filePath, options);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.Context = Context;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Context } from "./context";
|
|
2
2
|
import { Response } from "./response";
|
|
3
3
|
/**
|
|
4
4
|
* High-level contract that defines the framework entry port
|
|
@@ -9,12 +9,12 @@ import { Response } from "./response";
|
|
|
9
9
|
*/
|
|
10
10
|
export interface HttpAdapter {
|
|
11
11
|
/**
|
|
12
|
-
* Builds and returns a {@link
|
|
12
|
+
* Builds and returns a {@link Context} instance from
|
|
13
13
|
* the current connection context.
|
|
14
14
|
*
|
|
15
|
-
* @returns A promise that resolves to a {@link
|
|
15
|
+
* @returns A promise that resolves to a {@link Context} object
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
getContext(): Promise<Context>;
|
|
18
18
|
/**
|
|
19
19
|
* Sends a {@link Response} to the client, mapping its status,
|
|
20
20
|
* headers, and body to the underlying runtime protocol.
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { Response } from "./response";
|
|
2
2
|
export { Request } from "./request";
|
|
3
|
+
export { Context } from "./context";
|
|
3
4
|
export { NodeHttpAdapter } from "./nodeNativeHttp";
|
|
4
5
|
export { HttpMethods } from "./httpMethods";
|
|
5
6
|
export { HttpAdapter } from "./httpAdapter";
|
|
6
7
|
export { Logger } from "./logger";
|
|
8
|
+
export type { LogFormat, LoggerOptions } from "./logger";
|
package/dist/http/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Logger = exports.HttpMethods = exports.NodeHttpAdapter = exports.Request = exports.Response = void 0;
|
|
3
|
+
exports.Logger = exports.HttpMethods = exports.NodeHttpAdapter = exports.Context = exports.Request = exports.Response = void 0;
|
|
4
4
|
var response_1 = require("./response");
|
|
5
5
|
Object.defineProperty(exports, "Response", { enumerable: true, get: function () { return response_1.Response; } });
|
|
6
6
|
var request_1 = require("./request");
|
|
7
7
|
Object.defineProperty(exports, "Request", { enumerable: true, get: function () { return request_1.Request; } });
|
|
8
|
+
var context_1 = require("./context");
|
|
9
|
+
Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_1.Context; } });
|
|
8
10
|
var nodeNativeHttp_1 = require("./nodeNativeHttp");
|
|
9
11
|
Object.defineProperty(exports, "NodeHttpAdapter", { enumerable: true, get: function () { return nodeNativeHttp_1.NodeHttpAdapter; } });
|
|
10
12
|
var httpMethods_1 = require("./httpMethods");
|
package/dist/http/logger.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
export type LogFormat = "combined" | "common" | "dev" | "short" | "tiny";
|
|
3
|
+
export type LoggerOptions = {
|
|
4
|
+
format?: LogFormat;
|
|
5
|
+
stream?: NodeJS.WritableStream;
|
|
6
|
+
fileStream?: NodeJS.WritableStream;
|
|
7
|
+
};
|
|
2
8
|
/**
|
|
3
9
|
* Minimal HTTP request logger.
|
|
4
10
|
*
|
|
@@ -17,7 +23,9 @@ import { IncomingMessage, ServerResponse } from "node:http";
|
|
|
17
23
|
*/
|
|
18
24
|
export declare class Logger {
|
|
19
25
|
private stream;
|
|
20
|
-
|
|
26
|
+
private fileStream?;
|
|
27
|
+
private format;
|
|
28
|
+
constructor(options?: LoggerOptions);
|
|
21
29
|
/**
|
|
22
30
|
* Logs an HTTP request/response pair.
|
|
23
31
|
*
|
|
@@ -37,6 +45,7 @@ export declare class Logger {
|
|
|
37
45
|
* @param startTime - High-resolution timestamp captured at request start using `process.hrtime.bigint()`.
|
|
38
46
|
*/
|
|
39
47
|
log(req: IncomingMessage, res: ServerResponse, startTime: bigint): void;
|
|
48
|
+
private buildLogLine;
|
|
40
49
|
/**
|
|
41
50
|
* Applies ANSI color codes to an HTTP status code for terminal output.
|
|
42
51
|
*
|
package/dist/http/logger.js
CHANGED
|
@@ -19,8 +19,12 @@ exports.Logger = void 0;
|
|
|
19
19
|
*/
|
|
20
20
|
class Logger {
|
|
21
21
|
stream;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
fileStream;
|
|
23
|
+
format;
|
|
24
|
+
constructor(options = {}) {
|
|
25
|
+
this.stream = options.stream || process.stdout;
|
|
26
|
+
this.fileStream = options.fileStream;
|
|
27
|
+
this.format = options.format || "dev";
|
|
24
28
|
}
|
|
25
29
|
/**
|
|
26
30
|
* Logs an HTTP request/response pair.
|
|
@@ -41,14 +45,46 @@ class Logger {
|
|
|
41
45
|
* @param startTime - High-resolution timestamp captured at request start using `process.hrtime.bigint()`.
|
|
42
46
|
*/
|
|
43
47
|
log(req, res, startTime) {
|
|
44
|
-
const method = req.method || "-";
|
|
45
|
-
const url = req.url || "-";
|
|
46
|
-
const contentLength = res.getHeader("content-length") || "-";
|
|
47
48
|
const diff = process.hrtime.bigint() - startTime;
|
|
48
49
|
const responseTime = (Number(diff) / 1_000_000).toFixed(3);
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
this.stream.write(
|
|
50
|
+
const consoleLine = this.buildLogLine(req, res, responseTime, true);
|
|
51
|
+
const fileLine = this.buildLogLine(req, res, responseTime, false);
|
|
52
|
+
this.stream.write(consoleLine + "\n");
|
|
53
|
+
if (this.fileStream) {
|
|
54
|
+
this.fileStream.write(fileLine + "\n");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
buildLogLine(req, res, responseTime, useColor) {
|
|
58
|
+
const method = req.method || "-";
|
|
59
|
+
const url = req.url || "-";
|
|
60
|
+
const statusCode = useColor
|
|
61
|
+
? this.colorizeStatus(res.statusCode)
|
|
62
|
+
: String(res.statusCode);
|
|
63
|
+
const contentLength = res.getHeader("content-length")?.toString() || "-";
|
|
64
|
+
const remoteAddr = req.socket.remoteAddress || "-";
|
|
65
|
+
const httpVersion = req.httpVersion || "1.1";
|
|
66
|
+
const referrerHeader = req.headers.referer || req.headers.referrer;
|
|
67
|
+
const referrer = Array.isArray(referrerHeader)
|
|
68
|
+
? referrerHeader.join(", ")
|
|
69
|
+
: referrerHeader || "-";
|
|
70
|
+
const userAgentHeader = req.headers["user-agent"];
|
|
71
|
+
const userAgent = Array.isArray(userAgentHeader)
|
|
72
|
+
? userAgentHeader.join(", ")
|
|
73
|
+
: userAgentHeader || "-";
|
|
74
|
+
const date = new Date().toUTCString();
|
|
75
|
+
if (this.format === "tiny") {
|
|
76
|
+
return `${method} ${url} ${statusCode} ${contentLength} - ${responseTime} ms`;
|
|
77
|
+
}
|
|
78
|
+
if (this.format === "short") {
|
|
79
|
+
return `${remoteAddr} ${method} ${url} ${statusCode} ${contentLength} - ${responseTime} ms`;
|
|
80
|
+
}
|
|
81
|
+
if (this.format === "common") {
|
|
82
|
+
return `${remoteAddr} - - [${date}] "${method} ${url} HTTP/${httpVersion}" ${statusCode} ${contentLength}`;
|
|
83
|
+
}
|
|
84
|
+
if (this.format === "combined") {
|
|
85
|
+
return `${remoteAddr} - - [${date}] "${method} ${url} HTTP/${httpVersion}" ${statusCode} ${contentLength} "${referrer}" "${userAgent}"`;
|
|
86
|
+
}
|
|
87
|
+
return `${method} ${url} ${statusCode} ${responseTime} ms - ${contentLength}`;
|
|
52
88
|
}
|
|
53
89
|
/**
|
|
54
90
|
* Applies ANSI color codes to an HTTP status code for terminal output.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import type { HttpAdapter } from "./httpAdapter";
|
|
3
3
|
import { Response } from "./response";
|
|
4
|
-
import {
|
|
4
|
+
import { Context } from "./context";
|
|
5
|
+
import { type LoggerOptions } from "./logger";
|
|
5
6
|
/**
|
|
6
7
|
* Node.js HTTP adapter.
|
|
7
8
|
*
|
|
@@ -23,14 +24,14 @@ export declare class NodeHttpAdapter implements HttpAdapter {
|
|
|
23
24
|
* @param req - Native Node.js incoming request
|
|
24
25
|
* @param res - Native Node.js server response
|
|
25
26
|
*/
|
|
26
|
-
constructor(req: IncomingMessage, res: ServerResponse);
|
|
27
|
+
constructor(req: IncomingMessage, res: ServerResponse, loggerOptions?: LoggerOptions);
|
|
27
28
|
/**
|
|
28
|
-
* Builds and returns a {@link
|
|
29
|
+
* Builds and returns a {@link Context} instance from
|
|
29
30
|
* the incoming Node.js request.
|
|
30
31
|
*
|
|
31
|
-
* @returns A fully constructed {@link
|
|
32
|
+
* @returns A fully constructed {@link Context} instance
|
|
32
33
|
*/
|
|
33
|
-
|
|
34
|
+
getContext(): Promise<Context>;
|
|
34
35
|
/**
|
|
35
36
|
* Sends a framework {@link Response} to the client by mapping it
|
|
36
37
|
* to the native Node.js {@link ServerResponse}.
|