skyguard-js 1.0.1 → 1.0.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 (39) hide show
  1. package/README.md +59 -52
  2. package/dist/app.d.ts +1 -1
  3. package/dist/app.js +9 -13
  4. package/dist/exceptions/httpExceptions.d.ts +57 -0
  5. package/dist/exceptions/httpExceptions.js +108 -0
  6. package/dist/exceptions/index.d.ts +0 -4
  7. package/dist/exceptions/index.js +1 -10
  8. package/dist/http/nodeNativeHttp.js +6 -2
  9. package/dist/http/request.d.ts +3 -5
  10. package/dist/http/request.js +8 -12
  11. package/dist/middlewares/session.js +4 -4
  12. package/dist/parsers/contentParserManager.js +3 -3
  13. package/dist/parsers/jsonParser.js +2 -2
  14. package/dist/parsers/multipartParser.d.ts +1 -1
  15. package/dist/parsers/multipartParser.js +3 -3
  16. package/dist/parsers/xmlParser.d.ts +1 -1
  17. package/dist/parsers/xmlParser.js +13 -18
  18. package/dist/routing/layer.js +1 -1
  19. package/dist/routing/router.js +5 -4
  20. package/dist/sessions/fileSessionStorage.d.ts +156 -0
  21. package/dist/sessions/fileSessionStorage.js +292 -0
  22. package/dist/sessions/index.d.ts +1 -0
  23. package/dist/sessions/index.js +3 -1
  24. package/dist/sessions/memorySessionStorage.d.ts +3 -3
  25. package/dist/sessions/memorySessionStorage.js +6 -8
  26. package/dist/sessions/session.d.ts +4 -4
  27. package/dist/sessions/session.js +4 -7
  28. package/dist/sessions/sessionStorage.d.ts +6 -26
  29. package/dist/static/contentDisposition.js +1 -1
  30. package/dist/static/fileDownload.js +10 -8
  31. package/package.json +12 -5
  32. package/dist/exceptions/contentParserException.d.ts +0 -10
  33. package/dist/exceptions/contentParserException.js +0 -21
  34. package/dist/exceptions/fileDownloadException.d.ts +0 -4
  35. package/dist/exceptions/fileDownloadException.js +0 -11
  36. package/dist/exceptions/httpNotFoundException.d.ts +0 -7
  37. package/dist/exceptions/httpNotFoundException.js +0 -14
  38. package/dist/exceptions/sessionException.d.ts +0 -4
  39. package/dist/exceptions/sessionException.js +0 -11
package/README.md CHANGED
@@ -10,24 +10,24 @@ At its current stage, the framework focuses on **routing**, **internal architect
10
10
 
11
11
  ## 🎯 Current Goals
12
12
 
13
- * Provide a simple and expressive API to register and handle HTTP routes
14
- * Maintain a clean, extensible, and framework-agnostic architecture
15
- * Leverage TypeScript for strong typing and better developer experience
16
- * Serve as a learning project with progressive evolution
13
+ - Provide a simple and expressive API to register and handle HTTP routes
14
+ - Maintain a clean, extensible, and framework-agnostic architecture
15
+ - Leverage TypeScript for strong typing and better developer experience
16
+ - Serve as a learning project with progressive evolution
17
17
 
18
18
  ---
19
19
 
20
20
  ## ✨ Current Features
21
21
 
22
- * TypeScript-first design
23
- * HTTP routing by method (GET, POST, PUT, PATCH, DELETE)
24
- * Route groups with prefixes
25
- * Global, group, and route-level middlewares
26
- * Request / Response abstractions
27
- * Declarative data validation
28
- * Simple template engine with layouts and helpers
29
- * Static file serving
30
- * Session handling (via middleware)
22
+ - TypeScript-first design
23
+ - HTTP routing by method (GET, POST, PUT, PATCH, DELETE)
24
+ - Route groups with prefixes
25
+ - Global, group, and route-level middlewares
26
+ - Request / Response abstractions
27
+ - Declarative data validation
28
+ - Simple template engine with layouts and helpers
29
+ - Static file serving
30
+ - Session handling (via middleware)
31
31
 
