@lithia-js/core 1.0.0-canary.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 (91) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +13 -0
  3. package/LICENSE +21 -0
  4. package/README.md +60 -0
  5. package/dist/config.d.ts +101 -0
  6. package/dist/config.js +113 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/context/event-context.d.ts +53 -0
  9. package/dist/context/event-context.js +42 -0
  10. package/dist/context/event-context.js.map +1 -0
  11. package/dist/context/index.d.ts +16 -0
  12. package/dist/context/index.js +29 -0
  13. package/dist/context/index.js.map +1 -0
  14. package/dist/context/lithia-context.d.ts +47 -0
  15. package/dist/context/lithia-context.js +43 -0
  16. package/dist/context/lithia-context.js.map +1 -0
  17. package/dist/context/route-context.d.ts +74 -0
  18. package/dist/context/route-context.js +42 -0
  19. package/dist/context/route-context.js.map +1 -0
  20. package/dist/env.d.ts +1 -0
  21. package/dist/env.js +32 -0
  22. package/dist/env.js.map +1 -0
  23. package/dist/errors.d.ts +51 -0
  24. package/dist/errors.js +80 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/hooks/dependency-hooks.d.ts +105 -0
  27. package/dist/hooks/dependency-hooks.js +96 -0
  28. package/dist/hooks/dependency-hooks.js.map +1 -0
  29. package/dist/hooks/event-hooks.d.ts +61 -0
  30. package/dist/hooks/event-hooks.js +70 -0
  31. package/dist/hooks/event-hooks.js.map +1 -0
  32. package/dist/hooks/index.d.ts +41 -0
  33. package/dist/hooks/index.js +59 -0
  34. package/dist/hooks/index.js.map +1 -0
  35. package/dist/hooks/route-hooks.d.ts +154 -0
  36. package/dist/hooks/route-hooks.js +174 -0
  37. package/dist/hooks/route-hooks.js.map +1 -0
  38. package/dist/lib.d.ts +10 -0
  39. package/dist/lib.js +30 -0
  40. package/dist/lib.js.map +1 -0
  41. package/dist/lithia.d.ts +447 -0
  42. package/dist/lithia.js +649 -0
  43. package/dist/lithia.js.map +1 -0
  44. package/dist/logger.d.ts +11 -0
  45. package/dist/logger.js +55 -0
  46. package/dist/logger.js.map +1 -0
  47. package/dist/module-loader.d.ts +12 -0
  48. package/dist/module-loader.js +78 -0
  49. package/dist/module-loader.js.map +1 -0
  50. package/dist/server/event-processor.d.ts +195 -0
  51. package/dist/server/event-processor.js +253 -0
  52. package/dist/server/event-processor.js.map +1 -0
  53. package/dist/server/http-server.d.ts +196 -0
  54. package/dist/server/http-server.js +295 -0
  55. package/dist/server/http-server.js.map +1 -0
  56. package/dist/server/middlewares/validation.d.ts +12 -0
  57. package/dist/server/middlewares/validation.js +34 -0
  58. package/dist/server/middlewares/validation.js.map +1 -0
  59. package/dist/server/request-processor.d.ts +400 -0
  60. package/dist/server/request-processor.js +652 -0
  61. package/dist/server/request-processor.js.map +1 -0
  62. package/dist/server/request.d.ts +73 -0
  63. package/dist/server/request.js +207 -0
  64. package/dist/server/request.js.map +1 -0
  65. package/dist/server/response.d.ts +69 -0
  66. package/dist/server/response.js +173 -0
  67. package/dist/server/response.js.map +1 -0
  68. package/package.json +46 -0
  69. package/src/config.ts +212 -0
  70. package/src/context/event-context.ts +66 -0
  71. package/src/context/index.ts +32 -0
  72. package/src/context/lithia-context.ts +59 -0
  73. package/src/context/route-context.ts +89 -0
  74. package/src/env.ts +31 -0
  75. package/src/errors.ts +96 -0
  76. package/src/hooks/dependency-hooks.ts +122 -0
  77. package/src/hooks/event-hooks.ts +69 -0
  78. package/src/hooks/index.ts +58 -0
  79. package/src/hooks/route-hooks.ts +177 -0
  80. package/src/lib.ts +27 -0
  81. package/src/lithia.ts +777 -0
  82. package/src/logger.ts +66 -0
  83. package/src/module-loader.ts +45 -0
  84. package/src/server/event-processor.ts +344 -0
  85. package/src/server/http-server.ts +371 -0
  86. package/src/server/middlewares/validation.ts +46 -0
  87. package/src/server/request-processor.ts +860 -0
  88. package/src/server/request.ts +247 -0
  89. package/src/server/response.ts +204 -0
  90. package/tsconfig.build.tsbuildinfo +1 -0
  91. package/tsconfig.json +8 -0
