@nattyjs/core 0.0.1-beta.7 → 0.0.1-beta.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1204 -209
- package/dist/index.d.ts +307 -53
- package/dist/index.mjs +1156 -211
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const common = require('@nattyjs/common');
|
|
4
|
-
const tsyringe = require('tsyringe');
|
|
5
4
|
const pathToRegexp = require('path-to-regexp');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
require('reflect-metadata');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
9
|
+
|
|
10
|
+
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
6
11
|
|
|
7
12
|
function defineNattyConfig(config) {
|
|
8
13
|
return config;
|
|
@@ -27,6 +32,12 @@ function route(path) {
|
|
|
27
32
|
const CONTROLLER = "controller";
|
|
28
33
|
const INVALID_VALUE = "INVALID_VALUE";
|
|
29
34
|
const BLANK = "";
|
|
35
|
+
const DENY_BY_DEFAULT = {
|
|
36
|
+
type: "https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html#deny-by-default",
|
|
37
|
+
title: "Deny-by-default",
|
|
38
|
+
description: `Zero Trust Architecture (NIST SP 800-207) \u2014 Core principle is "never trust, always verify," which translates to deny-by-default behavior. OWASP Secure Defaults Principle \u2014 \u201CSecurity should be a default setting, and everything should be locked down unless explicitly permitted.\u201D`,
|
|
39
|
+
solution: `Please implement proper authentication and authorization checks. If this API needs to be accessed anonymously, add the @anonymous() decorator above the HTTP action.`
|
|
40
|
+
};
|
|
30
41
|
|
|
31
42
|
function get(path) {
|
|
32
43
|
return function(target, propertyKey, descriptor) {
|
|
@@ -48,6 +59,7 @@ function Delete() {
|
|
|
48
59
|
};
|
|
49
60
|
}
|
|
50
61
|
|
|
62
|
+
const HTTP_METHODS = ["get", "post", "put", "delete"];
|
|
51
63
|
const _StaticContainer = class {
|
|
52
64
|
setup(types) {
|
|
53
65
|
_StaticContainer.types = types;
|
|
@@ -59,11 +71,101 @@ const nattyContainer = new class {
|
|
|
59
71
|
constructor() {
|
|
60
72
|
this.container = /* @__PURE__ */ new Map();
|
|
61
73
|
this.containerState = /* @__PURE__ */ new Map();
|
|
74
|
+
this.compiledRoutes = {};
|
|
62
75
|
}
|
|
63
|
-
|
|
76
|
+
get types() {
|
|
77
|
+
return common.commonContainer.types;
|
|
78
|
+
}
|
|
79
|
+
setup(config, routes, resolver) {
|
|
64
80
|
this.config = config;
|
|
81
|
+
this.resolver = resolver;
|
|
82
|
+
this.applyRouteSnapshot(routes);
|
|
83
|
+
}
|
|
84
|
+
replaceRoutes(manifest) {
|
|
85
|
+
if (manifest.resolver)
|
|
86
|
+
this.resolver = manifest.resolver;
|
|
87
|
+
this.applyRouteSnapshot(manifest.routes);
|
|
88
|
+
}
|
|
89
|
+
applyRouteSnapshot(routes) {
|
|
65
90
|
this.routes = routes;
|
|
66
|
-
this.
|
|
91
|
+
this.compiledRoutes = this.createCompiledRoutes(routes);
|
|
92
|
+
}
|
|
93
|
+
createCompiledRoutes(routes) {
|
|
94
|
+
const compiledRoutes = {};
|
|
95
|
+
let declarationOrder = 0;
|
|
96
|
+
for (const method of HTTP_METHODS)
|
|
97
|
+
compiledRoutes[method] = [];
|
|
98
|
+
for (const [rootPath, routeConfig] of Object.entries(routes)) {
|
|
99
|
+
for (const method of HTTP_METHODS) {
|
|
100
|
+
const childRoutes = routeConfig[method];
|
|
101
|
+
if (!childRoutes)
|
|
102
|
+
continue;
|
|
103
|
+
for (const [childRoutePath, routeInfo] of Object.entries(childRoutes)) {
|
|
104
|
+
const childPath = this.normalizeChildPath(childRoutePath);
|
|
105
|
+
const configuredRoutePath = `${rootPath}${childPath}`;
|
|
106
|
+
compiledRoutes[method].push({
|
|
107
|
+
declarationOrder: declarationOrder++,
|
|
108
|
+
requestMethod: method,
|
|
109
|
+
configuredRoutePath,
|
|
110
|
+
matcher: pathToRegexp.match(configuredRoutePath, { decode: decodeURIComponent }),
|
|
111
|
+
routeConfig,
|
|
112
|
+
methodInfo: routeInfo,
|
|
113
|
+
specificity: this.getRouteSpecificity(configuredRoutePath)
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const sortedCompiledRoutes = {};
|
|
119
|
+
for (const method of HTTP_METHODS) {
|
|
120
|
+
sortedCompiledRoutes[method] = compiledRoutes[method].sort((routeA, routeB) => this.compareCompiledRoutes(routeA, routeB)).map(({ declarationOrder: declarationOrder2, specificity, ...route }) => route);
|
|
121
|
+
}
|
|
122
|
+
return sortedCompiledRoutes;
|
|
123
|
+
}
|
|
124
|
+
normalizeChildPath(childRoutePath) {
|
|
125
|
+
if (childRoutePath.indexOf("/") === 0)
|
|
126
|
+
return childRoutePath === "/" ? BLANK : childRoutePath;
|
|
127
|
+
return `/${childRoutePath}`;
|
|
128
|
+
}
|
|
129
|
+
getRouteSpecificity(routePath) {
|
|
130
|
+
const segments = routePath.split("/").filter(Boolean);
|
|
131
|
+
const segmentKinds = segments.map((segment) => this.getSegmentKind(segment));
|
|
132
|
+
return {
|
|
133
|
+
segments,
|
|
134
|
+
segmentKinds,
|
|
135
|
+
staticSegmentCount: segmentKinds.filter((kind) => kind === 2).length,
|
|
136
|
+
dynamicSegmentCount: segmentKinds.filter((kind) => kind === 1).length,
|
|
137
|
+
literalLength: segments.filter((segment) => !segment.startsWith(":")).reduce((length, segment) => length + segment.length, 0)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
getSegmentKind(segment) {
|
|
141
|
+
if (!segment)
|
|
142
|
+
return 0;
|
|
143
|
+
if (segment.startsWith(":"))
|
|
144
|
+
return 1;
|
|
145
|
+
return 2;
|
|
146
|
+
}
|
|
147
|
+
compareCompiledRoutes(routeA, routeB) {
|
|
148
|
+
const bySegmentSpecificity = this.compareSegmentSpecificity(routeA.specificity, routeB.specificity);
|
|
149
|
+
if (bySegmentSpecificity !== 0)
|
|
150
|
+
return bySegmentSpecificity;
|
|
151
|
+
if (routeA.specificity.staticSegmentCount !== routeB.specificity.staticSegmentCount)
|
|
152
|
+
return routeB.specificity.staticSegmentCount - routeA.specificity.staticSegmentCount;
|
|
153
|
+
if (routeA.specificity.dynamicSegmentCount !== routeB.specificity.dynamicSegmentCount)
|
|
154
|
+
return routeA.specificity.dynamicSegmentCount - routeB.specificity.dynamicSegmentCount;
|
|
155
|
+
if (routeA.specificity.literalLength !== routeB.specificity.literalLength)
|
|
156
|
+
return routeB.specificity.literalLength - routeA.specificity.literalLength;
|
|
157
|
+
return routeA.declarationOrder - routeB.declarationOrder;
|
|
158
|
+
}
|
|
159
|
+
compareSegmentSpecificity(routeA, routeB) {
|
|
160
|
+
const maxSharedSegments = Math.min(routeA.segmentKinds.length, routeB.segmentKinds.length);
|
|
161
|
+
for (let index = 0; index < maxSharedSegments; index++) {
|
|
162
|
+
if (routeA.segmentKinds[index] !== routeB.segmentKinds[index])
|
|
163
|
+
return routeB.segmentKinds[index] - routeA.segmentKinds[index];
|
|
164
|
+
}
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
getCompiledRoutes(method) {
|
|
168
|
+
return this.compiledRoutes[method] || [];
|
|
67
169
|
}
|
|
68
170
|
getTypes() {
|
|
69
171
|
return StaticContainer.types;
|
|
@@ -113,57 +215,133 @@ const nattyContainer = new class {
|
|
|
113
215
|
}
|
|
114
216
|
}();
|
|
115
217
|
|
|
218
|
+
function startWebSchedules(schedules) {
|
|
219
|
+
if (schedules && Array.isArray(schedules)) {
|
|
220
|
+
for (const schedule of schedules)
|
|
221
|
+
startWebSchedule(schedule);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async function startWebSchedule(config) {
|
|
225
|
+
if (config) {
|
|
226
|
+
const interval = setInterval(async () => {
|
|
227
|
+
try {
|
|
228
|
+
clearInterval(interval);
|
|
229
|
+
await config.scheduleFunction();
|
|
230
|
+
startWebSchedule(config);
|
|
231
|
+
} catch (ex) {
|
|
232
|
+
startWebSchedule(config);
|
|
233
|
+
}
|
|
234
|
+
}, config.interval);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
116
238
|
function init(config, appConfig) {
|
|
117
239
|
common.commonContainer.setupConfig(config);
|
|
118
240
|
common.commonContainer.setEnvTsDefinition(appConfig.envTsDefinition);
|
|
119
|
-
|
|
120
|
-
|
|
241
|
+
setupLegacyTypes(appConfig.types);
|
|
242
|
+
nattyContainer.setup(config, appConfig.routes, appConfig.resolver || defaultResolver);
|
|
243
|
+
callLifeCycleEvents(config, true);
|
|
244
|
+
const result = initializeModule(config);
|
|
245
|
+
callLifeCycleEvents(config);
|
|
246
|
+
startWebSchedules(config.webSchedules);
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
function setupLegacyTypes(types) {
|
|
250
|
+
if (types) {
|
|
251
|
+
common.commonContainer.types = {};
|
|
252
|
+
for (const [name, type] of Object.entries(types))
|
|
253
|
+
common.commonContainer.registerType({ name, ...type });
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function defaultResolver(path) {
|
|
257
|
+
if (typeof path === "function")
|
|
258
|
+
return path();
|
|
259
|
+
if (typeof path === "string") {
|
|
260
|
+
const normalizedPath = path.startsWith("/") ? `.${path}` : path;
|
|
261
|
+
return require(normalizedPath);
|
|
262
|
+
}
|
|
263
|
+
return {};
|
|
121
264
|
}
|
|
122
265
|
function initializeModule(config) {
|
|
123
266
|
if (config.app) {
|
|
124
267
|
return config.app.init(config);
|
|
125
268
|
}
|
|
126
269
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
270
|
+
async function callLifeCycleEvents(config, isPreInit = false) {
|
|
271
|
+
if (config.lifeCycle) {
|
|
272
|
+
if (config.lifeCycle.preInit && isPreInit) {
|
|
273
|
+
const preInit = config.lifeCycle.preInit();
|
|
274
|
+
if (preInit) {
|
|
275
|
+
if (preInit.cors) {
|
|
276
|
+
if (!config.cors) {
|
|
277
|
+
const jObject = { origin: [] };
|
|
278
|
+
config.cors = jObject;
|
|
279
|
+
} else if (!config.cors.origin)
|
|
280
|
+
config.cors.origin = [];
|
|
281
|
+
if (preInit.cors.origin)
|
|
282
|
+
preInit.cors.origin.forEach((t) => {
|
|
283
|
+
config.cors?.origin.push(t);
|
|
284
|
+
});
|
|
285
|
+
if (preInit.cors.methods)
|
|
286
|
+
config.cors.methods = preInit.cors.methods;
|
|
287
|
+
if (preInit.cors.optionsSuccessStatus)
|
|
288
|
+
config.cors.optionsSuccessStatus = preInit.cors.optionsSuccessStatus;
|
|
289
|
+
if (preInit.cors.preflightContinue)
|
|
290
|
+
config.cors.preflightContinue = preInit.cors.preflightContinue;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
144
293
|
}
|
|
294
|
+
if (config.lifeCycle.onStart) {
|
|
295
|
+
config.lifeCycle.onStart();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function getPreResponseBody(body, isBuffer = false) {
|
|
301
|
+
if (body === void 0 || body === null)
|
|
302
|
+
return void 0;
|
|
303
|
+
if (isBuffer)
|
|
304
|
+
return { buffer: body };
|
|
305
|
+
if (common.isObject(body) || Array.isArray(body))
|
|
306
|
+
return { json: body };
|
|
307
|
+
switch (typeof body) {
|
|
308
|
+
case "string":
|
|
309
|
+
return { string: body };
|
|
310
|
+
case "number":
|
|
311
|
+
return { number: body };
|
|
312
|
+
case "boolean":
|
|
313
|
+
return { boolean: body };
|
|
314
|
+
default:
|
|
315
|
+
return { json: body };
|
|
145
316
|
}
|
|
146
|
-
return bodyInfo;
|
|
147
317
|
}
|
|
148
318
|
|
|
149
319
|
class HttpResponse {
|
|
150
320
|
constructor(response) {
|
|
151
|
-
this._cookies =
|
|
321
|
+
this._cookies = [];
|
|
152
322
|
this._headers = new Headers();
|
|
323
|
+
this._isBuffer = false;
|
|
153
324
|
this.setValues(response);
|
|
154
325
|
}
|
|
155
326
|
setValues(responseInit) {
|
|
156
|
-
if (responseInit)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
327
|
+
if (!responseInit)
|
|
328
|
+
return;
|
|
329
|
+
if ("isBuffer" in responseInit)
|
|
330
|
+
this._isBuffer = !!responseInit.isBuffer;
|
|
331
|
+
if (responseInit.headers) {
|
|
332
|
+
for (const [key, value] of Object.entries(responseInit.headers)) {
|
|
333
|
+
this.headers.append(key, String(value));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (responseInit.cookies) {
|
|
337
|
+
for (const cookie of responseInit.cookies)
|
|
338
|
+
this.addCookie(cookie);
|
|
339
|
+
}
|
|
340
|
+
if ("status" in responseInit && responseInit.status !== void 0) {
|
|
341
|
+
this.status = responseInit.status;
|
|
342
|
+
}
|
|
343
|
+
if ("body" in responseInit) {
|
|
344
|
+
this.body = responseInit.body;
|
|
167
345
|
}
|
|
168
346
|
}
|
|
169
347
|
addCookie(cookie) {
|
|
@@ -173,7 +351,7 @@ class HttpResponse {
|
|
|
173
351
|
return this._cookies;
|
|
174
352
|
}
|
|
175
353
|
get status() {
|
|
176
|
-
return this._status;
|
|
354
|
+
return this._status ?? 200;
|
|
177
355
|
}
|
|
178
356
|
set status(value) {
|
|
179
357
|
this._status = value;
|
|
@@ -185,22 +363,62 @@ class HttpResponse {
|
|
|
185
363
|
return this._body;
|
|
186
364
|
}
|
|
187
365
|
set body(value) {
|
|
188
|
-
this._body = getPreResponseBody(value);
|
|
366
|
+
this._body = getPreResponseBody(value, this._isBuffer);
|
|
189
367
|
}
|
|
190
368
|
write(responseInit) {
|
|
191
369
|
this.setValues(responseInit);
|
|
192
370
|
}
|
|
193
371
|
}
|
|
194
372
|
|
|
195
|
-
class HttpException {
|
|
196
|
-
constructor(response) {
|
|
373
|
+
class HttpException extends Error {
|
|
374
|
+
constructor(response, message) {
|
|
375
|
+
const bodyMsg = response?.body?.message;
|
|
376
|
+
const msg = message ?? (typeof bodyMsg === "string" && bodyMsg.trim() ? bodyMsg : `HTTP ${response.status ?? 500}`);
|
|
377
|
+
super(msg);
|
|
378
|
+
this.name = this.constructor.name;
|
|
197
379
|
this.httpResponse = new HttpResponse(response);
|
|
380
|
+
const anyErr = Error;
|
|
381
|
+
if (typeof anyErr.captureStackTrace === "function") {
|
|
382
|
+
anyErr.captureStackTrace(this, this.constructor);
|
|
383
|
+
}
|
|
198
384
|
}
|
|
199
385
|
getResponse() {
|
|
200
386
|
return this.httpResponse;
|
|
201
387
|
}
|
|
202
388
|
}
|
|
203
389
|
|
|
390
|
+
class HttpRequest {
|
|
391
|
+
constructor(http) {
|
|
392
|
+
this.httpRequest = http;
|
|
393
|
+
}
|
|
394
|
+
get cookies() {
|
|
395
|
+
return this.httpRequest.cookies;
|
|
396
|
+
}
|
|
397
|
+
get url() {
|
|
398
|
+
return this.httpRequest.url;
|
|
399
|
+
}
|
|
400
|
+
get method() {
|
|
401
|
+
return this.httpRequest.method;
|
|
402
|
+
}
|
|
403
|
+
get headers() {
|
|
404
|
+
return this.httpRequest.headers;
|
|
405
|
+
}
|
|
406
|
+
get user() {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
get body() {
|
|
410
|
+
return this.httpRequest.body;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
class HttpContext {
|
|
415
|
+
constructor(request, context) {
|
|
416
|
+
this.request = new HttpRequest(request);
|
|
417
|
+
this.response = new HttpResponse();
|
|
418
|
+
this.context = context;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
204
422
|
var RequestPipeline = /* @__PURE__ */ ((RequestPipeline2) => {
|
|
205
423
|
RequestPipeline2[RequestPipeline2["onAuthentication"] = 0] = "onAuthentication";
|
|
206
424
|
RequestPipeline2[RequestPipeline2["onAuthorization"] = 1] = "onAuthorization";
|
|
@@ -327,20 +545,24 @@ class HttpNotFoundException extends HttpException {
|
|
|
327
545
|
var HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {
|
|
328
546
|
HttpStatusCode2[HttpStatusCode2["success"] = 200] = "success";
|
|
329
547
|
HttpStatusCode2[HttpStatusCode2["created"] = 201] = "created";
|
|
548
|
+
HttpStatusCode2[HttpStatusCode2["accepted"] = 202] = "accepted";
|
|
330
549
|
HttpStatusCode2[HttpStatusCode2["noContent"] = 204] = "noContent";
|
|
331
|
-
HttpStatusCode2[HttpStatusCode2["
|
|
550
|
+
HttpStatusCode2[HttpStatusCode2["movedPermanently"] = 301] = "movedPermanently";
|
|
551
|
+
HttpStatusCode2[HttpStatusCode2["found"] = 302] = "found";
|
|
552
|
+
HttpStatusCode2[HttpStatusCode2["badRequest"] = 400] = "badRequest";
|
|
332
553
|
HttpStatusCode2[HttpStatusCode2["unAuthorized"] = 401] = "unAuthorized";
|
|
333
554
|
HttpStatusCode2[HttpStatusCode2["forbiddenAccess"] = 403] = "forbiddenAccess";
|
|
334
|
-
HttpStatusCode2[HttpStatusCode2["
|
|
555
|
+
HttpStatusCode2[HttpStatusCode2["notFound"] = 404] = "notFound";
|
|
556
|
+
HttpStatusCode2[HttpStatusCode2["conflict"] = 409] = "conflict";
|
|
557
|
+
HttpStatusCode2[HttpStatusCode2["unprocessableEntity"] = 422] = "unprocessableEntity";
|
|
558
|
+
HttpStatusCode2[HttpStatusCode2["tooManyRequests"] = 429] = "tooManyRequests";
|
|
335
559
|
HttpStatusCode2[HttpStatusCode2["serverError"] = 500] = "serverError";
|
|
336
560
|
return HttpStatusCode2;
|
|
337
561
|
})(HttpStatusCode || {});
|
|
338
562
|
|
|
339
563
|
class BaseResult {
|
|
340
|
-
constructor(response,
|
|
341
|
-
this.response = response;
|
|
342
|
-
if (responseHeaders)
|
|
343
|
-
this.response = { ...this.response, ...responseHeaders };
|
|
564
|
+
constructor(response, extras) {
|
|
565
|
+
this.response = extras ? { ...response, ...extras } : response;
|
|
344
566
|
}
|
|
345
567
|
getResponse() {
|
|
346
568
|
return this.response;
|
|
@@ -348,6 +570,7 @@ class BaseResult {
|
|
|
348
570
|
}
|
|
349
571
|
|
|
350
572
|
function getResponseBodyObject(body, props) {
|
|
573
|
+
const sensitiveProps = common.commonContainer.nattyConfig?.secure?.sensitiveProps;
|
|
351
574
|
if (body instanceof common.List)
|
|
352
575
|
return getResponseBodyObject(body.values, body.props);
|
|
353
576
|
if (Array.isArray(body)) {
|
|
@@ -361,7 +584,8 @@ function getResponseBodyObject(body, props) {
|
|
|
361
584
|
const keys = Object.keys(body);
|
|
362
585
|
const getterProps = props ? Object.keys(props).map((key) => props[key]) : [];
|
|
363
586
|
for (const key of [...keys, ...getterProps])
|
|
364
|
-
|
|
587
|
+
if (!sensitiveProps || sensitiveProps.filter((t) => t == key.toLowerCase()).length == 0)
|
|
588
|
+
jObject[key] = getResponseBodyObject(body[key]);
|
|
365
589
|
return jObject;
|
|
366
590
|
}
|
|
367
591
|
return body;
|
|
@@ -385,10 +609,19 @@ class BaseResponse {
|
|
|
385
609
|
notFound() {
|
|
386
610
|
throw new HttpNotFoundException({});
|
|
387
611
|
}
|
|
612
|
+
normalizeHttpResponse(result) {
|
|
613
|
+
if (result instanceof HttpResponse)
|
|
614
|
+
return result;
|
|
615
|
+
if (result instanceof HttpException)
|
|
616
|
+
return result.getResponse();
|
|
617
|
+
if (result && typeof result === "object" && ("status" in result || "body" in result || "headers" in result || "cookies" in result || "isBuffer" in result))
|
|
618
|
+
return new HttpResponse(result);
|
|
619
|
+
return result;
|
|
620
|
+
}
|
|
388
621
|
}
|
|
389
622
|
|
|
390
623
|
function getTypedErrorMessage(type, value) {
|
|
391
|
-
const message = common.commonContainer.nattyConfig.modelBinding
|
|
624
|
+
const message = common.commonContainer.nattyConfig?.modelBinding?.errorMessage?.typed ? common.commonContainer.nattyConfig?.modelBinding?.errorMessage?.typed[type] : "";
|
|
392
625
|
return parseMessage(message, [value]);
|
|
393
626
|
}
|
|
394
627
|
function parseMessage(message, value) {
|
|
@@ -455,7 +688,7 @@ const entityContainer = new class {
|
|
|
455
688
|
}
|
|
456
689
|
getPropertyValidators(entityName, propName) {
|
|
457
690
|
const entityInfo = this.entityConfig[entityName];
|
|
458
|
-
const propertyInfo = entityInfo.properties[propName];
|
|
691
|
+
const propertyInfo = entityInfo ? entityInfo.properties[propName] : void 0;
|
|
459
692
|
return propertyInfo ? propertyInfo.validators : {};
|
|
460
693
|
}
|
|
461
694
|
getProperties(entityName) {
|
|
@@ -464,6 +697,115 @@ const entityContainer = new class {
|
|
|
464
697
|
}
|
|
465
698
|
}();
|
|
466
699
|
|
|
700
|
+
class ForbiddenAccessException extends HttpException {
|
|
701
|
+
constructor(data) {
|
|
702
|
+
super({
|
|
703
|
+
body: data,
|
|
704
|
+
status: 403
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
class UnauthorizedAccessException extends HttpException {
|
|
710
|
+
constructor(data) {
|
|
711
|
+
super({
|
|
712
|
+
body: data,
|
|
713
|
+
status: 401
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
class AcceptedException extends HttpException {
|
|
719
|
+
constructor(data) {
|
|
720
|
+
super({ body: data, status: HttpStatusCode.accepted });
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
class HttpConflictException extends HttpException {
|
|
725
|
+
constructor(data) {
|
|
726
|
+
super({ body: data, status: HttpStatusCode.conflict });
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
class HttpUnprocessableEntityException extends HttpException {
|
|
731
|
+
constructor(data) {
|
|
732
|
+
super({ body: data, status: HttpStatusCode.unprocessableEntity });
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function formatRetryAfter(value) {
|
|
737
|
+
if (typeof value === "number")
|
|
738
|
+
return String(Math.max(0, Math.floor(value)));
|
|
739
|
+
if (value instanceof Date)
|
|
740
|
+
return value.toUTCString();
|
|
741
|
+
return String(value);
|
|
742
|
+
}
|
|
743
|
+
class TooManyRequestsException extends HttpException {
|
|
744
|
+
constructor(data, retryAfter) {
|
|
745
|
+
super({
|
|
746
|
+
body: data,
|
|
747
|
+
status: HttpStatusCode.tooManyRequests,
|
|
748
|
+
headers: retryAfter !== void 0 ? { "Retry-After": formatRetryAfter(retryAfter) } : void 0
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
class RedirectException extends HttpException {
|
|
754
|
+
constructor(location, data) {
|
|
755
|
+
super({
|
|
756
|
+
body: data,
|
|
757
|
+
status: HttpStatusCode.found,
|
|
758
|
+
headers: { Location: location }
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
class RedirectPermanentException extends HttpException {
|
|
764
|
+
constructor(location, data) {
|
|
765
|
+
super({
|
|
766
|
+
body: data,
|
|
767
|
+
status: HttpStatusCode.movedPermanently,
|
|
768
|
+
headers: { Location: location }
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
class ProblemDetailsException extends HttpException {
|
|
774
|
+
constructor(problem, status, headers) {
|
|
775
|
+
const resolvedStatus = status ?? problem.status ?? 500;
|
|
776
|
+
super({
|
|
777
|
+
status: resolvedStatus,
|
|
778
|
+
body: { ...problem, status: resolvedStatus },
|
|
779
|
+
headers: {
|
|
780
|
+
"Content-Type": "application/problem+json; charset=utf-8",
|
|
781
|
+
...headers ?? {}
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
class ValidationProblemDetailsException extends ProblemDetailsException {
|
|
787
|
+
constructor(errors, detail, status = 400) {
|
|
788
|
+
super(
|
|
789
|
+
{
|
|
790
|
+
type: "https://tools.ietf.org/html/rfc7231#section-6.5.1",
|
|
791
|
+
title: "One or more validation errors occurred.",
|
|
792
|
+
status,
|
|
793
|
+
detail,
|
|
794
|
+
errors
|
|
795
|
+
},
|
|
796
|
+
status
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function CreateProblemDetail(modelName, detail) {
|
|
802
|
+
return {
|
|
803
|
+
type: "https://tools.ietf.org/html/rfc7231#section-6.5.1",
|
|
804
|
+
title: `The specified ${modelName} model props are invalid.`,
|
|
805
|
+
detail
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
|
|
467
809
|
class ParameterTypeConverter extends BaseResponse {
|
|
468
810
|
constructor() {
|
|
469
811
|
super(...arguments);
|
|
@@ -524,12 +866,14 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
524
866
|
} else {
|
|
525
867
|
if (this.isArrayType(property.type) && Array.isArray(value)) {
|
|
526
868
|
let arrayValue = body[property.name] = [];
|
|
527
|
-
let arrayInvalidProps = invalidProps[property.name] = [];
|
|
528
869
|
for (const item of value) {
|
|
529
870
|
const sanitizeValue = this.sanitizer[property.type.toLowerCase()] ? this.sanitizer[property.type.toLowerCase()](item) : item;
|
|
530
|
-
if (sanitizeValue === INVALID_VALUE)
|
|
871
|
+
if (sanitizeValue === INVALID_VALUE) {
|
|
872
|
+
let arrayInvalidProps = invalidProps[property.name];
|
|
873
|
+
if (!arrayInvalidProps)
|
|
874
|
+
arrayInvalidProps = invalidProps[property.name] = [];
|
|
531
875
|
arrayInvalidProps.push(property);
|
|
532
|
-
else
|
|
876
|
+
} else
|
|
533
877
|
arrayValue.push(sanitizeValue);
|
|
534
878
|
}
|
|
535
879
|
} else
|
|
@@ -550,14 +894,17 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
550
894
|
for (const parameterInfo of methodInfo.parameters) {
|
|
551
895
|
const value = jObject[parameterInfo.name];
|
|
552
896
|
if (value !== void 0) {
|
|
553
|
-
|
|
897
|
+
const sanitizedValue = SANITIZERS[parameterInfo.type](value);
|
|
898
|
+
if (sanitizedValue === null && sanitizedValue != value)
|
|
899
|
+
throw new HttpBadRequestException(CreateProblemDetail(parameterInfo.type, [{ [parameterInfo.name]: `The supplied data type must be "${parameterInfo.type}"` }]));
|
|
900
|
+
jObject[parameterInfo.name] = sanitizedValue;
|
|
554
901
|
}
|
|
555
902
|
}
|
|
556
903
|
return jObject;
|
|
557
904
|
}
|
|
558
905
|
convertToInstance(entityName, data) {
|
|
559
906
|
const typesInfo = this.types[entityName];
|
|
560
|
-
const target = this.getClassTarget(typesInfo.path) || entityContainer.getTarget(entityName);
|
|
907
|
+
const target = this.getClassTarget(typesInfo.path, entityName) || entityContainer.getTarget(entityName);
|
|
561
908
|
let instance = null;
|
|
562
909
|
if (target) {
|
|
563
910
|
instance = new target();
|
|
@@ -566,11 +913,10 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
566
913
|
instance = data;
|
|
567
914
|
return instance;
|
|
568
915
|
}
|
|
569
|
-
getClassTarget(
|
|
570
|
-
if (
|
|
571
|
-
const classInfo = resolver();
|
|
572
|
-
|
|
573
|
-
return classInfo[name];
|
|
916
|
+
getClassTarget(path, entityName) {
|
|
917
|
+
if (path) {
|
|
918
|
+
const classInfo = nattyContainer.resolver(path);
|
|
919
|
+
return classInfo[entityName];
|
|
574
920
|
}
|
|
575
921
|
return void 0;
|
|
576
922
|
}
|
|
@@ -606,8 +952,8 @@ class RouteParser extends ParameterTypeConverter {
|
|
|
606
952
|
get httpMethod() {
|
|
607
953
|
return this.httpContext.request.method.toLowerCase();
|
|
608
954
|
}
|
|
609
|
-
get
|
|
610
|
-
return nattyContainer.
|
|
955
|
+
get compiledRoutes() {
|
|
956
|
+
return nattyContainer.getCompiledRoutes(this.httpMethod);
|
|
611
957
|
}
|
|
612
958
|
init() {
|
|
613
959
|
const isMatched = this.matchRoute();
|
|
@@ -620,47 +966,46 @@ class RouteParser extends ParameterTypeConverter {
|
|
|
620
966
|
return controllerInfo[name];
|
|
621
967
|
}
|
|
622
968
|
matchRoute() {
|
|
623
|
-
|
|
624
|
-
const requestPathname = this.getRequestPathname();
|
|
625
|
-
for (const
|
|
626
|
-
const
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
this.routeInfo = {
|
|
639
|
-
path: `${common.commonContainer.nattyConfig.api.rootPath}/${requestPathname}`,
|
|
640
|
-
configuredRoutePath: `${common.commonContainer.nattyConfig.api.rootPath}/${configuredRoutePath}`,
|
|
641
|
-
controller: this.getController(routeConfig),
|
|
642
|
-
parameters: routeConfig.parameters,
|
|
643
|
-
methodInfo,
|
|
644
|
-
params: this.convert(methodInfo, matched.params),
|
|
645
|
-
queryParams: this.getQueryParams()
|
|
646
|
-
};
|
|
647
|
-
break;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
969
|
+
const requestUrl = this.getRequestUrl();
|
|
970
|
+
const requestPathname = this.getRequestPathname(requestUrl);
|
|
971
|
+
for (const route of this.compiledRoutes) {
|
|
972
|
+
const matched = route.matcher(requestPathname);
|
|
973
|
+
if (matched) {
|
|
974
|
+
this.routeInfo = {
|
|
975
|
+
path: `${common.commonContainer.nattyConfig.api.rootPath}/${requestPathname}`,
|
|
976
|
+
configuredRoutePath: `${common.commonContainer.nattyConfig.api.rootPath}/${route.configuredRoutePath}`,
|
|
977
|
+
controller: this.getController(route.routeConfig),
|
|
978
|
+
parameters: route.routeConfig.parameters,
|
|
979
|
+
methodInfo: route.methodInfo,
|
|
980
|
+
params: this.convert(route.methodInfo, matched.params),
|
|
981
|
+
queryParams: this.getQueryParams(requestUrl)
|
|
982
|
+
};
|
|
983
|
+
return true;
|
|
650
984
|
}
|
|
651
985
|
}
|
|
652
|
-
return
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
986
|
+
return false;
|
|
987
|
+
}
|
|
988
|
+
getRequestUrl() {
|
|
989
|
+
if (!this.parsedRequestUrl)
|
|
990
|
+
this.parsedRequestUrl = new URL(this.httpContext.request.url);
|
|
991
|
+
return this.parsedRequestUrl;
|
|
992
|
+
}
|
|
993
|
+
getRequestPathname(url) {
|
|
994
|
+
const apiRootPath = String(common.commonContainer.nattyConfig.api.rootPath || "").replace(/^\/+|\/+$/g, "");
|
|
995
|
+
const normalizedPathname = url.pathname.replace(/^\/+/, "");
|
|
996
|
+
if (!apiRootPath) {
|
|
997
|
+
return normalizedPathname;
|
|
998
|
+
}
|
|
999
|
+
if (normalizedPathname === apiRootPath) {
|
|
1000
|
+
return "";
|
|
1001
|
+
}
|
|
1002
|
+
const apiPrefix = `${apiRootPath}/`;
|
|
1003
|
+
if (normalizedPathname.startsWith(apiPrefix)) {
|
|
1004
|
+
return normalizedPathname.slice(apiPrefix.length);
|
|
1005
|
+
}
|
|
1006
|
+
return normalizedPathname;
|
|
1007
|
+
}
|
|
1008
|
+
getQueryParams(url) {
|
|
664
1009
|
const queryParams = {};
|
|
665
1010
|
for (const param of url.searchParams.keys())
|
|
666
1011
|
queryParams[param] = url.searchParams.get(param);
|
|
@@ -668,20 +1013,13 @@ class RouteParser extends ParameterTypeConverter {
|
|
|
668
1013
|
}
|
|
669
1014
|
}
|
|
670
1015
|
|
|
671
|
-
class UnauthorizedAccessException extends HttpException {
|
|
672
|
-
constructor(data) {
|
|
673
|
-
super({
|
|
674
|
-
body: data,
|
|
675
|
-
status: 401
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
1016
|
const decoratorStateContainer = new class {
|
|
681
1017
|
constructor() {
|
|
682
1018
|
this.controllerConfig = {};
|
|
1019
|
+
this.controllerSources = /* @__PURE__ */ new Map();
|
|
1020
|
+
this.sourceControllers = /* @__PURE__ */ new Map();
|
|
683
1021
|
}
|
|
684
|
-
register(params, type, additionalConfig) {
|
|
1022
|
+
register(params, type, additionalConfig, sourceFile) {
|
|
685
1023
|
const name = params.target.name || params.target.constructor.name;
|
|
686
1024
|
let controllerInfo = this.controllerConfig[name] || null;
|
|
687
1025
|
let controllerMethodInfo = null;
|
|
@@ -694,6 +1032,9 @@ const decoratorStateContainer = new class {
|
|
|
694
1032
|
controllerMethodInfo[type] = additionalConfig;
|
|
695
1033
|
} else
|
|
696
1034
|
controllerInfo.config[type] = additionalConfig;
|
|
1035
|
+
if (sourceFile) {
|
|
1036
|
+
this.trackControllerSource(name, sourceFile);
|
|
1037
|
+
}
|
|
697
1038
|
}
|
|
698
1039
|
getInfo(controllerName, methodName, type) {
|
|
699
1040
|
const controllerInfo = this.controllerConfig[controllerName];
|
|
@@ -706,6 +1047,55 @@ const decoratorStateContainer = new class {
|
|
|
706
1047
|
methodConfig = methodInfo[type];
|
|
707
1048
|
return { controllerConfig, methodConfig };
|
|
708
1049
|
}
|
|
1050
|
+
clearFromSource(sourceFile) {
|
|
1051
|
+
const normalizedSourceFile = this.normalizeFilePath(sourceFile);
|
|
1052
|
+
const controllerNames = Array.from(
|
|
1053
|
+
this.sourceControllers.get(normalizedSourceFile) || []
|
|
1054
|
+
);
|
|
1055
|
+
this.clearControllers(controllerNames);
|
|
1056
|
+
this.sourceControllers.delete(normalizedSourceFile);
|
|
1057
|
+
return controllerNames;
|
|
1058
|
+
}
|
|
1059
|
+
clearControllers(controllerNames) {
|
|
1060
|
+
const removedControllers = [];
|
|
1061
|
+
for (const controllerName of controllerNames) {
|
|
1062
|
+
const previousSource = this.controllerSources.get(controllerName);
|
|
1063
|
+
delete this.controllerConfig[controllerName];
|
|
1064
|
+
this.controllerSources.delete(controllerName);
|
|
1065
|
+
removedControllers.push(controllerName);
|
|
1066
|
+
if (previousSource) {
|
|
1067
|
+
const controllers = this.sourceControllers.get(previousSource);
|
|
1068
|
+
controllers?.delete(controllerName);
|
|
1069
|
+
if (controllers && controllers.size === 0) {
|
|
1070
|
+
this.sourceControllers.delete(previousSource);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
return removedControllers;
|
|
1075
|
+
}
|
|
1076
|
+
reset() {
|
|
1077
|
+
this.controllerConfig = {};
|
|
1078
|
+
this.controllerSources.clear();
|
|
1079
|
+
this.sourceControllers.clear();
|
|
1080
|
+
}
|
|
1081
|
+
trackControllerSource(controllerName, sourceFile) {
|
|
1082
|
+
const normalizedSourceFile = this.normalizeFilePath(sourceFile);
|
|
1083
|
+
const previousSource = this.controllerSources.get(controllerName);
|
|
1084
|
+
if (previousSource && previousSource !== normalizedSourceFile) {
|
|
1085
|
+
this.sourceControllers.get(previousSource)?.delete(controllerName);
|
|
1086
|
+
if (this.sourceControllers.get(previousSource)?.size === 0) {
|
|
1087
|
+
this.sourceControllers.delete(previousSource);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
this.controllerSources.set(controllerName, normalizedSourceFile);
|
|
1091
|
+
if (!this.sourceControllers.has(normalizedSourceFile)) {
|
|
1092
|
+
this.sourceControllers.set(normalizedSourceFile, /* @__PURE__ */ new Set());
|
|
1093
|
+
}
|
|
1094
|
+
this.sourceControllers.get(normalizedSourceFile)?.add(controllerName);
|
|
1095
|
+
}
|
|
1096
|
+
normalizeFilePath(filePath) {
|
|
1097
|
+
return path__default.resolve(filePath).replace(/\\/g, "/");
|
|
1098
|
+
}
|
|
709
1099
|
}();
|
|
710
1100
|
|
|
711
1101
|
var DecoratorType = /* @__PURE__ */ ((DecoratorType2) => {
|
|
@@ -722,22 +1112,13 @@ var DecoratorType = /* @__PURE__ */ ((DecoratorType2) => {
|
|
|
722
1112
|
return DecoratorType2;
|
|
723
1113
|
})(DecoratorType || {});
|
|
724
1114
|
|
|
725
|
-
class ForbiddenAccessException extends HttpException {
|
|
726
|
-
constructor(data) {
|
|
727
|
-
super({
|
|
728
|
-
body: data,
|
|
729
|
-
status: 403
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
|
|
734
1115
|
class AbstractExecutionContext {
|
|
735
1116
|
constructor(context, routeInfo) {
|
|
736
1117
|
this.context = context;
|
|
737
1118
|
this.routeInfo = routeInfo;
|
|
738
1119
|
}
|
|
739
1120
|
resolveService(instance) {
|
|
740
|
-
return
|
|
1121
|
+
return this.context.services.get(instance);
|
|
741
1122
|
}
|
|
742
1123
|
get request() {
|
|
743
1124
|
return this.context.request;
|
|
@@ -760,14 +1141,6 @@ class ActionExecutingContext extends AbstractExecutionContext {
|
|
|
760
1141
|
}
|
|
761
1142
|
}
|
|
762
1143
|
|
|
763
|
-
function CreateProblemDetail(modelName, detail) {
|
|
764
|
-
return {
|
|
765
|
-
type: "https://tools.ietf.org/html/rfc7231#section-6.5.1",
|
|
766
|
-
title: `The specified ${modelName} model props are invalid.`,
|
|
767
|
-
detail
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
|
|
771
1144
|
function runValidators(entityName, value) {
|
|
772
1145
|
const typeInfo = nattyContainer.types[entityName];
|
|
773
1146
|
let errors = {};
|
|
@@ -790,7 +1163,7 @@ function runValidators(entityName, value) {
|
|
|
790
1163
|
errors[propertyInfo.name] = arrayPropErrors.length > 0 ? arrayPropErrors : null;
|
|
791
1164
|
} else
|
|
792
1165
|
errors[propertyInfo.name] = runValidators(childEntityName, propValue);
|
|
793
|
-
if (Array.isArray(errors[propertyInfo.name]) && errors[propertyInfo.name].length == 0 || Object.keys(errors[propertyInfo.name]).length == 0)
|
|
1166
|
+
if (Array.isArray(errors[propertyInfo.name]) && errors[propertyInfo.name].length == 0 || Object.keys(errors[propertyInfo.name] ?? {}).length == 0)
|
|
794
1167
|
errors[propertyInfo.name] = null;
|
|
795
1168
|
}
|
|
796
1169
|
} else {
|
|
@@ -815,11 +1188,12 @@ function getTypeName(typeName) {
|
|
|
815
1188
|
}
|
|
816
1189
|
|
|
817
1190
|
class ModelBindingContext extends ParameterTypeConverter {
|
|
818
|
-
constructor(type, typeInfo, data) {
|
|
1191
|
+
constructor(type, typeInfo, data, throwOnValidationError = false) {
|
|
819
1192
|
super();
|
|
820
1193
|
this.type = type;
|
|
821
1194
|
this.typeInfo = typeInfo;
|
|
822
1195
|
this.data = data;
|
|
1196
|
+
this.throwOnValidationError = throwOnValidationError;
|
|
823
1197
|
this.serialize();
|
|
824
1198
|
}
|
|
825
1199
|
serialize() {
|
|
@@ -829,6 +1203,8 @@ class ModelBindingContext extends ParameterTypeConverter {
|
|
|
829
1203
|
else
|
|
830
1204
|
this.data = body;
|
|
831
1205
|
this.instance = this.convertToInstance(this.type, this.data);
|
|
1206
|
+
if (this.throwOnValidationError && !this.isValid)
|
|
1207
|
+
throw new HttpBadRequestException(CreateProblemDetail(this.type, this.errors));
|
|
832
1208
|
}
|
|
833
1209
|
get isValid() {
|
|
834
1210
|
const errors = runValidators(this.type, this.instance);
|
|
@@ -845,6 +1221,17 @@ class ActionExecutedContext extends AbstractExecutionContext {
|
|
|
845
1221
|
super(httpContext, routeInfo);
|
|
846
1222
|
this.content = content;
|
|
847
1223
|
}
|
|
1224
|
+
get response() {
|
|
1225
|
+
return this.context.response;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
class AuthorizationContext extends AbstractExecutionContext {
|
|
1230
|
+
constructor(models, context, routeInfo, config) {
|
|
1231
|
+
super(context, routeInfo);
|
|
1232
|
+
this.models = models;
|
|
1233
|
+
this.config = config;
|
|
1234
|
+
}
|
|
848
1235
|
}
|
|
849
1236
|
|
|
850
1237
|
class RequestProcessor extends RouteParser {
|
|
@@ -857,13 +1244,10 @@ class RequestProcessor extends RouteParser {
|
|
|
857
1244
|
case RequestPipeline.onAuthentication:
|
|
858
1245
|
await this.onAuthentication();
|
|
859
1246
|
break;
|
|
860
|
-
case RequestPipeline.onAuthorization:
|
|
861
|
-
await this.onAuthorization();
|
|
862
|
-
break;
|
|
863
1247
|
}
|
|
864
1248
|
}
|
|
865
1249
|
resolveFilter(instance) {
|
|
866
|
-
return
|
|
1250
|
+
return this.httpContext.services.get(instance);
|
|
867
1251
|
}
|
|
868
1252
|
getAuthenticationClass() {
|
|
869
1253
|
let authentication = void 0;
|
|
@@ -880,26 +1264,37 @@ class RequestProcessor extends RouteParser {
|
|
|
880
1264
|
const authentication = this.getAuthenticationClass();
|
|
881
1265
|
const authenticationFilter = authentication ? this.resolveFilter(authentication) : void 0;
|
|
882
1266
|
const anonymousInfo = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.anonymous);
|
|
1267
|
+
if (!authenticationFilter) {
|
|
1268
|
+
if (common.commonContainer.nattyConfig?.secure?.denyByDefault && !anonymousInfo.controllerConfig && !anonymousInfo.methodConfig)
|
|
1269
|
+
throw new UnauthorizedAccessException(DENY_BY_DEFAULT);
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
883
1272
|
if (authenticationFilter) {
|
|
884
1273
|
const result = await authenticationFilter.onAuthentication(this.httpContext);
|
|
885
1274
|
this.httpContext.user = result;
|
|
886
1275
|
if (!result.isAuthenticate && !anonymousInfo.controllerConfig && !anonymousInfo.methodConfig)
|
|
887
1276
|
throw new UnauthorizedAccessException(authenticationFilter.onFailedResponse());
|
|
888
|
-
await this.onAuthorization();
|
|
889
1277
|
}
|
|
890
1278
|
}
|
|
891
|
-
async onAuthorization() {
|
|
1279
|
+
async onAuthorization(methodParameters) {
|
|
892
1280
|
const authorization = common.commonContainer.globalConfig.authorization;
|
|
893
1281
|
const authorizationFilter = authorization ? this.resolveFilter(authorization) : void 0;
|
|
894
1282
|
const authorizeConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.authorize);
|
|
895
1283
|
const authenticationOnly = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.authenticationOnly);
|
|
896
|
-
if (this.httpContext.user?.isAuthenticate && authorizationFilter && (!authenticationOnly.controllerConfig && !authenticationOnly.methodConfig)) {
|
|
897
|
-
const
|
|
1284
|
+
if (this.httpContext.user?.isAuthenticate && authorizationFilter && (authorizeConfig.controllerConfig || authorizeConfig.methodConfig) && (!authenticationOnly.controllerConfig && !authenticationOnly.methodConfig)) {
|
|
1285
|
+
const authorizationContext = new AuthorizationContext(
|
|
1286
|
+
methodParameters.filter((t) => t instanceof ModelBindingContext),
|
|
1287
|
+
this.httpContext,
|
|
1288
|
+
this.routeInfo,
|
|
1289
|
+
authorizeConfig.methodConfig || authorizeConfig.controllerConfig
|
|
1290
|
+
);
|
|
1291
|
+
const result = await authorizationFilter.onAuthorization(authorizationContext, authorizationContext.config);
|
|
898
1292
|
if (!result)
|
|
899
1293
|
throw new ForbiddenAccessException(authorizationFilter.onFailedAuthorization());
|
|
900
1294
|
}
|
|
901
1295
|
}
|
|
902
1296
|
async onActionExecuting(methodParameters) {
|
|
1297
|
+
await this.onAuthorization(methodParameters);
|
|
903
1298
|
let actionFilters = common.commonContainer.globalConfig.actionFilters || [];
|
|
904
1299
|
const actionFiltersConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.useFilter);
|
|
905
1300
|
actionFilters = [...actionFilters, ...actionFiltersConfig.controllerConfig?.actionFilters || [], ...actionFiltersConfig.methodConfig?.actionFilters || []];
|
|
@@ -929,9 +1324,227 @@ class RequestProcessor extends RouteParser {
|
|
|
929
1324
|
}
|
|
930
1325
|
}
|
|
931
1326
|
|
|
1327
|
+
const PARAM_TOKENS_KEY = Symbol.for("natty:di:paramtokens");
|
|
1328
|
+
function getParamTokens(Cls) {
|
|
1329
|
+
return Reflect.getMetadata(PARAM_TOKENS_KEY, Cls);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
function isClassToken(x) {
|
|
1333
|
+
return typeof x === "function";
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
var Lifetime = /* @__PURE__ */ ((Lifetime2) => {
|
|
1337
|
+
Lifetime2["Singleton"] = "singleton";
|
|
1338
|
+
Lifetime2["Scoped"] = "scoped";
|
|
1339
|
+
Lifetime2["Transient"] = "transient";
|
|
1340
|
+
return Lifetime2;
|
|
1341
|
+
})(Lifetime || {});
|
|
1342
|
+
|
|
1343
|
+
function isDisposable(x) {
|
|
1344
|
+
return x && typeof x.dispose === "function";
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
class NattyScope {
|
|
1348
|
+
constructor(root) {
|
|
1349
|
+
this.root = root;
|
|
1350
|
+
this.scoped = /* @__PURE__ */ new Map();
|
|
1351
|
+
this.disposables = [];
|
|
1352
|
+
}
|
|
1353
|
+
createScope() {
|
|
1354
|
+
return new NattyScope(this.root);
|
|
1355
|
+
}
|
|
1356
|
+
set(token, value) {
|
|
1357
|
+
this.scoped.set(token, value);
|
|
1358
|
+
if (isDisposable(value))
|
|
1359
|
+
this.disposables.push(value);
|
|
1360
|
+
}
|
|
1361
|
+
tryGet(token) {
|
|
1362
|
+
try {
|
|
1363
|
+
return this.get(token);
|
|
1364
|
+
} catch {
|
|
1365
|
+
return void 0;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
get(token) {
|
|
1369
|
+
if (this.scoped.has(token))
|
|
1370
|
+
return this.scoped.get(token);
|
|
1371
|
+
const desc = this.root._getDescriptor(token);
|
|
1372
|
+
if (!desc) {
|
|
1373
|
+
if (typeof token === "function")
|
|
1374
|
+
return this.root.construct(token, this);
|
|
1375
|
+
throw new Error(`DI: No registration for token: ${String(token)}`);
|
|
1376
|
+
}
|
|
1377
|
+
if (desc.lifetime === Lifetime.Singleton) {
|
|
1378
|
+
return this.root.get(token);
|
|
1379
|
+
}
|
|
1380
|
+
if (desc.lifetime === Lifetime.Scoped) {
|
|
1381
|
+
const created = desc.useFactory ? desc.useFactory(this) : this.root.construct(desc.useClass, this);
|
|
1382
|
+
this.scoped.set(token, created);
|
|
1383
|
+
if (isDisposable(created))
|
|
1384
|
+
this.disposables.push(created);
|
|
1385
|
+
return created;
|
|
1386
|
+
}
|
|
1387
|
+
return desc.useFactory ? desc.useFactory(this) : this.root.construct(desc.useClass, this);
|
|
1388
|
+
}
|
|
1389
|
+
async dispose() {
|
|
1390
|
+
for (let i = this.disposables.length - 1; i >= 0; i--) {
|
|
1391
|
+
const d = this.disposables[i];
|
|
1392
|
+
await d.dispose();
|
|
1393
|
+
}
|
|
1394
|
+
this.disposables.length = 0;
|
|
1395
|
+
this.scoped.clear();
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
function normalizeFilePath$1(filePath) {
|
|
1400
|
+
return path__default.resolve(filePath).replace(/\\/g, "/");
|
|
1401
|
+
}
|
|
1402
|
+
class NattyContainer {
|
|
1403
|
+
constructor() {
|
|
1404
|
+
this.regs = /* @__PURE__ */ new Map();
|
|
1405
|
+
this.singletons = /* @__PURE__ */ new Map();
|
|
1406
|
+
this.tokenSources = /* @__PURE__ */ new Map();
|
|
1407
|
+
this.sourceTokens = /* @__PURE__ */ new Map();
|
|
1408
|
+
this.metadataKeySources = /* @__PURE__ */ new Map();
|
|
1409
|
+
this.sourceMetadataKeys = /* @__PURE__ */ new Map();
|
|
1410
|
+
}
|
|
1411
|
+
register(token, desc, sourceFile) {
|
|
1412
|
+
this.regs.set(token, desc);
|
|
1413
|
+
if (sourceFile) {
|
|
1414
|
+
this.trackTokenSource(token, sourceFile);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
addTransient(token, useClass, useFactory, sourceFile) {
|
|
1418
|
+
this.register(
|
|
1419
|
+
token,
|
|
1420
|
+
{ lifetime: Lifetime.Transient, useClass: useClass ?? token, useFactory },
|
|
1421
|
+
sourceFile
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
addScoped(token, useClass, useFactory, sourceFile) {
|
|
1425
|
+
this.register(
|
|
1426
|
+
token,
|
|
1427
|
+
{ lifetime: Lifetime.Scoped, useClass: useClass ?? token, useFactory },
|
|
1428
|
+
sourceFile
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
addSingleton(token, useClass, useFactory, sourceFile) {
|
|
1432
|
+
this.register(
|
|
1433
|
+
token,
|
|
1434
|
+
{ lifetime: Lifetime.Singleton, useClass: useClass ?? token, useFactory },
|
|
1435
|
+
sourceFile
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
addInstance(token, value, sourceFile) {
|
|
1439
|
+
this.register(token, { lifetime: Lifetime.Singleton, useValue: value }, sourceFile);
|
|
1440
|
+
this.singletons.set(token, value);
|
|
1441
|
+
}
|
|
1442
|
+
createScope() {
|
|
1443
|
+
return new NattyScope(this);
|
|
1444
|
+
}
|
|
1445
|
+
set(_token, _value) {
|
|
1446
|
+
throw new Error("Use scope.set(token, value) for per-request instances.");
|
|
1447
|
+
}
|
|
1448
|
+
tryGet(token) {
|
|
1449
|
+
try {
|
|
1450
|
+
return this.get(token);
|
|
1451
|
+
} catch {
|
|
1452
|
+
return void 0;
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
get(token) {
|
|
1456
|
+
const desc = this.regs.get(token);
|
|
1457
|
+
if (!desc) {
|
|
1458
|
+
if (isClassToken(token))
|
|
1459
|
+
return this.construct(token, this);
|
|
1460
|
+
throw new Error(`DI: No registration for token: ${String(token)}`);
|
|
1461
|
+
}
|
|
1462
|
+
if (desc.lifetime === Lifetime.Singleton) {
|
|
1463
|
+
if (desc.useValue !== void 0)
|
|
1464
|
+
return desc.useValue;
|
|
1465
|
+
if (this.singletons.has(token))
|
|
1466
|
+
return this.singletons.get(token);
|
|
1467
|
+
const created = desc.useFactory ? desc.useFactory(this) : this.construct(desc.useClass, this);
|
|
1468
|
+
this.singletons.set(token, created);
|
|
1469
|
+
return created;
|
|
1470
|
+
}
|
|
1471
|
+
throw new Error(
|
|
1472
|
+
`DI: Tried to resolve ${desc.lifetime} service from root container. Use httpContext.services.get(...)`
|
|
1473
|
+
);
|
|
1474
|
+
}
|
|
1475
|
+
construct(Cls, sp) {
|
|
1476
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", Cls) || [];
|
|
1477
|
+
const overrideTokens = getParamTokens(Cls) || [];
|
|
1478
|
+
const args = paramTypes.map((t, i) => sp.get(overrideTokens[i] ?? t));
|
|
1479
|
+
return new Cls(...args);
|
|
1480
|
+
}
|
|
1481
|
+
_getDescriptor(token) {
|
|
1482
|
+
return this.regs.get(token);
|
|
1483
|
+
}
|
|
1484
|
+
trackMetadataKey(sourceFile, key) {
|
|
1485
|
+
const normalizedSourceFile = normalizeFilePath$1(sourceFile);
|
|
1486
|
+
const previousSource = this.metadataKeySources.get(key);
|
|
1487
|
+
if (previousSource && previousSource !== normalizedSourceFile) {
|
|
1488
|
+
this.sourceMetadataKeys.get(previousSource)?.delete(key);
|
|
1489
|
+
if (this.sourceMetadataKeys.get(previousSource)?.size === 0) {
|
|
1490
|
+
this.sourceMetadataKeys.delete(previousSource);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
this.metadataKeySources.set(key, normalizedSourceFile);
|
|
1494
|
+
if (!this.sourceMetadataKeys.has(normalizedSourceFile)) {
|
|
1495
|
+
this.sourceMetadataKeys.set(normalizedSourceFile, /* @__PURE__ */ new Set());
|
|
1496
|
+
}
|
|
1497
|
+
this.sourceMetadataKeys.get(normalizedSourceFile)?.add(key);
|
|
1498
|
+
}
|
|
1499
|
+
clearRegistrationsFromSource(sourceFile) {
|
|
1500
|
+
const normalizedSourceFile = normalizeFilePath$1(sourceFile);
|
|
1501
|
+
const tokens = Array.from(this.sourceTokens.get(normalizedSourceFile) || []);
|
|
1502
|
+
const metadataKeys = Array.from(
|
|
1503
|
+
this.sourceMetadataKeys.get(normalizedSourceFile) || []
|
|
1504
|
+
);
|
|
1505
|
+
for (const token of tokens) {
|
|
1506
|
+
this.regs.delete(token);
|
|
1507
|
+
this.singletons.delete(token);
|
|
1508
|
+
this.tokenSources.delete(token);
|
|
1509
|
+
}
|
|
1510
|
+
for (const metadataKey of metadataKeys) {
|
|
1511
|
+
this.metadataKeySources.delete(metadataKey);
|
|
1512
|
+
}
|
|
1513
|
+
this.sourceTokens.delete(normalizedSourceFile);
|
|
1514
|
+
this.sourceMetadataKeys.delete(normalizedSourceFile);
|
|
1515
|
+
return {
|
|
1516
|
+
metadataKeys,
|
|
1517
|
+
tokens
|
|
1518
|
+
};
|
|
1519
|
+
}
|
|
1520
|
+
trackTokenSource(token, sourceFile) {
|
|
1521
|
+
const normalizedSourceFile = normalizeFilePath$1(sourceFile);
|
|
1522
|
+
const previousSource = this.tokenSources.get(token);
|
|
1523
|
+
if (previousSource && previousSource !== normalizedSourceFile) {
|
|
1524
|
+
this.sourceTokens.get(previousSource)?.delete(token);
|
|
1525
|
+
if (this.sourceTokens.get(previousSource)?.size === 0) {
|
|
1526
|
+
this.sourceTokens.delete(previousSource);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
this.tokenSources.set(token, normalizedSourceFile);
|
|
1530
|
+
if (!this.sourceTokens.has(normalizedSourceFile)) {
|
|
1531
|
+
this.sourceTokens.set(normalizedSourceFile, /* @__PURE__ */ new Set());
|
|
1532
|
+
}
|
|
1533
|
+
this.sourceTokens.get(normalizedSourceFile)?.add(token);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
const nattyServiceResolver = new NattyContainer();
|
|
1538
|
+
|
|
932
1539
|
class Resolver extends RequestProcessor {
|
|
933
1540
|
constructor(httpContext) {
|
|
934
1541
|
super(httpContext);
|
|
1542
|
+
this.registerDependency();
|
|
1543
|
+
}
|
|
1544
|
+
registerDependency() {
|
|
1545
|
+
this.httpContext.services = nattyServiceResolver.createScope();
|
|
1546
|
+
common.commonContainer.setMetadata(HttpContext.name, HttpContext, "services");
|
|
1547
|
+
this.httpContext.services.set(HttpContext, this.httpContext);
|
|
935
1548
|
}
|
|
936
1549
|
getControllerInstance() {
|
|
937
1550
|
const controller = this.routeInfo.controller;
|
|
@@ -939,18 +1552,27 @@ class Resolver extends RequestProcessor {
|
|
|
939
1552
|
const instance = new controller(...parameters);
|
|
940
1553
|
return instance;
|
|
941
1554
|
}
|
|
942
|
-
resolveClass(
|
|
943
|
-
return
|
|
1555
|
+
resolveClass(token) {
|
|
1556
|
+
return this.httpContext.services.get(token);
|
|
944
1557
|
}
|
|
945
1558
|
resolveConstructorParameters() {
|
|
946
1559
|
let parameters = [];
|
|
947
1560
|
for (const parameter of this.routeInfo.parameters) {
|
|
948
|
-
const
|
|
949
|
-
if (
|
|
950
|
-
parameters.push(this.resolveClass(
|
|
1561
|
+
const token = this.getConstructorParameterToken(parameter);
|
|
1562
|
+
if (token)
|
|
1563
|
+
parameters.push(this.resolveClass(token));
|
|
951
1564
|
}
|
|
952
1565
|
return parameters;
|
|
953
1566
|
}
|
|
1567
|
+
getConstructorParameterToken(parameter) {
|
|
1568
|
+
if (parameter.tokenKey) {
|
|
1569
|
+
return Symbol.for(parameter.tokenKey);
|
|
1570
|
+
}
|
|
1571
|
+
if (parameter.type) {
|
|
1572
|
+
return this.getClass(parameter.type);
|
|
1573
|
+
}
|
|
1574
|
+
return void 0;
|
|
1575
|
+
}
|
|
954
1576
|
getMethodParameters() {
|
|
955
1577
|
const parameters = new Array();
|
|
956
1578
|
for (const parameter of this.routeInfo.methodInfo.parameters) {
|
|
@@ -962,7 +1584,7 @@ class Resolver extends RequestProcessor {
|
|
|
962
1584
|
else if (queryParams[parameter.name] !== void 0)
|
|
963
1585
|
parameters.push(queryParams[parameter.name]);
|
|
964
1586
|
else if (typeInfo && this.httpContext.request.body.json) {
|
|
965
|
-
const context = new ModelBindingContext(parameter.type, typeInfo.props, this.httpContext.request.body.json);
|
|
1587
|
+
const context = new ModelBindingContext(parameter.type, typeInfo.props, this.httpContext.request.body.json, true);
|
|
966
1588
|
parameters.push(context);
|
|
967
1589
|
}
|
|
968
1590
|
}
|
|
@@ -1015,14 +1637,14 @@ class Resolver extends RequestProcessor {
|
|
|
1015
1637
|
if (onException) {
|
|
1016
1638
|
const instance = this.resolveClass(onException);
|
|
1017
1639
|
if (instance.onException)
|
|
1018
|
-
result = instance.onException({
|
|
1640
|
+
result = this.normalizeHttpResponse(instance.onException({
|
|
1019
1641
|
error: ex,
|
|
1020
1642
|
request: this.httpContext.request,
|
|
1021
1643
|
routeInfo: this.routeInfo
|
|
1022
|
-
});
|
|
1644
|
+
}));
|
|
1023
1645
|
} else
|
|
1024
1646
|
result = new HttpException({
|
|
1025
|
-
body:
|
|
1647
|
+
body: { message: ex.message, stack: ex.stack },
|
|
1026
1648
|
status: HttpStatusCode.serverError
|
|
1027
1649
|
}).getResponse();
|
|
1028
1650
|
}
|
|
@@ -1050,14 +1672,17 @@ class RequestHandler extends Resolver {
|
|
|
1050
1672
|
if (onException) {
|
|
1051
1673
|
const instance = this.resolveClass(onException);
|
|
1052
1674
|
if (instance.onException)
|
|
1053
|
-
return instance.onException({
|
|
1675
|
+
return this.normalizeHttpResponse(instance.onException({
|
|
1054
1676
|
error: ex,
|
|
1055
1677
|
request: this.httpContext.request,
|
|
1056
1678
|
routeInfo: this.routeInfo
|
|
1057
|
-
});
|
|
1679
|
+
}));
|
|
1058
1680
|
} else
|
|
1059
1681
|
return new HttpException({
|
|
1060
|
-
body:
|
|
1682
|
+
body: {
|
|
1683
|
+
message: ex?.message,
|
|
1684
|
+
stack: ex?.stack
|
|
1685
|
+
},
|
|
1061
1686
|
status: HttpStatusCode.serverError
|
|
1062
1687
|
});
|
|
1063
1688
|
}
|
|
@@ -1070,46 +1695,59 @@ class HttpHandler {
|
|
|
1070
1695
|
async processRequest(httpContext) {
|
|
1071
1696
|
const requestProcessor = new RequestHandler(httpContext);
|
|
1072
1697
|
const result = await requestProcessor.onRequest();
|
|
1073
|
-
|
|
1698
|
+
if (result instanceof HttpResponse) {
|
|
1699
|
+
return result;
|
|
1700
|
+
}
|
|
1701
|
+
if (result instanceof HttpException) {
|
|
1702
|
+
return result.getResponse();
|
|
1703
|
+
}
|
|
1704
|
+
return new HttpResponse({ body: result });
|
|
1074
1705
|
}
|
|
1075
1706
|
}
|
|
1076
1707
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
}
|
|
1081
|
-
get cookies() {
|
|
1082
|
-
return this.httpRequest.cookies;
|
|
1083
|
-
}
|
|
1084
|
-
get url() {
|
|
1085
|
-
return this.httpRequest.url;
|
|
1086
|
-
}
|
|
1087
|
-
get method() {
|
|
1088
|
-
return this.httpRequest.method;
|
|
1089
|
-
}
|
|
1090
|
-
get headers() {
|
|
1091
|
-
return this.httpRequest.headers;
|
|
1092
|
-
}
|
|
1093
|
-
get user() {
|
|
1094
|
-
return null;
|
|
1095
|
-
}
|
|
1096
|
-
get body() {
|
|
1097
|
-
return this.httpRequest.body;
|
|
1098
|
-
}
|
|
1708
|
+
const STACK_PATH_REGEX = /\bat (?:(?:.+?) \()?(.+):(\d+):(\d+)\)?$/;
|
|
1709
|
+
function normalizeFilePath(filePath) {
|
|
1710
|
+
return path__default.resolve(filePath).replace(/\\/g, "/");
|
|
1099
1711
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1712
|
+
function isInternalRegistrationFrame(filePath) {
|
|
1713
|
+
const normalizedPath = normalizeFilePath(filePath);
|
|
1714
|
+
return normalizedPath.includes("/packages/core/decorators/") || normalizedPath.includes("/packages/core/functions/") || normalizedPath.includes("/packages/core/domain/di/") || normalizedPath.includes("/packages/core/const/") || normalizedPath.includes("/packages/core/dist/") || normalizedPath.includes("/node_modules/@nattyjs/core/dist/");
|
|
1715
|
+
}
|
|
1716
|
+
function getRegistrationSourceFile() {
|
|
1717
|
+
const stack = new Error().stack;
|
|
1718
|
+
return getRegistrationSourceFileFromStack(stack);
|
|
1719
|
+
}
|
|
1720
|
+
function getRegistrationSourceFileFromStack(stack) {
|
|
1721
|
+
if (!stack) {
|
|
1722
|
+
return void 0;
|
|
1723
|
+
}
|
|
1724
|
+
const lines = stack.split("\n").slice(1);
|
|
1725
|
+
for (const line of lines) {
|
|
1726
|
+
const match = line.trim().match(STACK_PATH_REGEX);
|
|
1727
|
+
if (!match) {
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
const filePath = normalizeFilePath(match[1]);
|
|
1731
|
+
if (!isInternalRegistrationFrame(filePath)) {
|
|
1732
|
+
return filePath;
|
|
1733
|
+
}
|
|
1106
1734
|
}
|
|
1735
|
+
return void 0;
|
|
1107
1736
|
}
|
|
1108
1737
|
|
|
1109
1738
|
function injectable(options = {}) {
|
|
1110
1739
|
return (targetConstructor) => {
|
|
1111
|
-
|
|
1740
|
+
const lt = options.lifetime ?? Lifetime.Transient;
|
|
1741
|
+
const sourceFile = getRegistrationSourceFile();
|
|
1742
|
+
if (lt === Lifetime.Singleton)
|
|
1743
|
+
nattyServiceResolver.addSingleton(targetConstructor, void 0, void 0, sourceFile);
|
|
1744
|
+
else if (lt === Lifetime.Scoped)
|
|
1745
|
+
nattyServiceResolver.addScoped(targetConstructor, void 0, void 0, sourceFile);
|
|
1746
|
+
else
|
|
1747
|
+
nattyServiceResolver.addTransient(targetConstructor, void 0, void 0, sourceFile);
|
|
1112
1748
|
common.commonContainer.setMetadata(targetConstructor.name, targetConstructor, "services");
|
|
1749
|
+
if (sourceFile)
|
|
1750
|
+
nattyServiceResolver.trackMetadataKey(sourceFile, targetConstructor.name);
|
|
1113
1751
|
};
|
|
1114
1752
|
}
|
|
1115
1753
|
|
|
@@ -1121,7 +1759,7 @@ function $request(request) {
|
|
|
1121
1759
|
|
|
1122
1760
|
function filter(config) {
|
|
1123
1761
|
return (targetConstructor) => {
|
|
1124
|
-
|
|
1762
|
+
injectable({ lifetime: Lifetime.Transient })(targetConstructor);
|
|
1125
1763
|
};
|
|
1126
1764
|
}
|
|
1127
1765
|
|
|
@@ -1150,63 +1788,257 @@ class BaseController {
|
|
|
1150
1788
|
}
|
|
1151
1789
|
|
|
1152
1790
|
class OkResult extends BaseResult {
|
|
1153
|
-
constructor(value,
|
|
1154
|
-
super(
|
|
1155
|
-
|
|
1791
|
+
constructor(value, extras) {
|
|
1792
|
+
super(
|
|
1793
|
+
{
|
|
1794
|
+
status: HttpStatusCode.success,
|
|
1795
|
+
body: getResponseBodyObject(value ?? common.BLANK)
|
|
1796
|
+
},
|
|
1797
|
+
extras
|
|
1798
|
+
);
|
|
1156
1799
|
}
|
|
1157
1800
|
}
|
|
1158
|
-
function ok(value,
|
|
1159
|
-
return new OkResult(value
|
|
1801
|
+
function ok(value, extras) {
|
|
1802
|
+
return new OkResult(value, extras);
|
|
1160
1803
|
}
|
|
1161
1804
|
|
|
1162
|
-
class
|
|
1163
|
-
constructor(
|
|
1164
|
-
super({
|
|
1805
|
+
class CreatedResult extends BaseResult {
|
|
1806
|
+
constructor(value, extras) {
|
|
1807
|
+
super({ status: HttpStatusCode.created, body: getResponseBodyObject(value ?? common.BLANK) }, extras);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
function created(value, extras) {
|
|
1811
|
+
return new CreatedResult(value, extras);
|
|
1812
|
+
}
|
|
1813
|
+
function createdWith(location, value, extras) {
|
|
1814
|
+
const merged = {
|
|
1815
|
+
...extras ?? {},
|
|
1816
|
+
headers: { ...extras?.headers ?? {}, Location: location }
|
|
1817
|
+
};
|
|
1818
|
+
return new CreatedResult(value, merged);
|
|
1819
|
+
}
|
|
1820
|
+
function createdAt(location, value, extras) {
|
|
1821
|
+
return createdWith(location, value, extras);
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
class AcceptedResult extends BaseResult {
|
|
1825
|
+
constructor(value, extras) {
|
|
1826
|
+
super({ status: HttpStatusCode.accepted, body: getResponseBodyObject(value ?? common.BLANK) }, extras);
|
|
1827
|
+
this.value = value;
|
|
1165
1828
|
}
|
|
1166
1829
|
}
|
|
1167
|
-
function
|
|
1168
|
-
return new
|
|
1830
|
+
function accepted(value, extras) {
|
|
1831
|
+
return new AcceptedResult(value, extras);
|
|
1169
1832
|
}
|
|
1170
1833
|
|
|
1171
1834
|
class NoContentResult extends BaseResult {
|
|
1172
|
-
constructor(
|
|
1173
|
-
super(
|
|
1835
|
+
constructor(extras) {
|
|
1836
|
+
super(
|
|
1837
|
+
{
|
|
1838
|
+
status: HttpStatusCode.noContent,
|
|
1839
|
+
body: void 0
|
|
1840
|
+
},
|
|
1841
|
+
extras
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
function noContent(extras) {
|
|
1846
|
+
return new NoContentResult(extras);
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
class BadRequestResult extends BaseResult {
|
|
1850
|
+
constructor(value, extras) {
|
|
1851
|
+
super({ status: HttpStatusCode.badRequest, body: getResponseBodyObject(value ?? common.BLANK) }, extras);
|
|
1852
|
+
this.value = value;
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
function badRequest(value, extras) {
|
|
1856
|
+
return new BadRequestResult(value, extras);
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
class UnAuthorizedResult extends BaseResult {
|
|
1860
|
+
constructor(value, extras) {
|
|
1861
|
+
super({ status: HttpStatusCode.unAuthorized, body: getResponseBodyObject(value ?? common.BLANK) }, extras);
|
|
1862
|
+
this.value = value;
|
|
1174
1863
|
}
|
|
1175
1864
|
}
|
|
1176
|
-
function
|
|
1177
|
-
return new
|
|
1865
|
+
function unAuthorized(value, extras) {
|
|
1866
|
+
return new UnAuthorizedResult(value, extras);
|
|
1178
1867
|
}
|
|
1179
1868
|
|
|
1180
1869
|
class ForbiddenAccessInfoResult extends BaseResult {
|
|
1181
|
-
constructor(value,
|
|
1182
|
-
super(
|
|
1870
|
+
constructor(value, extras) {
|
|
1871
|
+
super(
|
|
1872
|
+
{
|
|
1873
|
+
status: HttpStatusCode.forbiddenAccess,
|
|
1874
|
+
body: getResponseBodyObject(value ?? common.BLANK)
|
|
1875
|
+
},
|
|
1876
|
+
extras
|
|
1877
|
+
);
|
|
1183
1878
|
}
|
|
1184
1879
|
}
|
|
1185
|
-
function forbiddenAccessInfo(value,
|
|
1186
|
-
return new ForbiddenAccessInfoResult(value,
|
|
1880
|
+
function forbiddenAccessInfo(value, extras) {
|
|
1881
|
+
return new ForbiddenAccessInfoResult(value, extras);
|
|
1882
|
+
}
|
|
1883
|
+
function forbiddenAccess(value, extras) {
|
|
1884
|
+
return new ForbiddenAccessInfoResult(value, extras);
|
|
1187
1885
|
}
|
|
1188
1886
|
|
|
1189
|
-
class
|
|
1190
|
-
constructor(
|
|
1191
|
-
super(
|
|
1887
|
+
class NotFoundResult extends BaseResult {
|
|
1888
|
+
constructor(value, extras) {
|
|
1889
|
+
super(
|
|
1890
|
+
{
|
|
1891
|
+
status: HttpStatusCode.notFound,
|
|
1892
|
+
body: getResponseBodyObject(value ?? common.BLANK)
|
|
1893
|
+
},
|
|
1894
|
+
extras
|
|
1895
|
+
);
|
|
1192
1896
|
}
|
|
1193
1897
|
}
|
|
1194
|
-
function
|
|
1195
|
-
return new
|
|
1898
|
+
function notFound(extras) {
|
|
1899
|
+
return new NotFoundResult(common.BLANK, extras);
|
|
1900
|
+
}
|
|
1901
|
+
function notFoundWith(value, extras) {
|
|
1902
|
+
return new NotFoundResult(value, extras);
|
|
1196
1903
|
}
|
|
1197
1904
|
|
|
1198
|
-
class
|
|
1199
|
-
constructor(value,
|
|
1200
|
-
super({
|
|
1905
|
+
class ConflictResult extends BaseResult {
|
|
1906
|
+
constructor(value, extras) {
|
|
1907
|
+
super({ status: HttpStatusCode.conflict, body: getResponseBodyObject(value ?? common.BLANK) }, extras);
|
|
1201
1908
|
this.value = value;
|
|
1202
1909
|
}
|
|
1203
1910
|
}
|
|
1204
|
-
function
|
|
1205
|
-
return new
|
|
1911
|
+
function conflict(value, extras) {
|
|
1912
|
+
return new ConflictResult(value, extras);
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
class UnprocessableEntityResult extends BaseResult {
|
|
1916
|
+
constructor(value, extras) {
|
|
1917
|
+
super({ status: HttpStatusCode.unprocessableEntity, body: getResponseBodyObject(value ?? common.BLANK) }, extras);
|
|
1918
|
+
this.value = value;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
function unprocessableEntity(value, extras) {
|
|
1922
|
+
return new UnprocessableEntityResult(value, extras);
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
class TooManyRequestsResult extends BaseResult {
|
|
1926
|
+
constructor(value, retryAfterSeconds, extras) {
|
|
1927
|
+
const merged = {
|
|
1928
|
+
...extras ?? {},
|
|
1929
|
+
headers: {
|
|
1930
|
+
...extras?.headers ?? {},
|
|
1931
|
+
...retryAfterSeconds != null ? { "Retry-After": String(retryAfterSeconds) } : {}
|
|
1932
|
+
}
|
|
1933
|
+
};
|
|
1934
|
+
super({ status: HttpStatusCode.tooManyRequests, body: getResponseBodyObject(value ?? common.BLANK) }, merged);
|
|
1935
|
+
this.value = value;
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
function tooManyRequests(value, retryAfterSeconds, extras) {
|
|
1939
|
+
return new TooManyRequestsResult(value, retryAfterSeconds, extras);
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
class RedirectResult extends BaseResult {
|
|
1943
|
+
constructor(location, permanent = false, extras) {
|
|
1944
|
+
const merged = {
|
|
1945
|
+
...extras ?? {},
|
|
1946
|
+
headers: { ...extras?.headers ?? {}, Location: location }
|
|
1947
|
+
};
|
|
1948
|
+
super({ status: permanent ? HttpStatusCode.movedPermanently : HttpStatusCode.found, body: void 0 }, merged);
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
function redirect(location, extras) {
|
|
1952
|
+
return new RedirectResult(location, false, extras);
|
|
1953
|
+
}
|
|
1954
|
+
function redirectPermanent(location, extras) {
|
|
1955
|
+
return new RedirectResult(location, true, extras);
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
class ProblemResult extends BaseResult {
|
|
1959
|
+
constructor(problem2, extras) {
|
|
1960
|
+
const status = problem2.status ?? HttpStatusCode.serverError;
|
|
1961
|
+
const merged = {
|
|
1962
|
+
...extras ?? {},
|
|
1963
|
+
headers: { ...extras?.headers ?? {}, "Content-Type": "application/problem+json; charset=utf-8" }
|
|
1964
|
+
};
|
|
1965
|
+
super({ status, body: { ...problem2, status } }, merged);
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
function problem(problem2, extras) {
|
|
1969
|
+
return new ProblemResult(problem2, extras);
|
|
1970
|
+
}
|
|
1971
|
+
function validationProblem(errors, detail, extras) {
|
|
1972
|
+
return new ProblemResult(
|
|
1973
|
+
{
|
|
1974
|
+
type: "https://tools.ietf.org/html/rfc7231#section-6.5.1",
|
|
1975
|
+
title: "One or more validation errors occurred.",
|
|
1976
|
+
status: HttpStatusCode.badRequest,
|
|
1977
|
+
detail,
|
|
1978
|
+
errors
|
|
1979
|
+
},
|
|
1980
|
+
extras
|
|
1981
|
+
);
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
class FileResult extends BaseResult {
|
|
1985
|
+
constructor(buffer, extras) {
|
|
1986
|
+
super({ status: HttpStatusCode.success, body: buffer, isBuffer: true }, extras);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
function file(buffer, extras) {
|
|
1990
|
+
return new FileResult(buffer, extras);
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
class StatusCodeResult extends BaseResult {
|
|
1994
|
+
constructor(status, value, extras) {
|
|
1995
|
+
super(
|
|
1996
|
+
{
|
|
1997
|
+
status,
|
|
1998
|
+
body: getResponseBodyObject(value ?? common.BLANK)
|
|
1999
|
+
},
|
|
2000
|
+
extras
|
|
2001
|
+
);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
function statusCode(status, value, extras) {
|
|
2005
|
+
return new StatusCodeResult(status, value, extras);
|
|
1206
2006
|
}
|
|
1207
2007
|
|
|
2008
|
+
const Results = {
|
|
2009
|
+
// 2xx
|
|
2010
|
+
ok: (value, extras) => ok(value, extras),
|
|
2011
|
+
created: (value, extras) => created(value, extras),
|
|
2012
|
+
createdWith: (location, value, extras) => createdWith(location, value, extras),
|
|
2013
|
+
createdAt: (location, value, extras) => createdAt(location, value, extras),
|
|
2014
|
+
accepted: (value, extras) => accepted(value, extras),
|
|
2015
|
+
noContent: (extras) => noContent(extras),
|
|
2016
|
+
file: (buffer, extras) => file(buffer, extras),
|
|
2017
|
+
statusCode: (status, value, extras) => statusCode(status, value, extras),
|
|
2018
|
+
// 4xx
|
|
2019
|
+
badRequest: (value, extras) => badRequest(value, extras),
|
|
2020
|
+
notFound: (extras) => notFound(extras),
|
|
2021
|
+
notFoundWith: (value, extras) => notFoundWith(value, extras),
|
|
2022
|
+
unAuthorized: (value, extras) => unAuthorized(value, extras),
|
|
2023
|
+
forbid: (value, extras) => forbiddenAccess(value, extras),
|
|
2024
|
+
conflict: (value, extras) => conflict(value, extras),
|
|
2025
|
+
unprocessableEntity: (value, extras) => unprocessableEntity(value, extras),
|
|
2026
|
+
tooManyRequests: (value, retryAfterSeconds, extras) => tooManyRequests(value, retryAfterSeconds, extras),
|
|
2027
|
+
// 3xx
|
|
2028
|
+
redirect: (location, extras) => redirect(location, extras),
|
|
2029
|
+
redirectPermanent: (location, extras) => redirectPermanent(location, extras),
|
|
2030
|
+
// problem
|
|
2031
|
+
problem: (p, extras) => problem(p, extras),
|
|
2032
|
+
validationProblem: (errors, detail, extras) => validationProblem(errors, detail, extras)
|
|
2033
|
+
};
|
|
2034
|
+
|
|
1208
2035
|
function base(params, type, additionaConfig) {
|
|
1209
|
-
decoratorStateContainer.register(
|
|
2036
|
+
decoratorStateContainer.register(
|
|
2037
|
+
params,
|
|
2038
|
+
type,
|
|
2039
|
+
additionaConfig,
|
|
2040
|
+
getRegistrationSourceFile()
|
|
2041
|
+
);
|
|
1210
2042
|
}
|
|
1211
2043
|
|
|
1212
2044
|
function useFilter(config) {
|
|
@@ -1231,42 +2063,205 @@ function authenticationOnly() {
|
|
|
1231
2063
|
};
|
|
1232
2064
|
}
|
|
1233
2065
|
|
|
2066
|
+
function onException(exceptionFilter) {
|
|
2067
|
+
return function(target, propertyKey, descriptor) {
|
|
2068
|
+
base({ target, propertyKey, descriptor }, DecoratorType.onException, exceptionFilter);
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
function setEnvInfo(envTsDefinition, envValueInfo) {
|
|
2073
|
+
if (envTsDefinition && envValueInfo) {
|
|
2074
|
+
common.commonContainer.setEnvTsDefinition(envTsDefinition);
|
|
2075
|
+
Object.keys(envValueInfo).forEach((key) => {
|
|
2076
|
+
if (envValueInfo[key])
|
|
2077
|
+
process.env[key] = envValueInfo[key];
|
|
2078
|
+
});
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
function authorize(permission) {
|
|
2083
|
+
return function(target, propertyKey, descriptor) {
|
|
2084
|
+
base({
|
|
2085
|
+
target,
|
|
2086
|
+
propertyKey,
|
|
2087
|
+
descriptor
|
|
2088
|
+
}, DecoratorType.authorize, permission);
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
function scoped(token) {
|
|
2093
|
+
return injectable({ lifetime: Lifetime.Scoped, token });
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
function transient(token) {
|
|
2097
|
+
return injectable({ lifetime: Lifetime.Transient, token });
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
function singleton(token) {
|
|
2101
|
+
return injectable({ lifetime: Lifetime.Singleton, token });
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
function getTokenTypeName(token) {
|
|
2105
|
+
if (typeof token !== "symbol") {
|
|
2106
|
+
return void 0;
|
|
2107
|
+
}
|
|
2108
|
+
const key = Symbol.keyFor(token);
|
|
2109
|
+
if (!key) {
|
|
2110
|
+
return void 0;
|
|
2111
|
+
}
|
|
2112
|
+
const separatorIndex = key.lastIndexOf("#");
|
|
2113
|
+
if (separatorIndex < 0 || separatorIndex === key.length - 1) {
|
|
2114
|
+
return void 0;
|
|
2115
|
+
}
|
|
2116
|
+
return key.slice(separatorIndex + 1);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
function registerLifetime(targetConstructor, sourceFile, lifetime) {
|
|
2120
|
+
if (lifetime === Lifetime.Singleton) {
|
|
2121
|
+
nattyServiceResolver.addSingleton(targetConstructor, void 0, void 0, sourceFile);
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
if (lifetime === Lifetime.Scoped) {
|
|
2125
|
+
nattyServiceResolver.addScoped(targetConstructor, void 0, void 0, sourceFile);
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
if (lifetime === Lifetime.Transient) {
|
|
2129
|
+
nattyServiceResolver.addTransient(targetConstructor, void 0, void 0, sourceFile);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
function registerAliasTypeName(token, sourceFile) {
|
|
2133
|
+
const typeName = getTokenTypeName(token);
|
|
2134
|
+
if (typeName) {
|
|
2135
|
+
common.commonContainer.setMetadata(typeName, token, "services");
|
|
2136
|
+
if (sourceFile)
|
|
2137
|
+
nattyServiceResolver.trackMetadataKey(sourceFile, typeName);
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
function registerDiToken(targetConstructor, token, options = {}) {
|
|
2141
|
+
const sourceFile = getRegistrationSourceFile();
|
|
2142
|
+
common.commonContainer.setMetadata(targetConstructor.name, targetConstructor, "services");
|
|
2143
|
+
if (sourceFile)
|
|
2144
|
+
nattyServiceResolver.trackMetadataKey(sourceFile, targetConstructor.name);
|
|
2145
|
+
registerAliasTypeName(token, sourceFile);
|
|
2146
|
+
registerLifetime(targetConstructor, sourceFile, options.lifetime);
|
|
2147
|
+
nattyServiceResolver.addTransient(
|
|
2148
|
+
token,
|
|
2149
|
+
void 0,
|
|
2150
|
+
(serviceProvider) => serviceProvider.get(targetConstructor),
|
|
2151
|
+
sourceFile
|
|
2152
|
+
);
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
function di(token, options = {}) {
|
|
2156
|
+
return (targetConstructor) => {
|
|
2157
|
+
registerDiToken(targetConstructor, token, options);
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
function createServiceScope() {
|
|
2162
|
+
return nattyServiceResolver.createScope();
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
function clearHotReloadRegistrations(files) {
|
|
2166
|
+
for (const filePath of files || []) {
|
|
2167
|
+
const result = nattyServiceResolver.clearRegistrationsFromSource(filePath);
|
|
2168
|
+
decoratorStateContainer.clearFromSource(filePath);
|
|
2169
|
+
for (const metadataKey of result.metadataKeys) {
|
|
2170
|
+
common.commonContainer.deleteMetadataValue(metadataKey, "services");
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
function clearHotReloadControllerMetadata(controllerNames) {
|
|
2176
|
+
decoratorStateContainer.clearControllers(controllerNames || []);
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
function replaceRoutes(manifest) {
|
|
2180
|
+
nattyContainer.replaceRoutes(manifest);
|
|
2181
|
+
}
|
|
2182
|
+
|
|
1234
2183
|
exports.$request = $request;
|
|
1235
2184
|
exports.AbstractModelState = AbstractModelState;
|
|
2185
|
+
exports.AcceptedException = AcceptedException;
|
|
2186
|
+
exports.AcceptedResult = AcceptedResult;
|
|
1236
2187
|
exports.BadRequestResult = BadRequestResult;
|
|
1237
2188
|
exports.BaseController = BaseController;
|
|
2189
|
+
exports.BaseResult = BaseResult;
|
|
2190
|
+
exports.ConflictResult = ConflictResult;
|
|
2191
|
+
exports.CreateProblemDetail = CreateProblemDetail;
|
|
1238
2192
|
exports.CreatedResult = CreatedResult;
|
|
1239
2193
|
exports.Delete = Delete;
|
|
2194
|
+
exports.FileResult = FileResult;
|
|
1240
2195
|
exports.ForbiddenAccessException = ForbiddenAccessException;
|
|
1241
2196
|
exports.ForbiddenAccessInfoResult = ForbiddenAccessInfoResult;
|
|
1242
2197
|
exports.HttpBadRequestException = HttpBadRequestException;
|
|
2198
|
+
exports.HttpConflictException = HttpConflictException;
|
|
1243
2199
|
exports.HttpContext = HttpContext;
|
|
1244
2200
|
exports.HttpException = HttpException;
|
|
1245
2201
|
exports.HttpHandler = HttpHandler;
|
|
1246
2202
|
exports.HttpNotFoundException = HttpNotFoundException;
|
|
1247
2203
|
exports.HttpResponse = HttpResponse;
|
|
2204
|
+
exports.HttpStatusCode = HttpStatusCode;
|
|
2205
|
+
exports.HttpUnprocessableEntityException = HttpUnprocessableEntityException;
|
|
2206
|
+
exports.Lifetime = Lifetime;
|
|
1248
2207
|
exports.ModelBindingContext = ModelBindingContext;
|
|
1249
2208
|
exports.NoContentResult = NoContentResult;
|
|
1250
2209
|
exports.NotFoundResult = NotFoundResult;
|
|
1251
2210
|
exports.OkResult = OkResult;
|
|
2211
|
+
exports.ProblemDetailsException = ProblemDetailsException;
|
|
2212
|
+
exports.ProblemResult = ProblemResult;
|
|
2213
|
+
exports.RedirectException = RedirectException;
|
|
2214
|
+
exports.RedirectPermanentException = RedirectPermanentException;
|
|
2215
|
+
exports.RedirectResult = RedirectResult;
|
|
2216
|
+
exports.Results = Results;
|
|
1252
2217
|
exports.RunOn = RunOn;
|
|
2218
|
+
exports.TooManyRequestsException = TooManyRequestsException;
|
|
2219
|
+
exports.TooManyRequestsResult = TooManyRequestsResult;
|
|
2220
|
+
exports.UnAuthorizedResult = UnAuthorizedResult;
|
|
1253
2221
|
exports.UnauthorizedAccessException = UnauthorizedAccessException;
|
|
2222
|
+
exports.UnprocessableEntityResult = UnprocessableEntityResult;
|
|
2223
|
+
exports.ValidationProblemDetailsException = ValidationProblemDetailsException;
|
|
2224
|
+
exports.accepted = accepted;
|
|
1254
2225
|
exports.anonymous = anonymous;
|
|
1255
2226
|
exports.authenticationOnly = authenticationOnly;
|
|
2227
|
+
exports.authorize = authorize;
|
|
1256
2228
|
exports.badRequest = badRequest;
|
|
2229
|
+
exports.clearHotReloadControllerMetadata = clearHotReloadControllerMetadata;
|
|
2230
|
+
exports.clearHotReloadRegistrations = clearHotReloadRegistrations;
|
|
2231
|
+
exports.conflict = conflict;
|
|
2232
|
+
exports.createServiceScope = createServiceScope;
|
|
1257
2233
|
exports.created = created;
|
|
2234
|
+
exports.createdAt = createdAt;
|
|
2235
|
+
exports.createdWith = createdWith;
|
|
1258
2236
|
exports.defineNattyConfig = defineNattyConfig;
|
|
2237
|
+
exports.di = di;
|
|
1259
2238
|
exports.entityContainer = entityContainer;
|
|
2239
|
+
exports.file = file;
|
|
1260
2240
|
exports.filter = filter;
|
|
2241
|
+
exports.forbiddenAccess = forbiddenAccess;
|
|
1261
2242
|
exports.forbiddenAccessInfo = forbiddenAccessInfo;
|
|
1262
2243
|
exports.get = get;
|
|
1263
2244
|
exports.init = init;
|
|
1264
2245
|
exports.injectable = injectable;
|
|
1265
2246
|
exports.noContent = noContent;
|
|
1266
2247
|
exports.notFound = notFound;
|
|
2248
|
+
exports.notFoundWith = notFoundWith;
|
|
1267
2249
|
exports.ok = ok;
|
|
2250
|
+
exports.onException = onException;
|
|
1268
2251
|
exports.post = post;
|
|
2252
|
+
exports.problem = problem;
|
|
1269
2253
|
exports.put = put;
|
|
2254
|
+
exports.redirect = redirect;
|
|
2255
|
+
exports.redirectPermanent = redirectPermanent;
|
|
1270
2256
|
exports.registerDecorator = registerDecorator;
|
|
2257
|
+
exports.replaceRoutes = replaceRoutes;
|
|
1271
2258
|
exports.route = route;
|
|
2259
|
+
exports.scoped = scoped;
|
|
2260
|
+
exports.setEnvInfo = setEnvInfo;
|
|
2261
|
+
exports.singleton = singleton;
|
|
2262
|
+
exports.tooManyRequests = tooManyRequests;
|
|
2263
|
+
exports.transient = transient;
|
|
2264
|
+
exports.unAuthorized = unAuthorized;
|
|
2265
|
+
exports.unprocessableEntity = unprocessableEntity;
|
|
1272
2266
|
exports.useFilter = useFilter;
|
|
2267
|
+
exports.validationProblem = validationProblem;
|