skyguard-js 1.0.0

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 (142) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +237 -0
  3. package/dist/app.d.ts +123 -0
  4. package/dist/app.js +198 -0
  5. package/dist/container/container.d.ts +60 -0
  6. package/dist/container/container.js +71 -0
  7. package/dist/exceptions/baseException.d.ts +6 -0
  8. package/dist/exceptions/baseException.js +15 -0
  9. package/dist/exceptions/contentDispositionException.d.ts +4 -0
  10. package/dist/exceptions/contentDispositionException.js +11 -0
  11. package/dist/exceptions/contentParserException.d.ts +10 -0
  12. package/dist/exceptions/contentParserException.js +21 -0
  13. package/dist/exceptions/fileDownloadException.d.ts +4 -0
  14. package/dist/exceptions/fileDownloadException.js +11 -0
  15. package/dist/exceptions/fileExistsException.d.ts +4 -0
  16. package/dist/exceptions/fileExistsException.js +11 -0
  17. package/dist/exceptions/helperExceptions.d.ts +10 -0
  18. package/dist/exceptions/helperExceptions.js +25 -0
  19. package/dist/exceptions/httpNotFoundException.d.ts +7 -0
  20. package/dist/exceptions/httpNotFoundException.js +14 -0
  21. package/dist/exceptions/index.d.ts +9 -0
  22. package/dist/exceptions/index.js +25 -0
  23. package/dist/exceptions/invalidHttpStatusException.d.ts +4 -0
  24. package/dist/exceptions/invalidHttpStatusException.js +11 -0
  25. package/dist/exceptions/sessionException.d.ts +4 -0
  26. package/dist/exceptions/sessionException.js +11 -0
  27. package/dist/exceptions/validationException.d.ts +13 -0
  28. package/dist/exceptions/validationException.js +32 -0
  29. package/dist/helpers/app.d.ts +4 -0
  30. package/dist/helpers/app.js +12 -0
  31. package/dist/helpers/http.d.ts +59 -0
  32. package/dist/helpers/http.js +77 -0
  33. package/dist/helpers/index.d.ts +1 -0
  34. package/dist/helpers/index.js +9 -0
  35. package/dist/http/httpAdapter.d.ts +26 -0
  36. package/dist/http/httpAdapter.js +2 -0
  37. package/dist/http/httpMethods.d.ts +14 -0
  38. package/dist/http/httpMethods.js +18 -0
  39. package/dist/http/index.d.ts +6 -0
  40. package/dist/http/index.js +13 -0
  41. package/dist/http/logger.d.ts +8 -0
  42. package/dist/http/logger.js +36 -0
  43. package/dist/http/nodeNativeHttp.d.ts +41 -0
  44. package/dist/http/nodeNativeHttp.js +73 -0
  45. package/dist/http/request.d.ts +85 -0
  46. package/dist/http/request.js +127 -0
  47. package/dist/http/response.d.ts +118 -0
  48. package/dist/http/response.js +179 -0
  49. package/dist/http/statusCodes.d.ts +1 -0
  50. package/dist/http/statusCodes.js +38 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.js +10 -0
  53. package/dist/middlewares/cors.d.ts +103 -0
  54. package/dist/middlewares/cors.js +91 -0
  55. package/dist/middlewares/session.d.ts +26 -0
  56. package/dist/middlewares/session.js +88 -0
  57. package/dist/parsers/contentParser.d.ts +27 -0
  58. package/dist/parsers/contentParser.js +2 -0
  59. package/dist/parsers/contentParserManager.d.ts +50 -0
  60. package/dist/parsers/contentParserManager.js +91 -0
  61. package/dist/parsers/index.d.ts +8 -0
  62. package/dist/parsers/index.js +30 -0
  63. package/dist/parsers/jsonParser.d.ts +10 -0
  64. package/dist/parsers/jsonParser.js +24 -0
  65. package/dist/parsers/multipartParser.d.ts +35 -0
  66. package/dist/parsers/multipartParser.js +120 -0
  67. package/dist/parsers/parserInterface.d.ts +37 -0
  68. package/dist/parsers/parserInterface.js +2 -0
  69. package/dist/parsers/textParser.d.ts +11 -0
  70. package/dist/parsers/textParser.js +19 -0
  71. package/dist/parsers/urlEncodedParser.d.ts +10 -0
  72. package/dist/parsers/urlEncodedParser.js +19 -0
  73. package/dist/parsers/xmlParser.d.ts +47 -0
  74. package/dist/parsers/xmlParser.js +158 -0
  75. package/dist/routing/index.d.ts +3 -0
  76. package/dist/routing/index.js +9 -0
  77. package/dist/routing/layer.d.ts +85 -0
  78. package/dist/routing/layer.js +117 -0
  79. package/dist/routing/router.d.ts +143 -0
  80. package/dist/routing/router.js +210 -0
  81. package/dist/routing/routerGroup.d.ts +79 -0
  82. package/dist/routing/routerGroup.js +103 -0
  83. package/dist/server/nodeNativeServer.d.ts +29 -0
  84. package/dist/server/nodeNativeServer.js +42 -0
  85. package/dist/sessions/cookieOptions.d.ts +72 -0
  86. package/dist/sessions/cookieOptions.js +2 -0
  87. package/dist/sessions/index.d.ts +4 -0
  88. package/dist/sessions/index.js +7 -0
  89. package/dist/sessions/memorySessionStorage.d.ts +112 -0
  90. package/dist/sessions/memorySessionStorage.js +170 -0
  91. package/dist/sessions/session.d.ts +80 -0
  92. package/dist/sessions/session.js +101 -0
  93. package/dist/sessions/sessionStorage.d.ts +105 -0
  94. package/dist/sessions/sessionStorage.js +2 -0
  95. package/dist/static/contentDisposition.d.ts +71 -0
  96. package/dist/static/contentDisposition.js +159 -0
  97. package/dist/static/fileDownload.d.ts +44 -0
  98. package/dist/static/fileDownload.js +88 -0
  99. package/dist/static/fileStaticHandler.d.ts +61 -0
  100. package/dist/static/fileStaticHandler.js +110 -0
  101. package/dist/static/index.d.ts +4 -0
  102. package/dist/static/index.js +11 -0
  103. package/dist/static/mimeTypes.d.ts +1 -0
  104. package/dist/static/mimeTypes.js +40 -0
  105. package/dist/tsconfig.tsbuildinfo +1 -0
  106. package/dist/types/index.d.ts +122 -0
  107. package/dist/types/index.js +2 -0
  108. package/dist/validators/index.d.ts +5 -0
  109. package/dist/validators/index.js +22 -0
  110. package/dist/validators/rules/booleanRule.d.ts +11 -0
  111. package/dist/validators/rules/booleanRule.js +22 -0
  112. package/dist/validators/rules/dateRule.d.ts +16 -0
  113. package/dist/validators/rules/dateRule.js +44 -0
  114. package/dist/validators/rules/emailRule.d.ts +12 -0
  115. package/dist/validators/rules/emailRule.js +24 -0
  116. package/dist/validators/rules/index.d.ts +6 -0
  117. package/dist/validators/rules/index.js +15 -0
  118. package/dist/validators/rules/numberRule.d.ts +17 -0
  119. package/dist/validators/rules/numberRule.js +30 -0
  120. package/dist/validators/rules/requiredRule.d.ts +11 -0
  121. package/dist/validators/rules/requiredRule.js +21 -0
  122. package/dist/validators/rules/stringRule.d.ts +18 -0
  123. package/dist/validators/rules/stringRule.js +32 -0
  124. package/dist/validators/types.d.ts +55 -0
  125. package/dist/validators/types.js +2 -0
  126. package/dist/validators/validationRule.d.ts +53 -0
  127. package/dist/validators/validationRule.js +37 -0
  128. package/dist/validators/validationSchema.d.ts +145 -0
  129. package/dist/validators/validationSchema.js +198 -0
  130. package/dist/validators/validator.d.ts +58 -0
  131. package/dist/validators/validator.js +91 -0
  132. package/dist/views/helpersTemplate.d.ts +104 -0
  133. package/dist/views/helpersTemplate.js +186 -0
  134. package/dist/views/index.d.ts +4 -0
  135. package/dist/views/index.js +9 -0
  136. package/dist/views/raptorEngine.d.ts +127 -0
  137. package/dist/views/raptorEngine.js +165 -0
  138. package/dist/views/templateEngine.d.ts +80 -0
  139. package/dist/views/templateEngine.js +204 -0
  140. package/dist/views/view.d.ts +55 -0
  141. package/dist/views/view.js +2 -0
  142. package/package.json +79 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pipe930
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,237 @@
1
+ # 🛡️✈️ Skyguard.js — TypeScript Web Framework
2
+
3
+ Skyguard.js is a **lightweight and experimental web framework**, inspired by **Express**, written entirely in **TypeScript**.
4
+
5
+ The main goal of this project is to **learn, experiment, and build a solid foundation** for a more complete backend framework in the future.
6
+
7
+ At its current stage, the framework focuses on **routing**, **internal architecture**, **type safety**, and **core HTTP abstractions**, leaving advanced features for later iterations.
8
+
9
+ ---
10
+
11
+ ## 🎯 Current Goals
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
17
+
18
+ ---
19
+
20
+ ## ✨ Current Features
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)
31
+
32
+ ---
33
+
34
+ ## 📦 Installation
35
+
36
+ ```bash
37
+ npm install skyguard-js
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 🏁 Basic Usage
43
+
44
+ ```ts
45
+ import { createApp } from "skyguard-js";
46
+ import { Response } from "skyguard-js/http";
47
+
48
+ const app = createApp();
49
+
50
+ app.get("/health", () => {
51
+ return Response.json({ status: "ok" });
52
+ });
53
+
54
+ app.listen(3000);
55
+ ```
56
+
57
+ ---
58
+
59
+ ## 🛣️ Routing
60
+
61
+ Routes are registered using HTTP methods on the `app` instance.
62
+
63
+ ```ts
64
+ app.get("/posts/{id}", (request: Request) => {
65
+ return Response.json(request.getParams());
66
+ });
67
+
68
+ app.post("/posts", (request: Request) => {
69
+ return Response.json(request.getData());
70
+ });
71
+ ```
72
+
73
+ Internally, the framework maps HTTP methods to route layers using an optimized routing table.
74
+
75
+ ---
76
+
77
+ ## 🧩 Route Groups
78
+
79
+ Route groups allow you to organize endpoints under a shared prefix.
80
+
81
+ ```ts
82
+ app.group("/api", (api) => {
83
+ api.get("/users", () => Response.json({ message: "Users" }));
84
+ api.get("/products", () => Response.json({ message: "Products" }));
85
+ });
86
+ ```
87
+
88
+ ---
89
+
90
+ ## 🛠️ Middlewares
91
+
92
+ Middlewares can be registered **globally**, **per group**, or **per route**.
93
+
94
+ ```ts
95
+ import { Request, Response } from "skyguard-js/http";
96
+ import { RouteHandler } from "skyguard-js/types";
97
+
98
+ const authMiddleware = async (
99
+ request: Request,
100
+ next: RouteHandler,
101
+ ): Promise<Response> => {
102
+ if (request.getHeaders["authorization"] !== "secret") {
103
+ return Response.json({ message: "Unauthorized" }).setStatus(401);
104
+ }
105
+
106
+ return next(request);
107
+ };
108
+
109
+ // Global middleware
110
+ app.middlewares([authMiddleware]);
111
+
112
+ // Group middleware
113
+ app.group("/admin", (admin) => {
114
+ admin.middlewares([authMiddleware]);
115
+ admin.get("/dashboard", () => Response.json({ ok: true }));
116
+ });
117
+
118
+ // Route-level middleware
119
+ app.get(
120
+ "/secure",
121
+ () => Response.json({ secure: true }),
122
+ [authMiddleware],
123
+ );
124
+ ```
125
+
126
+ ---
127
+
128
+ ## 📦 Data Validation
129
+
130
+ Skyguard.js provides a **declarative validation system** using schemas.
131
+
132
+ ```ts
133
+ import { ValidationSchema } from "skyguard-js/validation";
134
+
135
+ export const userSchema = ValidationSchema.create()
136
+ .field("name")
137
+ .required("Name is required")
138
+ .string({ maxLength: 60 })
139
+ .field("email")
140
+ .required()
141
+ .email()
142
+ .field("age")
143
+ .number({ min: 18, max: 99 })
144
+ .field("active")
145
+ .boolean()
146
+ .build();
147
+
148
+ app.post("/users", (request: Request) => {
149
+ const validatedData = request.validateData(userSchema);
150
+
151
+ return Response.json({
152
+ success: true,
153
+ data: validatedData,
154
+ });
155
+ });
156
+ ```
157
+
158
+ Validation is:
159
+
160
+ * Fail-fast per field
161
+ * Fully typed
162
+ * Reusable
163
+ * Decoupled from transport layer
164
+
165
+ ---
166
+
167
+ ## 📄 Views & Template Engine
168
+
169
+ To render HTML views, use the `render` helper.
170
+
171
+ ```ts
172
+ import { render } from "skyguard-js/helpers";
173
+
174
+ app.get("/home", () => {
175
+ return render(
176
+ "home",
177
+ {
178
+ title: "Products",
179
+ products: [
180
+ { name: "Laptop", price: 999.99 },
181
+ { name: "Mouse", price: 29.99 },
182
+ ],
183
+ user: { name: "John", role: "admin" },
184
+ },
185
+ "main",
186
+ );
187
+ });
188
+ ```
189
+
190
+ ### Supported features
191
+
192
+ * Variable interpolation (`{{ variable }}`)
193
+ * Conditionals (`{{#if}}`)
194
+ * Loops (`{{#each}}`)
195
+ * Layouts
196
+ * Partials
197
+ * Built-in helpers (`upper`, `lower`, `date`)
198
+ * Custom helpers
199
+
200
+ ---
201
+
202
+ ## 🧱 Project Status
203
+
204
+ ⚠️ **Early-stage project**
205
+
206
+ * Not production-ready
207
+ * API may change
208
+ * Features are still evolving
209
+ * Intended primarily for learning and experimentation
210
+
211
+ ---
212
+
213
+ ## 🔮 Roadmap (Tentative)
214
+
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
224
+
225
+ ---
226
+
227
+ ## 🧠 Motivation
228
+
229
+ This project was created to deeply understand how frameworks like **Express**, **Fastify**, and **Koa** work internally, by reimplementing their core ideas with a **modern TypeScript-first approach**.
230
+
231
+ ---
232
+
233
+ ## 📄 License
234
+
235
+ MIT License
236
+
237
+ ---
package/dist/app.d.ts ADDED
@@ -0,0 +1,123 @@
1
+ import { RouterGroup } from "./routing";
2
+ import { type HttpAdapter } from "./http";
3
+ import { type View } from "./views";
4
+ import type { Middleware, RouteHandler } from "./types";
5
+ /**
6
+ * The `App` class acts as the **execution kernel** and **lifecycle orchestrator**
7
+ * of the framework.
8
+ *
9
+ * It is responsible for:
10
+ * - Bootstrapping and exposing the routing system
11
+ * - Receiving normalized HTTP requests through adapters
12
+ * - Resolving the matching route
13
+ * - Executing the associated controller
14
+ * - Dispatching the final response to the client
15
+ *
16
+ * This class implements the **Singleton pattern** to guarantee
17
+ * a single application instance during the process lifecycle.
18
+ *
19
+ * The architecture fully decouples the core framework
20
+ * from the runtime platform (Node, Bun, Deno, etc.)
21
+ * through {@link HttpAdapter} and {@link Server}.
22
+ */
23
+ export declare class App {
24
+ /** Main routing system */
25
+ private router;
26
+ /** Underlying HTTP server implementation */
27
+ private server;
28
+ /**
29
+ * View engine used to render templates.
30
+ *
31
+ * Typically consumed inside controllers to generate HTML responses.
32
+ */
33
+ view: View;
34
+ /** Static file handler (optional) */
35
+ private staticFileHandler;
36
+ /**
37
+ * Bootstraps and configures the application.
38
+ *
39
+ * Acts as the **Composition Root** of the framework:
40
+ * this is the only place where concrete infrastructure
41
+ * implementations are instantiated and wired together.
42
+ *
43
+ * @returns The singleton `App` instance
44
+ */
45
+ static bootstrap(): App;
46
+ /**
47
+ * Main execution pipeline.
48
+ *
49
+ * Execution flow:
50
+ * 1. Retrieves the normalized request from the adapter
51
+ * 2. Attempts to serve a static file (if enabled)
52
+ * 3. Resolves the matching route
53
+ * 4. Executes the controller
54
+ * 5. Sends the response back to the client
55
+ *
56
+ * This method is platform-agnostic.
57
+ *
58
+ * @param adapter - HTTP adapter bridging the runtime with the framework
59
+ */
60
+ handle(adapter: HttpAdapter): Promise<void>;
61
+ /**
62
+ * Enables static file serving.
63
+ *
64
+ * @param publicPath - Absolute or relative public directory path
65
+ *
66
+ * @example
67
+ * app.staticFiles("public");
68
+ * // /public/css/style.css → /css/style.css
69
+ */
70
+ staticFiles(publicPath: string): void;
71
+ /**
72
+ * Starts the HTTP server on the given port.
73
+ *
74
+ * @example
75
+ * app.listen(3000);
76
+ *
77
+ * @param port - TCP port to listen on
78
+ */
79
+ listen(port: number): void;
80
+ /**
81
+ * Sets a global prefix for all routes.
82
+ *
83
+ * @param prefix - Route prefix (e.g. "api", "/v1")
84
+ *
85
+ * @example
86
+ * app.setPrefix("api");
87
+ * app.get("/users", handler); // → /api/users
88
+ */
89
+ setPrefix(prefix: string): void;
90
+ /** Registers a GET route */
91
+ get(path: string, action: RouteHandler, middlewares?: Middleware[]): void;
92
+ /** Registers a POST route */
93
+ post(path: string, action: RouteHandler, middlewares?: Middleware[]): void;
94
+ /** Registers a PUT route */
95
+ put(path: string, action: RouteHandler, middlewares?: Middleware[]): void;
96
+ /** Registers a PATCH route */
97
+ patch(path: string, action: RouteHandler, middlewares?: Middleware[]): void;
98
+ /** Registers a DELETE route */
99
+ delete(path: string, action: RouteHandler, middlewares?: Middleware[]): void;
100
+ /**
101
+ * Registers global middlewares.
102
+ *
103
+ * These are executed for every route.
104
+ */
105
+ middlewares(middlewares: Middleware[]): void;
106
+ /**
107
+ * Creates a route group with a shared prefix.
108
+ *
109
+ * @example
110
+ * app.group("/api", (api) => {
111
+ * api.get("/users", listUsers);
112
+ * api.post("/users", createUser);
113
+ * });
114
+ */
115
+ group(prefix: string, callback: (group: RouterGroup) => void): void;
116
+ /**
117
+ * Translates domain-level exceptions into HTTP responses.
118
+ *
119
+ * This method centralizes error handling and response mapping.
120
+ */
121
+ private handleError;
122
+ }
123
+ export declare const createApp: () => App;
package/dist/app.js ADDED
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createApp = exports.App = void 0;
4
+ const routing_1 = require("./routing");
5
+ const http_1 = require("./http");
6
+ const exceptions_1 = require("./exceptions");
7
+ const nodeNativeServer_1 = require("./server/nodeNativeServer");
8
+ const views_1 = require("./views");
9
+ const node_path_1 = require("node:path");
10
+ const app_1 = require("./helpers/app");
11
+ const fileStaticHandler_1 = require("./static/fileStaticHandler");
12
+ /**
13
+ * The `App` class acts as the **execution kernel** and **lifecycle orchestrator**
14
+ * of the framework.
15
+ *
16
+ * It is responsible for:
17
+ * - Bootstrapping and exposing the routing system
18
+ * - Receiving normalized HTTP requests through adapters
19
+ * - Resolving the matching route
20
+ * - Executing the associated controller
21
+ * - Dispatching the final response to the client
22
+ *
23
+ * This class implements the **Singleton pattern** to guarantee
24
+ * a single application instance during the process lifecycle.
25
+ *
26
+ * The architecture fully decouples the core framework
27
+ * from the runtime platform (Node, Bun, Deno, etc.)
28
+ * through {@link HttpAdapter} and {@link Server}.
29
+ */
30
+ class App {
31
+ /** Main routing system */
32
+ router;
33
+ /** Underlying HTTP server implementation */
34
+ server;
35
+ /**
36
+ * View engine used to render templates.
37
+ *
38
+ * Typically consumed inside controllers to generate HTML responses.
39
+ */
40
+ view;
41
+ /** Static file handler (optional) */
42
+ staticFileHandler = null;
43
+ /**
44
+ * Bootstraps and configures the application.
45
+ *
46
+ * Acts as the **Composition Root** of the framework:
47
+ * this is the only place where concrete infrastructure
48
+ * implementations are instantiated and wired together.
49
+ *
50
+ * @returns The singleton `App` instance
51
+ */
52
+ static bootstrap() {
53
+ const app = (0, app_1.singleton)(App);
54
+ app.router = new routing_1.Router();
55
+ app.server = new nodeNativeServer_1.NodeServer(app);
56
+ app.view = new views_1.RaptorEngine((0, node_path_1.join)(__dirname, "..", "views"));
57
+ return app;
58
+ }
59
+ /**
60
+ * Main execution pipeline.
61
+ *
62
+ * Execution flow:
63
+ * 1. Retrieves the normalized request from the adapter
64
+ * 2. Attempts to serve a static file (if enabled)
65
+ * 3. Resolves the matching route
66
+ * 4. Executes the controller
67
+ * 5. Sends the response back to the client
68
+ *
69
+ * This method is platform-agnostic.
70
+ *
71
+ * @param adapter - HTTP adapter bridging the runtime with the framework
72
+ */
73
+ async handle(adapter) {
74
+ try {
75
+ const request = await adapter.getRequest();
76
+ if (this.staticFileHandler && request.getMethod === http_1.HttpMethods.get) {
77
+ const staticResponse = await this.staticFileHandler.tryServeFile(request.getUrl);
78
+ if (staticResponse) {
79
+ adapter.sendResponse(staticResponse);
80
+ return;
81
+ }
82
+ }
83
+ const response = await this.router.resolve(request);
84
+ adapter.sendResponse(response);
85
+ }
86
+ catch (error) {
87
+ this.handleError(error, adapter);
88
+ }
89
+ }
90
+ /**
91
+ * Enables static file serving.
92
+ *
93
+ * @param publicPath - Absolute or relative public directory path
94
+ *
95
+ * @example
96
+ * app.staticFiles("public");
97
+ * // /public/css/style.css → /css/style.css
98
+ */
99
+ staticFiles(publicPath) {
100
+ this.staticFileHandler = new fileStaticHandler_1.StaticFileHandler(publicPath);
101
+ }
102
+ /**
103
+ * Starts the HTTP server on the given port.
104
+ *
105
+ * @example
106
+ * app.listen(3000);
107
+ *
108
+ * @param port - TCP port to listen on
109
+ */
110
+ listen(port) {
111
+ this.server.listen(port);
112
+ }
113
+ /**
114
+ * Sets a global prefix for all routes.
115
+ *
116
+ * @param prefix - Route prefix (e.g. "api", "/v1")
117
+ *
118
+ * @example
119
+ * app.setPrefix("api");
120
+ * app.get("/users", handler); // → /api/users
121
+ */
122
+ setPrefix(prefix) {
123
+ this.router.setPrefix(prefix);
124
+ }
125
+ /** Registers a GET route */
126
+ get(path, action, middlewares) {
127
+ this.router.get(path, action, middlewares);
128
+ }
129
+ /** Registers a POST route */
130
+ post(path, action, middlewares) {
131
+ this.router.post(path, action, middlewares);
132
+ }
133
+ /** Registers a PUT route */
134
+ put(path, action, middlewares) {
135
+ this.router.put(path, action, middlewares);
136
+ }
137
+ /** Registers a PATCH route */
138
+ patch(path, action, middlewares) {
139
+ this.router.patch(path, action, middlewares);
140
+ }
141
+ /** Registers a DELETE route */
142
+ delete(path, action, middlewares) {
143
+ this.router.delete(path, action, middlewares);
144
+ }
145
+ /**
146
+ * Registers global middlewares.
147
+ *
148
+ * These are executed for every route.
149
+ */
150
+ middlewares(middlewares) {
151
+ this.router.middlewares(middlewares);
152
+ }
153
+ /**
154
+ * Creates a route group with a shared prefix.
155
+ *
156
+ * @example
157
+ * app.group("/api", (api) => {
158
+ * api.get("/users", listUsers);
159
+ * api.post("/users", createUser);
160
+ * });
161
+ */
162
+ group(prefix, callback) {
163
+ this.router.group(prefix, callback);
164
+ }
165
+ /**
166
+ * Translates domain-level exceptions into HTTP responses.
167
+ *
168
+ * This method centralizes error handling and response mapping.
169
+ */
170
+ handleError(error, adapter) {
171
+ if (error instanceof exceptions_1.HttpNotFoundException) {
172
+ adapter.sendResponse(http_1.Response.text("Not Found").setStatus(404));
173
+ return;
174
+ }
175
+ if (error instanceof exceptions_1.ContentParserException) {
176
+ adapter.sendResponse(http_1.Response.json({ message: error.message }).setStatus(422));
177
+ return;
178
+ }
179
+ if (error instanceof exceptions_1.SessionException) {
180
+ adapter.sendResponse(http_1.Response.json({ message: error.message }).setStatus(401));
181
+ return;
182
+ }
183
+ if (error instanceof exceptions_1.ValidationException) {
184
+ adapter.sendResponse(http_1.Response.json({
185
+ success: false,
186
+ errors: error.getErrorsByField(),
187
+ }).setStatus(400));
188
+ return;
189
+ }
190
+ adapter.sendResponse(http_1.Response.text("Internal Server Error").setStatus(500));
191
+ console.error(error);
192
+ }
193
+ }
194
+ exports.App = App;
195
+ const createApp = () => {
196
+ return App.bootstrap();
197
+ };
198
+ exports.createApp = createApp;
@@ -0,0 +1,60 @@
1
+ import type { Constructor } from "../types";
2
+ /**
3
+ * Dependency Injection container.
4
+ *
5
+ * Stores and resolves application-wide singletons by constructor reference.
6
+ *
7
+ * @example
8
+ * class App {}
9
+ *
10
+ * // Create (or return) the singleton instance
11
+ * const app = Container.singleton(App);
12
+ *
13
+ * // Resolve an already-registered singleton
14
+ * const resolved = Container.resolve(App);
15
+ */
16
+ export declare class Container {
17
+ /**
18
+ * Singleton instances indexed by class constructor.
19
+ *
20
+ * @internal
21
+ */
22
+ private static instances;
23
+ /**
24
+ * Get or create a singleton instance for the given class.
25
+ *
26
+ * If no instance exists yet, the container will instantiate the class with
27
+ * `new classConstructor()` (no constructor arguments) and cache it.
28
+ *
29
+ * @typeParam T - Instance type produced by the constructor
30
+ * @param classConstructor - Class constructor used as the registration key
31
+ * @returns The singleton instance for the given class
32
+ *
33
+ * @example
34
+ * class Database {
35
+ * connect() {
36
+ * console.log("Connected");
37
+ * }
38
+ * }
39
+ *
40
+ * const db1 = Container.singleton(Database);
41
+ * const db2 = Container.singleton(Database);
42
+ * console.log(db1 === db2); // true
43
+ */
44
+ static singleton<T>(classConstructor: Constructor<T>): T;
45
+ /**
46
+ * Resolve a previously created singleton instance.
47
+ *
48
+ * This method does not create instances. If the class was never registered
49
+ * via {@link Container.singleton}, it returns `null`.
50
+ *
51
+ * @typeParam T - Instance type produced by the constructor
52
+ * @param classConstructor - Class constructor used as the registration key
53
+ * @returns The singleton instance, or `null` if it is not registered
54
+ *
55
+ * @example
56
+ * const db = Container.resolve(Database);
57
+ * if (db) db.connect();
58
+ */
59
+ static resolve<T>(classConstructor: Constructor<T>): T | null;
60
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Container = void 0;
4
+ /**
5
+ * Dependency Injection container.
6
+ *
7
+ * Stores and resolves application-wide singletons by constructor reference.
8
+ *
9
+ * @example
10
+ * class App {}
11
+ *
12
+ * // Create (or return) the singleton instance
13
+ * const app = Container.singleton(App);
14
+ *
15
+ * // Resolve an already-registered singleton
16
+ * const resolved = Container.resolve(App);
17
+ */
18
+ class Container {
19
+ /**
20
+ * Singleton instances indexed by class constructor.
21
+ *
22
+ * @internal
23
+ */
24
+ static instances = new Map();
25
+ /**
26
+ * Get or create a singleton instance for the given class.
27
+ *
28
+ * If no instance exists yet, the container will instantiate the class with
29
+ * `new classConstructor()` (no constructor arguments) and cache it.
30
+ *
31
+ * @typeParam T - Instance type produced by the constructor
32
+ * @param classConstructor - Class constructor used as the registration key
33
+ * @returns The singleton instance for the given class
34
+ *
35
+ * @example
36
+ * class Database {
37
+ * connect() {
38
+ * console.log("Connected");
39
+ * }
40
+ * }
41
+ *
42
+ * const db1 = Container.singleton(Database);
43
+ * const db2 = Container.singleton(Database);
44
+ * console.log(db1 === db2); // true
45
+ */
46
+ static singleton(classConstructor) {
47
+ if (!this.instances.has(classConstructor)) {
48
+ const instance = new classConstructor();
49
+ this.instances.set(classConstructor, instance);
50
+ }
51
+ return this.instances.get(classConstructor);
52
+ }
53
+ /**
54
+ * Resolve a previously created singleton instance.
55
+ *
56
+ * This method does not create instances. If the class was never registered
57
+ * via {@link Container.singleton}, it returns `null`.
58
+ *
59
+ * @typeParam T - Instance type produced by the constructor
60
+ * @param classConstructor - Class constructor used as the registration key
61
+ * @returns The singleton instance, or `null` if it is not registered
62
+ *
63
+ * @example
64
+ * const db = Container.resolve(Database);
65
+ * if (db) db.connect();
66
+ */
67
+ static resolve(classConstructor) {
68
+ return this.instances.get(classConstructor) ?? null;
69
+ }
70
+ }
71
+ exports.Container = Container;