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.
Files changed (52) hide show
  1. package/README.md +9 -462
  2. package/dist/app.d.ts +34 -10
  3. package/dist/app.js +59 -27
  4. package/dist/crypto/hasher.js +2 -1
  5. package/dist/crypto/jwt.js +2 -1
  6. package/dist/http/context.d.ts +115 -0
  7. package/dist/http/context.js +147 -0
  8. package/dist/http/httpAdapter.d.ts +4 -4
  9. package/dist/http/index.d.ts +2 -0
  10. package/dist/http/index.js +3 -1
  11. package/dist/http/logger.d.ts +10 -1
  12. package/dist/http/logger.js +44 -8
  13. package/dist/http/nodeNativeHttp.d.ts +6 -5
  14. package/dist/http/nodeNativeHttp.js +13 -6
  15. package/dist/http/request.d.ts +4 -0
  16. package/dist/http/request.js +12 -4
  17. package/dist/http/response.d.ts +21 -2
  18. package/dist/http/response.js +30 -2
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +3 -2
  21. package/dist/middlewares/cors.d.ts +10 -4
  22. package/dist/middlewares/cors.js +35 -18
  23. package/dist/middlewares/csrf.js +33 -33
  24. package/dist/middlewares/index.d.ts +1 -1
  25. package/dist/middlewares/rateLimiter.d.ts +58 -6
  26. package/dist/middlewares/rateLimiter.js +149 -40
  27. package/dist/middlewares/session.js +4 -4
  28. package/dist/routing/routeResolveFunc.d.ts +10 -0
  29. package/dist/routing/routeResolveFunc.js +21 -0
  30. package/dist/routing/router.d.ts +16 -10
  31. package/dist/routing/router.js +32 -25
  32. package/dist/routing/routerGroup.d.ts +10 -5
  33. package/dist/routing/routerGroup.js +11 -10
  34. package/dist/sessions/databaseSessionStorage.d.ts +52 -0
  35. package/dist/sessions/databaseSessionStorage.js +166 -0
  36. package/dist/sessions/fileSessionStorage.js +1 -1
  37. package/dist/sessions/index.d.ts +1 -0
  38. package/dist/sessions/index.js +3 -1
  39. package/dist/sessions/memorySessionStorage.js +1 -1
  40. package/dist/storage/storage.d.ts +3 -3
  41. package/dist/storage/storage.js +7 -7
  42. package/dist/storage/types.d.ts +5 -5
  43. package/dist/storage/uploader.d.ts +9 -9
  44. package/dist/storage/uploader.js +62 -62
  45. package/dist/types/index.d.ts +11 -10
  46. package/dist/validators/rules/bigIntRule.d.ts +0 -6
  47. package/dist/validators/rules/bigIntRule.js +0 -24
  48. package/dist/validators/validationRule.js +1 -1
  49. package/dist/validators/validationSchema.js +8 -8
  50. package/package.json +2 -2
  51. package/dist/helpers/http.d.ts +0 -95
  52. 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 = exports.App = void 0;
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 request = await adapter.getRequest();
70
- if (this.staticFileHandler && request.method === http_1.HttpMethods.get) {
71
- const staticResponse = await this.staticFileHandler.tryServeFile(request.url);
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(request);
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 = "127.0.0.1") {
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
- /** Registers a GET route */
166
- get(path, action, middlewares) {
167
- this.router.get(path, action, middlewares);
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
- /** Registers a POST route */
170
- post(path, action, middlewares) {
171
- this.router.post(path, action, middlewares);
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
- /** Registers a PUT route */
174
- put(path, action, middlewares) {
175
- this.router.put(path, action, middlewares);
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
- /** Registers a PATCH route */
178
- patch(path, action, middlewares) {
179
- this.router.patch(path, action, middlewares);
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
- /** Registers a DELETE route */
182
- delete(path, action, middlewares) {
183
- this.router.delete(path, action, middlewares);
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 (request, next) => {
192
- * console.log(request.header);
193
- * return await next(request);
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
  };
@@ -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 = new HasherCrypto();
261
+ exports.Hasher = container_1.Container.singleton(HasherCrypto);
@@ -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 = new 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 { Request } from "./request";
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 Request} instance from
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 Request} object
15
+ * @returns A promise that resolves to a {@link Context} object
16
16
  */
17
- getRequest(): Promise<Request>;
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.
@@ -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";
@@ -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");
@@ -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
- constructor();
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
  *
@@ -19,8 +19,12 @@ exports.Logger = void 0;
19
19
  */
20
20
  class Logger {
21
21
  stream;
22
- constructor() {
23
- this.stream = process.stdout;
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 coloredStatus = this.colorizeStatus(res.statusCode);
50
- const logLine = `${method} ${url} ${coloredStatus} ${responseTime} ms - ${contentLength.toString()}`;
51
- this.stream.write(logLine + "\n");
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 { Request } from "./request";
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 Request} instance from
29
+ * Builds and returns a {@link Context} instance from
29
30
  * the incoming Node.js request.
30
31
  *
31
- * @returns A fully constructed {@link Request} instance
32
+ * @returns A fully constructed {@link Context} instance
32
33
  */
33
- getRequest(): Promise<Request>;
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}.