@catbee/utils 0.0.8-rc.1 → 0.0.8-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/esm/config.d.ts +0 -1
- package/build/esm/config.js +6 -7
- package/build/esm/index.d.ts +0 -1
- package/build/esm/index.js +0 -1
- package/build/esm/servers/server.builder.d.ts +0 -1
- package/build/esm/servers/server.builder.js +99 -147
- package/build/esm/servers/server.d.ts +0 -1
- package/build/esm/servers/server.js +591 -876
- package/build/esm/types/api-response.d.ts +0 -1
- package/build/esm/types/api-response.js +0 -1
- package/build/esm/types/index.d.ts +0 -1
- package/build/esm/types/index.js +0 -1
- package/build/esm/types/server.d.ts +0 -1
- package/build/esm/types/server.js +0 -1
- package/build/esm/utils/array.utils.d.ts +0 -1
- package/build/esm/utils/array.utils.js +48 -86
- package/build/esm/utils/async.utils.d.ts +0 -1
- package/build/esm/utils/async.utils.js +247 -524
- package/build/esm/utils/cache.utils.d.ts +0 -1
- package/build/esm/utils/cache.utils.js +96 -301
- package/build/esm/utils/context-store.utils.d.ts +0 -1
- package/build/esm/utils/context-store.utils.js +62 -79
- package/build/esm/utils/crypto.utils.d.ts +0 -1
- package/build/esm/utils/crypto.utils.js +78 -175
- package/build/esm/utils/date.utils.d.ts +0 -1
- package/build/esm/utils/date.utils.js +47 -53
- package/build/esm/utils/decorators.utils.d.ts +30 -27
- package/build/esm/utils/decorators.utils.js +417 -461
- package/build/esm/utils/dir.utils.d.ts +0 -1
- package/build/esm/utils/dir.utils.js +264 -786
- package/build/esm/utils/env.utils.d.ts +0 -1
- package/build/esm/utils/env.utils.js +180 -271
- package/build/esm/utils/exception.utils.d.ts +0 -1
- package/build/esm/utils/exception.utils.js +112 -289
- package/build/esm/utils/fs.utils.d.ts +0 -1
- package/build/esm/utils/fs.utils.js +169 -401
- package/build/esm/utils/http-status-codes.d.ts +0 -1
- package/build/esm/utils/http-status-codes.js +0 -1
- package/build/esm/utils/id.utils.d.ts +0 -1
- package/build/esm/utils/id.utils.js +5 -9
- package/build/esm/utils/logger.utils.d.ts +0 -1
- package/build/esm/utils/logger.utils.js +34 -71
- package/build/esm/utils/middleware.utils.d.ts +0 -1
- package/build/esm/utils/middleware.utils.js +65 -155
- package/build/esm/utils/obj.utils.d.ts +0 -1
- package/build/esm/utils/obj.utils.js +69 -176
- package/build/esm/utils/performance.utils.d.ts +0 -1
- package/build/esm/utils/performance.utils.js +92 -195
- package/build/esm/utils/request.utils.d.ts +0 -1
- package/build/esm/utils/request.utils.js +41 -74
- package/build/esm/utils/response.utils.d.ts +0 -1
- package/build/esm/utils/response.utils.js +84 -107
- package/build/esm/utils/stream.utils.d.ts +0 -1
- package/build/esm/utils/stream.utils.js +38 -113
- package/build/esm/utils/string.utils.d.ts +0 -1
- package/build/esm/utils/string.utils.js +6 -11
- package/build/esm/utils/type.utils.d.ts +0 -1
- package/build/esm/utils/type.utils.js +8 -12
- package/build/esm/utils/url.utils.d.ts +0 -1
- package/build/esm/utils/url.utils.js +49 -127
- package/build/esm/utils/validate.utils.d.ts +0 -1
- package/build/esm/utils/validate.utils.js +23 -40
- package/package.json +3 -33
- package/build/esm/config.js.map +0 -1
- package/build/esm/index.js.map +0 -1
- package/build/esm/servers/server.builder.js.map +0 -1
- package/build/esm/servers/server.js.map +0 -1
- package/build/esm/types/api-response.js.map +0 -1
- package/build/esm/types/index.js.map +0 -1
- package/build/esm/types/server.js.map +0 -1
- package/build/esm/utils/array.utils.js.map +0 -1
- package/build/esm/utils/async.utils.js.map +0 -1
- package/build/esm/utils/cache.utils.js.map +0 -1
- package/build/esm/utils/context-store.utils.js.map +0 -1
- package/build/esm/utils/crypto.utils.js.map +0 -1
- package/build/esm/utils/date.utils.js.map +0 -1
- package/build/esm/utils/decorators.utils.js.map +0 -1
- package/build/esm/utils/dir.utils.js.map +0 -1
- package/build/esm/utils/env.utils.js.map +0 -1
- package/build/esm/utils/exception.utils.js.map +0 -1
- package/build/esm/utils/fs.utils.js.map +0 -1
- package/build/esm/utils/http-status-codes.js.map +0 -1
- package/build/esm/utils/id.utils.js.map +0 -1
- package/build/esm/utils/logger.utils.js.map +0 -1
- package/build/esm/utils/middleware.utils.js.map +0 -1
- package/build/esm/utils/obj.utils.js.map +0 -1
- package/build/esm/utils/performance.utils.js.map +0 -1
- package/build/esm/utils/request.utils.js.map +0 -1
- package/build/esm/utils/response.utils.js.map +0 -1
- package/build/esm/utils/stream.utils.js.map +0 -1
- package/build/esm/utils/string.utils.js.map +0 -1
- package/build/esm/utils/type.utils.js.map +0 -1
- package/build/esm/utils/url.utils.js.map +0 -1
- package/build/esm/utils/validate.utils.js.map +0 -1
- package/build/esnext/config.d.ts +0 -122
- package/build/esnext/config.js +0 -133
- package/build/esnext/config.js.map +0 -1
- package/build/esnext/index.d.ts +0 -27
- package/build/esnext/index.js +0 -50
- package/build/esnext/index.js.map +0 -1
- package/build/esnext/servers/server.builder.d.ts +0 -508
- package/build/esnext/servers/server.builder.js +0 -657
- package/build/esnext/servers/server.builder.js.map +0 -1
- package/build/esnext/servers/server.d.ts +0 -256
- package/build/esnext/servers/server.js +0 -955
- package/build/esnext/servers/server.js.map +0 -1
- package/build/esnext/types/api-response.d.ts +0 -152
- package/build/esnext/types/api-response.js +0 -34
- package/build/esnext/types/api-response.js.map +0 -1
- package/build/esnext/types/index.d.ts +0 -125
- package/build/esnext/types/index.js +0 -25
- package/build/esnext/types/index.js.map +0 -1
- package/build/esnext/types/server.d.ts +0 -268
- package/build/esnext/types/server.js +0 -25
- package/build/esnext/types/server.js.map +0 -1
- package/build/esnext/utils/array.utils.d.ts +0 -168
- package/build/esnext/utils/array.utils.js +0 -345
- package/build/esnext/utils/array.utils.js.map +0 -1
- package/build/esnext/utils/async.utils.d.ts +0 -265
- package/build/esnext/utils/async.utils.js +0 -620
- package/build/esnext/utils/async.utils.js.map +0 -1
- package/build/esnext/utils/cache.utils.d.ts +0 -153
- package/build/esnext/utils/cache.utils.js +0 -293
- package/build/esnext/utils/cache.utils.js.map +0 -1
- package/build/esnext/utils/context-store.utils.d.ts +0 -189
- package/build/esnext/utils/context-store.utils.js +0 -289
- package/build/esnext/utils/context-store.utils.js.map +0 -1
- package/build/esnext/utils/crypto.utils.d.ts +0 -160
- package/build/esnext/utils/crypto.utils.js +0 -276
- package/build/esnext/utils/crypto.utils.js.map +0 -1
- package/build/esnext/utils/date.utils.d.ts +0 -159
- package/build/esnext/utils/date.utils.js +0 -384
- package/build/esnext/utils/date.utils.js.map +0 -1
- package/build/esnext/utils/decorators.utils.d.ts +0 -508
- package/build/esnext/utils/decorators.utils.js +0 -877
- package/build/esnext/utils/decorators.utils.js.map +0 -1
- package/build/esnext/utils/dir.utils.d.ts +0 -196
- package/build/esnext/utils/dir.utils.js +0 -477
- package/build/esnext/utils/dir.utils.js.map +0 -1
- package/build/esnext/utils/env.utils.d.ts +0 -377
- package/build/esnext/utils/env.utils.js +0 -785
- package/build/esnext/utils/env.utils.js.map +0 -1
- package/build/esnext/utils/exception.utils.d.ts +0 -230
- package/build/esnext/utils/exception.utils.js +0 -381
- package/build/esnext/utils/exception.utils.js.map +0 -1
- package/build/esnext/utils/fs.utils.d.ts +0 -164
- package/build/esnext/utils/fs.utils.js +0 -349
- package/build/esnext/utils/fs.utils.js.map +0 -1
- package/build/esnext/utils/http-status-codes.d.ts +0 -266
- package/build/esnext/utils/http-status-codes.js +0 -295
- package/build/esnext/utils/http-status-codes.js.map +0 -1
- package/build/esnext/utils/id.utils.d.ts +0 -36
- package/build/esnext/utils/id.utils.js +0 -84
- package/build/esnext/utils/id.utils.js.map +0 -1
- package/build/esnext/utils/logger.utils.d.ts +0 -160
- package/build/esnext/utils/logger.utils.js +0 -300
- package/build/esnext/utils/logger.utils.js.map +0 -1
- package/build/esnext/utils/middleware.utils.d.ts +0 -100
- package/build/esnext/utils/middleware.utils.js +0 -236
- package/build/esnext/utils/middleware.utils.js.map +0 -1
- package/build/esnext/utils/obj.utils.d.ts +0 -124
- package/build/esnext/utils/obj.utils.js +0 -413
- package/build/esnext/utils/obj.utils.js.map +0 -1
- package/build/esnext/utils/performance.utils.d.ts +0 -136
- package/build/esnext/utils/performance.utils.js +0 -271
- package/build/esnext/utils/performance.utils.js.map +0 -1
- package/build/esnext/utils/request.utils.d.ts +0 -86
- package/build/esnext/utils/request.utils.js +0 -186
- package/build/esnext/utils/request.utils.js.map +0 -1
- package/build/esnext/utils/response.utils.d.ts +0 -163
- package/build/esnext/utils/response.utils.js +0 -247
- package/build/esnext/utils/response.utils.js.map +0 -1
- package/build/esnext/utils/stream.utils.d.ts +0 -88
- package/build/esnext/utils/stream.utils.js +0 -210
- package/build/esnext/utils/stream.utils.js.map +0 -1
- package/build/esnext/utils/string.utils.d.ts +0 -93
- package/build/esnext/utils/string.utils.js +0 -165
- package/build/esnext/utils/string.utils.js.map +0 -1
- package/build/esnext/utils/type.utils.d.ts +0 -90
- package/build/esnext/utils/type.utils.js +0 -187
- package/build/esnext/utils/type.utils.js.map +0 -1
- package/build/esnext/utils/url.utils.d.ts +0 -141
- package/build/esnext/utils/url.utils.js +0 -304
- package/build/esnext/utils/url.utils.js.map +0 -1
- package/build/esnext/utils/validate.utils.d.ts +0 -177
- package/build/esnext/utils/validate.utils.js +0 -320
- package/build/esnext/utils/validate.utils.js.map +0 -1
- package/build/src/config.d.ts +0 -122
- package/build/src/config.js +0 -138
- package/build/src/config.js.map +0 -1
- package/build/src/index.d.ts +0 -27
- package/build/src/index.js +0 -69
- package/build/src/index.js.map +0 -1
- package/build/src/servers/server.builder.d.ts +0 -508
- package/build/src/servers/server.builder.js +0 -661
- package/build/src/servers/server.builder.js.map +0 -1
- package/build/src/servers/server.d.ts +0 -256
- package/build/src/servers/server.js +0 -962
- package/build/src/servers/server.js.map +0 -1
- package/build/src/types/api-response.d.ts +0 -152
- package/build/src/types/api-response.js +0 -37
- package/build/src/types/api-response.js.map +0 -1
- package/build/src/types/index.d.ts +0 -125
- package/build/src/types/index.js +0 -26
- package/build/src/types/index.js.map +0 -1
- package/build/src/types/server.d.ts +0 -268
- package/build/src/types/server.js +0 -26
- package/build/src/types/server.js.map +0 -1
- package/build/src/utils/array.utils.d.ts +0 -168
- package/build/src/utils/array.utils.js +0 -364
- package/build/src/utils/array.utils.js.map +0 -1
- package/build/src/utils/async.utils.d.ts +0 -265
- package/build/src/utils/async.utils.js +0 -641
- package/build/src/utils/async.utils.js.map +0 -1
- package/build/src/utils/cache.utils.d.ts +0 -153
- package/build/src/utils/cache.utils.js +0 -297
- package/build/src/utils/cache.utils.js.map +0 -1
- package/build/src/utils/context-store.utils.d.ts +0 -189
- package/build/src/utils/context-store.utils.js +0 -296
- package/build/src/utils/context-store.utils.js.map +0 -1
- package/build/src/utils/crypto.utils.d.ts +0 -160
- package/build/src/utils/crypto.utils.js +0 -293
- package/build/src/utils/crypto.utils.js.map +0 -1
- package/build/src/utils/date.utils.d.ts +0 -159
- package/build/src/utils/date.utils.js +0 -396
- package/build/src/utils/date.utils.js.map +0 -1
- package/build/src/utils/decorators.utils.d.ts +0 -508
- package/build/src/utils/decorators.utils.js +0 -896
- package/build/src/utils/decorators.utils.js.map +0 -1
- package/build/src/utils/dir.utils.d.ts +0 -196
- package/build/src/utils/dir.utils.js +0 -501
- package/build/src/utils/dir.utils.js.map +0 -1
- package/build/src/utils/env.utils.d.ts +0 -377
- package/build/src/utils/env.utils.js +0 -789
- package/build/src/utils/env.utils.js.map +0 -1
- package/build/src/utils/exception.utils.d.ts +0 -230
- package/build/src/utils/exception.utils.js +0 -407
- package/build/src/utils/exception.utils.js.map +0 -1
- package/build/src/utils/fs.utils.d.ts +0 -164
- package/build/src/utils/fs.utils.js +0 -372
- package/build/src/utils/fs.utils.js.map +0 -1
- package/build/src/utils/http-status-codes.d.ts +0 -266
- package/build/src/utils/http-status-codes.js +0 -298
- package/build/src/utils/http-status-codes.js.map +0 -1
- package/build/src/utils/id.utils.d.ts +0 -36
- package/build/src/utils/id.utils.js +0 -91
- package/build/src/utils/id.utils.js.map +0 -1
- package/build/src/utils/logger.utils.d.ts +0 -160
- package/build/src/utils/logger.utils.js +0 -346
- package/build/src/utils/logger.utils.js.map +0 -1
- package/build/src/utils/middleware.utils.d.ts +0 -100
- package/build/src/utils/middleware.utils.js +0 -244
- package/build/src/utils/middleware.utils.js.map +0 -1
- package/build/src/utils/obj.utils.d.ts +0 -124
- package/build/src/utils/obj.utils.js +0 -429
- package/build/src/utils/obj.utils.js.map +0 -1
- package/build/src/utils/performance.utils.d.ts +0 -136
- package/build/src/utils/performance.utils.js +0 -278
- package/build/src/utils/performance.utils.js.map +0 -1
- package/build/src/utils/request.utils.d.ts +0 -86
- package/build/src/utils/request.utils.js +0 -195
- package/build/src/utils/request.utils.js.map +0 -1
- package/build/src/utils/response.utils.d.ts +0 -163
- package/build/src/utils/response.utils.js +0 -260
- package/build/src/utils/response.utils.js.map +0 -1
- package/build/src/utils/stream.utils.d.ts +0 -88
- package/build/src/utils/stream.utils.js +0 -218
- package/build/src/utils/stream.utils.js.map +0 -1
- package/build/src/utils/string.utils.d.ts +0 -93
- package/build/src/utils/string.utils.js +0 -179
- package/build/src/utils/string.utils.js.map +0 -1
- package/build/src/utils/type.utils.d.ts +0 -90
- package/build/src/utils/type.utils.js +0 -196
- package/build/src/utils/type.utils.js.map +0 -1
- package/build/src/utils/url.utils.d.ts +0 -141
- package/build/src/utils/url.utils.js +0 -317
- package/build/src/utils/url.utils.js.map +0 -1
- package/build/src/utils/validate.utils.d.ts +0 -177
- package/build/src/utils/validate.utils.js +0 -345
- package/build/src/utils/validate.utils.js.map +0 -1
|
@@ -21,89 +21,6 @@
|
|
|
21
21
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
|
-
var __assign = (this && this.__assign) || function () {
|
|
25
|
-
__assign = Object.assign || function(t) {
|
|
26
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
27
|
-
s = arguments[i];
|
|
28
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
29
|
-
t[p] = s[p];
|
|
30
|
-
}
|
|
31
|
-
return t;
|
|
32
|
-
};
|
|
33
|
-
return __assign.apply(this, arguments);
|
|
34
|
-
};
|
|
35
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
45
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
46
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
47
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
48
|
-
function step(op) {
|
|
49
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
50
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
51
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
52
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
53
|
-
switch (op[0]) {
|
|
54
|
-
case 0: case 1: t = op; break;
|
|
55
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
56
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
57
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
58
|
-
default:
|
|
59
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
60
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
61
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
62
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
63
|
-
if (t[2]) _.ops.pop();
|
|
64
|
-
_.trys.pop(); continue;
|
|
65
|
-
}
|
|
66
|
-
op = body.call(thisArg, _);
|
|
67
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
68
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
72
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
73
|
-
if (!m) return o;
|
|
74
|
-
var i = m.call(o), r, ar = [], e;
|
|
75
|
-
try {
|
|
76
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
77
|
-
}
|
|
78
|
-
catch (error) { e = { error: error }; }
|
|
79
|
-
finally {
|
|
80
|
-
try {
|
|
81
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
82
|
-
}
|
|
83
|
-
finally { if (e) throw e.error; }
|
|
84
|
-
}
|
|
85
|
-
return ar;
|
|
86
|
-
};
|
|
87
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
88
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
89
|
-
if (ar || !(i in from)) {
|
|
90
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
91
|
-
ar[i] = from[i];
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
95
|
-
};
|
|
96
|
-
var __values = (this && this.__values) || function(o) {
|
|
97
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
98
|
-
if (m) return m.call(o);
|
|
99
|
-
if (o && typeof o.length === "number") return {
|
|
100
|
-
next: function () {
|
|
101
|
-
if (o && i >= o.length) o = void 0;
|
|
102
|
-
return { value: o && o[i++], done: !o };
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
106
|
-
};
|
|
107
24
|
import 'reflect-metadata';
|
|
108
25
|
import { getLogger } from './logger.utils';
|
|
109
26
|
import { createFinalErrorResponse } from './response.utils';
|
|
@@ -111,78 +28,146 @@ import { HttpStatusCodes } from './http-status-codes';
|
|
|
111
28
|
import { rateLimit } from 'express-rate-limit';
|
|
112
29
|
import { TTLCache } from './cache.utils';
|
|
113
30
|
// Metadata keys
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
31
|
+
const ROUTES_KEY = Symbol('routes');
|
|
32
|
+
const MIDDLEWARE_KEY = Symbol('middlewares');
|
|
33
|
+
const PARAMS_KEY = Symbol('params');
|
|
34
|
+
const HTTP_CODE_KEY = Symbol('httpCode');
|
|
35
|
+
const HEADER_KEY = Symbol('headers');
|
|
36
|
+
const BEFORE_KEY = Symbol('before');
|
|
37
|
+
const AFTER_KEY = Symbol('after');
|
|
38
|
+
const ROLES_KEY = Symbol('roles');
|
|
39
|
+
const REDIRECT_KEY = Symbol('redirect');
|
|
40
|
+
const CACHE_KEY = Symbol('cache');
|
|
41
|
+
const RATE_LIMIT_KEY = Symbol('rateLimit');
|
|
42
|
+
const CONTENT_TYPE_KEY = Symbol('contentType');
|
|
43
|
+
const VERSION_KEY = Symbol('version');
|
|
44
|
+
const TIMEOUT_KEY = Symbol('timeout');
|
|
45
|
+
const LOG_KEY = Symbol('log');
|
|
129
46
|
/**
|
|
130
47
|
* RateLimiter cache that uses TTLCache for automatic TTL and LRU handling.
|
|
131
48
|
*/
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (ttlMs === void 0) { ttlMs = 5 * 60 * 1000; }
|
|
49
|
+
class RateLimiterCache {
|
|
50
|
+
cache;
|
|
51
|
+
constructor(maxSize = 100, ttlMs = 5 * 60 * 1000) {
|
|
136
52
|
this.cache = new TTLCache({
|
|
137
|
-
maxSize
|
|
138
|
-
ttlMs
|
|
53
|
+
maxSize,
|
|
54
|
+
ttlMs
|
|
139
55
|
});
|
|
140
56
|
}
|
|
141
|
-
|
|
142
|
-
return
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
57
|
+
generateKey(options) {
|
|
58
|
+
return `${options.max}:${options.windowMs}:${options.standardHeaders}:${options.legacyHeaders}`;
|
|
59
|
+
}
|
|
60
|
+
get(options) {
|
|
61
|
+
const key = this.generateKey(options);
|
|
62
|
+
const cached = this.cache.get(key);
|
|
147
63
|
if (cached) {
|
|
148
64
|
return cached.limiter;
|
|
149
65
|
}
|
|
150
66
|
// Create new limiter
|
|
151
|
-
|
|
152
|
-
|
|
67
|
+
const limiter = rateLimit({
|
|
68
|
+
...options,
|
|
69
|
+
handler: (req, res) => {
|
|
70
|
+
const errorResponse = createFinalErrorResponse(req, HttpStatusCodes.TOO_MANY_REQUESTS, 'Too Many Requests');
|
|
153
71
|
res.status(HttpStatusCodes.TOO_MANY_REQUESTS).json(errorResponse);
|
|
154
|
-
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
155
74
|
// Store in cache
|
|
156
75
|
this.cache.set(key, {
|
|
157
|
-
limiter
|
|
76
|
+
limiter,
|
|
158
77
|
config: key
|
|
159
78
|
});
|
|
160
79
|
return limiter;
|
|
161
|
-
}
|
|
162
|
-
|
|
80
|
+
}
|
|
81
|
+
clear() {
|
|
163
82
|
this.cache.clear();
|
|
164
|
-
}
|
|
165
|
-
|
|
83
|
+
}
|
|
84
|
+
size() {
|
|
166
85
|
return this.cache.size();
|
|
167
|
-
}
|
|
168
|
-
|
|
86
|
+
}
|
|
87
|
+
destroy() {
|
|
169
88
|
this.cache.destroy();
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
}());
|
|
173
|
-
export { RateLimiterCache };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
174
91
|
// Global cache instance
|
|
175
|
-
|
|
92
|
+
const rateLimiterCache = new RateLimiterCache();
|
|
93
|
+
export class DIContainer {
|
|
94
|
+
instances = new Map();
|
|
95
|
+
constructing = new Map();
|
|
96
|
+
register(target) {
|
|
97
|
+
// Mark as injectable, but do not instantiate yet
|
|
98
|
+
if (!this.instances.has(target) && !this.constructing.has(target)) {
|
|
99
|
+
// No-op: instantiation is deferred until get()
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
get(target) {
|
|
103
|
+
// Return existing instance if available
|
|
104
|
+
if (this.instances.has(target)) {
|
|
105
|
+
return this.instances.get(target);
|
|
106
|
+
}
|
|
107
|
+
// If currently constructing, return the proxy (for circular refs)
|
|
108
|
+
if (this.constructing.has(target)) {
|
|
109
|
+
return this.constructing.get(target);
|
|
110
|
+
}
|
|
111
|
+
// Mark as constructing (for circular dependency support)
|
|
112
|
+
let proxy = {};
|
|
113
|
+
this.constructing.set(target, proxy);
|
|
114
|
+
// Resolve constructor dependencies
|
|
115
|
+
const paramTypes = Reflect.getMetadata('design:paramtypes', target) || [];
|
|
116
|
+
const dependencies = paramTypes.map(dep => this.get(dep));
|
|
117
|
+
const instance = new target(...dependencies);
|
|
118
|
+
// Copy instance properties to proxy (for circular refs)
|
|
119
|
+
Object.assign(proxy, instance);
|
|
120
|
+
// Replace proxy with real instance
|
|
121
|
+
this.instances.set(target, proxy);
|
|
122
|
+
this.constructing.delete(target);
|
|
123
|
+
// Copy prototype (for instanceof checks)
|
|
124
|
+
Object.setPrototypeOf(proxy, target.prototype);
|
|
125
|
+
return proxy;
|
|
126
|
+
}
|
|
127
|
+
clear() {
|
|
128
|
+
this.instances.clear();
|
|
129
|
+
this.constructing.clear();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const diContainer = new DIContainer();
|
|
176
133
|
function normalizeHeaderValue(value) {
|
|
177
134
|
if (typeof value === 'undefined')
|
|
178
135
|
return undefined;
|
|
179
136
|
if (typeof value === 'string')
|
|
180
137
|
return value;
|
|
181
|
-
if (Array.isArray(value) && value.every(
|
|
138
|
+
if (Array.isArray(value) && value.every(item => typeof item === 'string')) {
|
|
182
139
|
return value;
|
|
183
140
|
}
|
|
184
141
|
return String(value);
|
|
185
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Injectable decorator for marking classes as injectable.
|
|
145
|
+
*
|
|
146
|
+
* @returns Class decorator that marks a class as injectable and registers it with the DI container.
|
|
147
|
+
*/
|
|
148
|
+
export function Injectable() {
|
|
149
|
+
return target => {
|
|
150
|
+
Reflect.defineMetadata('injectable', true, target);
|
|
151
|
+
diContainer.register(target);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Inject decorator for injecting dependencies into class properties.
|
|
156
|
+
*
|
|
157
|
+
* @param targetClass - The class to inject
|
|
158
|
+
* @returns Property decorator that injects the specified class into the property
|
|
159
|
+
*/
|
|
160
|
+
export function Inject(targetClass) {
|
|
161
|
+
return (target, propertyKey) => {
|
|
162
|
+
Object.defineProperty(target, propertyKey, {
|
|
163
|
+
get: function () {
|
|
164
|
+
return diContainer.get(targetClass);
|
|
165
|
+
},
|
|
166
|
+
enumerable: true,
|
|
167
|
+
configurable: true
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
}
|
|
186
171
|
/**
|
|
187
172
|
* Factory function that creates HTTP method decorators.
|
|
188
173
|
*
|
|
@@ -190,12 +175,12 @@ function normalizeHeaderValue(value) {
|
|
|
190
175
|
* @returns A method decorator function
|
|
191
176
|
*/
|
|
192
177
|
function createRouteDecorator(method) {
|
|
193
|
-
return
|
|
194
|
-
return
|
|
195
|
-
|
|
178
|
+
return (path) => {
|
|
179
|
+
return (target, propertyKey, descriptor) => {
|
|
180
|
+
const routes = Reflect.getMetadata(ROUTES_KEY, target.constructor) || [];
|
|
196
181
|
routes.push({
|
|
197
|
-
path
|
|
198
|
-
method
|
|
182
|
+
path,
|
|
183
|
+
method,
|
|
199
184
|
handlerName: propertyKey
|
|
200
185
|
});
|
|
201
186
|
Reflect.defineMetadata(ROUTES_KEY, routes, target.constructor);
|
|
@@ -216,7 +201,7 @@ function createRouteDecorator(method) {
|
|
|
216
201
|
* }
|
|
217
202
|
* ```
|
|
218
203
|
*/
|
|
219
|
-
export
|
|
204
|
+
export const Get = createRouteDecorator('get');
|
|
220
205
|
/**
|
|
221
206
|
* Decorator for POST HTTP method routes.
|
|
222
207
|
*
|
|
@@ -231,56 +216,56 @@ export var Get = createRouteDecorator('get');
|
|
|
231
216
|
* }
|
|
232
217
|
* ```
|
|
233
218
|
*/
|
|
234
|
-
export
|
|
219
|
+
export const Post = createRouteDecorator('post');
|
|
235
220
|
/**
|
|
236
221
|
* Decorator for PUT HTTP method routes.
|
|
237
222
|
*
|
|
238
223
|
* @param path - URL path for the route
|
|
239
224
|
* @returns Method decorator
|
|
240
225
|
*/
|
|
241
|
-
export
|
|
226
|
+
export const Put = createRouteDecorator('put');
|
|
242
227
|
/**
|
|
243
228
|
* Decorator for PATCH HTTP method routes.
|
|
244
229
|
*
|
|
245
230
|
* @param path - URL path for the route
|
|
246
231
|
* @returns Method decorator
|
|
247
232
|
*/
|
|
248
|
-
export
|
|
233
|
+
export const Patch = createRouteDecorator('patch');
|
|
249
234
|
/**
|
|
250
235
|
* Decorator for DELETE HTTP method routes.
|
|
251
236
|
*
|
|
252
237
|
* @param path - URL path for the route
|
|
253
238
|
* @returns Method decorator
|
|
254
239
|
*/
|
|
255
|
-
export
|
|
240
|
+
export const Delete = createRouteDecorator('delete');
|
|
256
241
|
/**
|
|
257
242
|
* Decorator for OPTIONS HTTP method routes.
|
|
258
243
|
*
|
|
259
244
|
* @param path - URL path for the route
|
|
260
245
|
* @returns Method decorator
|
|
261
246
|
*/
|
|
262
|
-
export
|
|
247
|
+
export const Options = createRouteDecorator('options');
|
|
263
248
|
/**
|
|
264
249
|
* Decorator for HEAD HTTP method routes.
|
|
265
250
|
*
|
|
266
251
|
* @param path - URL path for the route
|
|
267
252
|
* @returns Method decorator
|
|
268
253
|
*/
|
|
269
|
-
export
|
|
254
|
+
export const Head = createRouteDecorator('head');
|
|
270
255
|
/**
|
|
271
256
|
* Decorator for TRACE HTTP method routes.
|
|
272
257
|
*
|
|
273
258
|
* @param path - URL path for the route
|
|
274
259
|
* @returns Method decorator
|
|
275
260
|
*/
|
|
276
|
-
export
|
|
261
|
+
export const Trace = createRouteDecorator('trace');
|
|
277
262
|
/**
|
|
278
263
|
* Decorator for CONNECT HTTP method routes.
|
|
279
264
|
*
|
|
280
265
|
* @param path - URL path for the route
|
|
281
266
|
* @returns Method decorator
|
|
282
267
|
*/
|
|
283
|
-
export
|
|
268
|
+
export const Connect = createRouteDecorator('connect');
|
|
284
269
|
/**
|
|
285
270
|
* Decorator that marks a class as a controller with a base path.
|
|
286
271
|
* Used as the entry point for routing configuration.
|
|
@@ -297,7 +282,7 @@ export var Connect = createRouteDecorator('connect');
|
|
|
297
282
|
* ```
|
|
298
283
|
*/
|
|
299
284
|
export function Controller(basePath) {
|
|
300
|
-
return
|
|
285
|
+
return target => {
|
|
301
286
|
Reflect.defineMetadata('basePath', basePath, target);
|
|
302
287
|
};
|
|
303
288
|
}
|
|
@@ -317,14 +302,10 @@ export function Controller(basePath) {
|
|
|
317
302
|
* }
|
|
318
303
|
* ```
|
|
319
304
|
*/
|
|
320
|
-
export function Use() {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
middlewares
|
|
324
|
-
}
|
|
325
|
-
return function (target, propertyKey, _descriptor) {
|
|
326
|
-
var existing = Reflect.getMetadata(MIDDLEWARE_KEY, target, propertyKey) || [];
|
|
327
|
-
Reflect.defineMetadata(MIDDLEWARE_KEY, __spreadArray(__spreadArray([], __read(existing), false), __read(middlewares), false), target, propertyKey);
|
|
305
|
+
export function Use(...middlewares) {
|
|
306
|
+
return (target, propertyKey, _descriptor) => {
|
|
307
|
+
const existing = Reflect.getMetadata(MIDDLEWARE_KEY, target, propertyKey) || [];
|
|
308
|
+
Reflect.defineMetadata(MIDDLEWARE_KEY, [...existing, ...middlewares], target, propertyKey);
|
|
328
309
|
};
|
|
329
310
|
}
|
|
330
311
|
/**
|
|
@@ -335,12 +316,12 @@ export function Use() {
|
|
|
335
316
|
* @returns Parameter decorator function
|
|
336
317
|
*/
|
|
337
318
|
function createParamDecorator(type, key) {
|
|
338
|
-
return
|
|
339
|
-
return
|
|
340
|
-
|
|
319
|
+
return (paramKey) => {
|
|
320
|
+
return (target, propertyKey, parameterIndex) => {
|
|
321
|
+
const params = Reflect.getMetadata(PARAMS_KEY, target, propertyKey) || [];
|
|
341
322
|
// Ensure parameters are ordered by index
|
|
342
|
-
params.push({ index: parameterIndex, type
|
|
343
|
-
params.sort(
|
|
323
|
+
params.push({ index: parameterIndex, type, key: paramKey || key });
|
|
324
|
+
params.sort((a, b) => a.index - b.index);
|
|
344
325
|
Reflect.defineMetadata(PARAMS_KEY, params, target, propertyKey);
|
|
345
326
|
};
|
|
346
327
|
};
|
|
@@ -359,7 +340,7 @@ function createParamDecorator(type, key) {
|
|
|
359
340
|
* }
|
|
360
341
|
* ```
|
|
361
342
|
*/
|
|
362
|
-
export
|
|
343
|
+
export const Query = createParamDecorator('query');
|
|
363
344
|
/**
|
|
364
345
|
* Decorator that extracts route parameters from request.
|
|
365
346
|
*
|
|
@@ -374,7 +355,7 @@ export var Query = createParamDecorator('query');
|
|
|
374
355
|
* }
|
|
375
356
|
* ```
|
|
376
357
|
*/
|
|
377
|
-
export
|
|
358
|
+
export const Param = createParamDecorator('param');
|
|
378
359
|
/**
|
|
379
360
|
* Decorator that extracts body or body property from request.
|
|
380
361
|
*
|
|
@@ -394,7 +375,7 @@ export var Param = createParamDecorator('param');
|
|
|
394
375
|
* }
|
|
395
376
|
* ```
|
|
396
377
|
*/
|
|
397
|
-
export
|
|
378
|
+
export const Body = createParamDecorator('body');
|
|
398
379
|
/**
|
|
399
380
|
* Decorator that injects the entire request object.
|
|
400
381
|
*
|
|
@@ -409,7 +390,7 @@ export var Body = createParamDecorator('body');
|
|
|
409
390
|
* }
|
|
410
391
|
* ```
|
|
411
392
|
*/
|
|
412
|
-
export
|
|
393
|
+
export const Req = createParamDecorator('req');
|
|
413
394
|
/**
|
|
414
395
|
* Decorator that injects the response object.
|
|
415
396
|
*
|
|
@@ -424,7 +405,7 @@ export var Req = createParamDecorator('req');
|
|
|
424
405
|
* }
|
|
425
406
|
* ```
|
|
426
407
|
*/
|
|
427
|
-
export
|
|
408
|
+
export const Res = createParamDecorator('res');
|
|
428
409
|
/**
|
|
429
410
|
* Decorator that sets a custom HTTP status code for a response.
|
|
430
411
|
*
|
|
@@ -442,7 +423,7 @@ export var Res = createParamDecorator('res');
|
|
|
442
423
|
* ```
|
|
443
424
|
*/
|
|
444
425
|
export function HttpCode(status) {
|
|
445
|
-
return
|
|
426
|
+
return (target, propertyKey, _descriptor) => {
|
|
446
427
|
Reflect.defineMetadata(HTTP_CODE_KEY, status, target, propertyKey);
|
|
447
428
|
};
|
|
448
429
|
}
|
|
@@ -495,11 +476,19 @@ export function Header(name, value) {
|
|
|
495
476
|
* ```
|
|
496
477
|
*/
|
|
497
478
|
export function Headers(headers, value) {
|
|
498
|
-
return
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
479
|
+
return (target, propertyKey) => {
|
|
480
|
+
if (typeof propertyKey === 'undefined') {
|
|
481
|
+
// Class decorator
|
|
482
|
+
const existing = Reflect.getMetadata(HEADER_KEY, target) || {};
|
|
483
|
+
const newHeaders = typeof headers === 'string' ? { [headers]: value } : headers;
|
|
484
|
+
Reflect.defineMetadata(HEADER_KEY, { ...existing, ...newHeaders }, target);
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
// Method decorator
|
|
488
|
+
const existing = Reflect.getMetadata(HEADER_KEY, target, propertyKey) || {};
|
|
489
|
+
const newHeaders = typeof headers === 'string' ? { [headers]: value } : headers;
|
|
490
|
+
Reflect.defineMetadata(HEADER_KEY, { ...existing, ...newHeaders }, target, propertyKey);
|
|
491
|
+
}
|
|
503
492
|
};
|
|
504
493
|
}
|
|
505
494
|
/**
|
|
@@ -519,8 +508,8 @@ export function Headers(headers, value) {
|
|
|
519
508
|
* ```
|
|
520
509
|
*/
|
|
521
510
|
export function Before(fn) {
|
|
522
|
-
return
|
|
523
|
-
|
|
511
|
+
return (target, propertyKey, _descriptor) => {
|
|
512
|
+
const hooks = Reflect.getMetadata(BEFORE_KEY, target, propertyKey) || [];
|
|
524
513
|
hooks.push(fn);
|
|
525
514
|
Reflect.defineMetadata(BEFORE_KEY, hooks, target, propertyKey);
|
|
526
515
|
};
|
|
@@ -543,8 +532,8 @@ export function Before(fn) {
|
|
|
543
532
|
* ```
|
|
544
533
|
*/
|
|
545
534
|
export function After(fn) {
|
|
546
|
-
return
|
|
547
|
-
|
|
535
|
+
return (target, propertyKey, _descriptor) => {
|
|
536
|
+
const hooks = Reflect.getMetadata(AFTER_KEY, target, propertyKey) || [];
|
|
548
537
|
hooks.push(fn);
|
|
549
538
|
Reflect.defineMetadata(AFTER_KEY, hooks, target, propertyKey);
|
|
550
539
|
};
|
|
@@ -553,6 +542,8 @@ export function After(fn) {
|
|
|
553
542
|
* Decorator that requires specific roles for accessing a route.
|
|
554
543
|
* Must be used with authentication middleware.
|
|
555
544
|
*
|
|
545
|
+
* Check req.user.roles for user roles[].
|
|
546
|
+
*
|
|
556
547
|
* @param roles - List of roles that can access this route
|
|
557
548
|
* @returns Method decorator
|
|
558
549
|
*
|
|
@@ -566,13 +557,16 @@ export function After(fn) {
|
|
|
566
557
|
* }
|
|
567
558
|
* ```
|
|
568
559
|
*/
|
|
569
|
-
export function Roles() {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
560
|
+
export function Roles(...roles) {
|
|
561
|
+
return (target, propertyKey, _descriptor) => {
|
|
562
|
+
if (typeof propertyKey === 'undefined') {
|
|
563
|
+
// Class decorator
|
|
564
|
+
Reflect.defineMetadata(ROLES_KEY, roles, target);
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
// Method decorator
|
|
568
|
+
Reflect.defineMetadata(ROLES_KEY, roles, target, propertyKey);
|
|
569
|
+
}
|
|
576
570
|
};
|
|
577
571
|
}
|
|
578
572
|
/**
|
|
@@ -598,11 +592,10 @@ export function Roles() {
|
|
|
598
592
|
* }
|
|
599
593
|
* ```
|
|
600
594
|
*/
|
|
601
|
-
export function Redirect(url, statusCode) {
|
|
602
|
-
|
|
603
|
-
return function (target, propertyKey, descriptor) {
|
|
595
|
+
export function Redirect(url, statusCode = 302) {
|
|
596
|
+
return (target, propertyKey, descriptor) => {
|
|
604
597
|
// Store the redirect information in metadata
|
|
605
|
-
Reflect.defineMetadata(REDIRECT_KEY, { url
|
|
598
|
+
Reflect.defineMetadata(REDIRECT_KEY, { url, statusCode }, target, propertyKey);
|
|
606
599
|
return descriptor;
|
|
607
600
|
};
|
|
608
601
|
}
|
|
@@ -622,8 +615,15 @@ export function Redirect(url, statusCode) {
|
|
|
622
615
|
* ```
|
|
623
616
|
*/
|
|
624
617
|
export function Cache(ttlSeconds) {
|
|
625
|
-
return
|
|
626
|
-
|
|
618
|
+
return (target, propertyKey, _descriptor) => {
|
|
619
|
+
if (typeof propertyKey === 'undefined') {
|
|
620
|
+
// Class decorator
|
|
621
|
+
Reflect.defineMetadata(CACHE_KEY, { ttlSeconds }, target);
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
// Method decorator
|
|
625
|
+
Reflect.defineMetadata(CACHE_KEY, { ttlSeconds }, target, propertyKey);
|
|
626
|
+
}
|
|
627
627
|
};
|
|
628
628
|
}
|
|
629
629
|
/**
|
|
@@ -648,9 +648,20 @@ export function Cache(ttlSeconds) {
|
|
|
648
648
|
* ```
|
|
649
649
|
*/
|
|
650
650
|
export function RateLimit(options) {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
651
|
+
const opts = {
|
|
652
|
+
standardHeaders: true,
|
|
653
|
+
legacyHeaders: false,
|
|
654
|
+
...options
|
|
655
|
+
};
|
|
656
|
+
return (target, propertyKey, _descriptor) => {
|
|
657
|
+
if (typeof propertyKey === 'undefined') {
|
|
658
|
+
// Class decorator
|
|
659
|
+
Reflect.defineMetadata(RATE_LIMIT_KEY, opts, target);
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
// Method decorator
|
|
663
|
+
Reflect.defineMetadata(RATE_LIMIT_KEY, opts, target, propertyKey);
|
|
664
|
+
}
|
|
654
665
|
};
|
|
655
666
|
}
|
|
656
667
|
/**
|
|
@@ -669,8 +680,8 @@ export function RateLimit(options) {
|
|
|
669
680
|
* ```
|
|
670
681
|
*/
|
|
671
682
|
export function ContentType(type) {
|
|
672
|
-
return
|
|
673
|
-
Reflect.defineMetadata(CONTENT_TYPE_KEY, { type
|
|
683
|
+
return (target, propertyKey, _descriptor) => {
|
|
684
|
+
Reflect.defineMetadata(CONTENT_TYPE_KEY, { type }, target, propertyKey);
|
|
674
685
|
};
|
|
675
686
|
}
|
|
676
687
|
/**
|
|
@@ -703,9 +714,21 @@ export function ContentType(type) {
|
|
|
703
714
|
* ```
|
|
704
715
|
*/
|
|
705
716
|
export function Version(version, options) {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
717
|
+
const opts = {
|
|
718
|
+
addPrefix: true,
|
|
719
|
+
addHeader: true,
|
|
720
|
+
headerName: 'X-API-Version',
|
|
721
|
+
...options
|
|
722
|
+
};
|
|
723
|
+
return (target, propertyKey, _descriptor) => {
|
|
724
|
+
if (typeof propertyKey === 'undefined') {
|
|
725
|
+
// Class decorator
|
|
726
|
+
Reflect.defineMetadata(VERSION_KEY, { version, options: opts }, target);
|
|
727
|
+
}
|
|
728
|
+
else {
|
|
729
|
+
// Method decorator
|
|
730
|
+
Reflect.defineMetadata(VERSION_KEY, { version, options: opts }, target, propertyKey);
|
|
731
|
+
}
|
|
709
732
|
};
|
|
710
733
|
}
|
|
711
734
|
/**
|
|
@@ -724,8 +747,15 @@ export function Version(version, options) {
|
|
|
724
747
|
* ```
|
|
725
748
|
*/
|
|
726
749
|
export function Timeout(ms) {
|
|
727
|
-
return
|
|
728
|
-
|
|
750
|
+
return (target, propertyKey, _descriptor) => {
|
|
751
|
+
if (typeof propertyKey === 'undefined') {
|
|
752
|
+
// Class decorator
|
|
753
|
+
Reflect.defineMetadata(TIMEOUT_KEY, { ms }, target);
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
// Method decorator
|
|
757
|
+
Reflect.defineMetadata(TIMEOUT_KEY, { ms }, target, propertyKey);
|
|
758
|
+
}
|
|
729
759
|
};
|
|
730
760
|
}
|
|
731
761
|
/**
|
|
@@ -757,9 +787,23 @@ export function Timeout(ms) {
|
|
|
757
787
|
* ```
|
|
758
788
|
*/
|
|
759
789
|
export function Log(options) {
|
|
760
|
-
return
|
|
761
|
-
|
|
762
|
-
|
|
790
|
+
return (target, propertyKey, _descriptor) => {
|
|
791
|
+
const config = {
|
|
792
|
+
logEntry: true,
|
|
793
|
+
logExit: true,
|
|
794
|
+
logBody: false,
|
|
795
|
+
logParams: false,
|
|
796
|
+
logResponse: false,
|
|
797
|
+
...options
|
|
798
|
+
};
|
|
799
|
+
if (typeof propertyKey === 'undefined') {
|
|
800
|
+
// Class decorator
|
|
801
|
+
Reflect.defineMetadata(LOG_KEY, config, target);
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
// Method decorator
|
|
805
|
+
Reflect.defineMetadata(LOG_KEY, config, target, propertyKey);
|
|
806
|
+
}
|
|
763
807
|
};
|
|
764
808
|
}
|
|
765
809
|
/**
|
|
@@ -770,288 +814,200 @@ export function Log(options) {
|
|
|
770
814
|
* @param controllers - Array of controller classes
|
|
771
815
|
*/
|
|
772
816
|
export function registerControllers(router, controllers) {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
817
|
+
controllers.forEach(ControllerClass => {
|
|
818
|
+
// Use DI container to resolve controller (constructor injection + property injection)
|
|
819
|
+
const instance = diContainer.get(ControllerClass);
|
|
820
|
+
const basePath = Reflect.getMetadata('basePath', ControllerClass) || '';
|
|
821
|
+
const routes = Reflect.getMetadata(ROUTES_KEY, ControllerClass) || [];
|
|
778
822
|
// Get controller-level decorators (fallback values)
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
routes.forEach(
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
var middlewares = Reflect.getMetadata(MIDDLEWARE_KEY, instance, handlerName) || [];
|
|
791
|
-
var params = Reflect.getMetadata(PARAMS_KEY, instance, handlerName) || [];
|
|
792
|
-
var httpCode = Reflect.getMetadata(HTTP_CODE_KEY, instance, handlerName);
|
|
823
|
+
const controllerRateLimit = Reflect.getMetadata(RATE_LIMIT_KEY, ControllerClass);
|
|
824
|
+
const controllerCache = Reflect.getMetadata(CACHE_KEY, ControllerClass);
|
|
825
|
+
const controllerTimeout = Reflect.getMetadata(TIMEOUT_KEY, ControllerClass);
|
|
826
|
+
const controllerVersion = Reflect.getMetadata(VERSION_KEY, ControllerClass);
|
|
827
|
+
const controllerRoles = Reflect.getMetadata(ROLES_KEY, ControllerClass);
|
|
828
|
+
const controllerLogConfig = Reflect.getMetadata(LOG_KEY, ControllerClass);
|
|
829
|
+
const controllerHeaders = Reflect.getMetadata(HEADER_KEY, ControllerClass) || {};
|
|
830
|
+
routes.forEach(({ path, method, handlerName }) => {
|
|
831
|
+
const middlewares = Reflect.getMetadata(MIDDLEWARE_KEY, instance, handlerName) || [];
|
|
832
|
+
const params = Reflect.getMetadata(PARAMS_KEY, instance, handlerName) || [];
|
|
833
|
+
const httpCode = Reflect.getMetadata(HTTP_CODE_KEY, instance, handlerName);
|
|
793
834
|
// Merge controller-level and method-level headers
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
835
|
+
const methodHeaders = Reflect.getMetadata(HEADER_KEY, instance, handlerName) || {};
|
|
836
|
+
const headers = { ...controllerHeaders, ...methodHeaders };
|
|
837
|
+
const beforeHooks = Reflect.getMetadata(BEFORE_KEY, instance, handlerName) || [];
|
|
838
|
+
const afterHooks = Reflect.getMetadata(AFTER_KEY, instance, handlerName) || [];
|
|
839
|
+
const redirect = Reflect.getMetadata(REDIRECT_KEY, instance, handlerName);
|
|
840
|
+
const contentType = Reflect.getMetadata(CONTENT_TYPE_KEY, instance, handlerName);
|
|
800
841
|
// Use method-level decorators if present, otherwise fall back to controller-level
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
842
|
+
const roles = Reflect.getMetadata(ROLES_KEY, instance, handlerName) || controllerRoles || [];
|
|
843
|
+
const cache = Reflect.getMetadata(CACHE_KEY, instance, handlerName) || controllerCache;
|
|
844
|
+
const rateLimitOptions = Reflect.getMetadata(RATE_LIMIT_KEY, instance, handlerName) || controllerRateLimit;
|
|
845
|
+
const version = Reflect.getMetadata(VERSION_KEY, instance, handlerName) || controllerVersion;
|
|
846
|
+
const timeout = Reflect.getMetadata(TIMEOUT_KEY, instance, handlerName) || controllerTimeout;
|
|
847
|
+
const logConfig = Reflect.getMetadata(LOG_KEY, instance, handlerName) || controllerLogConfig;
|
|
807
848
|
// Create rate limiter for this specific route if needed
|
|
808
|
-
|
|
849
|
+
let rateLimiter = null;
|
|
809
850
|
if (rateLimitOptions) {
|
|
810
851
|
try {
|
|
811
852
|
rateLimiter = rateLimiterCache.get(rateLimitOptions);
|
|
812
853
|
}
|
|
813
854
|
catch (err) {
|
|
814
|
-
getLogger().warn({ err
|
|
855
|
+
getLogger().warn({ err }, 'express-rate-limit not available, skipping rate limiting for this route');
|
|
815
856
|
}
|
|
816
857
|
}
|
|
817
|
-
|
|
818
|
-
if (
|
|
819
|
-
finalPath =
|
|
858
|
+
let finalPath = path;
|
|
859
|
+
if (version?.options?.addPrefix) {
|
|
860
|
+
finalPath = `/${version.version}${path}`;
|
|
820
861
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
timedOut
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
// Handle timeout setup
|
|
835
|
-
if (timeout) {
|
|
836
|
-
timeoutId = setTimeout(function () {
|
|
837
|
-
if (!res.headersSent && !timedOut) {
|
|
838
|
-
timedOut = true;
|
|
839
|
-
var errorResponse = createFinalErrorResponse(req, HttpStatusCodes.REQUEST_TIMEOUT, 'Request timed out');
|
|
840
|
-
res.status(HttpStatusCodes.REQUEST_TIMEOUT).json(errorResponse);
|
|
841
|
-
}
|
|
842
|
-
}, timeout.ms);
|
|
843
|
-
}
|
|
844
|
-
if (timedOut)
|
|
845
|
-
return [2 /*return*/];
|
|
846
|
-
if (!rateLimiter) return [3 /*break*/, 3];
|
|
847
|
-
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
848
|
-
rateLimiter(req, res, function (err) {
|
|
849
|
-
if (err)
|
|
850
|
-
reject(err);
|
|
851
|
-
else
|
|
852
|
-
resolve();
|
|
853
|
-
});
|
|
854
|
-
})];
|
|
855
|
-
case 2:
|
|
856
|
-
_o.sent();
|
|
857
|
-
_o.label = 3;
|
|
858
|
-
case 3:
|
|
859
|
-
// Handle content type
|
|
860
|
-
if (!res.headersSent && contentType) {
|
|
861
|
-
res.setHeader('Content-Type', contentType.type);
|
|
862
|
-
}
|
|
863
|
-
// Handle versioning header
|
|
864
|
-
if (((_j = version === null || version === void 0 ? void 0 : version.options) === null || _j === void 0 ? void 0 : _j.addHeader) && ((_k = version === null || version === void 0 ? void 0 : version.options) === null || _k === void 0 ? void 0 : _k.headerName) && (version === null || version === void 0 ? void 0 : version.version)) {
|
|
865
|
-
if (!res.headersSent) {
|
|
866
|
-
res.setHeader(version.options.headerName, version.version);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
// Handle caching
|
|
870
|
-
if (cache && !res.headersSent) {
|
|
871
|
-
res.setHeader('Cache-Control', "public, max-age=".concat(cache.ttlSeconds));
|
|
872
|
-
}
|
|
873
|
-
// Handle logging - entry
|
|
874
|
-
if (logConfig === null || logConfig === void 0 ? void 0 : logConfig.logEntry) {
|
|
875
|
-
logger = getLogger();
|
|
876
|
-
logData = {
|
|
877
|
-
method: req.method,
|
|
878
|
-
url: req.originalUrl || req.url,
|
|
879
|
-
userAgent: req.get('User-Agent')
|
|
880
|
-
};
|
|
881
|
-
if (logConfig.logParams) {
|
|
882
|
-
logData.params = req.params;
|
|
883
|
-
logData.query = req.query;
|
|
884
|
-
}
|
|
885
|
-
if (logConfig.logBody)
|
|
886
|
-
logData.body = req.body;
|
|
887
|
-
logger.info({ entry: logData }, 'Route Entry:');
|
|
888
|
-
}
|
|
889
|
-
// Handle roles-based access control
|
|
890
|
-
if (roles.length && !((_m = (_l = req === null || req === void 0 ? void 0 : req.user) === null || _l === void 0 ? void 0 : _l.roles) === null || _m === void 0 ? void 0 : _m.some(function (role) { return roles.includes(role); }))) {
|
|
891
|
-
errorResponse = createFinalErrorResponse(req, HttpStatusCodes.FORBIDDEN, 'Forbidden Insufficient Roles');
|
|
892
|
-
res.status(HttpStatusCodes.FORBIDDEN).json(errorResponse);
|
|
893
|
-
if (timeoutId) {
|
|
894
|
-
clearTimeout(timeoutId);
|
|
895
|
-
}
|
|
896
|
-
return [2 /*return*/];
|
|
897
|
-
}
|
|
898
|
-
// Process static redirect if configured
|
|
899
|
-
if (redirect && redirect.url) {
|
|
900
|
-
if (timeoutId) {
|
|
901
|
-
clearTimeout(timeoutId);
|
|
902
|
-
}
|
|
903
|
-
return [2 /*return*/, res.redirect(redirect.statusCode, redirect.url)];
|
|
904
|
-
}
|
|
905
|
-
_o.label = 4;
|
|
906
|
-
case 4:
|
|
907
|
-
_o.trys.push([4, 9, 10, 11]);
|
|
908
|
-
beforeHooks_1 = __values(beforeHooks), beforeHooks_1_1 = beforeHooks_1.next();
|
|
909
|
-
_o.label = 5;
|
|
910
|
-
case 5:
|
|
911
|
-
if (!!beforeHooks_1_1.done) return [3 /*break*/, 8];
|
|
912
|
-
fn = beforeHooks_1_1.value;
|
|
913
|
-
return [4 /*yield*/, fn(req, res)];
|
|
914
|
-
case 6:
|
|
915
|
-
_o.sent();
|
|
916
|
-
_o.label = 7;
|
|
917
|
-
case 7:
|
|
918
|
-
beforeHooks_1_1 = beforeHooks_1.next();
|
|
919
|
-
return [3 /*break*/, 5];
|
|
920
|
-
case 8: return [3 /*break*/, 11];
|
|
921
|
-
case 9:
|
|
922
|
-
e_1_1 = _o.sent();
|
|
923
|
-
e_1 = { error: e_1_1 };
|
|
924
|
-
return [3 /*break*/, 11];
|
|
925
|
-
case 10:
|
|
926
|
-
try {
|
|
927
|
-
if (beforeHooks_1_1 && !beforeHooks_1_1.done && (_e = beforeHooks_1.return)) _e.call(beforeHooks_1);
|
|
928
|
-
}
|
|
929
|
-
finally { if (e_1) throw e_1.error; }
|
|
930
|
-
return [7 /*endfinally*/];
|
|
931
|
-
case 11:
|
|
932
|
-
args_1 = [];
|
|
933
|
-
if (params.length) {
|
|
934
|
-
params.forEach(function (_a) {
|
|
935
|
-
var _b;
|
|
936
|
-
var index = _a.index, type = _a.type, key = _a.key;
|
|
937
|
-
switch (type) {
|
|
938
|
-
case 'query':
|
|
939
|
-
args_1[index] = key ? req.query[key] : req.query;
|
|
940
|
-
break;
|
|
941
|
-
case 'param':
|
|
942
|
-
args_1[index] = key ? req.params[key] : req.params;
|
|
943
|
-
break;
|
|
944
|
-
case 'body':
|
|
945
|
-
args_1[index] = key ? (_b = req.body) === null || _b === void 0 ? void 0 : _b[key] : req.body;
|
|
946
|
-
break;
|
|
947
|
-
case 'req':
|
|
948
|
-
args_1[index] = req;
|
|
949
|
-
break;
|
|
950
|
-
case 'res':
|
|
951
|
-
args_1[index] = res;
|
|
952
|
-
break;
|
|
953
|
-
}
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
result = (_f = instance)[handlerName].apply(_f, __spreadArray([], __read(args_1), false));
|
|
957
|
-
if (!(result instanceof Promise)) return [3 /*break*/, 13];
|
|
958
|
-
return [4 /*yield*/, result];
|
|
959
|
-
case 12:
|
|
960
|
-
_a = _o.sent();
|
|
961
|
-
return [3 /*break*/, 14];
|
|
962
|
-
case 13:
|
|
963
|
-
_a = result;
|
|
964
|
-
_o.label = 14;
|
|
965
|
-
case 14:
|
|
966
|
-
awaited = _a;
|
|
967
|
-
// Clear timeout if operation completed
|
|
968
|
-
if (timeoutId) {
|
|
969
|
-
clearTimeout(timeoutId);
|
|
970
|
-
}
|
|
971
|
-
if (timedOut)
|
|
972
|
-
return [2 /*return*/];
|
|
973
|
-
// Handle dynamic redirects
|
|
974
|
-
if (redirect && awaited && typeof awaited === 'object' && 'url' in awaited) {
|
|
975
|
-
redirectUrl = awaited.url;
|
|
976
|
-
redirectStatus = awaited.statusCode || redirect.statusCode;
|
|
977
|
-
return [2 /*return*/, res.redirect(redirectStatus, redirectUrl)];
|
|
978
|
-
}
|
|
979
|
-
if (!res.headersSent && typeof awaited !== 'undefined') {
|
|
980
|
-
if (httpCode)
|
|
981
|
-
res.status(httpCode);
|
|
982
|
-
try {
|
|
983
|
-
for (_b = __values(Object.entries(headers)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
984
|
-
_d = __read(_c.value, 2), k = _d[0], v = _d[1];
|
|
985
|
-
normalized = normalizeHeaderValue(v);
|
|
986
|
-
if (typeof normalized !== 'undefined') {
|
|
987
|
-
res.set(k, normalized);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
992
|
-
finally {
|
|
993
|
-
try {
|
|
994
|
-
if (_c && !_c.done && (_g = _b.return)) _g.call(_b);
|
|
995
|
-
}
|
|
996
|
-
finally { if (e_3) throw e_3.error; }
|
|
997
|
-
}
|
|
998
|
-
res.json(awaited);
|
|
999
|
-
}
|
|
1000
|
-
// Handle logging - exit
|
|
1001
|
-
if (logConfig === null || logConfig === void 0 ? void 0 : logConfig.logExit) {
|
|
1002
|
-
logger = getLogger();
|
|
1003
|
-
logData = {
|
|
1004
|
-
method: req.method,
|
|
1005
|
-
url: req.originalUrl || req.url,
|
|
1006
|
-
statusCode: res.statusCode,
|
|
1007
|
-
duration: "".concat(Date.now() - req.startTime, "ms")
|
|
1008
|
-
};
|
|
1009
|
-
if (logConfig.logResponse)
|
|
1010
|
-
logData.response = awaited;
|
|
1011
|
-
logger.info({ exit: logData }, 'Route Exit:');
|
|
862
|
+
const handler = async (req, res, next) => {
|
|
863
|
+
// Set start time for duration tracking
|
|
864
|
+
req['startTime'] = Date.now();
|
|
865
|
+
let timeoutId;
|
|
866
|
+
let timedOut = false;
|
|
867
|
+
try {
|
|
868
|
+
// Handle timeout setup
|
|
869
|
+
if (timeout) {
|
|
870
|
+
timeoutId = setTimeout(() => {
|
|
871
|
+
if (!res.headersSent && !timedOut) {
|
|
872
|
+
timedOut = true;
|
|
873
|
+
const errorResponse = createFinalErrorResponse(req, HttpStatusCodes.REQUEST_TIMEOUT, 'Request timed out');
|
|
874
|
+
res.status(HttpStatusCodes.REQUEST_TIMEOUT).json(errorResponse);
|
|
1012
875
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
876
|
+
}, timeout.ms);
|
|
877
|
+
}
|
|
878
|
+
if (timedOut)
|
|
879
|
+
return;
|
|
880
|
+
// Handle rate limiting
|
|
881
|
+
if (rateLimiter) {
|
|
882
|
+
await new Promise((resolve, reject) => {
|
|
883
|
+
rateLimiter(req, res, (err) => {
|
|
884
|
+
if (err)
|
|
885
|
+
reject(err);
|
|
886
|
+
else
|
|
887
|
+
resolve();
|
|
888
|
+
});
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
// Handle content type
|
|
892
|
+
if (!res.headersSent && contentType) {
|
|
893
|
+
res.setHeader('Content-Type', contentType.type);
|
|
894
|
+
}
|
|
895
|
+
// Handle versioning header
|
|
896
|
+
if (version?.options?.addHeader && version?.options?.headerName && version?.version) {
|
|
897
|
+
if (!res.headersSent) {
|
|
898
|
+
res.setHeader(version.options.headerName, version.version);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
// Handle caching
|
|
902
|
+
if (cache && !res.headersSent) {
|
|
903
|
+
res.setHeader('Cache-Control', `public, max-age=${cache.ttlSeconds}`);
|
|
904
|
+
}
|
|
905
|
+
// Handle logging - entry
|
|
906
|
+
if (logConfig?.logEntry) {
|
|
907
|
+
const logger = getLogger();
|
|
908
|
+
const logData = {
|
|
909
|
+
method: req.method,
|
|
910
|
+
url: req.originalUrl || req.url,
|
|
911
|
+
userAgent: req.get('User-Agent')
|
|
912
|
+
};
|
|
913
|
+
if (logConfig.logParams) {
|
|
914
|
+
logData.params = req.params;
|
|
915
|
+
logData.query = req.query;
|
|
916
|
+
}
|
|
917
|
+
if (logConfig.logBody)
|
|
918
|
+
logData.body = req.body;
|
|
919
|
+
logger.info({ entry: logData }, 'Route Entry:');
|
|
920
|
+
}
|
|
921
|
+
// Handle roles-based access control
|
|
922
|
+
if (roles.length && !req?.user?.roles?.some((role) => roles.includes(role))) {
|
|
923
|
+
const errorResponse = createFinalErrorResponse(req, HttpStatusCodes.FORBIDDEN, 'Forbidden Insufficient Roles');
|
|
924
|
+
res.status(HttpStatusCodes.FORBIDDEN).json(errorResponse);
|
|
925
|
+
if (timeoutId) {
|
|
926
|
+
clearTimeout(timeoutId);
|
|
927
|
+
}
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
// Process static redirect if configured
|
|
931
|
+
if (redirect && redirect.url) {
|
|
932
|
+
if (timeoutId) {
|
|
933
|
+
clearTimeout(timeoutId);
|
|
934
|
+
}
|
|
935
|
+
return res.redirect(redirect.statusCode, redirect.url);
|
|
936
|
+
}
|
|
937
|
+
for (const fn of beforeHooks)
|
|
938
|
+
await fn(req, res);
|
|
939
|
+
const args = [];
|
|
940
|
+
if (params.length) {
|
|
941
|
+
params.forEach(({ index, type, key }) => {
|
|
942
|
+
switch (type) {
|
|
943
|
+
case 'query':
|
|
944
|
+
args[index] = key ? req.query[key] : req.query;
|
|
945
|
+
break;
|
|
946
|
+
case 'param':
|
|
947
|
+
args[index] = key ? req.params[key] : req.params;
|
|
948
|
+
break;
|
|
949
|
+
case 'body':
|
|
950
|
+
args[index] = key ? req.body?.[key] : req.body;
|
|
951
|
+
break;
|
|
952
|
+
case 'req':
|
|
953
|
+
args[index] = req;
|
|
954
|
+
break;
|
|
955
|
+
case 'res':
|
|
956
|
+
args[index] = res;
|
|
957
|
+
break;
|
|
1036
958
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
const result = instance[handlerName](...args);
|
|
962
|
+
// Support both sync and async handlers
|
|
963
|
+
const awaited = result instanceof Promise ? await result : result;
|
|
964
|
+
// Clear timeout if operation completed
|
|
965
|
+
if (timeoutId) {
|
|
966
|
+
clearTimeout(timeoutId);
|
|
967
|
+
}
|
|
968
|
+
if (timedOut)
|
|
969
|
+
return;
|
|
970
|
+
// Handle dynamic redirects
|
|
971
|
+
if (redirect && awaited && typeof awaited === 'object' && 'url' in awaited) {
|
|
972
|
+
const redirectUrl = awaited.url;
|
|
973
|
+
const redirectStatus = awaited.statusCode || redirect.statusCode;
|
|
974
|
+
return res.redirect(redirectStatus, redirectUrl);
|
|
975
|
+
}
|
|
976
|
+
if (!res.headersSent && typeof awaited !== 'undefined') {
|
|
977
|
+
if (httpCode)
|
|
978
|
+
res.status(httpCode);
|
|
979
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
980
|
+
const normalized = normalizeHeaderValue(v);
|
|
981
|
+
if (typeof normalized !== 'undefined') {
|
|
982
|
+
res.set(k, normalized);
|
|
1044
983
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
case 24: return [2 /*return*/];
|
|
984
|
+
}
|
|
985
|
+
res.json(awaited);
|
|
1048
986
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
987
|
+
// Handle logging - exit
|
|
988
|
+
if (logConfig?.logExit) {
|
|
989
|
+
const logger = getLogger();
|
|
990
|
+
const logData = {
|
|
991
|
+
method: req.method,
|
|
992
|
+
url: req.originalUrl || req.url,
|
|
993
|
+
statusCode: res.statusCode,
|
|
994
|
+
duration: `${Date.now() - req.startTime}ms`
|
|
995
|
+
};
|
|
996
|
+
if (logConfig.logResponse)
|
|
997
|
+
logData.response = awaited;
|
|
998
|
+
logger.info({ exit: logData }, 'Route Exit:');
|
|
999
|
+
}
|
|
1000
|
+
for (const fn of afterHooks)
|
|
1001
|
+
await fn(req, res, awaited);
|
|
1002
|
+
}
|
|
1003
|
+
catch (err) {
|
|
1004
|
+
if (timeoutId) {
|
|
1005
|
+
clearTimeout(timeoutId);
|
|
1006
|
+
}
|
|
1007
|
+
next(err);
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
router[method](basePath + finalPath, ...middlewares, handler);
|
|
1052
1011
|
});
|
|
1053
1012
|
});
|
|
1054
1013
|
}
|
|
1055
|
-
// Export for testing purposes
|
|
1056
|
-
export { rateLimiterCache };
|
|
1057
|
-
//# sourceMappingURL=decorators.utils.js.map
|