@nattyjs/core 0.0.1-beta.63 → 0.0.1-beta.65
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 +397 -64
- package/dist/index.d.ts +109 -83
- package/dist/index.mjs +388 -66
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
const common = require('@nattyjs/common');
|
|
4
4
|
const pathToRegexp = require('path-to-regexp');
|
|
5
|
+
const path = require('node:path');
|
|
5
6
|
require('reflect-metadata');
|
|
6
7
|
|
|
8
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
9
|
+
|
|
10
|
+
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
11
|
+
|
|
7
12
|
function defineNattyConfig(config) {
|
|
8
13
|
return config;
|
|
9
14
|
}
|
|
@@ -54,6 +59,7 @@ function Delete() {
|
|
|
54
59
|
};
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
const HTTP_METHODS = ["get", "post", "put", "delete"];
|
|
57
63
|
const _StaticContainer = class {
|
|
58
64
|
setup(types) {
|
|
59
65
|
_StaticContainer.types = types;
|
|
@@ -65,14 +71,56 @@ const nattyContainer = new class {
|
|
|
65
71
|
constructor() {
|
|
66
72
|
this.container = /* @__PURE__ */ new Map();
|
|
67
73
|
this.containerState = /* @__PURE__ */ new Map();
|
|
74
|
+
this.compiledRoutes = {};
|
|
68
75
|
}
|
|
69
76
|
get types() {
|
|
70
77
|
return common.commonContainer.types;
|
|
71
78
|
}
|
|
72
79
|
setup(config, routes, resolver) {
|
|
73
80
|
this.config = config;
|
|
74
|
-
this.routes = routes;
|
|
75
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) {
|
|
90
|
+
this.routes = routes;
|
|
91
|
+
this.compiledRoutes = this.createCompiledRoutes(routes);
|
|
92
|
+
}
|
|
93
|
+
createCompiledRoutes(routes) {
|
|
94
|
+
const compiledRoutes = {};
|
|
95
|
+
for (const method of HTTP_METHODS)
|
|
96
|
+
compiledRoutes[method] = [];
|
|
97
|
+
for (const [rootPath, routeConfig] of Object.entries(routes)) {
|
|
98
|
+
for (const method of HTTP_METHODS) {
|
|
99
|
+
const childRoutes = routeConfig[method];
|
|
100
|
+
if (!childRoutes)
|
|
101
|
+
continue;
|
|
102
|
+
for (const [childRoutePath, routeInfo] of Object.entries(childRoutes)) {
|
|
103
|
+
const childPath = this.normalizeChildPath(childRoutePath);
|
|
104
|
+
const configuredRoutePath = `${rootPath}${childPath}`;
|
|
105
|
+
compiledRoutes[method].push({
|
|
106
|
+
requestMethod: method,
|
|
107
|
+
configuredRoutePath,
|
|
108
|
+
matcher: pathToRegexp.match(configuredRoutePath, { decode: decodeURIComponent }),
|
|
109
|
+
routeConfig,
|
|
110
|
+
methodInfo: routeInfo
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return compiledRoutes;
|
|
116
|
+
}
|
|
117
|
+
normalizeChildPath(childRoutePath) {
|
|
118
|
+
if (childRoutePath.indexOf("/") === 0)
|
|
119
|
+
return childRoutePath === "/" ? BLANK : childRoutePath;
|
|
120
|
+
return `/${childRoutePath}`;
|
|
121
|
+
}
|
|
122
|
+
getCompiledRoutes(method) {
|
|
123
|
+
return this.compiledRoutes[method] || [];
|
|
76
124
|
}
|
|
77
125
|
getTypes() {
|
|
78
126
|
return StaticContainer.types;
|
|
@@ -145,13 +193,28 @@ async function startWebSchedule(config) {
|
|
|
145
193
|
function init(config, appConfig) {
|
|
146
194
|
common.commonContainer.setupConfig(config);
|
|
147
195
|
common.commonContainer.setEnvTsDefinition(appConfig.envTsDefinition);
|
|
148
|
-
|
|
196
|
+
setupLegacyTypes(appConfig.types);
|
|
197
|
+
nattyContainer.setup(config, appConfig.routes, appConfig.resolver || defaultResolver);
|
|
149
198
|
callLifeCycleEvents(config, true);
|
|
150
199
|
const result = initializeModule(config);
|
|
151
200
|
callLifeCycleEvents(config);
|
|
152
201
|
startWebSchedules(config.webSchedules);
|
|
153
202
|
return result;
|
|
154
203
|
}
|
|
204
|
+
function setupLegacyTypes(types) {
|
|
205
|
+
if (types) {
|
|
206
|
+
common.commonContainer.types = {};
|
|
207
|
+
for (const [name, type] of Object.entries(types))
|
|
208
|
+
common.commonContainer.registerType({ name, ...type });
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function defaultResolver(path) {
|
|
212
|
+
if (typeof path === "function")
|
|
213
|
+
return path();
|
|
214
|
+
if (typeof path === "string")
|
|
215
|
+
return require(path);
|
|
216
|
+
return {};
|
|
217
|
+
}
|
|
155
218
|
function initializeModule(config) {
|
|
156
219
|
if (config.app) {
|
|
157
220
|
return config.app.init(config);
|
|
@@ -833,8 +896,8 @@ class RouteParser extends ParameterTypeConverter {
|
|
|
833
896
|
get httpMethod() {
|
|
834
897
|
return this.httpContext.request.method.toLowerCase();
|
|
835
898
|
}
|
|
836
|
-
get
|
|
837
|
-
return nattyContainer.
|
|
899
|
+
get compiledRoutes() {
|
|
900
|
+
return nattyContainer.getCompiledRoutes(this.httpMethod);
|
|
838
901
|
}
|
|
839
902
|
init() {
|
|
840
903
|
const isMatched = this.matchRoute();
|
|
@@ -847,47 +910,38 @@ class RouteParser extends ParameterTypeConverter {
|
|
|
847
910
|
return controllerInfo[name];
|
|
848
911
|
}
|
|
849
912
|
matchRoute() {
|
|
850
|
-
|
|
851
|
-
const requestPathname = this.getRequestPathname();
|
|
852
|
-
for (const
|
|
853
|
-
const
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
this.routeInfo = {
|
|
866
|
-
path: `${common.commonContainer.nattyConfig.api.rootPath}/${requestPathname}`,
|
|
867
|
-
configuredRoutePath: `${common.commonContainer.nattyConfig.api.rootPath}/${configuredRoutePath}`,
|
|
868
|
-
controller: this.getController(routeConfig),
|
|
869
|
-
parameters: routeConfig.parameters,
|
|
870
|
-
methodInfo,
|
|
871
|
-
params: this.convert(methodInfo, matched.params),
|
|
872
|
-
queryParams: this.getQueryParams()
|
|
873
|
-
};
|
|
874
|
-
break;
|
|
875
|
-
}
|
|
876
|
-
}
|
|
913
|
+
const requestUrl = this.getRequestUrl();
|
|
914
|
+
const requestPathname = this.getRequestPathname(requestUrl);
|
|
915
|
+
for (const route of this.compiledRoutes) {
|
|
916
|
+
const matched = route.matcher(requestPathname);
|
|
917
|
+
if (matched) {
|
|
918
|
+
this.routeInfo = {
|
|
919
|
+
path: `${common.commonContainer.nattyConfig.api.rootPath}/${requestPathname}`,
|
|
920
|
+
configuredRoutePath: `${common.commonContainer.nattyConfig.api.rootPath}/${route.configuredRoutePath}`,
|
|
921
|
+
controller: this.getController(route.routeConfig),
|
|
922
|
+
parameters: route.routeConfig.parameters,
|
|
923
|
+
methodInfo: route.methodInfo,
|
|
924
|
+
params: this.convert(route.methodInfo, matched.params),
|
|
925
|
+
queryParams: this.getQueryParams(requestUrl)
|
|
926
|
+
};
|
|
927
|
+
return true;
|
|
877
928
|
}
|
|
878
929
|
}
|
|
879
|
-
return
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
932
|
+
getRequestUrl() {
|
|
933
|
+
if (!this.parsedRequestUrl)
|
|
934
|
+
this.parsedRequestUrl = new URL(this.httpContext.request.url);
|
|
935
|
+
return this.parsedRequestUrl;
|
|
880
936
|
}
|
|
881
|
-
getRequestPathname() {
|
|
937
|
+
getRequestPathname(url) {
|
|
882
938
|
const apiRootPath = common.commonContainer.nattyConfig.api.rootPath;
|
|
883
|
-
const url = new URL(this.httpContext.request.url);
|
|
884
939
|
let splitUrl = url.pathname.split(`${apiRootPath}/`);
|
|
885
940
|
if (splitUrl.length > 1)
|
|
886
941
|
return splitUrl[1];
|
|
887
942
|
return url.pathname;
|
|
888
943
|
}
|
|
889
|
-
getQueryParams() {
|
|
890
|
-
const url = new URL(this.httpContext.request.url);
|
|
944
|
+
getQueryParams(url) {
|
|
891
945
|
const queryParams = {};
|
|
892
946
|
for (const param of url.searchParams.keys())
|
|
893
947
|
queryParams[param] = url.searchParams.get(param);
|
|
@@ -898,8 +952,10 @@ class RouteParser extends ParameterTypeConverter {
|
|
|
898
952
|
const decoratorStateContainer = new class {
|
|
899
953
|
constructor() {
|
|
900
954
|
this.controllerConfig = {};
|
|
955
|
+
this.controllerSources = /* @__PURE__ */ new Map();
|
|
956
|
+
this.sourceControllers = /* @__PURE__ */ new Map();
|
|
901
957
|
}
|
|
902
|
-
register(params, type, additionalConfig) {
|
|
958
|
+
register(params, type, additionalConfig, sourceFile) {
|
|
903
959
|
const name = params.target.name || params.target.constructor.name;
|
|
904
960
|
let controllerInfo = this.controllerConfig[name] || null;
|
|
905
961
|
let controllerMethodInfo = null;
|
|
@@ -912,6 +968,9 @@ const decoratorStateContainer = new class {
|
|
|
912
968
|
controllerMethodInfo[type] = additionalConfig;
|
|
913
969
|
} else
|
|
914
970
|
controllerInfo.config[type] = additionalConfig;
|
|
971
|
+
if (sourceFile) {
|
|
972
|
+
this.trackControllerSource(name, sourceFile);
|
|
973
|
+
}
|
|
915
974
|
}
|
|
916
975
|
getInfo(controllerName, methodName, type) {
|
|
917
976
|
const controllerInfo = this.controllerConfig[controllerName];
|
|
@@ -924,6 +983,55 @@ const decoratorStateContainer = new class {
|
|
|
924
983
|
methodConfig = methodInfo[type];
|
|
925
984
|
return { controllerConfig, methodConfig };
|
|
926
985
|
}
|
|
986
|
+
clearFromSource(sourceFile) {
|
|
987
|
+
const normalizedSourceFile = this.normalizeFilePath(sourceFile);
|
|
988
|
+
const controllerNames = Array.from(
|
|
989
|
+
this.sourceControllers.get(normalizedSourceFile) || []
|
|
990
|
+
);
|
|
991
|
+
this.clearControllers(controllerNames);
|
|
992
|
+
this.sourceControllers.delete(normalizedSourceFile);
|
|
993
|
+
return controllerNames;
|
|
994
|
+
}
|
|
995
|
+
clearControllers(controllerNames) {
|
|
996
|
+
const removedControllers = [];
|
|
997
|
+
for (const controllerName of controllerNames) {
|
|
998
|
+
const previousSource = this.controllerSources.get(controllerName);
|
|
999
|
+
delete this.controllerConfig[controllerName];
|
|
1000
|
+
this.controllerSources.delete(controllerName);
|
|
1001
|
+
removedControllers.push(controllerName);
|
|
1002
|
+
if (previousSource) {
|
|
1003
|
+
const controllers = this.sourceControllers.get(previousSource);
|
|
1004
|
+
controllers?.delete(controllerName);
|
|
1005
|
+
if (controllers && controllers.size === 0) {
|
|
1006
|
+
this.sourceControllers.delete(previousSource);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
return removedControllers;
|
|
1011
|
+
}
|
|
1012
|
+
reset() {
|
|
1013
|
+
this.controllerConfig = {};
|
|
1014
|
+
this.controllerSources.clear();
|
|
1015
|
+
this.sourceControllers.clear();
|
|
1016
|
+
}
|
|
1017
|
+
trackControllerSource(controllerName, sourceFile) {
|
|
1018
|
+
const normalizedSourceFile = this.normalizeFilePath(sourceFile);
|
|
1019
|
+
const previousSource = this.controllerSources.get(controllerName);
|
|
1020
|
+
if (previousSource && previousSource !== normalizedSourceFile) {
|
|
1021
|
+
this.sourceControllers.get(previousSource)?.delete(controllerName);
|
|
1022
|
+
if (this.sourceControllers.get(previousSource)?.size === 0) {
|
|
1023
|
+
this.sourceControllers.delete(previousSource);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
this.controllerSources.set(controllerName, normalizedSourceFile);
|
|
1027
|
+
if (!this.sourceControllers.has(normalizedSourceFile)) {
|
|
1028
|
+
this.sourceControllers.set(normalizedSourceFile, /* @__PURE__ */ new Set());
|
|
1029
|
+
}
|
|
1030
|
+
this.sourceControllers.get(normalizedSourceFile)?.add(controllerName);
|
|
1031
|
+
}
|
|
1032
|
+
normalizeFilePath(filePath) {
|
|
1033
|
+
return path__default.resolve(filePath).replace(/\\/g, "/");
|
|
1034
|
+
}
|
|
927
1035
|
}();
|
|
928
1036
|
|
|
929
1037
|
var DecoratorType = /* @__PURE__ */ ((DecoratorType2) => {
|
|
@@ -1016,11 +1124,12 @@ function getTypeName(typeName) {
|
|
|
1016
1124
|
}
|
|
1017
1125
|
|
|
1018
1126
|
class ModelBindingContext extends ParameterTypeConverter {
|
|
1019
|
-
constructor(type, typeInfo, data) {
|
|
1127
|
+
constructor(type, typeInfo, data, throwOnValidationError = false) {
|
|
1020
1128
|
super();
|
|
1021
1129
|
this.type = type;
|
|
1022
1130
|
this.typeInfo = typeInfo;
|
|
1023
1131
|
this.data = data;
|
|
1132
|
+
this.throwOnValidationError = throwOnValidationError;
|
|
1024
1133
|
this.serialize();
|
|
1025
1134
|
}
|
|
1026
1135
|
serialize() {
|
|
@@ -1030,7 +1139,7 @@ class ModelBindingContext extends ParameterTypeConverter {
|
|
|
1030
1139
|
else
|
|
1031
1140
|
this.data = body;
|
|
1032
1141
|
this.instance = this.convertToInstance(this.type, this.data);
|
|
1033
|
-
if (!this.isValid)
|
|
1142
|
+
if (this.throwOnValidationError && !this.isValid)
|
|
1034
1143
|
throw new HttpBadRequestException(CreateProblemDetail(this.type, this.errors));
|
|
1035
1144
|
}
|
|
1036
1145
|
get isValid() {
|
|
@@ -1091,8 +1200,11 @@ class RequestProcessor extends RouteParser {
|
|
|
1091
1200
|
const authentication = this.getAuthenticationClass();
|
|
1092
1201
|
const authenticationFilter = authentication ? this.resolveFilter(authentication) : void 0;
|
|
1093
1202
|
const anonymousInfo = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.anonymous);
|
|
1094
|
-
if (!
|
|
1095
|
-
|
|
1203
|
+
if (!authenticationFilter) {
|
|
1204
|
+
if (common.commonContainer.nattyConfig?.secure?.denyByDefault && !anonymousInfo.controllerConfig && !anonymousInfo.methodConfig)
|
|
1205
|
+
throw new UnauthorizedAccessException(DENY_BY_DEFAULT);
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1096
1208
|
if (authenticationFilter) {
|
|
1097
1209
|
const result = await authenticationFilter.onAuthentication(this.httpContext);
|
|
1098
1210
|
this.httpContext.user = result;
|
|
@@ -1112,7 +1224,7 @@ class RequestProcessor extends RouteParser {
|
|
|
1112
1224
|
this.routeInfo,
|
|
1113
1225
|
authorizeConfig.methodConfig || authorizeConfig.controllerConfig
|
|
1114
1226
|
);
|
|
1115
|
-
const result = await authorizationFilter.onAuthorization(authorizationContext);
|
|
1227
|
+
const result = await authorizationFilter.onAuthorization(authorizationContext, authorizationContext.config);
|
|
1116
1228
|
if (!result)
|
|
1117
1229
|
throw new ForbiddenAccessException(authorizationFilter.onFailedAuthorization());
|
|
1118
1230
|
}
|
|
@@ -1220,25 +1332,47 @@ class NattyScope {
|
|
|
1220
1332
|
}
|
|
1221
1333
|
}
|
|
1222
1334
|
|
|
1335
|
+
function normalizeFilePath$1(filePath) {
|
|
1336
|
+
return path__default.resolve(filePath).replace(/\\/g, "/");
|
|
1337
|
+
}
|
|
1223
1338
|
class NattyContainer {
|
|
1224
1339
|
constructor() {
|
|
1225
1340
|
this.regs = /* @__PURE__ */ new Map();
|
|
1226
1341
|
this.singletons = /* @__PURE__ */ new Map();
|
|
1342
|
+
this.tokenSources = /* @__PURE__ */ new Map();
|
|
1343
|
+
this.sourceTokens = /* @__PURE__ */ new Map();
|
|
1344
|
+
this.metadataKeySources = /* @__PURE__ */ new Map();
|
|
1345
|
+
this.sourceMetadataKeys = /* @__PURE__ */ new Map();
|
|
1227
1346
|
}
|
|
1228
|
-
register(token, desc) {
|
|
1347
|
+
register(token, desc, sourceFile) {
|
|
1229
1348
|
this.regs.set(token, desc);
|
|
1349
|
+
if (sourceFile) {
|
|
1350
|
+
this.trackTokenSource(token, sourceFile);
|
|
1351
|
+
}
|
|
1230
1352
|
}
|
|
1231
|
-
addTransient(token, useClass, useFactory) {
|
|
1232
|
-
this.register(
|
|
1353
|
+
addTransient(token, useClass, useFactory, sourceFile) {
|
|
1354
|
+
this.register(
|
|
1355
|
+
token,
|
|
1356
|
+
{ lifetime: Lifetime.Transient, useClass: useClass ?? token, useFactory },
|
|
1357
|
+
sourceFile
|
|
1358
|
+
);
|
|
1233
1359
|
}
|
|
1234
|
-
addScoped(token, useClass, useFactory) {
|
|
1235
|
-
this.register(
|
|
1360
|
+
addScoped(token, useClass, useFactory, sourceFile) {
|
|
1361
|
+
this.register(
|
|
1362
|
+
token,
|
|
1363
|
+
{ lifetime: Lifetime.Scoped, useClass: useClass ?? token, useFactory },
|
|
1364
|
+
sourceFile
|
|
1365
|
+
);
|
|
1236
1366
|
}
|
|
1237
|
-
addSingleton(token, useClass, useFactory) {
|
|
1238
|
-
this.register(
|
|
1367
|
+
addSingleton(token, useClass, useFactory, sourceFile) {
|
|
1368
|
+
this.register(
|
|
1369
|
+
token,
|
|
1370
|
+
{ lifetime: Lifetime.Singleton, useClass: useClass ?? token, useFactory },
|
|
1371
|
+
sourceFile
|
|
1372
|
+
);
|
|
1239
1373
|
}
|
|
1240
|
-
addInstance(token, value) {
|
|
1241
|
-
this.register(token, { lifetime: Lifetime.Singleton, useValue: value });
|
|
1374
|
+
addInstance(token, value, sourceFile) {
|
|
1375
|
+
this.register(token, { lifetime: Lifetime.Singleton, useValue: value }, sourceFile);
|
|
1242
1376
|
this.singletons.set(token, value);
|
|
1243
1377
|
}
|
|
1244
1378
|
createScope() {
|
|
@@ -1283,6 +1417,57 @@ class NattyContainer {
|
|
|
1283
1417
|
_getDescriptor(token) {
|
|
1284
1418
|
return this.regs.get(token);
|
|
1285
1419
|
}
|
|
1420
|
+
trackMetadataKey(sourceFile, key) {
|
|
1421
|
+
const normalizedSourceFile = normalizeFilePath$1(sourceFile);
|
|
1422
|
+
const previousSource = this.metadataKeySources.get(key);
|
|
1423
|
+
if (previousSource && previousSource !== normalizedSourceFile) {
|
|
1424
|
+
this.sourceMetadataKeys.get(previousSource)?.delete(key);
|
|
1425
|
+
if (this.sourceMetadataKeys.get(previousSource)?.size === 0) {
|
|
1426
|
+
this.sourceMetadataKeys.delete(previousSource);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
this.metadataKeySources.set(key, normalizedSourceFile);
|
|
1430
|
+
if (!this.sourceMetadataKeys.has(normalizedSourceFile)) {
|
|
1431
|
+
this.sourceMetadataKeys.set(normalizedSourceFile, /* @__PURE__ */ new Set());
|
|
1432
|
+
}
|
|
1433
|
+
this.sourceMetadataKeys.get(normalizedSourceFile)?.add(key);
|
|
1434
|
+
}
|
|
1435
|
+
clearRegistrationsFromSource(sourceFile) {
|
|
1436
|
+
const normalizedSourceFile = normalizeFilePath$1(sourceFile);
|
|
1437
|
+
const tokens = Array.from(this.sourceTokens.get(normalizedSourceFile) || []);
|
|
1438
|
+
const metadataKeys = Array.from(
|
|
1439
|
+
this.sourceMetadataKeys.get(normalizedSourceFile) || []
|
|
1440
|
+
);
|
|
1441
|
+
for (const token of tokens) {
|
|
1442
|
+
this.regs.delete(token);
|
|
1443
|
+
this.singletons.delete(token);
|
|
1444
|
+
this.tokenSources.delete(token);
|
|
1445
|
+
}
|
|
1446
|
+
for (const metadataKey of metadataKeys) {
|
|
1447
|
+
this.metadataKeySources.delete(metadataKey);
|
|
1448
|
+
}
|
|
1449
|
+
this.sourceTokens.delete(normalizedSourceFile);
|
|
1450
|
+
this.sourceMetadataKeys.delete(normalizedSourceFile);
|
|
1451
|
+
return {
|
|
1452
|
+
metadataKeys,
|
|
1453
|
+
tokens
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
trackTokenSource(token, sourceFile) {
|
|
1457
|
+
const normalizedSourceFile = normalizeFilePath$1(sourceFile);
|
|
1458
|
+
const previousSource = this.tokenSources.get(token);
|
|
1459
|
+
if (previousSource && previousSource !== normalizedSourceFile) {
|
|
1460
|
+
this.sourceTokens.get(previousSource)?.delete(token);
|
|
1461
|
+
if (this.sourceTokens.get(previousSource)?.size === 0) {
|
|
1462
|
+
this.sourceTokens.delete(previousSource);
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
this.tokenSources.set(token, normalizedSourceFile);
|
|
1466
|
+
if (!this.sourceTokens.has(normalizedSourceFile)) {
|
|
1467
|
+
this.sourceTokens.set(normalizedSourceFile, /* @__PURE__ */ new Set());
|
|
1468
|
+
}
|
|
1469
|
+
this.sourceTokens.get(normalizedSourceFile)?.add(token);
|
|
1470
|
+
}
|
|
1286
1471
|
}
|
|
1287
1472
|
|
|
1288
1473
|
const nattyServiceResolver = new NattyContainer();
|
|
@@ -1303,18 +1488,27 @@ class Resolver extends RequestProcessor {
|
|
|
1303
1488
|
const instance = new controller(...parameters);
|
|
1304
1489
|
return instance;
|
|
1305
1490
|
}
|
|
1306
|
-
resolveClass(
|
|
1307
|
-
return this.httpContext.services.get(
|
|
1491
|
+
resolveClass(token) {
|
|
1492
|
+
return this.httpContext.services.get(token);
|
|
1308
1493
|
}
|
|
1309
1494
|
resolveConstructorParameters() {
|
|
1310
1495
|
let parameters = [];
|
|
1311
1496
|
for (const parameter of this.routeInfo.parameters) {
|
|
1312
|
-
const
|
|
1313
|
-
if (
|
|
1314
|
-
parameters.push(this.resolveClass(
|
|
1497
|
+
const token = this.getConstructorParameterToken(parameter);
|
|
1498
|
+
if (token)
|
|
1499
|
+
parameters.push(this.resolveClass(token));
|
|
1315
1500
|
}
|
|
1316
1501
|
return parameters;
|
|
1317
1502
|
}
|
|
1503
|
+
getConstructorParameterToken(parameter) {
|
|
1504
|
+
if (parameter.tokenKey) {
|
|
1505
|
+
return Symbol.for(parameter.tokenKey);
|
|
1506
|
+
}
|
|
1507
|
+
if (parameter.type) {
|
|
1508
|
+
return this.getClass(parameter.type);
|
|
1509
|
+
}
|
|
1510
|
+
return void 0;
|
|
1511
|
+
}
|
|
1318
1512
|
getMethodParameters() {
|
|
1319
1513
|
const parameters = new Array();
|
|
1320
1514
|
for (const parameter of this.routeInfo.methodInfo.parameters) {
|
|
@@ -1326,7 +1520,7 @@ class Resolver extends RequestProcessor {
|
|
|
1326
1520
|
else if (queryParams[parameter.name] !== void 0)
|
|
1327
1521
|
parameters.push(queryParams[parameter.name]);
|
|
1328
1522
|
else if (typeInfo && this.httpContext.request.body.json) {
|
|
1329
|
-
const context = new ModelBindingContext(parameter.type, typeInfo.props, this.httpContext.request.body.json);
|
|
1523
|
+
const context = new ModelBindingContext(parameter.type, typeInfo.props, this.httpContext.request.body.json, true);
|
|
1330
1524
|
parameters.push(context);
|
|
1331
1525
|
}
|
|
1332
1526
|
}
|
|
@@ -1386,7 +1580,7 @@ class Resolver extends RequestProcessor {
|
|
|
1386
1580
|
});
|
|
1387
1581
|
} else
|
|
1388
1582
|
result = new HttpException({
|
|
1389
|
-
body:
|
|
1583
|
+
body: { message: ex.message, stack: ex.stack },
|
|
1390
1584
|
status: HttpStatusCode.serverError
|
|
1391
1585
|
}).getResponse();
|
|
1392
1586
|
}
|
|
@@ -1421,7 +1615,10 @@ class RequestHandler extends Resolver {
|
|
|
1421
1615
|
});
|
|
1422
1616
|
} else
|
|
1423
1617
|
return new HttpException({
|
|
1424
|
-
body:
|
|
1618
|
+
body: {
|
|
1619
|
+
message: ex?.message,
|
|
1620
|
+
stack: ex?.stack
|
|
1621
|
+
},
|
|
1425
1622
|
status: HttpStatusCode.serverError
|
|
1426
1623
|
});
|
|
1427
1624
|
}
|
|
@@ -1434,20 +1631,59 @@ class HttpHandler {
|
|
|
1434
1631
|
async processRequest(httpContext) {
|
|
1435
1632
|
const requestProcessor = new RequestHandler(httpContext);
|
|
1436
1633
|
const result = await requestProcessor.onRequest();
|
|
1437
|
-
|
|
1634
|
+
if (result instanceof HttpResponse) {
|
|
1635
|
+
return result;
|
|
1636
|
+
}
|
|
1637
|
+
if (result instanceof HttpException) {
|
|
1638
|
+
return result.getResponse();
|
|
1639
|
+
}
|
|
1640
|
+
return new HttpResponse({ body: result });
|
|
1438
1641
|
}
|
|
1439
1642
|
}
|
|
1440
1643
|
|
|
1644
|
+
const STACK_PATH_REGEX = /\bat (?:(?:.+?) \()?(.+):(\d+):(\d+)\)?$/;
|
|
1645
|
+
function normalizeFilePath(filePath) {
|
|
1646
|
+
return path__default.resolve(filePath).replace(/\\/g, "/");
|
|
1647
|
+
}
|
|
1648
|
+
function isInternalRegistrationFrame(filePath) {
|
|
1649
|
+
const normalizedPath = normalizeFilePath(filePath);
|
|
1650
|
+
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/");
|
|
1651
|
+
}
|
|
1652
|
+
function getRegistrationSourceFile() {
|
|
1653
|
+
const stack = new Error().stack;
|
|
1654
|
+
return getRegistrationSourceFileFromStack(stack);
|
|
1655
|
+
}
|
|
1656
|
+
function getRegistrationSourceFileFromStack(stack) {
|
|
1657
|
+
if (!stack) {
|
|
1658
|
+
return void 0;
|
|
1659
|
+
}
|
|
1660
|
+
const lines = stack.split("\n").slice(1);
|
|
1661
|
+
for (const line of lines) {
|
|
1662
|
+
const match = line.trim().match(STACK_PATH_REGEX);
|
|
1663
|
+
if (!match) {
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
const filePath = normalizeFilePath(match[1]);
|
|
1667
|
+
if (!isInternalRegistrationFrame(filePath)) {
|
|
1668
|
+
return filePath;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
return void 0;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1441
1674
|
function injectable(options = {}) {
|
|
1442
1675
|
return (targetConstructor) => {
|
|
1443
1676
|
const lt = options.lifetime ?? Lifetime.Transient;
|
|
1677
|
+
const sourceFile = getRegistrationSourceFile();
|
|
1444
1678
|
if (lt === Lifetime.Singleton)
|
|
1445
|
-
nattyServiceResolver.addSingleton(targetConstructor);
|
|
1679
|
+
nattyServiceResolver.addSingleton(targetConstructor, void 0, void 0, sourceFile);
|
|
1446
1680
|
else if (lt === Lifetime.Scoped)
|
|
1447
|
-
nattyServiceResolver.addScoped(targetConstructor);
|
|
1681
|
+
nattyServiceResolver.addScoped(targetConstructor, void 0, void 0, sourceFile);
|
|
1448
1682
|
else
|
|
1449
|
-
nattyServiceResolver.addTransient(targetConstructor);
|
|
1683
|
+
nattyServiceResolver.addTransient(targetConstructor, void 0, void 0, sourceFile);
|
|
1450
1684
|
common.commonContainer.setMetadata(targetConstructor.name, targetConstructor, "services");
|
|
1685
|
+
if (sourceFile)
|
|
1686
|
+
nattyServiceResolver.trackMetadataKey(sourceFile, targetConstructor.name);
|
|
1451
1687
|
};
|
|
1452
1688
|
}
|
|
1453
1689
|
|
|
@@ -1733,7 +1969,12 @@ const Results = {
|
|
|
1733
1969
|
};
|
|
1734
1970
|
|
|
1735
1971
|
function base(params, type, additionaConfig) {
|
|
1736
|
-
decoratorStateContainer.register(
|
|
1972
|
+
decoratorStateContainer.register(
|
|
1973
|
+
params,
|
|
1974
|
+
type,
|
|
1975
|
+
additionaConfig,
|
|
1976
|
+
getRegistrationSourceFile()
|
|
1977
|
+
);
|
|
1737
1978
|
}
|
|
1738
1979
|
|
|
1739
1980
|
function useFilter(config) {
|
|
@@ -1758,6 +1999,12 @@ function authenticationOnly() {
|
|
|
1758
1999
|
};
|
|
1759
2000
|
}
|
|
1760
2001
|
|
|
2002
|
+
function onException(exceptionFilter) {
|
|
2003
|
+
return function(target, propertyKey, descriptor) {
|
|
2004
|
+
base({ target, propertyKey, descriptor }, DecoratorType.onException, exceptionFilter);
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
|
|
1761
2008
|
function setEnvInfo(envTsDefinition, envValueInfo) {
|
|
1762
2009
|
if (envTsDefinition && envValueInfo) {
|
|
1763
2010
|
common.commonContainer.setEnvTsDefinition(envTsDefinition);
|
|
@@ -1790,6 +2037,85 @@ function singleton(token) {
|
|
|
1790
2037
|
return injectable({ lifetime: Lifetime.Singleton, token });
|
|
1791
2038
|
}
|
|
1792
2039
|
|
|
2040
|
+
function getTokenTypeName(token) {
|
|
2041
|
+
if (typeof token !== "symbol") {
|
|
2042
|
+
return void 0;
|
|
2043
|
+
}
|
|
2044
|
+
const key = Symbol.keyFor(token);
|
|
2045
|
+
if (!key) {
|
|
2046
|
+
return void 0;
|
|
2047
|
+
}
|
|
2048
|
+
const separatorIndex = key.lastIndexOf("#");
|
|
2049
|
+
if (separatorIndex < 0 || separatorIndex === key.length - 1) {
|
|
2050
|
+
return void 0;
|
|
2051
|
+
}
|
|
2052
|
+
return key.slice(separatorIndex + 1);
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
function registerLifetime(targetConstructor, sourceFile, lifetime) {
|
|
2056
|
+
if (lifetime === Lifetime.Singleton) {
|
|
2057
|
+
nattyServiceResolver.addSingleton(targetConstructor, void 0, void 0, sourceFile);
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
if (lifetime === Lifetime.Scoped) {
|
|
2061
|
+
nattyServiceResolver.addScoped(targetConstructor, void 0, void 0, sourceFile);
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
if (lifetime === Lifetime.Transient) {
|
|
2065
|
+
nattyServiceResolver.addTransient(targetConstructor, void 0, void 0, sourceFile);
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
function registerAliasTypeName(token, sourceFile) {
|
|
2069
|
+
const typeName = getTokenTypeName(token);
|
|
2070
|
+
if (typeName) {
|
|
2071
|
+
common.commonContainer.setMetadata(typeName, token, "services");
|
|
2072
|
+
if (sourceFile)
|
|
2073
|
+
nattyServiceResolver.trackMetadataKey(sourceFile, typeName);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
function registerDiToken(targetConstructor, token, options = {}) {
|
|
2077
|
+
const sourceFile = getRegistrationSourceFile();
|
|
2078
|
+
common.commonContainer.setMetadata(targetConstructor.name, targetConstructor, "services");
|
|
2079
|
+
if (sourceFile)
|
|
2080
|
+
nattyServiceResolver.trackMetadataKey(sourceFile, targetConstructor.name);
|
|
2081
|
+
registerAliasTypeName(token, sourceFile);
|
|
2082
|
+
registerLifetime(targetConstructor, sourceFile, options.lifetime);
|
|
2083
|
+
nattyServiceResolver.addTransient(
|
|
2084
|
+
token,
|
|
2085
|
+
void 0,
|
|
2086
|
+
(serviceProvider) => serviceProvider.get(targetConstructor),
|
|
2087
|
+
sourceFile
|
|
2088
|
+
);
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
function di(token, options = {}) {
|
|
2092
|
+
return (targetConstructor) => {
|
|
2093
|
+
registerDiToken(targetConstructor, token, options);
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
function createServiceScope() {
|
|
2098
|
+
return nattyServiceResolver.createScope();
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
function clearHotReloadRegistrations(files) {
|
|
2102
|
+
for (const filePath of files || []) {
|
|
2103
|
+
const result = nattyServiceResolver.clearRegistrationsFromSource(filePath);
|
|
2104
|
+
decoratorStateContainer.clearFromSource(filePath);
|
|
2105
|
+
for (const metadataKey of result.metadataKeys) {
|
|
2106
|
+
common.commonContainer.deleteMetadataValue(metadataKey, "services");
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
function clearHotReloadControllerMetadata(controllerNames) {
|
|
2112
|
+
decoratorStateContainer.clearControllers(controllerNames || []);
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
function replaceRoutes(manifest) {
|
|
2116
|
+
nattyContainer.replaceRoutes(manifest);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
1793
2119
|
exports.$request = $request;
|
|
1794
2120
|
exports.AbstractModelState = AbstractModelState;
|
|
1795
2121
|
exports.AcceptedException = AcceptedException;
|
|
@@ -1813,6 +2139,7 @@ exports.HttpNotFoundException = HttpNotFoundException;
|
|
|
1813
2139
|
exports.HttpResponse = HttpResponse;
|
|
1814
2140
|
exports.HttpStatusCode = HttpStatusCode;
|
|
1815
2141
|
exports.HttpUnprocessableEntityException = HttpUnprocessableEntityException;
|
|
2142
|
+
exports.Lifetime = Lifetime;
|
|
1816
2143
|
exports.ModelBindingContext = ModelBindingContext;
|
|
1817
2144
|
exports.NoContentResult = NoContentResult;
|
|
1818
2145
|
exports.NotFoundResult = NotFoundResult;
|
|
@@ -1835,11 +2162,15 @@ exports.anonymous = anonymous;
|
|
|
1835
2162
|
exports.authenticationOnly = authenticationOnly;
|
|
1836
2163
|
exports.authorize = authorize;
|
|
1837
2164
|
exports.badRequest = badRequest;
|
|
2165
|
+
exports.clearHotReloadControllerMetadata = clearHotReloadControllerMetadata;
|
|
2166
|
+
exports.clearHotReloadRegistrations = clearHotReloadRegistrations;
|
|
1838
2167
|
exports.conflict = conflict;
|
|
2168
|
+
exports.createServiceScope = createServiceScope;
|
|
1839
2169
|
exports.created = created;
|
|
1840
2170
|
exports.createdAt = createdAt;
|
|
1841
2171
|
exports.createdWith = createdWith;
|
|
1842
2172
|
exports.defineNattyConfig = defineNattyConfig;
|
|
2173
|
+
exports.di = di;
|
|
1843
2174
|
exports.entityContainer = entityContainer;
|
|
1844
2175
|
exports.file = file;
|
|
1845
2176
|
exports.filter = filter;
|
|
@@ -1852,12 +2183,14 @@ exports.noContent = noContent;
|
|
|
1852
2183
|
exports.notFound = notFound;
|
|
1853
2184
|
exports.notFoundWith = notFoundWith;
|
|
1854
2185
|
exports.ok = ok;
|
|
2186
|
+
exports.onException = onException;
|
|
1855
2187
|
exports.post = post;
|
|
1856
2188
|
exports.problem = problem;
|
|
1857
2189
|
exports.put = put;
|
|
1858
2190
|
exports.redirect = redirect;
|
|
1859
2191
|
exports.redirectPermanent = redirectPermanent;
|
|
1860
2192
|
exports.registerDecorator = registerDecorator;
|
|
2193
|
+
exports.replaceRoutes = replaceRoutes;
|
|
1861
2194
|
exports.route = route;
|
|
1862
2195
|
exports.scoped = scoped;
|
|
1863
2196
|
exports.setEnvInfo = setEnvInfo;
|