@vercube/core 0.0.30 → 0.0.32
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/dist/index.d.mts +73 -1
- package/dist/index.mjs +301 -51
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1127,6 +1127,78 @@ declare class StandardSchemaValidationProvider implements ValidationProvider {
|
|
|
1127
1127
|
validate(schema: ValidationTypes.Schema, data: ValidationTypes.Input): ValidationTypes.Result | Promise<ValidationTypes.Result>;
|
|
1128
1128
|
}
|
|
1129
1129
|
//#endregion
|
|
1130
|
+
//#region src/Services/Router/RequestContext.d.ts
|
|
1131
|
+
/**
|
|
1132
|
+
* Request context storage using AsyncLocalStorage.
|
|
1133
|
+
* This allows storing request-specific data that is automatically cleaned up after the request completes.
|
|
1134
|
+
*/
|
|
1135
|
+
declare class RequestContext {
|
|
1136
|
+
/** The storage for the request context */
|
|
1137
|
+
private readonly fStorage;
|
|
1138
|
+
/**
|
|
1139
|
+
* Initializes the request storage.
|
|
1140
|
+
*/
|
|
1141
|
+
constructor();
|
|
1142
|
+
/**
|
|
1143
|
+
* Runs a function within a request context.
|
|
1144
|
+
*
|
|
1145
|
+
* This initializes a new context for the request. The context is automatically cleaned up
|
|
1146
|
+
* by Node.js's AsyncLocalStorage when the function completes (either successfully or with an error).
|
|
1147
|
+
*
|
|
1148
|
+
* The cleanup happens automatically - you don't need to manually clear the context.
|
|
1149
|
+
* The context is available throughout the entire async execution chain of the function,
|
|
1150
|
+
* including all nested async operations, but is automatically destroyed when the function
|
|
1151
|
+
* passed to `run()` completes.
|
|
1152
|
+
*
|
|
1153
|
+
* @param fn - The function to run within the context
|
|
1154
|
+
* @returns The result of the function
|
|
1155
|
+
*/
|
|
1156
|
+
run<T>(fn: () => Promise<T>): Promise<T>;
|
|
1157
|
+
/**
|
|
1158
|
+
* Sets a value in the current request context.
|
|
1159
|
+
*
|
|
1160
|
+
* @param key - The key to store the value under
|
|
1161
|
+
* @param value - The value to store
|
|
1162
|
+
* @throws Error if called outside of a request context
|
|
1163
|
+
*/
|
|
1164
|
+
set(key: string, value: unknown): void;
|
|
1165
|
+
/**
|
|
1166
|
+
* Gets a value from the current request context.
|
|
1167
|
+
*
|
|
1168
|
+
* @param key - The key to retrieve
|
|
1169
|
+
* @returns The value if found, undefined otherwise
|
|
1170
|
+
* @throws Error if called outside of a request context
|
|
1171
|
+
*/
|
|
1172
|
+
get<T = unknown>(key: string): T | undefined;
|
|
1173
|
+
/**
|
|
1174
|
+
* Gets a value from the current request context, or returns a default value if not found.
|
|
1175
|
+
*
|
|
1176
|
+
* @param key - The key to retrieve
|
|
1177
|
+
* @param defaultValue - The default value to return if key is not found
|
|
1178
|
+
* @returns The value if found, defaultValue otherwise
|
|
1179
|
+
*/
|
|
1180
|
+
getOrDefault<T = unknown>(key: string, defaultValue: T): T;
|
|
1181
|
+
/**
|
|
1182
|
+
* Checks if a key exists in the current request context.
|
|
1183
|
+
*
|
|
1184
|
+
* @param key - The key to check
|
|
1185
|
+
* @returns True if the key exists, false otherwise
|
|
1186
|
+
*/
|
|
1187
|
+
has(key: string): boolean;
|
|
1188
|
+
/**
|
|
1189
|
+
* Gets all keys in the current request context.
|
|
1190
|
+
*
|
|
1191
|
+
* @returns Array of keys in the context
|
|
1192
|
+
*/
|
|
1193
|
+
keys(): string[];
|
|
1194
|
+
/**
|
|
1195
|
+
* Gets all values in the current request context.
|
|
1196
|
+
*
|
|
1197
|
+
* @returns Map of all key-value pairs in the context
|
|
1198
|
+
*/
|
|
1199
|
+
getAll(): Map<string, unknown>;
|
|
1200
|
+
}
|
|
1201
|
+
//#endregion
|
|
1130
1202
|
//#region src/Errors/HttpError.d.ts
|
|
1131
1203
|
/**
|
|
1132
1204
|
* Represents an HTTP error.
|
|
@@ -1623,4 +1695,4 @@ declare function initializeMetadataMethod(target: any, propertyName: string): Me
|
|
|
1623
1695
|
*/
|
|
1624
1696
|
declare function initializeMetadata(target: any): MetadataTypes.Ctx;
|
|
1625
1697
|
//#endregion
|
|
1626
|
-
export { App, BadRequestError, BaseMiddleware, BasePlugin, Body, ConfigTypes, Connect, Controller, CreateAppOptions, DeepPartial, Delete, ErrorHandlerProvider, FastResponse, ForbiddenError, Get, GlobalMiddlewareRegistry, HTTPStatus, Head, Header, Headers, HooksService, HooksTypes, HttpError, HttpServer, HttpStatusCode, InternalServerError, Listen, MaybePromise, MetadataResolver, MetadataTypes, MethodNotAllowedError, Middleware$1 as Middleware, MiddlewareOptions, MultipartFormData, NotAcceptableError, NotFoundError, Options, Param, Patch, Post, Put, QueryParam, QueryParams, Redirect, Request$1 as Request, Response$1 as Response, Router, RouterTypes, RuntimeConfig$1 as RuntimeConfig, SetHeader, StandardSchemaValidationProvider, Status, Trace, UnauthorizedError, ValidationProvider, ValidationTypes, createApp, createMetadataCtx, createMetadataMethod, defineConfig, initializeMetadata, initializeMetadataMethod, loadVercubeConfig };
|
|
1698
|
+
export { App, BadRequestError, BaseMiddleware, BasePlugin, Body, ConfigTypes, Connect, Controller, CreateAppOptions, DeepPartial, Delete, ErrorHandlerProvider, FastResponse, ForbiddenError, Get, GlobalMiddlewareRegistry, HTTPStatus, Head, Header, Headers, HooksService, HooksTypes, HttpError, HttpServer, HttpStatusCode, InternalServerError, Listen, MaybePromise, MetadataResolver, MetadataTypes, MethodNotAllowedError, Middleware$1 as Middleware, MiddlewareOptions, MultipartFormData, NotAcceptableError, NotFoundError, Options, Param, Patch, Post, Put, QueryParam, QueryParams, Redirect, Request$1 as Request, RequestContext, Response$1 as Response, Router, RouterTypes, RuntimeConfig$1 as RuntimeConfig, SetHeader, StandardSchemaValidationProvider, Status, Trace, UnauthorizedError, ValidationProvider, ValidationTypes, createApp, createMetadataCtx, createMetadataMethod, defineConfig, initializeMetadata, initializeMetadataMethod, loadVercubeConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseDecorator, Container, Inject, InjectOptional, createDecorator, initializeContainer } from "@vercube/di";
|
|
2
2
|
import { FastResponse, serve } from "srvx";
|
|
3
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
4
|
import { addRoute, createRouter, findRoute } from "rou3";
|
|
4
5
|
import { createReadStream } from "node:fs";
|
|
5
6
|
import { stat } from "node:fs/promises";
|
|
@@ -332,6 +333,107 @@ var GlobalMiddlewareRegistry = class {
|
|
|
332
333
|
}
|
|
333
334
|
};
|
|
334
335
|
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/Services/Router/RequestContext.ts
|
|
338
|
+
/**
|
|
339
|
+
* Request context storage using AsyncLocalStorage.
|
|
340
|
+
* This allows storing request-specific data that is automatically cleaned up after the request completes.
|
|
341
|
+
*/
|
|
342
|
+
var RequestContext = class {
|
|
343
|
+
/** The storage for the request context */
|
|
344
|
+
fStorage;
|
|
345
|
+
/**
|
|
346
|
+
* Initializes the request storage.
|
|
347
|
+
*/
|
|
348
|
+
constructor() {
|
|
349
|
+
this.fStorage = new AsyncLocalStorage();
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Runs a function within a request context.
|
|
353
|
+
*
|
|
354
|
+
* This initializes a new context for the request. The context is automatically cleaned up
|
|
355
|
+
* by Node.js's AsyncLocalStorage when the function completes (either successfully or with an error).
|
|
356
|
+
*
|
|
357
|
+
* The cleanup happens automatically - you don't need to manually clear the context.
|
|
358
|
+
* The context is available throughout the entire async execution chain of the function,
|
|
359
|
+
* including all nested async operations, but is automatically destroyed when the function
|
|
360
|
+
* passed to `run()` completes.
|
|
361
|
+
*
|
|
362
|
+
* @param fn - The function to run within the context
|
|
363
|
+
* @returns The result of the function
|
|
364
|
+
*/
|
|
365
|
+
async run(fn) {
|
|
366
|
+
const context = /* @__PURE__ */ new Map();
|
|
367
|
+
return this.fStorage.run(context, fn);
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Sets a value in the current request context.
|
|
371
|
+
*
|
|
372
|
+
* @param key - The key to store the value under
|
|
373
|
+
* @param value - The value to store
|
|
374
|
+
* @throws Error if called outside of a request context
|
|
375
|
+
*/
|
|
376
|
+
set(key, value) {
|
|
377
|
+
const context = this.fStorage.getStore();
|
|
378
|
+
if (!context) throw new Error("RequestContext.set() called outside of request context. The context is automatically initialized by RequestHandler.");
|
|
379
|
+
context.set(key, value);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Gets a value from the current request context.
|
|
383
|
+
*
|
|
384
|
+
* @param key - The key to retrieve
|
|
385
|
+
* @returns The value if found, undefined otherwise
|
|
386
|
+
* @throws Error if called outside of a request context
|
|
387
|
+
*/
|
|
388
|
+
get(key) {
|
|
389
|
+
const context = this.fStorage.getStore();
|
|
390
|
+
if (!context) throw new Error("RequestContext.get() called outside of request context. The context is automatically initialized by RequestHandler.");
|
|
391
|
+
return context.get(key);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Gets a value from the current request context, or returns a default value if not found.
|
|
395
|
+
*
|
|
396
|
+
* @param key - The key to retrieve
|
|
397
|
+
* @param defaultValue - The default value to return if key is not found
|
|
398
|
+
* @returns The value if found, defaultValue otherwise
|
|
399
|
+
*/
|
|
400
|
+
getOrDefault(key, defaultValue) {
|
|
401
|
+
const value = this.get(key);
|
|
402
|
+
return value === void 0 ? defaultValue : value;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Checks if a key exists in the current request context.
|
|
406
|
+
*
|
|
407
|
+
* @param key - The key to check
|
|
408
|
+
* @returns True if the key exists, false otherwise
|
|
409
|
+
*/
|
|
410
|
+
has(key) {
|
|
411
|
+
const context = this.fStorage.getStore();
|
|
412
|
+
if (!context) return false;
|
|
413
|
+
return context.has(key);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Gets all keys in the current request context.
|
|
417
|
+
*
|
|
418
|
+
* @returns Array of keys in the context
|
|
419
|
+
*/
|
|
420
|
+
keys() {
|
|
421
|
+
const context = this.fStorage.getStore();
|
|
422
|
+
if (!context) return [];
|
|
423
|
+
return [...context.keys()];
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Gets all values in the current request context.
|
|
427
|
+
*
|
|
428
|
+
* @returns Map of all key-value pairs in the context
|
|
429
|
+
*/
|
|
430
|
+
getAll() {
|
|
431
|
+
const context = this.fStorage.getStore();
|
|
432
|
+
if (!context) return /* @__PURE__ */ new Map();
|
|
433
|
+
return new Map(context);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
|
|
335
437
|
//#endregion
|
|
336
438
|
//#region \0@oxc-project+runtime@0.95.0/helpers/decorate.js
|
|
337
439
|
function __decorate(decorators, target, key, desc) {
|
|
@@ -402,35 +504,34 @@ var RequestHandler = class {
|
|
|
402
504
|
* @returns {Promise<Response>} The HTTP response
|
|
403
505
|
*/
|
|
404
506
|
async handlePreflight(request) {
|
|
507
|
+
return this.runWithContext(async () => {
|
|
508
|
+
return this.internalHandlePreflight(request);
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Internal method that handles preflight request processing logic.
|
|
513
|
+
*
|
|
514
|
+
* @param request - The incoming HTTP request
|
|
515
|
+
* @returns {Promise<Response>} The HTTP response
|
|
516
|
+
* @private
|
|
517
|
+
*/
|
|
518
|
+
async internalHandlePreflight(request) {
|
|
405
519
|
try {
|
|
406
|
-
let fakeResponse =
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (hookResponse instanceof Response) return hookResponse;
|
|
417
|
-
else if (hookResponse !== null) fakeResponse = this.processOverrideResponse(hookResponse, fakeResponse);
|
|
418
|
-
hookResponse = await hook.middleware.onResponse?.(request, fakeResponse, {
|
|
419
|
-
middlewareArgs: hook.args,
|
|
420
|
-
methodArgs: []
|
|
421
|
-
});
|
|
422
|
-
if (hookResponse instanceof Response) return hookResponse;
|
|
423
|
-
else if (hookResponse !== null) fakeResponse = this.processOverrideResponse(hookResponse, fakeResponse);
|
|
424
|
-
} catch (error) {
|
|
425
|
-
return await Promise.resolve(this.gContainer.get(ErrorHandlerProvider).handleError(error));
|
|
426
|
-
}
|
|
427
|
-
return new Response(null, {
|
|
428
|
-
status: fakeResponse.status ?? 204,
|
|
429
|
-
statusText: fakeResponse.statusText ?? "No Content",
|
|
430
|
-
headers: fakeResponse.headers
|
|
520
|
+
let fakeResponse = this.createInitialResponse(request);
|
|
521
|
+
const globalMiddlewares = this.gGlobalMiddlewareRegistry.middlewares;
|
|
522
|
+
const resolvedMiddlewares = this.resolveMiddlewares(globalMiddlewares);
|
|
523
|
+
const result = await this.executeMiddlewares(resolvedMiddlewares, {
|
|
524
|
+
request,
|
|
525
|
+
response: fakeResponse,
|
|
526
|
+
methodArgs: [],
|
|
527
|
+
handlerResponse: void 0,
|
|
528
|
+
executeRequest: true,
|
|
529
|
+
executeResponse: true
|
|
431
530
|
});
|
|
531
|
+
if (result.earlyReturn) return result.earlyReturn;
|
|
532
|
+
return this.createFinalResponse(result.response, null, 204, "No Content");
|
|
432
533
|
} catch (error) {
|
|
433
|
-
return this.
|
|
534
|
+
return await this.handleError(error);
|
|
434
535
|
}
|
|
435
536
|
}
|
|
436
537
|
/**
|
|
@@ -449,48 +550,196 @@ var RequestHandler = class {
|
|
|
449
550
|
* @returns {Promise<Response>} The HTTP response
|
|
450
551
|
*/
|
|
451
552
|
async handleRequest(request, route) {
|
|
553
|
+
return this.runWithContext(async () => {
|
|
554
|
+
return this.internalHandleRequest(request, route);
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Internal method that handles the request processing logic.
|
|
559
|
+
* This is separated from handleRequest to allow running with or without request context.
|
|
560
|
+
*
|
|
561
|
+
* @param {Request} request - The incoming HTTP request
|
|
562
|
+
* @param {RouterTypes.RouteMatched<RouterTypes.RouterHandler>} route - The matched route with handler data
|
|
563
|
+
* @returns {Promise<Response>} The HTTP response
|
|
564
|
+
* @private
|
|
565
|
+
*/
|
|
566
|
+
async internalHandleRequest(request, route) {
|
|
452
567
|
try {
|
|
453
568
|
const { instance, propertyName, actions = [], args = [], middlewares = {
|
|
454
569
|
beforeMiddlewares: [],
|
|
455
570
|
afterMiddlewares: []
|
|
456
571
|
} } = route.data;
|
|
457
|
-
let fakeResponse =
|
|
572
|
+
let fakeResponse = this.createInitialResponse(request);
|
|
458
573
|
const resolvedArgs = args.length > 0 ? await this.gMetadataResolver.resolveArgs(args, {
|
|
459
574
|
...route,
|
|
460
575
|
request,
|
|
461
576
|
response: fakeResponse
|
|
462
577
|
}) : [];
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
578
|
+
const beforeResult = await this.executeMiddlewares(middlewares.beforeMiddlewares, {
|
|
579
|
+
request,
|
|
580
|
+
response: fakeResponse,
|
|
581
|
+
methodArgs: resolvedArgs,
|
|
582
|
+
handlerResponse: void 0,
|
|
583
|
+
executeRequest: true,
|
|
584
|
+
executeResponse: false
|
|
585
|
+
});
|
|
586
|
+
if (beforeResult.earlyReturn) return beforeResult.earlyReturn;
|
|
587
|
+
fakeResponse = beforeResult.response;
|
|
472
588
|
for (const action of actions) {
|
|
473
589
|
const actionResponse = action.handler(request, fakeResponse);
|
|
474
|
-
if (actionResponse
|
|
590
|
+
if (actionResponse != null) fakeResponse = this.processOverrideResponse(actionResponse, fakeResponse);
|
|
475
591
|
}
|
|
476
592
|
let handlerResponse = instance[propertyName].call(instance, ...resolvedArgs?.map((a) => a.resolved) ?? []);
|
|
477
593
|
if (handlerResponse instanceof Promise) handlerResponse = await handlerResponse;
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
const body = fakeResponse?.body ?? JSON.stringify(handlerResponse);
|
|
486
|
-
return new Response(body, {
|
|
487
|
-
status: fakeResponse.status ?? 200,
|
|
488
|
-
statusText: fakeResponse.statusText ?? "OK",
|
|
489
|
-
headers: fakeResponse.headers
|
|
594
|
+
const afterResult = await this.executeMiddlewares(middlewares.afterMiddlewares, {
|
|
595
|
+
request,
|
|
596
|
+
response: fakeResponse,
|
|
597
|
+
methodArgs: resolvedArgs,
|
|
598
|
+
handlerResponse,
|
|
599
|
+
executeRequest: false,
|
|
600
|
+
executeResponse: true
|
|
490
601
|
});
|
|
602
|
+
if (afterResult.earlyReturn) return afterResult.earlyReturn;
|
|
603
|
+
fakeResponse = afterResult.response;
|
|
604
|
+
if (handlerResponse instanceof Response) return handlerResponse;
|
|
605
|
+
return this.createFinalResponse(fakeResponse, handlerResponse, 200, "OK");
|
|
491
606
|
} catch (error) {
|
|
492
|
-
return this.
|
|
607
|
+
return await this.handleError(error);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Runs a function within a request context if available, otherwise runs it directly
|
|
612
|
+
*
|
|
613
|
+
* @param fn - The function to run
|
|
614
|
+
* @returns The result of the function
|
|
615
|
+
* @private
|
|
616
|
+
*/
|
|
617
|
+
async runWithContext(fn) {
|
|
618
|
+
const requestContext = this.gContainer.getOptional(RequestContext);
|
|
619
|
+
if (requestContext) return requestContext.run(fn);
|
|
620
|
+
return fn();
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Creates an initial FastResponse with Content-Type header from the request
|
|
624
|
+
*
|
|
625
|
+
* @param request - The incoming HTTP request
|
|
626
|
+
* @returns The initial FastResponse
|
|
627
|
+
* @private
|
|
628
|
+
*/
|
|
629
|
+
createInitialResponse(request) {
|
|
630
|
+
return new FastResponse(void 0, { headers: { "Content-Type": request.headers.get("Content-Type") ?? "application/json" } });
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Handles errors by delegating to ErrorHandlerProvider
|
|
634
|
+
*
|
|
635
|
+
* @param error - The error to handle
|
|
636
|
+
* @returns The error response
|
|
637
|
+
* @private
|
|
638
|
+
*/
|
|
639
|
+
async handleError(error) {
|
|
640
|
+
return this.gContainer.get(ErrorHandlerProvider).handleError(error);
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Resolves middleware instances from middleware definitions
|
|
644
|
+
*
|
|
645
|
+
* @param middlewares - Array of middleware definitions
|
|
646
|
+
* @returns Array of resolved middleware definitions
|
|
647
|
+
* @private
|
|
648
|
+
*/
|
|
649
|
+
resolveMiddlewares(middlewares) {
|
|
650
|
+
return middlewares.map((m) => ({
|
|
651
|
+
...m,
|
|
652
|
+
middleware: this.gContainer.resolve(m.middleware)
|
|
653
|
+
}));
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Executes a middleware's onRequest hook
|
|
657
|
+
*
|
|
658
|
+
* @param hook - The middleware definition
|
|
659
|
+
* @param request - The HTTP request
|
|
660
|
+
* @param response - The current response
|
|
661
|
+
* @param methodArgs - Resolved method arguments
|
|
662
|
+
* @returns Response if middleware returns one, or updated response, or null
|
|
663
|
+
* @private
|
|
664
|
+
*/
|
|
665
|
+
async executeMiddlewareRequest(hook, request, response, methodArgs) {
|
|
666
|
+
const hookResponse = await hook.middleware.onRequest?.(request, response, {
|
|
667
|
+
middlewareArgs: hook.args,
|
|
668
|
+
methodArgs
|
|
669
|
+
});
|
|
670
|
+
if (hookResponse instanceof Response) return hookResponse;
|
|
671
|
+
if (hookResponse !== null && hookResponse !== void 0) return this.processOverrideResponse(hookResponse, response);
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Executes a middleware's onResponse hook
|
|
676
|
+
*
|
|
677
|
+
* @param hook - The middleware definition
|
|
678
|
+
* @param request - The HTTP request
|
|
679
|
+
* @param response - The current response
|
|
680
|
+
* @param payload - The handler response payload
|
|
681
|
+
* @returns Response if middleware returns one, or updated response, or null
|
|
682
|
+
* @private
|
|
683
|
+
*/
|
|
684
|
+
async executeMiddlewareResponse(hook, request, response, payload) {
|
|
685
|
+
const hookResponse = await hook.middleware.onResponse?.(request, response, payload);
|
|
686
|
+
if (hookResponse instanceof Response) return hookResponse;
|
|
687
|
+
if (hookResponse !== null && hookResponse !== void 0) return this.processOverrideResponse(hookResponse, response);
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Executes middlewares with configurable hooks (onRequest, onResponse, or both)
|
|
692
|
+
*
|
|
693
|
+
* @param middlewares - Array of middleware definitions
|
|
694
|
+
* @param options - Options for executing middlewares
|
|
695
|
+
* @returns Object with earlyReturn if middleware returns Response, or updated response
|
|
696
|
+
* @private
|
|
697
|
+
*/
|
|
698
|
+
async executeMiddlewares(middlewares, options) {
|
|
699
|
+
const { request, response, methodArgs, handlerResponse, executeRequest, executeResponse } = options;
|
|
700
|
+
let currentResponse = response;
|
|
701
|
+
for await (const hook of middlewares) try {
|
|
702
|
+
if (executeRequest) {
|
|
703
|
+
const requestResult = await this.executeMiddlewareRequest(hook, request, currentResponse, methodArgs);
|
|
704
|
+
if (requestResult instanceof Response) return {
|
|
705
|
+
earlyReturn: requestResult,
|
|
706
|
+
response: currentResponse
|
|
707
|
+
};
|
|
708
|
+
if (requestResult !== null && requestResult !== currentResponse) currentResponse = requestResult;
|
|
709
|
+
}
|
|
710
|
+
if (executeResponse) {
|
|
711
|
+
const responseResult = await this.executeMiddlewareResponse(hook, request, currentResponse, handlerResponse);
|
|
712
|
+
if (responseResult instanceof Response) return {
|
|
713
|
+
earlyReturn: responseResult,
|
|
714
|
+
response: currentResponse
|
|
715
|
+
};
|
|
716
|
+
if (responseResult !== null && responseResult !== currentResponse) currentResponse = responseResult;
|
|
717
|
+
}
|
|
718
|
+
} catch (error) {
|
|
719
|
+
return {
|
|
720
|
+
earlyReturn: await this.handleError(error),
|
|
721
|
+
response: currentResponse
|
|
722
|
+
};
|
|
493
723
|
}
|
|
724
|
+
return { response: currentResponse };
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Creates the final Response object from the processed fakeResponse and handler response
|
|
728
|
+
*
|
|
729
|
+
* @param fakeResponse - The processed FastResponse
|
|
730
|
+
* @param handlerResponse - The handler response payload (used if fakeResponse.body is not set)
|
|
731
|
+
* @param defaultStatus - Default status code if not set
|
|
732
|
+
* @param defaultStatusText - Default status text if not set
|
|
733
|
+
* @returns The final Response object
|
|
734
|
+
* @private
|
|
735
|
+
*/
|
|
736
|
+
createFinalResponse(fakeResponse, handlerResponse, defaultStatus, defaultStatusText) {
|
|
737
|
+
const body = ("body" in fakeResponse && fakeResponse.body != null ? fakeResponse.body : null) ?? JSON.stringify(handlerResponse);
|
|
738
|
+
return new Response(body, {
|
|
739
|
+
status: fakeResponse.status ?? defaultStatus,
|
|
740
|
+
statusText: fakeResponse.statusText ?? defaultStatusText,
|
|
741
|
+
headers: fakeResponse.headers
|
|
742
|
+
});
|
|
494
743
|
}
|
|
495
744
|
/**
|
|
496
745
|
* Processes and merges response overrides from middlewares or actions
|
|
@@ -1163,6 +1412,7 @@ function createContainer(config) {
|
|
|
1163
1412
|
container.bind(RequestHandler);
|
|
1164
1413
|
container.bind(RuntimeConfig);
|
|
1165
1414
|
container.bind(GlobalMiddlewareRegistry);
|
|
1415
|
+
container.bind(RequestContext);
|
|
1166
1416
|
container.bind(ValidationProvider, StandardSchemaValidationProvider);
|
|
1167
1417
|
return container;
|
|
1168
1418
|
}
|
|
@@ -2900,4 +3150,4 @@ let HttpStatusCode = /* @__PURE__ */ function(HttpStatusCode$1) {
|
|
|
2900
3150
|
}({});
|
|
2901
3151
|
|
|
2902
3152
|
//#endregion
|
|
2903
|
-
export { App, BadRequestError, BaseMiddleware, BasePlugin, Body, Connect, Controller, Delete, ErrorHandlerProvider, FastResponse, ForbiddenError, Get, GlobalMiddlewareRegistry, HTTPStatus, Head, Header, Headers$1 as Headers, HooksService, HttpError, HttpServer, HttpStatusCode, InternalServerError, Listen, MetadataResolver, MethodNotAllowedError, Middleware, MultipartFormData, NotAcceptableError, NotFoundError, Options, Param, Patch, Post, Put, QueryParam, QueryParams, Redirect, Request, Response$1 as Response, Router, RuntimeConfig, SetHeader, StandardSchemaValidationProvider, Status, Trace, UnauthorizedError, ValidationProvider, createApp, createMetadataCtx, createMetadataMethod, defineConfig, initializeMetadata, initializeMetadataMethod, loadVercubeConfig };
|
|
3153
|
+
export { App, BadRequestError, BaseMiddleware, BasePlugin, Body, Connect, Controller, Delete, ErrorHandlerProvider, FastResponse, ForbiddenError, Get, GlobalMiddlewareRegistry, HTTPStatus, Head, Header, Headers$1 as Headers, HooksService, HttpError, HttpServer, HttpStatusCode, InternalServerError, Listen, MetadataResolver, MethodNotAllowedError, Middleware, MultipartFormData, NotAcceptableError, NotFoundError, Options, Param, Patch, Post, Put, QueryParam, QueryParams, Redirect, Request, RequestContext, Response$1 as Response, Router, RuntimeConfig, SetHeader, StandardSchemaValidationProvider, Status, Trace, UnauthorizedError, ValidationProvider, createApp, createMetadataCtx, createMetadataMethod, defineConfig, initializeMetadata, initializeMetadataMethod, loadVercubeConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercube/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Core module for Vercube framework",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"pathe": "2.0.3",
|
|
29
29
|
"rou3": "0.7.9",
|
|
30
30
|
"srvx": "0.9.4",
|
|
31
|
-
"@vercube/di": "0.0.
|
|
32
|
-
"@vercube/logger": "0.0.
|
|
31
|
+
"@vercube/di": "0.0.32",
|
|
32
|
+
"@vercube/logger": "0.0.32"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"rolldown": "1.0.0-beta.45",
|