@@ -0,0 +1,652 @@
1
+ "use strict";
2
+ /**
3
+ * Request processor module for HTTP request handling.
4
+ *
5
+ * This module is the core of Lithia's request processing pipeline. It handles:
6
+ * - Route matching and parameter extraction
7
+ * - Static file serving
8
+ * - CORS preflight and headers
9
+ * - Middleware execution chain
10
+ * - Route handler invocation
11
+ * - Error handling and logging
12
+ *
13
+ * @module server/request-processor
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.RequestProcessor = void 0;
17
+ const node_crypto_1 = require("node:crypto");
18
+ const node_fs_1 = require("node:fs");
19
+ const node_path_1 = require("node:path");
20
+ const utils_1 = require("@lithia-js/utils");
21
+ const route_context_1 = require("../context/route-context");
22
+ const errors_1 = require("../errors");
23
+ const logger_1 = require("../logger");
24
+ const module_loader_1 = require("../module-loader");
25
+ /**
26
+ * Request processor for the Lithia HTTP pipeline.
27
+ *
28
+ * This class orchestrates the entire request processing flow from receiving
29
+ * an HTTP request to sending a response. It manages:
30
+ *
31
+ * - **CORS handling**: Preflight requests and CORS headers
32
+ * - **Static files**: Serving files from configured static directories
33
+ * - **Route matching**: Finding the route that matches the request path
34
+ * - **Parameter extraction**: Extracting dynamic route parameters
35
+ * - **Middleware execution**: Running global and route-specific middlewares
36
+ * - **Handler invocation**: Executing the route handler function
37
+ * - **Error handling**: Converting exceptions to structured JSON responses
38
+ * - **Request logging**: Logging all requests with timing and status codes
39
+ *
40
+ * @remarks
41
+ * The processor uses AsyncLocalStorage to provide request context to hooks,
42
+ * allowing route handlers to access request/response without explicit parameters.
43
+ *
44
+ * In development mode, route modules are reloaded on each request (cache busting).
45
+ * In production, modules are cached for better performance.
46
+ */
47
+ class RequestProcessor {
48
+ lithia;
49
+ httpServer;
50
+ /**
51
+ * Creates a new request processor.
52
+ *
53
+ * @param lithia - The Lithia application instance
54
+ */
55
+ constructor(lithia, httpServer) {
56
+ this.lithia = lithia;
57
+ this.httpServer = httpServer;
58
+ }
59
+ /**
60
+ * Processes an incoming HTTP request through the complete pipeline.
61
+ *
62
+ * This is the main entry point for request processing. The method executes
63
+ * the following steps in order:
64
+ *
65
+ * 1. Initialize request context for hooks
66
+ * 2. Handle CORS preflight (OPTIONS) requests
67
+ * 3. Add standard response headers
68
+ * 4. Attempt to serve static files
69
+ * 5. Match request to a route
70
+ * 6. Extract dynamic route parameters
71
+ * 7. Load the route module
72
+ * 8. Execute global middlewares
73
+ * 9. Execute route-specific middlewares
74
+ * 10. Execute the route handler
75
+ * 11. Log the request with timing
76
+ *
77
+ * Any errors thrown during this process are caught and handled by
78
+ * {@link handleError}, which sends a structured error response.
79
+ *
80
+ * @param req - The incoming HTTP request
81
+ * @param res - The HTTP response object
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const processor = new RequestProcessor(lithia);
86
+ * await processor.processRequest(req, res);
87
+ * ```
88
+ */
89
+ async processRequest(req, res) {
90
+ const start = process.hrtime.bigint();
91
+ // Initialize context for hooks
92
+ const routeCtx = {
93
+ req,
94
+ res,
95
+ socketServer: this.httpServer.socketIO,
96
+ };
97
+ await this.lithia.runWithContext(async () => {
98
+ await route_context_1.routeContext.run(routeCtx, async () => {
99
+ try {
100
+ // Handle CORS
101
+ if (this.handleCors(req, res)) {
102
+ this.logRequest(req, res, start);
103
+ return;
104
+ }
105
+ // Add basic headers
106
+ res.addHeader("X-Powered-By", "Lithia");
107
+ // Serve static files
108
+ if (await this.serveStaticFile(req, res)) {
109
+ this.logRequest(req, res, start);
110
+ return;
111
+ }
112
+ // Find matching route
113
+ const route = this.findMatchingRoute(req.pathname, req.method);
114
+ if (!route) {
115
+ this.sendNotFound(req, res);
116
+ this.logRequest(req, res, start);
117
+ return;
118
+ }
119
+ // Update context with matched route
120
+ routeCtx.route = route;
121
+ // Extract params if dynamic route
122
+ if (route.dynamic) {
123
+ req.params = this.extractParams(req.pathname, route);
124
+ }
125
+ // Import route module
126
+ const module = await this.importRouteModule(route);
127
+ // Execute global middlewares
128
+ if (this.lithia.globalMiddlewares &&
129
+ this.lithia.globalMiddlewares.length > 0) {
130
+ const globalMiddlewareError = await this.executeMiddlewares(this.lithia.globalMiddlewares, req, res);
131
+ if (res._ended || globalMiddlewareError) {
132
+ if (globalMiddlewareError) {
133
+ throw globalMiddlewareError;
134
+ }
135
+ this.logRequest(req, res, start);
136
+ return;
137
+ }
138
+ }
139
+ // Execute middlewares if present
140
+ if (module.middlewares && module.middlewares.length > 0) {
141
+ const middlewareError = await this.executeMiddlewares(module.middlewares, req, res);
142
+ // If middleware ended response or errored, stop processing
143
+ if (res._ended || middlewareError) {
144
+ if (middlewareError) {
145
+ throw middlewareError;
146
+ }
147
+ this.logRequest(req, res, start);
148
+ return;
149
+ }
150
+ }
151
+ // Execute route handler
152
+ if (module.default) {
153
+ await module.default(req, res);
154
+ }
155
+ // End response if not already ended
156
+ if (!res._ended) {
157
+ res.end();
158
+ }
159
+ this.logRequest(req, res, start);
160
+ }
161
+ catch (err) {
162
+ this.handleError(err, req, res, start);
163
+ }
164
+ });
165
+ });
166
+ }
167
+ /**
168
+ * Executes an array of middlewares sequentially.
169
+ *
170
+ * Middlewares are executed in order. Each middleware must call `next()`
171
+ * to continue to the next middleware in the chain. If a middleware does
172
+ * not call `next()`, the chain stops and subsequent middlewares are not
173
+ * executed.
174
+ *
175
+ * If any middleware throws an error, execution stops immediately and the
176
+ * error is returned.
177
+ *
178
+ * @param middlewares - Array of middleware functions to execute
179
+ * @param req - The HTTP request object
180
+ * @param res - The HTTP response object
181
+ * @returns null if successful, or an Error if a middleware threw
182
+ *
183
+ * @private
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * const error = await this.executeMiddlewares(middlewares, req, res);
188
+ * if (error) {
189
+ * throw error;
190
+ * }
191
+ * ```
192
+ */
193
+ async executeMiddlewares(middlewares, req, res) {
194
+ let currentIndex = 0;
195
+ const next = () => {
196
+ currentIndex++;
197
+ };
198
+ try {
199
+ for (let i = 0; i < middlewares.length; i++) {
200
+ currentIndex = i;
201
+ await middlewares[i](req, res, next);
202
+ // If response was ended by middleware, stop processing
203
+ if (res._ended) {
204
+ return null;
205
+ }
206
+ // If next() wasn't called, stop middleware chain
207
+ if (currentIndex === i) {
208
+ return null;
209
+ }
210
+ }
211
+ return null;
212
+ }
213
+ catch (err) {
214
+ return err instanceof Error ? err : new Error(String(err));
215
+ }
216
+ }
217
+ /**
218
+ * Sends a structured 404 JSON response for unmatched routes.
219
+ *
220
+ * This method is called when no route matches the requested path.
221
+ * It sends a standardized error response with status 404.
222
+ *
223
+ * @param req - The HTTP request that didn't match any route
224
+ * @param res - The HTTP response object
225
+ *
226
+ * @private
227
+ */
228
+ sendNotFound(req, res) {
229
+ const response = {
230
+ error: {
231
+ message: "The requested resource was not found",
232
+ statusCode: 404,
233
+ timestamp: new Date().toISOString(),
234
+ path: req.pathname,
235
+ method: req.method,
236
+ },
237
+ };
238
+ res.status(404).json(response);
239
+ }
240
+ /**
241
+ * Centralized error handler for the request pipeline.
242
+ *
243
+ * This method handles all errors thrown during request processing:
244
+ *
245
+ * **Development mode:**
246
+ * - Returns detailed error messages
247
+ * - Includes full error stacks
248
+ * - Shows validation issues if present
249
+ *
250
+ * **Production mode:**
251
+ * - Returns generic error messages
252
+ * - Includes error digest for log correlation
253
+ * - Hides sensitive error details
254
+ *
255
+ * All server errors (5xx) are logged with the error digest for correlation
256
+ * between client responses and server logs.
257
+ *
258
+ * @param err - The error that was thrown
259
+ * @param req - The HTTP request that caused the error
260
+ * @param res - The HTTP response object
261
+ * @param start - High-resolution timestamp when request processing started
262
+ *
263
+ * @private
264
+ */
265
+ handleError(err, req, res, start) {
266
+ const isDevelopment = this.lithia.getEnvironment() === "development";
267
+ // Don't send error response if already sent
268
+ if (res._ended) {
269
+ this.logRequest(req, res, start);
270
+ return;
271
+ }
272
+ // Generate error digest (both dev and prod)
273
+ const digest = this.generateErrorDigest(err);
274
+ // Build error details
275
+ const errorMessage = err instanceof Error ? err.message : "Internal Server Error";
276
+ const errorStack = err instanceof Error ? err.stack : undefined;
277
+ let statusCode = 500;
278
+ let clientMessage = isDevelopment
279
+ ? errorMessage
280
+ : "An internal server error occurred";
281
+ let issues;
282
+ if (err instanceof errors_1.ValidationError) {
283
+ statusCode = 400;
284
+ clientMessage = err.message;
285
+ issues = err.issues;
286
+ }
287
+ if (statusCode >= 500) {
288
+ // Log error with digest (same format for both environments)
289
+ logger_1.logger.error(`[Digest: ${(0, utils_1.red)(digest)}] ${errorStack}`);
290
+ }
291
+ // Build error response
292
+ const response = {
293
+ error: {
294
+ message: clientMessage,
295
+ statusCode,
296
+ timestamp: new Date().toISOString(),
297
+ path: req.pathname,
298
+ method: req.method,
299
+ digest: digest,
300
+ issues,
301
+ },
302
+ };
303
+ res.status(statusCode).json(response);
304
+ this.logRequest(req, res, start);
305
+ }
306
+ /**
307
+ * Logs a completed request with color-coded status and timing.
308
+ *
309
+ * The log includes:
310
+ * - HTTP status code (color-coded by range)
311
+ * - HTTP method (GET, POST, etc.)
312
+ * - Request pathname
313
+ * - Processing duration in milliseconds
314
+ *
315
+ * Status colors:
316
+ * - 2xx: Green (success)
317
+ * - 3xx: Cyan (redirect)
318
+ * - 4xx: Yellow (client error)
319
+ * - 5xx: Red (server error)
320
+ *
321
+ * @param req - The HTTP request that was processed
322
+ * @param res - The HTTP response that was sent
323
+ * @param start - High-resolution timestamp when processing started
324
+ *
325
+ * @private
326
+ */
327
+ /**
328
+ * Logs a completed request with color-coded status and timing.
329
+ *
330
+ * The log includes:
331
+ * - HTTP status code (color-coded by range)
332
+ * - HTTP method (GET, POST, etc.)
333
+ * - Request pathname
334
+ * - Processing duration in milliseconds
335
+ *
336
+ * Status colors:
337
+ * - 2xx: Green (success)
338
+ * - 3xx: Cyan (redirect)
339
+ * - 4xx: Yellow (client error)
340
+ * - 5xx: Red (server error)
341
+ *
342
+ * Respects the `logging.requests` configuration flag. Critical errors
343
+ * (5xx) are always logged regardless of the flag.
344
+ *
345
+ * @param req - The HTTP request that was processed
346
+ * @param res - The HTTP response that was sent
347
+ * @param start - High-resolution timestamp when processing started
348
+ *
349
+ * @private
350
+ */
351
+ logRequest(req, res, start) {
352
+ const status = res.statusCode || 200;
353
+ // Always log critical errors (5xx), otherwise respect the logging.requests flag
354
+ const shouldLog = status >= 500 || this.lithia.options.logging?.requests !== false;
355
+ if (!shouldLog)
356
+ return;
357
+ const end = process.hrtime.bigint();
358
+ const duration = Number(end - start) / 1_000_000;
359
+ const durationStr = `${duration.toFixed(2)}ms`;
360
+ let statusStr = status.toString();
361
+ if (status >= 500) {
362
+ statusStr = (0, utils_1.red)(statusStr);
363
+ }
364
+ else if (status >= 400) {
365
+ statusStr = (0, utils_1.yellow)(statusStr);
366
+ }
367
+ else if (status >= 300) {
368
+ statusStr = (0, utils_1.cyan)(statusStr);
369
+ }
370
+ else {
371
+ statusStr = (0, utils_1.green)(statusStr);
372
+ }
373
+ logger_1.logger.info(`[${statusStr}] ${req.method} ${req.pathname} - ${durationStr}`);
374
+ }
375
+ /**
376
+ * Generates a short hexadecimal digest for error correlation.
377
+ *
378
+ * The digest is used to correlate server-side error logs with client-facing
379
+ * error responses. This allows developers to find the detailed error in logs
380
+ * using the digest shown to the client.
381
+ *
382
+ * The digest is generated from:
383
+ * - Error message and stack
384
+ * - Current timestamp
385
+ * - Random factor for uniqueness
386
+ *
387
+ * @param err - The error to generate a digest for
388
+ * @returns An 8-character hexadecimal digest
389
+ *
390
+ * @private
391
+ */
392
+ generateErrorDigest(err) {
393
+ // Create a unique digest based on error message, timestamp, and random factor
394
+ const errorString = err instanceof Error ? `${err.message}${err.stack}` : String(err);
395
+ const hash = (0, node_crypto_1.createHash)("sha256")
396
+ .update(`${errorString}${Date.now()}${Math.random()}`)
397
+ .digest("hex");
398
+ // Return first 8 characters (similar to Next.js)
399
+ return hash.substring(0, 8);
400
+ }
401
+ /**
402
+ * Handles CORS preflight requests and applies CORS headers.
403
+ *
404
+ * This method:
405
+ * 1. Checks if the request origin is allowed based on CORS configuration
406
+ * 2. Adds appropriate CORS headers to the response
407
+ * 3. Handles OPTIONS preflight requests
408
+ *
409
+ * **CORS Headers Applied:**
410
+ * - `Access-Control-Allow-Origin`: Allowed origin
411
+ * - `Access-Control-Allow-Credentials`: If credentials are enabled
412
+ * - `Access-Control-Allow-Methods`: Allowed HTTP methods
413
+ * - `Access-Control-Allow-Headers`: Allowed request headers
414
+ * - `Access-Control-Max-Age`: Preflight cache duration
415
+ * - `Access-Control-Expose-Headers`: Headers exposed to client
416
+ *
417
+ * @param req - The HTTP request
418
+ * @param res - The HTTP response
419
+ * @returns true if the request was an OPTIONS preflight that was handled, false otherwise
420
+ *
421
+ * @private
422
+ */
423
+ handleCors(req, res) {
424
+ const cors = this.lithia.options.http.cors;
425
+ if (!cors)
426
+ return false;
427
+ const origin = req.headers.origin;
428
+ // Check if origin is allowed
429
+ let allowedOrigin;
430
+ // Handle credentials with wildcard origin
431
+ if (cors.credentials && cors.origin?.includes("*")) {
432
+ allowedOrigin = origin;
433
+ }
434
+ else if (cors.origin?.includes("*")) {
435
+ allowedOrigin = "*";
436
+ }
437
+ else if (origin && cors.origin?.includes(origin)) {
438
+ allowedOrigin = origin;
439
+ }
440
+ if (allowedOrigin) {
441
+ res.addHeader("Access-Control-Allow-Origin", allowedOrigin);
442
+ res.addHeader("Vary", "Origin");
443
+ if (cors.credentials) {
444
+ res.addHeader("Access-Control-Allow-Credentials", "true");
445
+ }
446
+ if (req.method === "OPTIONS") {
447
+ if (cors.methods) {
448
+ res.addHeader("Access-Control-Allow-Methods", cors.methods.join(", "));
449
+ }
450
+ if (cors.allowedHeaders) {
451
+ res.addHeader("Access-Control-Allow-Headers", cors.allowedHeaders.join(", "));
452
+ }
453
+ if (cors.maxAge) {
454
+ res.addHeader("Access-Control-Max-Age", cors.maxAge.toString());
455
+ }
456
+ res.status(204).end();
457
+ return true;
458
+ }
459
+ if (cors.exposedHeaders) {
460
+ res.addHeader("Access-Control-Expose-Headers", cors.exposedHeaders.join(", "));
461
+ }
462
+ }
463
+ return false;
464
+ }
465
+ /**
466
+ * Attempts to serve a static file from the configured static directory.
467
+ *
468
+ * This method:
469
+ * 1. Checks if static file serving is enabled
470
+ * 2. Only serves for GET and HEAD requests
471
+ * 3. Strips configured prefix from the path
472
+ * 4. Prevents directory traversal attacks
473
+ * 5. Determines MIME type from file extension
474
+ * 6. Sends the file with appropriate Content-Type header
475
+ *
476
+ * @param req - The HTTP request
477
+ * @param res - The HTTP response
478
+ * @returns true if a static file was served, false otherwise
479
+ * @throws {StaticFileMimeMissingError} If file extension has no configured MIME type
480
+ *
481
+ * @private
482
+ */
483
+ async serveStaticFile(req, res) {
484
+ const staticConfig = this.lithia.options.static;
485
+ if (!staticConfig || !staticConfig.root)
486
+ return false;
487
+ // Skip if method is not GET or HEAD
488
+ if (req.method !== "GET" && req.method !== "HEAD")
489
+ return false;
490
+ let filePath = req.pathname;
491
+ // Handle prefix stripping
492
+ if (staticConfig.prefix) {
493
+ if (!filePath.startsWith(staticConfig.prefix))
494
+ return false;
495
+ filePath = filePath.slice(staticConfig.prefix.length);
496
+ }
497
+ // Prevent directory traversal
498
+ const normalizedPath = (0, node_path_1.join)(staticConfig.root, filePath);
499
+ if (filePath.includes(".."))
500
+ return false;
501
+ try {
502
+ const stats = (0, node_fs_1.statSync)(normalizedPath);
503
+ if (stats.isFile()) {
504
+ const ext = (0, node_path_1.extname)(normalizedPath).toLowerCase();
505
+ const mime = this.lithia.options.http.mimeTypes?.[ext];
506
+ if (!mime) {
507
+ throw new errors_1.StaticFileMimeMissingError(ext, filePath);
508
+ }
509
+ res.addHeader("Content-Type", mime);
510
+ res.sendFile(normalizedPath);
511
+ return true;
512
+ }
513
+ }
514
+ catch (e) {
515
+ if (e instanceof errors_1.LithiaError)
516
+ throw e;
517
+ // file not found or other error, fallback to routes
518
+ }
519
+ return false;
520
+ }
521
+ /**
522
+ * Finds a route matching the given pathname and HTTP method.
523
+ *
524
+ * Routes are matched in the order they were registered. The first route
525
+ * that matches both the path pattern (via regex) and HTTP method is returned.
526
+ *
527
+ * @param pathname - The request pathname to match
528
+ * @param method - The HTTP method (GET, POST, etc.)
529
+ * @returns The matched Route, or undefined if no match found
530
+ *
531
+ * @private
532
+ */
533
+ findMatchingRoute(pathname, method) {
534
+ const routes = this.lithia.getRoutes();
535
+ return routes.find((route) => {
536
+ // Check method match
537
+ const methodMatches = !route.method || route.method.toUpperCase() === method.toUpperCase();
538
+ // Check path match using regex
539
+ const pathMatches = this.matchesPath(pathname, route);
540
+ return methodMatches && pathMatches;
541
+ });
542
+ }
543
+ /**
544
+ * Tests whether a pathname matches a route's regex pattern.
545
+ *
546
+ * @param pathname - The pathname to test
547
+ * @param route - The route with the regex pattern
548
+ * @returns true if the pathname matches the route's regex, false otherwise
549
+ *
550
+ * @private
551
+ */
552
+ matchesPath(pathname, route) {
553
+ try {
554
+ const regex = new RegExp(route.regex);
555
+ return regex.test(pathname);
556
+ }
557
+ catch (err) {
558
+ logger_1.logger.error(`Invalid route regex for ${route.path}:`, err);
559
+ return false;
560
+ }
561
+ }
562
+ /**
563
+ * Imports a route module from the file system.
564
+ *
565
+ * In **development mode**, uses cache-busting to reload the module on each
566
+ * request, enabling hot reloading without server restart.
567
+ *
568
+ * In **production mode**, uses standard dynamic imports with caching for
569
+ * better performance.
570
+ *
571
+ * The method also validates the module structure:
572
+ * - Must have a default export
573
+ * - Default export must be a function
574
+ * - Default export must be async
575
+ *
576
+ * @param route - The route whose module should be imported
577
+ * @returns The loaded and validated route module
578
+ * @throws {InvalidRouteModuleError} If the module structure is invalid
579
+ * @throws {Error} If the module fails to load
580
+ *
581
+ * @private
582
+ */
583
+ async importRouteModule(route) {
584
+ try {
585
+ const isDevelopment = this.lithia.getEnvironment() === "development";
586
+ const mod = await (0, module_loader_1.coldImport)(route.filePath, isDevelopment);
587
+ if (!mod.default) {
588
+ throw new errors_1.InvalidRouteModuleError(route.filePath, "missing default export");
589
+ }
590
+ if (typeof mod.default !== "function") {
591
+ throw new errors_1.InvalidRouteModuleError(route.filePath, "default export is not a function");
592
+ }
593
+ if (!(0, module_loader_1.isAsyncFunction)(mod.default)) {
594
+ throw new errors_1.InvalidRouteModuleError(route.filePath, "default export is not an async function");
595
+ }
596
+ return mod;
597
+ }
598
+ catch (err) {
599
+ if (err instanceof errors_1.InvalidRouteModuleError) {
600
+ throw err;
601
+ }
602
+ throw new Error(`Failed to import route: ${route.path}`);
603
+ }
604
+ }
605
+ /**
606
+ * Extracts named route parameters from the pathname.
607
+ *
608
+ * For dynamic routes like `/users/:id/posts/:postId`, this method:
609
+ * 1. Matches the pathname against the route's regex
610
+ * 2. Extracts parameter names from the route path (e.g., "id", "postId")
611
+ * 3. Maps regex capture groups to parameter names
612
+ * 4. URL-decodes parameter values
613
+ *
614
+ * @param pathname - The request pathname
615
+ * @param route - The matched route with dynamic segments
616
+ * @returns Object mapping parameter names to their values
617
+ *
618
+ * @private
619
+ *
620
+ * @example
621
+ * ```typescript
622
+ * // Route: /users/:id/posts/:postId
623
+ * // Pathname: /users/123/posts/456
624
+ * // Returns: { id: '123', postId: '456' }
625
+ * ```
626
+ */
627
+ extractParams(pathname, route) {
628
+ const params = {};
629
+ try {
630
+ const regex = new RegExp(route.regex);
631
+ const match = pathname.match(regex);
632
+ if (!match)
633
+ return params;
634
+ // Extract parameter names from the route path
635
+ const paramNames = (route.path.match(/:([^/]+)/g) || []).map((p) => p.slice(1));
636
+ // Match groups start at index 1 (index 0 is full match)
637
+ paramNames.forEach((name, idx) => {
638
+ const value = match[idx + 1];
639
+ if (value !== undefined) {
640
+ params[name] = decodeURIComponent(value);
641
+ }
642
+ });
643
+ return params;
644
+ }
645
+ catch (err) {
646
+ logger_1.logger.error(`Failed to extract params from ${pathname}:`, err);
647
+ return params;
648
+ }
649
+ }
650
+ }
651
+ exports.RequestProcessor = RequestProcessor;
652
+ //# sourceMappingURL=request-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-processor.js","sourceRoot":"","sources":["../../src/server/request-processor.ts"],"names":[],"mappings":"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"}