@spinajs/http 2.0.485 → 2.0.487
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 +370 -5
- package/lib/cjs/base-controller.d.ts +35 -0
- package/lib/cjs/base-controller.d.ts.map +1 -0
- package/lib/cjs/base-controller.js +100 -0
- package/lib/cjs/base-controller.js.map +1 -0
- package/lib/cjs/cache.d.ts +25 -3
- package/lib/cjs/cache.d.ts.map +1 -1
- package/lib/cjs/cache.js +26 -9
- package/lib/cjs/cache.js.map +1 -1
- package/lib/cjs/cli/GenerateControllerCache.d.ts +13 -4
- package/lib/cjs/cli/GenerateControllerCache.d.ts.map +1 -1
- package/lib/cjs/cli/GenerateControllerCache.js +37 -10
- package/lib/cjs/cli/GenerateControllerCache.js.map +1 -1
- package/lib/cjs/controller-sources.d.ts +36 -0
- package/lib/cjs/controller-sources.d.ts.map +1 -0
- package/lib/cjs/controller-sources.js +73 -0
- package/lib/cjs/controller-sources.js.map +1 -0
- package/lib/cjs/controllers.d.ts +19 -36
- package/lib/cjs/controllers.d.ts.map +1 -1
- package/lib/cjs/controllers.js +98 -302
- package/lib/cjs/controllers.js.map +1 -1
- package/lib/cjs/exceptions.d.ts +12 -0
- package/lib/cjs/exceptions.d.ts.map +1 -1
- package/lib/cjs/exceptions.js +15 -1
- package/lib/cjs/exceptions.js.map +1 -1
- package/lib/cjs/index.d.ts +4 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +4 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/middlewares/RequestId.d.ts.map +1 -1
- package/lib/cjs/middlewares/RequestId.js +4 -0
- package/lib/cjs/middlewares/RequestId.js.map +1 -1
- package/lib/cjs/route-builder.d.ts +61 -0
- package/lib/cjs/route-builder.d.ts.map +1 -0
- package/lib/cjs/route-builder.js +228 -0
- package/lib/cjs/route-builder.js.map +1 -0
- package/lib/mjs/base-controller.d.ts +35 -0
- package/lib/mjs/base-controller.d.ts.map +1 -0
- package/lib/mjs/base-controller.js +93 -0
- package/lib/mjs/base-controller.js.map +1 -0
- package/lib/mjs/cache.d.ts +25 -3
- package/lib/mjs/cache.d.ts.map +1 -1
- package/lib/mjs/cache.js +25 -10
- package/lib/mjs/cache.js.map +1 -1
- package/lib/mjs/cli/GenerateControllerCache.d.ts +13 -4
- package/lib/mjs/cli/GenerateControllerCache.d.ts.map +1 -1
- package/lib/mjs/cli/GenerateControllerCache.js +39 -12
- package/lib/mjs/cli/GenerateControllerCache.js.map +1 -1
- package/lib/mjs/controller-sources.d.ts +36 -0
- package/lib/mjs/controller-sources.d.ts.map +1 -0
- package/lib/mjs/controller-sources.js +69 -0
- package/lib/mjs/controller-sources.js.map +1 -0
- package/lib/mjs/controllers.d.ts +19 -36
- package/lib/mjs/controllers.d.ts.map +1 -1
- package/lib/mjs/controllers.js +95 -298
- package/lib/mjs/controllers.js.map +1 -1
- package/lib/mjs/exceptions.d.ts +12 -0
- package/lib/mjs/exceptions.d.ts.map +1 -1
- package/lib/mjs/exceptions.js +12 -0
- package/lib/mjs/exceptions.js.map +1 -1
- package/lib/mjs/index.d.ts +4 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +4 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/middlewares/RequestId.d.ts.map +1 -1
- package/lib/mjs/middlewares/RequestId.js +4 -0
- package/lib/mjs/middlewares/RequestId.js.map +1 -1
- package/lib/mjs/route-builder.d.ts +61 -0
- package/lib/mjs/route-builder.d.ts.map +1 -0
- package/lib/mjs/route-builder.js +216 -0
- package/lib/mjs/route-builder.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +12 -12
|
@@ -29,6 +29,10 @@ let RequestId = class RequestId extends interfaces_js_1.ServerMiddleware {
|
|
|
29
29
|
before() {
|
|
30
30
|
return (req, res, next) => {
|
|
31
31
|
req.storage.requestId = (0, uuid_1.v4)();
|
|
32
|
+
// Emitted here, not in after(): ServerMiddleware after() handlers never
|
|
33
|
+
// run for matched controller routes ( response is flushed inside the
|
|
34
|
+
// controllers router without calling next() ).
|
|
35
|
+
res.header('x-request-id', req.storage.requestId);
|
|
32
36
|
// Continue an inbound W3C traceparent ( or start a new trace ) and seed
|
|
33
37
|
// traceId / spanId onto req.storage so the ambient log context merges them
|
|
34
38
|
// into every log line — trace ids are shared across services.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestId.js","sourceRoot":"","sources":["../../../src/middlewares/RequestId.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oDAAyE;AAEzE,+BAAoC;AACpC,oCAAyC;AACzC,sCAAiF;AAG1E,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,gCAAgB;IAC7C;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjB,CAAC;IAEM,KAAK;QACV,uEAAuE;QACvE,0EAA0E;QAC1E,uEAAuE;QACvE,yEAAyE;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,MAAM;QACX,OAAO,CAAC,GAAa,EAAE,GAAqB,EAAE,IAA0B,EAAE,EAAE;YAC1E,GAAG,CAAC,OAAO,CAAC,SAAS,GAAG,IAAA,SAAM,GAAE,CAAC;YAEjC,wEAAwE;YACxE,2EAA2E;YAC3E,8DAA8D;YAC9D,MAAM,EAAE,GAAkB,IAAA,qBAAe,EAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAuB,CAAC,CAAC;YAC5F,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC;YACjC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC;YAE/B,oEAAoE;YACpE,0EAA0E;YAC1E,yEAAyE;YACzE,2EAA2E;YAC3E,sDAAsD;YACtD,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,IAAA,uBAAiB,EAAC,EAAE,CAAC,CAAC,CAAC;YAEjD,IAAI,EAAE,CAAC;QACT,CAAC,CAAC;IACJ,CAAC;CACF,CAAA;
|
|
1
|
+
{"version":3,"file":"RequestId.js","sourceRoot":"","sources":["../../../src/middlewares/RequestId.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oDAAyE;AAEzE,+BAAoC;AACpC,oCAAyC;AACzC,sCAAiF;AAG1E,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,gCAAgB;IAC7C;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjB,CAAC;IAEM,KAAK;QACV,uEAAuE;QACvE,0EAA0E;QAC1E,uEAAuE;QACvE,yEAAyE;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,MAAM;QACX,OAAO,CAAC,GAAa,EAAE,GAAqB,EAAE,IAA0B,EAAE,EAAE;YAC1E,GAAG,CAAC,OAAO,CAAC,SAAS,GAAG,IAAA,SAAM,GAAE,CAAC;YAEjC,wEAAwE;YACxE,qEAAqE;YACrE,+CAA+C;YAC/C,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAElD,wEAAwE;YACxE,2EAA2E;YAC3E,8DAA8D;YAC9D,MAAM,EAAE,GAAkB,IAAA,qBAAe,EAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAuB,CAAC,CAAC;YAC5F,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC;YACjC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC;YAE/B,oEAAoE;YACpE,0EAA0E;YAC1E,yEAAyE;YACzE,2EAA2E;YAC3E,sDAAsD;YACtD,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,IAAA,uBAAiB,EAAC,EAAE,CAAC,CAAC,CAAC;YAEjD,IAAI,EAAE,CAAC;QACT,CAAC,CAAC;IACJ,CAAC;CACF,CAAA;AAxCY,8BAAS;oBAAT,SAAS;IADrB,IAAA,eAAU,EAAC,gCAAgB,CAAC;;GAChB,SAAS,CAwCrB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import Express from 'express';
|
|
3
|
+
import { IContainer } from '@spinajs/di';
|
|
4
|
+
import { Log } from '@spinajs/log';
|
|
5
|
+
import { Configuration } from '@spinajs/configuration';
|
|
6
|
+
import { Request as sRequest, IController, IControllerDescriptor, RouteMiddleware, IRoute, BasePolicy, IActionLocalStoregeContext } from './interfaces.js';
|
|
7
|
+
/**
|
|
8
|
+
* Controller shape needed by the route wiring helpers: the IController
|
|
9
|
+
* surface plus indexed access to action methods. Structural on purpose —
|
|
10
|
+
* avoids importing BaseController and creating a module cycle.
|
|
11
|
+
*/
|
|
12
|
+
export type ControllerActionHost = IController & {
|
|
13
|
+
[action: string]: any;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Computes the final express path for a route: `/BasePath/Path`, falling back
|
|
17
|
+
* to the method name when the route has no explicit path, with optional
|
|
18
|
+
* global route prefix (`http.controllers.route.prefix`).
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildRoutePath(basePath: string, route: IRoute, globalPrefix?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Resolves controller-wise + route-wise middleware descriptors into instances.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveRouteMiddlewares(descriptor: IControllerDescriptor, route: IRoute, container: IContainer): Promise<RouteMiddleware[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves controller-wise + route-wise policy descriptors into instances.
|
|
27
|
+
*
|
|
28
|
+
* String policy descriptors are configuration keys pointing at a policy type
|
|
29
|
+
* name. A key that does not resolve to a registered BasePolicy type throws
|
|
30
|
+
* {@link RouteRegistrationException} — a silently dropped policy would leave
|
|
31
|
+
* the route unprotected.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveRoutePolicies(descriptor: IControllerDescriptor, route: IRoute, container: IContainer, cfg: Configuration, log: Log, controllerName: string, path: string): Promise<BasePolicy[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Express handler gating a route behind its policies.
|
|
36
|
+
*
|
|
37
|
+
* Executes all policies enabled for the route; if at least ONE policy resolves
|
|
38
|
+
* without error the route is allowed to execute. This allows multiple access
|
|
39
|
+
* paths to a resource, e.g. token access & session.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createPolicyGate(policies: BasePolicy[], route: IRoute, controller: IController, log: Log): Express.RequestHandler;
|
|
42
|
+
/**
|
|
43
|
+
* Wraps a middleware onBefore/onAfter action into an express handler that
|
|
44
|
+
* forwards both resolution and rejection to `next`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function wrapMiddlewareAction(source: object, action: (req: Express.Request, res: Express.Response, route: IRoute, controller: IController) => Promise<void>, route: IRoute, controller: IController): Express.RequestHandler;
|
|
47
|
+
/**
|
|
48
|
+
* Express handler invoking the controller action: extracts route arguments,
|
|
49
|
+
* runs the action inside the request-scoped AsyncLocalStorage context, lets
|
|
50
|
+
* middlewares inspect the produced Response and stores it in
|
|
51
|
+
* `res.locals.response` for the response pipeline. All sync and async errors
|
|
52
|
+
* are forwarded to `next`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createActionHandler(controller: ControllerActionHost, route: IRoute, enabledMiddlewares: RouteMiddleware[], storage: AsyncLocalStorage<IActionLocalStoregeContext>): Express.RequestHandler;
|
|
55
|
+
/**
|
|
56
|
+
* Extracts route argument values for an action call. Route-arg handlers are
|
|
57
|
+
* resolved from DI by parameter type and executed in Priority order
|
|
58
|
+
* (higher first).
|
|
59
|
+
*/
|
|
60
|
+
export declare function extractRouteArgs(route: IRoute, req: sRequest, res: Express.Response, controllerName: string): Promise<any[]>;
|
|
61
|
+
//# sourceMappingURL=route-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-builder.d.ts","sourceRoot":"","sources":["../../src/route-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,OAAO,MAAM,SAAS,CAAC;AAI9B,OAAO,EAAM,UAAU,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAY,WAAW,EAAE,qBAAqB,EAAqB,eAAe,EAAE,MAAM,EAAyB,UAAU,EAAiB,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAG9N;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG;IAAE,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAE3E;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAmB7F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAM3I;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,qBAAqB,EACjC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,aAAa,EAClB,GAAG,EAAE,GAAG,EACR,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,EAAE,CAAC,CAkBvB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,cAAc,CAiDjI;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,EAC9G,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,WAAW,GACtB,OAAO,CAAC,cAAc,CAgBxB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,MAAM,EACb,kBAAkB,EAAE,eAAe,EAAE,EACrC,OAAO,EAAE,iBAAiB,CAAC,0BAA0B,CAAC,GACrD,OAAO,CAAC,cAAc,CA2CxB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAkClI"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildRoutePath = buildRoutePath;
|
|
7
|
+
exports.resolveRouteMiddlewares = resolveRouteMiddlewares;
|
|
8
|
+
exports.resolveRoutePolicies = resolveRoutePolicies;
|
|
9
|
+
exports.createPolicyGate = createPolicyGate;
|
|
10
|
+
exports.wrapMiddlewareAction = wrapMiddlewareAction;
|
|
11
|
+
exports.createActionHandler = createActionHandler;
|
|
12
|
+
exports.extractRouteArgs = extractRouteArgs;
|
|
13
|
+
const util_1 = require("@spinajs/util");
|
|
14
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
15
|
+
const di_1 = require("@spinajs/di");
|
|
16
|
+
const exceptions_1 = require("@spinajs/exceptions");
|
|
17
|
+
const interfaces_js_1 = require("./interfaces.js");
|
|
18
|
+
const exceptions_js_1 = require("./exceptions.js");
|
|
19
|
+
/**
|
|
20
|
+
* Computes the final express path for a route: `/BasePath/Path`, falling back
|
|
21
|
+
* to the method name when the route has no explicit path, with optional
|
|
22
|
+
* global route prefix (`http.controllers.route.prefix`).
|
|
23
|
+
*/
|
|
24
|
+
function buildRoutePath(basePath, route, globalPrefix) {
|
|
25
|
+
let path = '';
|
|
26
|
+
if (route.Path) {
|
|
27
|
+
if (route.Path === '/') {
|
|
28
|
+
path = `/${basePath}`;
|
|
29
|
+
}
|
|
30
|
+
else if (basePath === '/') {
|
|
31
|
+
path = `/${route.Path}`;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
path = `/${basePath}/${route.Path}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
path = `/${basePath}/${String(route.Method)}`;
|
|
39
|
+
}
|
|
40
|
+
if (globalPrefix) {
|
|
41
|
+
path = `/${globalPrefix}${path}`;
|
|
42
|
+
}
|
|
43
|
+
return path;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolves controller-wise + route-wise middleware descriptors into instances.
|
|
47
|
+
*/
|
|
48
|
+
function resolveRouteMiddlewares(descriptor, route, container) {
|
|
49
|
+
return Promise.all(descriptor.Middlewares.concat(route.Middlewares || []).map((m) => {
|
|
50
|
+
return container.resolve(m.Type, m.Options);
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Resolves controller-wise + route-wise policy descriptors into instances.
|
|
55
|
+
*
|
|
56
|
+
* String policy descriptors are configuration keys pointing at a policy type
|
|
57
|
+
* name. A key that does not resolve to a registered BasePolicy type throws
|
|
58
|
+
* {@link RouteRegistrationException} — a silently dropped policy would leave
|
|
59
|
+
* the route unprotected.
|
|
60
|
+
*/
|
|
61
|
+
function resolveRoutePolicies(descriptor, route, container, cfg, log, controllerName, path) {
|
|
62
|
+
return Promise.all(descriptor.Policies.concat(route.Policies || []).map((m) => {
|
|
63
|
+
if (lodash_1.default.isString(m.Type)) {
|
|
64
|
+
const policyType = cfg.get(m.Type);
|
|
65
|
+
if (!policyType || !di_1.DI.checkType(interfaces_js_1.BasePolicy, policyType)) {
|
|
66
|
+
throw new exceptions_js_1.RouteRegistrationException(`No policy named ${policyType ?? '<undefined>'} is registered for route ${controllerName}::${String(route.Method)} at path ${path} ( check your configuration at ${m.Type} )`);
|
|
67
|
+
}
|
|
68
|
+
log.trace(`Policy ${policyType} is used in controller ${controllerName}::${String(route.Method)} at path ${path}`);
|
|
69
|
+
return container.resolve(policyType, m.Options);
|
|
70
|
+
}
|
|
71
|
+
log.trace(`Policy ${m.Type.name} is used in controller ${controllerName}::${String(route.Method)} at path ${path}`);
|
|
72
|
+
return container.resolve(m.Type, m.Options);
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Express handler gating a route behind its policies.
|
|
77
|
+
*
|
|
78
|
+
* Executes all policies enabled for the route; if at least ONE policy resolves
|
|
79
|
+
* without error the route is allowed to execute. This allows multiple access
|
|
80
|
+
* paths to a resource, e.g. token access & session.
|
|
81
|
+
*/
|
|
82
|
+
function createPolicyGate(policies, route, controller, log) {
|
|
83
|
+
const routeName = `${controller.constructor.name}:${String(route.Method)} ${controller.BasePath}/${String(route.Path || route.Method)}`;
|
|
84
|
+
return (req, _res, next) => {
|
|
85
|
+
// Only policies enabled for this concrete route participate in the gate.
|
|
86
|
+
// A route whose policies are ALL disabled has no active authorization
|
|
87
|
+
// check, so it is allowed through — same semantics as having no policies
|
|
88
|
+
// at all. Computing this up front is what prevents the request from
|
|
89
|
+
// hanging: `Promise.allSettled([])` resolves to `[]`, which matches
|
|
90
|
+
// neither the fulfilled nor the rejected branch below, so `next` would
|
|
91
|
+
// never be called.
|
|
92
|
+
const enabledPolicies = policies.filter((p) => p.isEnabled(route, controller));
|
|
93
|
+
if (enabledPolicies.length === 0) {
|
|
94
|
+
next();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
Promise.allSettled(enabledPolicies.map((p) => {
|
|
98
|
+
return p
|
|
99
|
+
.execute(req, route, controller)
|
|
100
|
+
.then(() => {
|
|
101
|
+
log.trace(`Policy succeded for route ${routeName}, policy: ${p.constructor.name}`);
|
|
102
|
+
})
|
|
103
|
+
.catch((err) => {
|
|
104
|
+
log.trace(`Policy failed for route ${routeName} error ${err}, policy: ${p.constructor.name}`);
|
|
105
|
+
throw err;
|
|
106
|
+
});
|
|
107
|
+
}))
|
|
108
|
+
.then((results) => {
|
|
109
|
+
const fullfilled = results.find((r) => r.status === 'fulfilled');
|
|
110
|
+
if (fullfilled) {
|
|
111
|
+
log.trace(`Policy for route ${routeName} succeded, continue execution`);
|
|
112
|
+
next();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Every policy rejected — forward the first failure to the express
|
|
116
|
+
// error handler. Use next(err) directly (not `throw next(...)`,
|
|
117
|
+
// which would reject this .then() with `undefined` as an unhandled
|
|
118
|
+
// rejection while the error was already forwarded).
|
|
119
|
+
const failed = results.find((r) => r.status === 'rejected');
|
|
120
|
+
next(failed ? failed.reason : new exceptions_1.UnexpectedServerError('Policy evaluation produced no result'));
|
|
121
|
+
})
|
|
122
|
+
// Guard against unexpected throws in the settle/handler chain so the
|
|
123
|
+
// request can never stall without a response.
|
|
124
|
+
.catch((err) => next(err));
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Wraps a middleware onBefore/onAfter action into an express handler that
|
|
129
|
+
* forwards both resolution and rejection to `next`.
|
|
130
|
+
*/
|
|
131
|
+
function wrapMiddlewareAction(source, action, route, controller) {
|
|
132
|
+
const wrapper = (req, res, next) => {
|
|
133
|
+
action(req, res, route, controller)
|
|
134
|
+
.then(() => {
|
|
135
|
+
next();
|
|
136
|
+
})
|
|
137
|
+
.catch((err) => {
|
|
138
|
+
next(err);
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
Object.defineProperty(wrapper, 'name', {
|
|
142
|
+
value: source.constructor.name,
|
|
143
|
+
writable: true,
|
|
144
|
+
});
|
|
145
|
+
return wrapper;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Express handler invoking the controller action: extracts route arguments,
|
|
149
|
+
* runs the action inside the request-scoped AsyncLocalStorage context, lets
|
|
150
|
+
* middlewares inspect the produced Response and stores it in
|
|
151
|
+
* `res.locals.response` for the response pipeline. All sync and async errors
|
|
152
|
+
* are forwarded to `next`.
|
|
153
|
+
*/
|
|
154
|
+
function createActionHandler(controller, route, enabledMiddlewares, storage) {
|
|
155
|
+
const actionHandler = async (req, res, next) => {
|
|
156
|
+
try {
|
|
157
|
+
await storage.run(req.storage, async () => {
|
|
158
|
+
const args = (await extractRouteArgs(route, req, res, controller.constructor.name)).concat([req, res, next]);
|
|
159
|
+
try {
|
|
160
|
+
const result = controller[route.Method].call(controller, ...args);
|
|
161
|
+
if ((0, util_1.isPromise)(result)) {
|
|
162
|
+
result
|
|
163
|
+
.then((r) => {
|
|
164
|
+
if (r instanceof interfaces_js_1.Response) {
|
|
165
|
+
enabledMiddlewares.forEach((x) => x.onResponse(r, route, controller));
|
|
166
|
+
}
|
|
167
|
+
res.locals.response = r;
|
|
168
|
+
next();
|
|
169
|
+
})
|
|
170
|
+
.catch((err) => {
|
|
171
|
+
next(err);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
if (result instanceof interfaces_js_1.Response) {
|
|
176
|
+
enabledMiddlewares.forEach((x) => x.onResponse(result, route, controller));
|
|
177
|
+
}
|
|
178
|
+
res.locals.response = result;
|
|
179
|
+
next();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
next(err);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
next(err);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
Object.defineProperty(actionHandler, 'name', {
|
|
192
|
+
value: controller.constructor.name,
|
|
193
|
+
writable: true,
|
|
194
|
+
});
|
|
195
|
+
return actionHandler;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Extracts route argument values for an action call. Route-arg handlers are
|
|
199
|
+
* resolved from DI by parameter type and executed in Priority order
|
|
200
|
+
* (higher first).
|
|
201
|
+
*/
|
|
202
|
+
async function extractRouteArgs(route, req, res, controllerName) {
|
|
203
|
+
const callArgs = new Array(route.Parameters.size);
|
|
204
|
+
const argsCache = new Map();
|
|
205
|
+
let callData = {
|
|
206
|
+
Payload: {},
|
|
207
|
+
};
|
|
208
|
+
// Sort parameters by priority (higher priority first)
|
|
209
|
+
// Get all parameters as array, resolve their handlers to check priority, then sort
|
|
210
|
+
const paramsWithPriority = await Promise.all(Array.from(route.Parameters.values()).map(async (param) => {
|
|
211
|
+
const handler = await (0, util_1.tryGetHash)(argsCache, param.Type, () => di_1.DI.resolve(param.Type));
|
|
212
|
+
return { param, handler, priority: handler?.Priority ?? 0 };
|
|
213
|
+
}));
|
|
214
|
+
// Sort by priority descending (higher priority first)
|
|
215
|
+
const sortedParams = paramsWithPriority.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
216
|
+
for (const { param, handler: routeArgsHandler } of sortedParams) {
|
|
217
|
+
if (!routeArgsHandler) {
|
|
218
|
+
throw new exceptions_1.UnexpectedServerError(`Route parameter not registered for parameter: ${param.Name},
|
|
219
|
+
in method: ${String(route.Method)},
|
|
220
|
+
in controller: ${controllerName}. Check if you have registered it in DI container.`);
|
|
221
|
+
}
|
|
222
|
+
const { Args, CallData } = await routeArgsHandler.extract(callData, callArgs, param, req, res, route);
|
|
223
|
+
callData = CallData;
|
|
224
|
+
callArgs[param.Index] = Args;
|
|
225
|
+
}
|
|
226
|
+
return callArgs;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=route-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-builder.js","sourceRoot":"","sources":["../../src/route-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import Express from 'express';
|
|
3
|
+
import { AsyncService, IContainer } from '@spinajs/di';
|
|
4
|
+
import { Log } from '@spinajs/log';
|
|
5
|
+
import { DataValidator } from '@spinajs/validation';
|
|
6
|
+
import { Configuration } from '@spinajs/configuration';
|
|
7
|
+
import { IController, IControllerDescriptor, IActionLocalStoregeContext } from './interfaces.js';
|
|
8
|
+
export declare abstract class BaseController extends AsyncService implements IController {
|
|
9
|
+
/**
|
|
10
|
+
* Array index getter
|
|
11
|
+
*/
|
|
12
|
+
[action: string]: any;
|
|
13
|
+
protected _router: Express.Router;
|
|
14
|
+
protected _container: IContainer;
|
|
15
|
+
protected _validator: DataValidator;
|
|
16
|
+
protected _log: Log;
|
|
17
|
+
protected _actionLocalStorage: AsyncLocalStorage<IActionLocalStoregeContext>;
|
|
18
|
+
protected _cfg: Configuration;
|
|
19
|
+
/**
|
|
20
|
+
* Express router with middleware stack
|
|
21
|
+
*/
|
|
22
|
+
get Router(): Express.Router;
|
|
23
|
+
/**
|
|
24
|
+
* Controller descriptor
|
|
25
|
+
*/
|
|
26
|
+
get Descriptor(): IControllerDescriptor;
|
|
27
|
+
/**
|
|
28
|
+
* Base path for all controller routes eg. my/custom/path/
|
|
29
|
+
*
|
|
30
|
+
* It can be defined via `@BasePath` decorator, defaults to controller name without `Controller` part.
|
|
31
|
+
*/
|
|
32
|
+
get BasePath(): string;
|
|
33
|
+
resolve(): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=base-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-controller.d.ts","sourceRoot":"","sources":["../../src/base-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAyB,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAU,GAAG,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAOjG,8BAAsB,cAAe,SAAQ,YAAa,YAAW,WAAW;IAC9E;;OAEG;IACH,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC;IAEtB,SAAS,CAAC,OAAO,EAAG,OAAO,CAAC,MAAM,CAAC;IAGnC,SAAS,CAAC,UAAU,EAAG,UAAU,CAAC;IAGlC,SAAS,CAAC,UAAU,EAAG,aAAa,CAAC;IAGrC,SAAS,CAAC,IAAI,EAAG,GAAG,CAAC;IAGrB,SAAS,CAAC,mBAAmB,EAAG,iBAAiB,CAAC,0BAA0B,CAAC,CAAC;IAG9E,SAAS,CAAC,IAAI,EAAG,aAAa,CAAC;IAE/B;;OAEG;IACH,IAAW,MAAM,IAAI,OAAO,CAAC,MAAM,CAElC;IAED;;OAEG;IACH,IAAW,UAAU,IAAI,qBAAqB,CAE7C;IAED;;;;OAIG;IACH,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAEY,OAAO;CAsCrB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
11
|
+
import Express from 'express';
|
|
12
|
+
import { AsyncService, Autoinject, Container } from '@spinajs/di';
|
|
13
|
+
import { Logger, Log } from '@spinajs/log';
|
|
14
|
+
import { DataValidator } from '@spinajs/validation';
|
|
15
|
+
import { Configuration } from '@spinajs/configuration';
|
|
16
|
+
import { CONTROLLED_DESCRIPTOR_SYMBOL } from './decorators.js';
|
|
17
|
+
import { RouteRegistrationException } from './exceptions.js';
|
|
18
|
+
import { __handle_response__ } from './response.js';
|
|
19
|
+
import { __handle_error__ } from './error.js';
|
|
20
|
+
import { buildRoutePath, resolveRouteMiddlewares, resolveRoutePolicies, createPolicyGate, createActionHandler, wrapMiddlewareAction } from './route-builder.js';
|
|
21
|
+
export class BaseController extends AsyncService {
|
|
22
|
+
/**
|
|
23
|
+
* Express router with middleware stack
|
|
24
|
+
*/
|
|
25
|
+
get Router() {
|
|
26
|
+
return this._router;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Controller descriptor
|
|
30
|
+
*/
|
|
31
|
+
get Descriptor() {
|
|
32
|
+
return Reflect.getMetadata(CONTROLLED_DESCRIPTOR_SYMBOL, this);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Base path for all controller routes eg. my/custom/path/
|
|
36
|
+
*
|
|
37
|
+
* It can be defined via `@BasePath` decorator, defaults to controller name without `Controller` part.
|
|
38
|
+
*/
|
|
39
|
+
get BasePath() {
|
|
40
|
+
return this.Descriptor.BasePath ? this.Descriptor.BasePath : this.constructor.name.toLowerCase();
|
|
41
|
+
}
|
|
42
|
+
async resolve() {
|
|
43
|
+
await super.resolve();
|
|
44
|
+
if (!this.Descriptor) {
|
|
45
|
+
this._log.warn(`Controller ${this.constructor.name} does not have descriptor. If its abstract or base class ignore this message.`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this._router = Express.Router();
|
|
49
|
+
for (const [, route] of this.Descriptor.Routes) {
|
|
50
|
+
// Fail fast: an unknown route type means the route decorator never set a
|
|
51
|
+
// valid express method — mounting the rest of the controller while
|
|
52
|
+
// silently dropping this route would hide the bug.
|
|
53
|
+
if (route.InternalType === 'unknown') {
|
|
54
|
+
throw new RouteRegistrationException(`Unknown route type for ${this.constructor.name}::${String(route.Method)}`);
|
|
55
|
+
}
|
|
56
|
+
const path = buildRoutePath(this.BasePath, route, this._cfg.get('http.controllers.route.prefix'));
|
|
57
|
+
const middlewares = await resolveRouteMiddlewares(this.Descriptor, route, this._container);
|
|
58
|
+
const policies = await resolveRoutePolicies(this.Descriptor, route, this._container, this._cfg, this._log, this.constructor.name, path);
|
|
59
|
+
const enabledMiddlewares = middlewares.filter((m) => m.isEnabled(route, this));
|
|
60
|
+
this._log.trace(`Registering route ${route.Type.toUpperCase()} ${this.constructor.name}::${String(route.Method)} at ${path}`);
|
|
61
|
+
const handlers = [
|
|
62
|
+
createPolicyGate(policies, route, this, this._log),
|
|
63
|
+
...enabledMiddlewares.map((m) => wrapMiddlewareAction(m, m.onBefore.bind(m), route, this)),
|
|
64
|
+
createActionHandler(this, route, enabledMiddlewares, this._actionLocalStorage),
|
|
65
|
+
...enabledMiddlewares.map((m) => wrapMiddlewareAction(m, m.onAfter.bind(m), route, this)),
|
|
66
|
+
__handle_response__(),
|
|
67
|
+
__handle_error__(),
|
|
68
|
+
];
|
|
69
|
+
this._router[route.InternalType](path, handlers);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
__decorate([
|
|
74
|
+
Autoinject(Container),
|
|
75
|
+
__metadata("design:type", Object)
|
|
76
|
+
], BaseController.prototype, "_container", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
Autoinject(),
|
|
79
|
+
__metadata("design:type", DataValidator)
|
|
80
|
+
], BaseController.prototype, "_validator", void 0);
|
|
81
|
+
__decorate([
|
|
82
|
+
Logger('http'),
|
|
83
|
+
__metadata("design:type", Log)
|
|
84
|
+
], BaseController.prototype, "_log", void 0);
|
|
85
|
+
__decorate([
|
|
86
|
+
Autoinject(),
|
|
87
|
+
__metadata("design:type", AsyncLocalStorage)
|
|
88
|
+
], BaseController.prototype, "_actionLocalStorage", void 0);
|
|
89
|
+
__decorate([
|
|
90
|
+
Autoinject(Configuration),
|
|
91
|
+
__metadata("design:type", Configuration)
|
|
92
|
+
], BaseController.prototype, "_cfg", void 0);
|
|
93
|
+
//# sourceMappingURL=base-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-controller.js","sourceRoot":"","sources":["../../src/base-controller.ts"],"names":[],"mappings":"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"}
|
package/lib/mjs/cache.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { AsyncService, ClassInfo } from '@spinajs/di';
|
|
3
3
|
import { fs as fFs, FileHasher } from '@spinajs/fs';
|
|
4
|
-
import type { BaseController } from './
|
|
4
|
+
import type { BaseController } from './base-controller.js';
|
|
5
5
|
import { Log } from '@spinajs/log';
|
|
6
6
|
export interface IParamDoc {
|
|
7
7
|
name: string;
|
|
@@ -83,8 +83,18 @@ export declare class DefaultControllerCache extends AsyncService {
|
|
|
83
83
|
protected CacheFS: fFs;
|
|
84
84
|
protected Hasher: FileHasher;
|
|
85
85
|
resolve(): Promise<void>;
|
|
86
|
-
/**
|
|
87
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Returns parameter-name map used for route argument binding.
|
|
88
|
+
*
|
|
89
|
+
* Cache entries are keyed by source-file content hash, so a changed file
|
|
90
|
+
* naturally gets a fresh entry. `options.rebuild` forces regeneration and
|
|
91
|
+
* overwrite even when entries for the current hash already exist — used by
|
|
92
|
+
* the `http:controllers:cache` CLI command to refresh a pre-built cache
|
|
93
|
+
* (e.g. inside a docker image build).
|
|
94
|
+
*/
|
|
95
|
+
getCache(controller: ClassInfo<BaseController>, options?: {
|
|
96
|
+
rebuild?: boolean;
|
|
97
|
+
}): Promise<Record<string, string[]>>;
|
|
88
98
|
/** Whether `file` points at a real on-disk source we can parse. */
|
|
89
99
|
private isResolvableSource;
|
|
90
100
|
/**
|
|
@@ -160,4 +170,16 @@ export declare class DefaultControllerCache extends AsyncService {
|
|
|
160
170
|
*/
|
|
161
171
|
private schemaFromNamedType;
|
|
162
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Whether a ClassInfo `file` points at a real on-disk source. Bracketed
|
|
175
|
+
* sentinels (e.g. `<di>`, `<dynamic>`) are used by Controllers for entries
|
|
176
|
+
* that were never loaded from a file.
|
|
177
|
+
*/
|
|
178
|
+
export declare function isOnDiskSource(file: string | undefined): boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Pull parameter names from `Function.prototype.toString()` output. Modern V8
|
|
181
|
+
* preserves the literal signature so we can regex out `(a, b = 1, ...rest)`.
|
|
182
|
+
* Stripped of default values and TypeScript type annotations.
|
|
183
|
+
*/
|
|
184
|
+
export declare function parseFnParamNames(fn: Function): string[];
|
|
163
185
|
//# sourceMappingURL=cache.d.ts.map
|
package/lib/mjs/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,OAAO,EAAE,YAAY,EAAc,SAAS,EAAa,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,EAAE,IAAI,GAAG,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"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"}
|
package/lib/mjs/cache.js
CHANGED
|
@@ -51,8 +51,16 @@ let DefaultControllerCache = class DefaultControllerCache extends AsyncService {
|
|
|
51
51
|
await super.resolve();
|
|
52
52
|
this.Log.info(`Controller cache dir is: ${this.CacheFS.resolvePath('')}`);
|
|
53
53
|
}
|
|
54
|
-
/**
|
|
55
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Returns parameter-name map used for route argument binding.
|
|
56
|
+
*
|
|
57
|
+
* Cache entries are keyed by source-file content hash, so a changed file
|
|
58
|
+
* naturally gets a fresh entry. `options.rebuild` forces regeneration and
|
|
59
|
+
* overwrite even when entries for the current hash already exist — used by
|
|
60
|
+
* the `http:controllers:cache` CLI command to refresh a pre-built cache
|
|
61
|
+
* (e.g. inside a docker image build).
|
|
62
|
+
*/
|
|
63
|
+
async getCache(controller, options) {
|
|
56
64
|
// Sentinel values like `<di>` are set by Controllers.resolve() / add() for
|
|
57
65
|
// controllers registered through DI rather than a file scan. There's no
|
|
58
66
|
// on-disk source to parse, so fall back to a runtime extraction of
|
|
@@ -63,8 +71,9 @@ let DefaultControllerCache = class DefaultControllerCache extends AsyncService {
|
|
|
63
71
|
const file = resolvePath(controller.file.replace('.js', '.d.ts'));
|
|
64
72
|
const hash = await this.Hasher.hash(file);
|
|
65
73
|
const docHash = `doc_${hash}`;
|
|
66
|
-
const
|
|
67
|
-
const
|
|
74
|
+
const rebuild = options?.rebuild === true;
|
|
75
|
+
const paramExists = !rebuild && (await this.CacheFS.exists(hash));
|
|
76
|
+
const docExists = !rebuild && (await this.CacheFS.exists(docHash));
|
|
68
77
|
if (!paramExists || !docExists) {
|
|
69
78
|
this.Log.info(`Generating controller cache for ${controller.name}`);
|
|
70
79
|
const { parameters, documentation } = this.extractAll(file, controller.name);
|
|
@@ -78,11 +87,7 @@ let DefaultControllerCache = class DefaultControllerCache extends AsyncService {
|
|
|
78
87
|
}
|
|
79
88
|
/** Whether `file` points at a real on-disk source we can parse. */
|
|
80
89
|
isResolvableSource(file) {
|
|
81
|
-
|
|
82
|
-
return false;
|
|
83
|
-
// Bracketed sentinels (e.g. `<di>`, `<dynamic>`) are used by Controllers
|
|
84
|
-
// for entries that were never loaded from a file.
|
|
85
|
-
return !(file.startsWith('<') && file.endsWith('>'));
|
|
90
|
+
return isOnDiskSource(file);
|
|
86
91
|
}
|
|
87
92
|
/**
|
|
88
93
|
* Fallback: derive route method parameter names by parsing each method's
|
|
@@ -537,6 +542,16 @@ DefaultControllerCache = __decorate([
|
|
|
537
542
|
Singleton()
|
|
538
543
|
], DefaultControllerCache);
|
|
539
544
|
export { DefaultControllerCache };
|
|
545
|
+
/**
|
|
546
|
+
* Whether a ClassInfo `file` points at a real on-disk source. Bracketed
|
|
547
|
+
* sentinels (e.g. `<di>`, `<dynamic>`) are used by Controllers for entries
|
|
548
|
+
* that were never loaded from a file.
|
|
549
|
+
*/
|
|
550
|
+
export function isOnDiskSource(file) {
|
|
551
|
+
if (!file)
|
|
552
|
+
return false;
|
|
553
|
+
return !(file.startsWith('<') && file.endsWith('>'));
|
|
554
|
+
}
|
|
540
555
|
/** Rightmost identifier of an entity name. */
|
|
541
556
|
function entityNameRight(name) {
|
|
542
557
|
return ts.isIdentifier(name) ? name.text : name.right.text;
|
|
@@ -546,7 +561,7 @@ function entityNameRight(name) {
|
|
|
546
561
|
* preserves the literal signature so we can regex out `(a, b = 1, ...rest)`.
|
|
547
562
|
* Stripped of default values and TypeScript type annotations.
|
|
548
563
|
*/
|
|
549
|
-
function parseFnParamNames(fn) {
|
|
564
|
+
export function parseFnParamNames(fn) {
|
|
550
565
|
const src = Function.prototype.toString.call(fn);
|
|
551
566
|
const match = src.match(/^[^(]*\(([\s\S]*?)\)/);
|
|
552
567
|
if (!match)
|