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.
- package/README.md +59 -52
- package/dist/app.d.ts +1 -1
- package/dist/app.js +9 -13
- package/dist/exceptions/httpExceptions.d.ts +57 -0
- package/dist/exceptions/httpExceptions.js +108 -0
- package/dist/exceptions/index.d.ts +0 -4
- package/dist/exceptions/index.js +1 -10
- package/dist/http/nodeNativeHttp.js +6 -2
- package/dist/http/request.d.ts +3 -5
- package/dist/http/request.js +8 -12
- package/dist/middlewares/session.js +4 -4
- package/dist/parsers/contentParserManager.js +3 -3
- package/dist/parsers/jsonParser.js +2 -2
- package/dist/parsers/multipartParser.d.ts +1 -1
- package/dist/parsers/multipartParser.js +3 -3
- package/dist/parsers/xmlParser.d.ts +1 -1
- package/dist/parsers/xmlParser.js +13 -18
- package/dist/routing/layer.js +1 -1
- package/dist/routing/router.js +5 -4
- package/dist/sessions/fileSessionStorage.d.ts +156 -0
- package/dist/sessions/fileSessionStorage.js +292 -0
- package/dist/sessions/index.d.ts +1 -0
- package/dist/sessions/index.js +3 -1
- package/dist/sessions/memorySessionStorage.d.ts +3 -3
- package/dist/sessions/memorySessionStorage.js +6 -8
- package/dist/sessions/session.d.ts +4 -4
- package/dist/sessions/session.js +4 -7
- package/dist/sessions/sessionStorage.d.ts +6 -26
- package/dist/static/contentDisposition.js +1 -1
- package/dist/static/fileDownload.js +10 -8
- package/package.json +12 -5
- package/dist/exceptions/contentParserException.d.ts +0 -10
- package/dist/exceptions/contentParserException.js +0 -21
- package/dist/exceptions/fileDownloadException.d.ts +0 -4
- package/dist/exceptions/fileDownloadException.js +0 -11
- package/dist/exceptions/httpNotFoundException.d.ts +0 -7
- package/dist/exceptions/httpNotFoundException.js +0 -14
- package/dist/exceptions/sessionException.d.ts +0 -4
- 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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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",
|
|
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",
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
138
|
-
|
|
145
|
+
.required("Name is required")
|
|
146
|
+
.string({ maxLength: 60 })
|
|
139
147
|
.field("email")
|
|
140
|
-
|
|
141
|
-
|
|
148
|
+
.required()
|
|
149
|
+
.email()
|
|
142
150
|
.field("age")
|
|
143
|
-
|
|
151
|
+
.number({ min: 18, max: 99 })
|
|
144
152
|
.field("active")
|
|
145
|
-
|
|
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
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
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
|
|
174
|
-
adapter.sendResponse(http_1.Response.
|
|
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.
|
|
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";
|
package/dist/exceptions/index.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InvalidHttpStatusException = exports.
|
|
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
|
-
|
|
46
|
-
|
|
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
|
/**
|
package/dist/http/request.d.ts
CHANGED
|
@@ -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;
|
package/dist/http/request.js
CHANGED
|
@@ -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
|
|
101
|
-
return
|
|
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(
|
|
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
|
|
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()
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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 {
|
|
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
|
|
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 {
|
|
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
|
|
37
|
+
throw new httpExceptions_1.UnprocessableContentError("Missing boundary in multipart/form-data");
|
|
38
38
|
}
|
|
39
39
|
return this.parseMultipart(buffer, boundary);
|
|
40
40
|
}
|