32
32
  ---
33
33
 
@@ -51,7 +51,7 @@ app.get("/health", () => {
51
51
  });
52
52
 
53
53
  app.run(3000, () => {
54
- console.log(`Server running in port: http://localhost:${3000}`)
54
+ console.log(`Server running in port: http://localhost:${3000}`);
55
55
  });
56
56
  ```
57
57
 
@@ -80,7 +80,7 @@ Internally, the framework maps HTTP methods to route layers using an optimized r
80
80
  Route groups allow you to organize endpoints under a shared prefix.
81
81
 
82
82
  ```ts
83
- app.group("/api", (api) => {
83
+ app.group("/api", api => {
84
84
  api.get("/users", () => Response.json({ message: "Users" }));
85
85
  api.get("/products", () => Response.json({ message: "Products" }));
86
86
  });
@@ -110,17 +110,25 @@ const authMiddleware = async (
110
110
  app.middlewares([authMiddleware]);
111
111
 
112
112
  // Group middleware
113
- app.group("/admin", (admin) => {
113
+ app.group("/admin", admin => {
114
114
  admin.middlewares([authMiddleware]);
115
115
  admin.get("/dashboard", () => Response.json({ ok: true }));
116
116
  });
117
117
 
118
118
  // Route-level middleware
119
- app.get(
120
- "/secure",
121
- () => Response.json({ secure: true }),
122
- [authMiddleware],
123
- );
119
+ app.get("/secure", () => Response.json({ secure: true }), [authMiddleware]);
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Static Files
125
+
126
+ To serve static files, use the `static` method.
127
+
128
+ ```ts
129
+ import { join } from "node:path";
130
+
131
+ app.static(join(__dirname, "..", "static"));
124
132
  ```
125
133
 
126
134
  ---
@@ -134,15 +142,15 @@ import { ValidationSchema } from "skyguard-js/validation";
134
142
 
135
143
  export const userSchema = ValidationSchema.create()
136
144
  .field("name")
137
- .required("Name is required")
138
- .string({ maxLength: 60 })
145
+ .required("Name is required")
146
+ .string({ maxLength: 60 })
139
147
  .field("email")
140
- .required()
141
- .email()
148
+ .required()
149
+ .email()
142
150
  .field("age")
143
- .number({ min: 18, max: 99 })
151
+ .number({ min: 18, max: 99 })
144
152
  .field("active")
145
- .boolean()
153
+ .boolean()
146
154
  .build();
147
155
 
148
156
  app.post("/users", (request: Request) => {
@@ -157,10 +165,10 @@ app.post("/users", (request: Request) => {
157
165
 
158
166
  Validation is:
159
167
 
160
- * Fail-fast per field
161
- * Fully typed
162
- * Reusable
163
- * Decoupled from transport layer
168
+ - Fail-fast per field
169
+ - Fully typed
170
+ - Reusable
171
+ - Decoupled from transport layer
164
172
 
165
173
  ---
166
174
 
@@ -189,13 +197,13 @@ app.get("/home", () => {
189
197
 
190
198
  ### Supported features
191
199
 
192
- * Variable interpolation (`{{ variable }}`)
193
- * Conditionals (`{{#if}}`)
194
- * Loops (`{{#each}}`)
195
- * Layouts
196
- * Partials
197
- * Built-in helpers (`upper`, `lower`, `date`)
198
- * Custom helpers
200
+ - Variable interpolation (`{{ variable }}`)
201
+ - Conditionals (`{{#if}}`)
202
+ - Loops (`{{#each}}`)
203
+ - Layouts
204
+ - Partials
205
+ - Built-in helpers (`upper`, `lower`, `date`)
206
+ - Custom helpers
199
207
 
200
208
  ---
201
209
 
@@ -203,24 +211,23 @@ app.get("/home", () => {
203
211
 
204
212
  ⚠️ **Early-stage project**
205
213
 
206
- * Not production-ready
207
- * API may change
208
- * Features are still evolving
209
- * Intended primarily for learning and experimentation
214
+ - Not production-ready
215
+ - API may change
216
+ - Features are still evolving
217
+ - Intended primarily for learning and experimentation
210
218
 
211
219
  ---
212
220
 
213
221
  ## 🔮 Roadmap (Tentative)
214
222
 
215
- * Middleware system (✅)
216
- * Template engine (✅)
217
- * Request / Response abstraction (✅)
218
- * Data validation (✅)
219
- * Error handling improvements
220
- * Database & ORM integration
221
- * Authentication & authorization
222
- * Sessions & cookies (in progress)
223
- * Plugin system
223
+ - Middleware system (✅)
224
+ - Template engine (✅)
225
+ - Request / Response abstraction (✅)
226
+ - Data validation (✅)
227
+ - Error handling improvements (✅)
228
+ - Sessions & cookies (in progress)
229
+ - Authentication & authorization
230
+ - Database & ORM integration
224
231
 
225
232
  ---
226
233
 
@@ -234,4 +241,4 @@ This project was created to deeply understand how frameworks like **Express**, *
234
241
 
235
242
  MIT License
236
243
 
237
- ---
244
+ ---
package/dist/app.d.ts CHANGED
@@ -73,7 +73,7 @@ export declare class App {
73
73
  *
74
74
  * @param port - TCP port to listen on
75
75
  */
76
- run(port: number, callback: VoidFunction): void;
76
+ run(port: number, callback: VoidFunction, hostname?: string): void;
77
77
  /**
78
78
  * Sets a global prefix for all routes.
79
79
  *
package/dist/app.js CHANGED
@@ -9,6 +9,7 @@ const node_path_1 = require("node:path");
9
9
  const app_1 = require("./helpers/app");
10
10
  const fileStaticHandler_1 = require("./static/fileStaticHandler");
11
11
  const node_http_1 = require("node:http");
12
+ const httpExceptions_1 = require("./exceptions/httpExceptions");
12
13
  /**
13
14
  * The `App` class acts as the **execution kernel** and **lifecycle orchestrator**
14
15
  * of the framework.
@@ -104,11 +105,11 @@ class App {
104
105
  *
105
106
  * @param port - TCP port to listen on
106
107
  */
107
- run(port, callback) {
108
+ run(port, callback, hostname = "127.0.0.1") {
108
109
  (0, node_http_1.createServer)((req, res) => {
109
110
  const adapter = new http_1.NodeHttpAdapter(req, res);
110
111
  void this.handle(adapter);
111
- }).listen(port, () => {
112
+ }).listen(port, hostname, () => {
112
113
  callback();
113
114
  });
114
115
  }
@@ -170,16 +171,8 @@ class App {
170
171
  * This method centralizes error handling and response mapping.
171
172
  */
172
173
  handleError(error, adapter) {
173
- if (error instanceof exceptions_1.HttpNotFoundException) {
174
- adapter.sendResponse(http_1.Response.text("Not Found").setStatus(404));
175
- return;
176
- }
177
- if (error instanceof exceptions_1.ContentParserException) {
178
- adapter.sendResponse(http_1.Response.json({ message: error.message }).setStatus(422));
179
- return;
180
- }
181
- if (error instanceof exceptions_1.SessionException) {
182
- adapter.sendResponse(http_1.Response.json({ message: error.message }).setStatus(401));
174
+ if (error instanceof httpExceptions_1.HttpException) {
175
+ adapter.sendResponse(http_1.Response.json(error.toJSON()).setStatus(error.statusCode));
183
176
  return;
184
177
  }
185
178
  if (error instanceof exceptions_1.ValidationException) {
@@ -189,7 +182,10 @@ class App {
189
182
  }).setStatus(400));
190
183
  return;
191
184
  }
192
- adapter.sendResponse(http_1.Response.text("Internal Server Error").setStatus(500));
185
+ adapter.sendResponse(http_1.Response.json({
186
+ statusCode: 500,
187
+ message: "Internal Server Error",
188
+ }).setStatus(500));
193
189
  console.error(error);
194
190
  }
195
191
  }
@@ -0,0 +1,57 @@
1
+ export interface HttpExceptionOptions {
2
+ message?: string;
3
+ statusCode?: number;
4
+ code?: string;
5
+ }
6
+ export declare class HttpException extends Error {
7
+ readonly statusCode: number;
8
+ readonly code: string;
9
+ constructor(options: HttpExceptionOptions);
10
+ toJSON(): {
11
+ message: string;
12
+ statusCode: number;
13
+ code: string;
14
+ };
15
+ }
16
+ export declare class BadRequestError extends HttpException {
17
+ constructor(message: string);
18
+ }
19
+ export declare class UnauthorizedError extends HttpException {
20
+ constructor(message: string);
21
+ }
22
+ export declare class ForbiddenError extends HttpException {
23
+ constructor(message: string);
24
+ }
25
+ export declare class NotFoundError extends HttpException {
26
+ constructor(message: string);
27
+ }
28
+ export declare class RequestTimeoutError extends HttpException {
29
+ constructor(message: string);
30
+ }
31
+ export declare class ConflictError extends HttpException {
32
+ constructor(message: string);
33
+ }
34
+ export declare class UnsopportedMediaTypeError extends HttpException {
35
+ constructor(message: string);
36
+ }
37
+ export declare class UnprocessableContentError extends HttpException {
38
+ constructor(message: string);
39
+ }
40
+ export declare class TooManyRequestsError extends HttpException {
41
+ constructor(message: string);
42
+ }
43
+ export declare class InternalServerError extends HttpException {
44
+ constructor(message: string);
45
+ }
46
+ export declare class NotImplementedError extends HttpException {
47
+ constructor(message: string);
48
+ }
49
+ export declare class BadGatewayError extends HttpException {
50
+ constructor(message: string);
51
+ }
52
+ export declare class ServiceUnavailableError extends HttpException {
53
+ constructor(message: string);
54
+ }
55
+ export declare class GatewayTimeoutError extends HttpException {
56
+ constructor(message: string);
57
+ }
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GatewayTimeoutError = exports.ServiceUnavailableError = exports.BadGatewayError = exports.NotImplementedError = exports.InternalServerError = exports.TooManyRequestsError = exports.UnprocessableContentError = exports.UnsopportedMediaTypeError = exports.ConflictError = exports.RequestTimeoutError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.HttpException = void 0;
4
+ class HttpException extends Error {
5
+ statusCode;
6
+ code;
7
+ constructor(options) {
8
+ super(options.message ?? "Internal Server Error");
9
+ this.name = this.constructor.name;
10
+ this.statusCode = options.statusCode ?? 500;
11
+ this.code = options.code ?? "INTERNAL_SERVER_ERROR";
12
+ Error.captureStackTrace(this, this.constructor);
13
+ }
14
+ toJSON() {
15
+ return {
16
+ message: this.message,
17
+ statusCode: this.statusCode,
18
+ code: this.code,
19
+ };
20
+ }
21
+ }
22
+ exports.HttpException = HttpException;
23
+ // Errores 4xx - Client
24
+ class BadRequestError extends HttpException {
25
+ constructor(message) {
26
+ super({ message, statusCode: 400, code: "BAD_REQUEST" });
27
+ }
28
+ }
29
+ exports.BadRequestError = BadRequestError;
30
+ class UnauthorizedError extends HttpException {
31
+ constructor(message) {
32
+ super({ message, statusCode: 401, code: "UNAUTHORIZED" });
33
+ }
34
+ }
35
+ exports.UnauthorizedError = UnauthorizedError;
36
+ class ForbiddenError extends HttpException {
37
+ constructor(message) {
38
+ super({ message, statusCode: 403, code: "FORBIDDEN" });
39
+ }
40
+ }
41
+ exports.ForbiddenError = ForbiddenError;
42
+ class NotFoundError extends HttpException {
43
+ constructor(message) {
44
+ super({ message, statusCode: 404, code: "NOT_FOUND" });
45
+ }
46
+ }
47
+ exports.NotFoundError = NotFoundError;
48
+ class RequestTimeoutError extends HttpException {
49
+ constructor(message) {
50
+ super({ message, statusCode: 408, code: "REQUEST_TIMEOUT" });
51
+ }
52
+ }
53
+ exports.RequestTimeoutError = RequestTimeoutError;
54
+ class ConflictError extends HttpException {
55
+ constructor(message) {
56
+ super({ message, statusCode: 409, code: "CONFLICT" });
57
+ }
58
+ }
59
+ exports.ConflictError = ConflictError;
60
+ class UnsopportedMediaTypeError extends HttpException {
61
+ constructor(message) {
62
+ super({ message, statusCode: 415, code: "UNSOPPORTED_MEDIA_TYPE" });
63
+ }
64
+ }
65
+ exports.UnsopportedMediaTypeError = UnsopportedMediaTypeError;
66
+ class UnprocessableContentError extends HttpException {
67
+ constructor(message) {
68
+ super({ message, statusCode: 422, code: "UNPROCESSABLE_CONTENT" });
69
+ }
70
+ }
71
+ exports.UnprocessableContentError = UnprocessableContentError;
72
+ class TooManyRequestsError extends HttpException {
73
+ constructor(message) {
74
+ super({ message, statusCode: 429, code: "TOO_MANY_REQUESTS" });
75
+ }
76
+ }
77
+ exports.TooManyRequestsError = TooManyRequestsError;
78
+ // Errores 5xx - Servidor
79
+ class InternalServerError extends HttpException {
80
+ constructor(message) {
81
+ super({ message, statusCode: 500, code: "INTERNAL_SERVER_ERROR" });
82
+ }
83
+ }
84
+ exports.InternalServerError = InternalServerError;
85
+ class NotImplementedError extends HttpException {
86
+ constructor(message) {
87
+ super({ message, statusCode: 501, code: "NOT_IMPLEMENTED" });
88
+ }
89
+ }
90
+ exports.NotImplementedError = NotImplementedError;
91
+ class BadGatewayError extends HttpException {
92
+ constructor(message) {
93
+ super({ message, statusCode: 502, code: "BAD_GATEWAY" });
94
+ }
95
+ }
96
+ exports.BadGatewayError = BadGatewayError;
97
+ class ServiceUnavailableError extends HttpException {
98
+ constructor(message) {
99
+ super({ message, statusCode: 503, code: "SERVICE_UNAVAILABLE" });
100
+ }
101
+ }
102
+ exports.ServiceUnavailableError = ServiceUnavailableError;
103
+ class GatewayTimeoutError extends HttpException {
104
+ constructor(message) {
105
+ super({ message, statusCode: 504, code: "GATEWAY_TIMEOUT" });
106
+ }
107
+ }
108
+ exports.GatewayTimeoutError = GatewayTimeoutError;
@@ -1,9 +1,5 @@
1
- export { ContentParserException, ReadBodyException, } from "./contentParserException";
2
1
  export { FileNotExistsException } from "./fileExistsException";
3
- export { HttpNotFoundException } from "./httpNotFoundException";
4
2
  export { HelperExecutionException, HelperNotFoundException, HelperArgumentException, } from "./helperExceptions";
5
3
  export { ValidationException, ValidatorFieldException, } from "./validationException";
6
4
  export { ContentDispositionException } from "./contentDispositionException";
7
- export { FileDownloadException } from "./fileDownloadException";
8
- export { SessionException } from "./sessionException";
9
5
  export { InvalidHttpStatusException } from "./invalidHttpStatusException";
@@ -1,13 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InvalidHttpStatusException = exports.SessionException = exports.FileDownloadException = exports.ContentDispositionException = exports.ValidatorFieldException = exports.ValidationException = exports.HelperArgumentException = exports.HelperNotFoundException = exports.HelperExecutionException = exports.HttpNotFoundException = exports.FileNotExistsException = exports.ReadBodyException = exports.ContentParserException = void 0;
4
- var contentParserException_1 = require("./contentParserException");
5
- Object.defineProperty(exports, "ContentParserException", { enumerable: true, get: function () { return contentParserException_1.ContentParserException; } });
6
- Object.defineProperty(exports, "ReadBodyException", { enumerable: true, get: function () { return contentParserException_1.ReadBodyException; } });
3
+ exports.InvalidHttpStatusException = exports.ContentDispositionException = exports.ValidatorFieldException = exports.ValidationException = exports.HelperArgumentException = exports.HelperNotFoundException = exports.HelperExecutionException = exports.FileNotExistsException = void 0;
7
4
  var fileExistsException_1 = require("./fileExistsException");
8
5
  Object.defineProperty(exports, "FileNotExistsException", { enumerable: true, get: function () { return fileExistsException_1.FileNotExistsException; } });
9
- var httpNotFoundException_1 = require("./httpNotFoundException");
10
- Object.defineProperty(exports, "HttpNotFoundException", { enumerable: true, get: function () { return httpNotFoundException_1.HttpNotFoundException; } });
11
6
  var helperExceptions_1 = require("./helperExceptions");
12
7
  Object.defineProperty(exports, "HelperExecutionException", { enumerable: true, get: function () { return helperExceptions_1.HelperExecutionException; } });
13
8
  Object.defineProperty(exports, "HelperNotFoundException", { enumerable: true, get: function () { return helperExceptions_1.HelperNotFoundException; } });
@@ -17,9 +12,5 @@ Object.defineProperty(exports, "ValidationException", { enumerable: true, get: f
17
12
  Object.defineProperty(exports, "ValidatorFieldException", { enumerable: true, get: function () { return validationException_1.ValidatorFieldException; } });
18
13
  var contentDispositionException_1 = require("./contentDispositionException");
19
14
  Object.defineProperty(exports, "ContentDispositionException", { enumerable: true, get: function () { return contentDispositionException_1.ContentDispositionException; } });
20
- var fileDownloadException_1 = require("./fileDownloadException");
21
- Object.defineProperty(exports, "FileDownloadException", { enumerable: true, get: function () { return fileDownloadException_1.FileDownloadException; } });
22
- var sessionException_1 = require("./sessionException");
23
- Object.defineProperty(exports, "SessionException", { enumerable: true, get: function () { return sessionException_1.SessionException; } });
24
15
  var invalidHttpStatusException_1 = require("./invalidHttpStatusException");
25
16
  Object.defineProperty(exports, "InvalidHttpStatusException", { enumerable: true, get: function () { return invalidHttpStatusException_1.InvalidHttpStatusException; } });
@@ -42,8 +42,12 @@ class NodeHttpAdapter {
42
42
  .setMethod(this.req.method || httpMethods_1.HttpMethods.get)
43
43
  .setQueryParams(Object.fromEntries(url.searchParams.entries()))
44
44
  .setHeaders(this.req.headers);
45
- const parsedData = await this.contentParser.parse(this.req);
46
- request.setData(parsedData);
45
+ if (request.getMethod === httpMethods_1.HttpMethods.post ||
46
+ request.getMethod === httpMethods_1.HttpMethods.put ||
47
+ request.getMethod === httpMethods_1.HttpMethods.patch) {
48
+ const parsedData = await this.contentParser.parse(this.req);
49
+ request.setData(parsedData);
50
+ }
47
51
  return request;
48
52
  }
49
53
  /**
@@ -1,6 +1,5 @@
1
1
  import { HttpMethods } from "./httpMethods";
2
2
  import type { Headers, HttpValue } from "../types";
3
- import { Layer } from "../routing/layer";
4
3
  import { FieldDefinition } from "../validators";
5
4
  import { Session } from "../sessions";
6
5
  /**
@@ -18,8 +17,6 @@ import { Session } from "../sessions";
18
17
  export declare class Request {
19
18
  /** Normalized request path (e.g. "/api/users/42") */
20
19
  private url;
21
- /** Routing layer that resolved this request */
22
- private layer;
23
20
  /** Incoming HTTP headers */
24
21
  private headers;
25
22
  /** Normalized HTTP method */
@@ -28,14 +25,14 @@ export declare class Request {
28
25
  private data;
29
26
  /** Query string parameters */
30
27
  private query;
28
+ /** Dynamic route parameters (path params) */
29
+ private params;
31
30
  /** Session associated with the request */
32
31
  private session;
33
32
  constructor(url: string);
34
33
  get getUrl(): string;
35
34
  get getMethod(): HttpMethods;
36
35
  setMethod(method: HttpMethods): this;
37
- get getLayer(): Layer;
38
- setLayer(layer: Layer): this;
39
36
  get getHeaders(): Headers;
40
37
  setHeaders(headers: Headers): this;
41
38
  /**
@@ -70,6 +67,7 @@ export declare class Request {
70
67
  * request.getParams("id"); // "42"
71
68
  */
72
69
  getParams(key?: string): HttpValue;
70
+ setParams(params: Record<string, string>): this;
73
71
  getData(): Record<string, unknown>;
74
72
  setData(data: Record<string, any>): this;
75
73
  get getSession(): Session;
@@ -17,8 +17,6 @@ const validators_1 = require("../validators");
17
17
  class Request {
18
18
  /** Normalized request path (e.g. "/api/users/42") */
19
19
  url;
20
- /** Routing layer that resolved this request */
21
- layer;
22
20
  /** Incoming HTTP headers */
23
21
  headers;
24
22
  /** Normalized HTTP method */
@@ -27,6 +25,8 @@ class Request {
27
25
  data = {};
28
26
  /** Query string parameters */
29
27
  query = {};
28
+ /** Dynamic route parameters (path params) */
29
+ params = {};
30
30
  /** Session associated with the request */
31
31
  session;
32
32
  constructor(url) {
@@ -42,13 +42,6 @@ class Request {
42
42
  this.method = method;
43
43
  return this;
44
44
  }
45
- get getLayer() {
46
- return this.layer;
47
- }
48
- setLayer(layer) {
49
- this.layer = layer;
50
- return this;
51
- }
52
45
  get getHeaders() {
53
46
  return this.headers;
54
47
  }
@@ -95,10 +88,13 @@ class Request {
95
88
  * request.getParams("id"); // "42"
96
89
  */
97
90
  getParams(key = null) {
98
- const parameters = this.layer.parseParameters(this.url);
99
91
  if (key === null)
100
- return parameters;
101
- return parameters[key] ?? null;
92
+ return this.params;
93
+ return this.params[key] ?? null;
94
+ }
95
+ setParams(params) {
96
+ this.params = params;
97
+ return this;
102
98
  }
103
99
  getData() {
104
100
  return this.data;
@@ -15,7 +15,7 @@ const sessions_1 = require("../sessions");
15
15
  function parseCookies(cookieHeader) {
16
16
  if (!cookieHeader)
17
17
  return {};
18
- return Object.fromEntries(cookieHeader.split(";").map((cookie) => {
18
+ return Object.fromEntries(cookieHeader.split(";").map(cookie => {
19
19
  const [key, ...value] = cookie.trim().split("=");
20
20
  return [key, decodeURIComponent(value.join("="))];
21
21
  }));
@@ -70,15 +70,15 @@ const sessions = (StorageClass, options = {}) => {
70
70
  path: options.path ?? "/",
71
71
  };
72
72
  return async (request, next) => {
73
- const cookies = parseCookies(request.getHeaders["cookie"] || "");
73
+ const cookies = parseCookies(request.getHeaders.cookie || "");
74
74
  const sessionId = cookies[config.cookieName];
75
75
  const storage = new StorageClass(options.maxAge || timeMaxAge);
76
76
  if (sessionId)
77
- storage.load(sessionId);
77
+ await storage.load(sessionId);
78
78
  const session = new sessions_1.Session(storage);
79
79
  request.setSession(session);
80
80
  const response = await next(request);
81
- if (storage.id() !== null) {
81
+ if (storage.id()) {
82
82
  const cookieValue = buildSessionCookie(storage.id(), config);
83
83
  response.setHeader("Set-Cookie", cookieValue);
84
84
  }
@@ -6,7 +6,7 @@ const multipartParser_1 = require("./multipartParser");
6
6
  const textParser_1 = require("./textParser");
7
7
  const urlEncodedParser_1 = require("./urlEncodedParser");
8
8
  const xmlParser_1 = require("./xmlParser");
9
- const contentParserException_1 = require("../exceptions/contentParserException");
9
+ const httpExceptions_1 = require("../exceptions/httpExceptions");
10
10
  /**
11
11
  * Main request body parsing manager.
12
12
  *
@@ -74,7 +74,7 @@ class ContentParserManager {
74
74
  resolve(Buffer.concat(chunks));
75
75
  });
76
76
  req.on("error", () => {
77
- reject(new contentParserException_1.ReadBodyException());
77
+ reject(new httpExceptions_1.UnprocessableContentError("Failed to read request body"));
78
78
  });
79
79
  });
80
80
  }
@@ -85,7 +85,7 @@ class ContentParserManager {
85
85
  * @returns Matching parser or `null` if none is found
86
86
  */
87
87
  findParser(contentType) {
88
- return this.parsers.find((parser) => parser.canParse(contentType)) || null;
88
+ return this.parsers.find(parser => parser.canParse(contentType)) || null;
89
89
  }
90
90
  }
91
91
  exports.ContentParserManager = ContentParserManager;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.JsonParser = void 0;
4
- const contentParserException_1 = require("../exceptions/contentParserException");
4
+ const httpExceptions_1 = require("../exceptions/httpExceptions");
5
5
  /**
6
6
  * JSON content parser.
7
7
  *
@@ -17,7 +17,7 @@ class JsonParser {
17
17
  return JSON.parse(text);
18
18
  }
19
19
  catch {
20
- throw new contentParserException_1.ContentParserException("Invalid JSON content");
20
+ throw new httpExceptions_1.UnprocessableContentError("Invalid JSON content");
21
21
  }
22
22
  }
23
23
  }
@@ -19,7 +19,7 @@ export declare class MultipartParser implements ContentParser {
19
19
  * @param body - Raw request body
20
20
  * @param contentType - Full `Content-Type` header value
21
21
  * @returns Parsed multipart data (fields and files)
22
- * @throws {ContentParserException} If the multipart boundary is missing
22
+ * @throws {UnprocessableContentError} If the multipart boundary is missing
23
23
  *
24
24
  * @example
25
25
  * // Typically called through ContentParserManager based on Content-Type:
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MultipartParser = void 0;
4
- const contentParserException_1 = require("../exceptions/contentParserException");
4
+ const httpExceptions_1 = require("../exceptions/httpExceptions");
5
5
  /**
6
6
  * `multipart/form-data` content parser.
7
7
  *
@@ -23,7 +23,7 @@ class MultipartParser {
23
23
  * @param body - Raw request body
24
24
  * @param contentType - Full `Content-Type` header value
25
25
  * @returns Parsed multipart data (fields and files)
26
- * @throws {ContentParserException} If the multipart boundary is missing
26
+ * @throws {UnprocessableContentError} If the multipart boundary is missing
27
27
  *
28
28
  * @example
29
29
  * // Typically called through ContentParserManager based on Content-Type:
@@ -34,7 +34,7 @@ class MultipartParser {
34
34
  const buffer = Buffer.isBuffer(body) ? body : Buffer.from(body);
35
35
  const boundary = this.extractBoundary(contentType);
36
36
  if (!boundary) {
37
- throw new contentParserException_1.ContentParserException("Missing boundary in multipart/form-data");
37
+ throw new httpExceptions_1.UnprocessableContentError("Missing boundary in multipart/form-data");
38
38
  }
39
39
  return this.parseMultipart(buffer, boundary);
40
40
  }