@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 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
- nattyContainer.setup(config, appConfig.routes, appConfig.resolver);
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 appRoutes() {
837
- return nattyContainer.routes;
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
- let isMatched = false;
851
- const requestPathname = this.getRequestPathname();
852
- for (const [key, value] of Object.entries(this.appRoutes)) {
853
- const rootPath = key;
854
- const routeConfig = value;
855
- const childRoutes = routeConfig[this.httpMethod];
856
- if (childRoutes) {
857
- for (const [key2, value2] of Object.entries(childRoutes)) {
858
- const childPath = key2.indexOf(common.RIGHT_SLASH) == 0 ? key2 === common.RIGHT_SLASH ? common.BLANK : key2 : `/${key2}`;
859
- const methodInfo = value2;
860
- const configuredRoutePath = `${rootPath}${childPath}`;
861
- const routeMatch = pathToRegexp.match(`${rootPath}${childPath}`, { decode: decodeURIComponent });
862
- const matched = routeMatch(requestPathname);
863
- if (matched) {
864
- isMatched = true;
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 isMatched;
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 (!anonymousInfo.controllerConfig && !anonymousInfo.methodConfig && !authenticationFilter)
1095
- throw new UnauthorizedAccessException(DENY_BY_DEFAULT);
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(token, { lifetime: Lifetime.Transient, useClass: useClass ?? token, useFactory });
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(token, { lifetime: Lifetime.Scoped, useClass: useClass ?? token, useFactory });
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(token, { lifetime: Lifetime.Singleton, useClass: useClass ?? token, useFactory });
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(classConstruct) {
1307
- return this.httpContext.services.get(classConstruct);
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 classConstruct = this.getClass(parameter.type);
1313
- if (classConstruct)
1314
- parameters.push(this.resolveClass(classConstruct));
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: getPreResponseBody({ message: ex.message, stack: ex.stack }),
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: ex,
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
- return result;
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(params, type, additionaConfig);
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;