@futdevpro/nts-dynamo 1.15.155 → 1.15.157

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.
Files changed (48) hide show
  1. package/README.md +10 -10
  2. package/__documentations/2026-08-22-bfr-ctm-018-content-free-endpoint-errors.md +54 -0
  3. package/__documentations/2026-08-22-bfr-ctm-020-content-free-request-telemetry.md +65 -0
  4. package/__documentations/2026-08-22-content-free-process-error-boundary.md +21 -1
  5. package/build/_models/control-models/endpoint-params.control-model.d.ts +6 -0
  6. package/build/_models/control-models/endpoint-params.control-model.d.ts.map +1 -1
  7. package/build/_models/control-models/endpoint-params.control-model.js +71 -146
  8. package/build/_models/control-models/endpoint-params.control-model.js.map +1 -1
  9. package/build/_models/interfaces/request-telemetry-settings.interface.d.ts +10 -0
  10. package/build/_models/interfaces/request-telemetry-settings.interface.d.ts.map +1 -0
  11. package/build/_models/interfaces/request-telemetry-settings.interface.js +3 -0
  12. package/build/_models/interfaces/request-telemetry-settings.interface.js.map +1 -0
  13. package/build/_models/interfaces/request-telemetry-snapshot.interface.d.ts +29 -0
  14. package/build/_models/interfaces/request-telemetry-snapshot.interface.d.ts.map +1 -0
  15. package/build/_models/interfaces/request-telemetry-snapshot.interface.js +3 -0
  16. package/build/_models/interfaces/request-telemetry-snapshot.interface.js.map +1 -0
  17. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.d.ts +1 -0
  18. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.d.ts.map +1 -1
  19. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.js +1 -0
  20. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.js.map +1 -1
  21. package/build/_services/core/request-telemetry.control-service.d.ts +51 -0
  22. package/build/_services/core/request-telemetry.control-service.d.ts.map +1 -0
  23. package/build/_services/core/request-telemetry.control-service.js +286 -0
  24. package/build/_services/core/request-telemetry.control-service.js.map +1 -0
  25. package/build/_services/route/routing-module.service.d.ts.map +1 -1
  26. package/build/_services/route/routing-module.service.js +13 -10
  27. package/build/_services/route/routing-module.service.js.map +1 -1
  28. package/build/_services/server/app.server.d.ts +5 -0
  29. package/build/_services/server/app.server.d.ts.map +1 -1
  30. package/build/_services/server/app.server.js +13 -0
  31. package/build/_services/server/app.server.js.map +1 -1
  32. package/build/index.d.ts +3 -0
  33. package/build/index.d.ts.map +1 -1
  34. package/build/index.js +3 -0
  35. package/build/index.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/_models/control-models/endpoint-params.control-model.spec.ts +87 -2
  38. package/src/_models/control-models/endpoint-params.control-model.ts +93 -182
  39. package/src/_models/interfaces/request-telemetry-settings.interface.ts +9 -0
  40. package/src/_models/interfaces/request-telemetry-snapshot.interface.ts +30 -0
  41. package/src/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.ts +1 -0
  42. package/src/_services/core/request-telemetry.control-service.spec.ts +217 -0
  43. package/src/_services/core/request-telemetry.control-service.ts +381 -0
  44. package/src/_services/route/routing-module.service.ts +27 -18
  45. package/src/_services/server/app.server.ts +29 -9
  46. package/src/_services/shared.static-service.spec.ts +57 -57
  47. package/src/_services/shared.static-service.ts +48 -48
  48. package/src/index.ts +5 -2
@@ -1,14 +1,14 @@
1
- import { Request } from 'express';
2
-
3
- import { DyFM_GeoIpLocation } from '@futdevpro/fsm-dynamo/location';
4
-
5
- import { DyNTS_Shared } from './shared.static-service';
1
+ import { Request } from 'express';
2
+
3
+ import { DyFM_GeoIpLocation } from '@futdevpro/fsm-dynamo/location';
4
+
5
+ import { DyNTS_Shared } from './shared.static-service';
6
6
 
7
7
  describe('| DyNTS_Shared', () => {
8
8
  describe('| getIpFromRequest', () => {
9
- it('| should extract IP from x-forwarded-for header', () => {
10
- const consoleLogSpy: jasmine.Spy = spyOn(console, 'log');
11
- const mockRequest = {
9
+ it('| should extract IP from x-forwarded-for header', () => {
10
+ const consoleLogSpy: jasmine.Spy = spyOn(console, 'log');
11
+ const mockRequest = {
12
12
  headers: {
13
13
  'x-forwarded-for': '192.168.1.1, 10.0.0.1, 172.16.0.1',
14
14
  },
@@ -18,9 +18,9 @@ describe('| DyNTS_Shared', () => {
18
18
  } as any as Request;
19
19
 
20
20
  const ip = DyNTS_Shared.getIpFromRequest(mockRequest);
21
-
22
- expect(ip).toBe('172.16.0.1');
23
- expect(consoleLogSpy).not.toHaveBeenCalled();
21
+
22
+ expect(ip).toBe('172.16.0.1');
23
+ expect(consoleLogSpy).not.toHaveBeenCalled();
24
24
  });
25
25
 
26
26
  it('| should extract IP from socket.remoteAddress when x-forwarded-for is not present', () => {
@@ -67,52 +67,52 @@ describe('| DyNTS_Shared', () => {
67
67
  });
68
68
  });
69
69
 
70
- describe('| getLocationDataByRequest', () => {
71
- it('| should return null without logging the request IP when provider is unavailable', () => {
72
- const consoleLogSpy: jasmine.Spy = spyOn(console, 'log');
73
-
74
- spyOn<any>(DyNTS_Shared, 'getGeoIpProvider').and.returnValue(null);
75
- const mockRequest = {
76
- headers: {
77
- 'x-forwarded-for': '198.51.100.17',
78
- },
79
- socket: {
80
- remoteAddress: '127.0.0.1',
81
- },
82
- } as any as Request;
83
-
84
- expect(DyNTS_Shared.getLocationDataByRequest(mockRequest)).toBeNull();
85
- expect(consoleLogSpy).not.toHaveBeenCalled();
86
- });
87
- });
88
-
89
- describe('| getLocationByIp', () => {
90
- it('| should use the optional local provider when available', () => {
91
- const location: DyFM_GeoIpLocation = {
92
- range: [ 0, 1 ],
93
- country: 'HU',
94
- region: '',
95
- eu: '1',
96
- timezone: 'Europe/Budapest',
97
- city: 'Budapest',
98
- ll: [ 47.4979, 19.0402 ],
99
- metro: 0,
100
- area: 10,
101
- };
102
- const lookupSpy: jasmine.Spy = jasmine.createSpy('lookup').and.returnValue(location);
103
-
104
- spyOn<any>(DyNTS_Shared, 'getGeoIpProvider').and.returnValue({ lookup: lookupSpy });
105
-
106
- expect(DyNTS_Shared.getLocationByIp('203.0.113.7')).toEqual(location);
107
- expect(lookupSpy).toHaveBeenCalledOnceWith('203.0.113.7');
108
- });
109
-
110
- it('| should return null when the optional provider is unavailable', () => {
111
- spyOn<any>(DyNTS_Shared, 'getGeoIpProvider').and.returnValue(null);
112
-
113
- expect(DyNTS_Shared.getLocationByIp('203.0.113.7')).toBeNull();
114
- });
115
- });
70
+ describe('| getLocationDataByRequest', () => {
71
+ it('| should return null without logging the request IP when provider is unavailable', () => {
72
+ const consoleLogSpy: jasmine.Spy = spyOn(console, 'log');
73
+
74
+ spyOn<any>(DyNTS_Shared, 'getGeoIpProvider').and.returnValue(null);
75
+ const mockRequest = {
76
+ headers: {
77
+ 'x-forwarded-for': '198.51.100.17',
78
+ },
79
+ socket: {
80
+ remoteAddress: '127.0.0.1',
81
+ },
82
+ } as any as Request;
83
+
84
+ expect(DyNTS_Shared.getLocationDataByRequest(mockRequest)).toBeNull();
85
+ expect(consoleLogSpy).not.toHaveBeenCalled();
86
+ });
87
+ });
88
+
89
+ describe('| getLocationByIp', () => {
90
+ it('| should use the optional local provider when available', () => {
91
+ const location: DyFM_GeoIpLocation = {
92
+ range: [ 0, 1 ],
93
+ country: 'HU',
94
+ region: '',
95
+ eu: '1',
96
+ timezone: 'Europe/Budapest',
97
+ city: 'Budapest',
98
+ ll: [ 47.4979, 19.0402 ],
99
+ metro: 0,
100
+ area: 10,
101
+ };
102
+ const lookupSpy: jasmine.Spy = jasmine.createSpy('lookup').and.returnValue(location);
103
+
104
+ spyOn<any>(DyNTS_Shared, 'getGeoIpProvider').and.returnValue({ lookup: lookupSpy });
105
+
106
+ expect(DyNTS_Shared.getLocationByIp('203.0.113.7')).toEqual(location);
107
+ expect(lookupSpy).toHaveBeenCalledOnceWith('203.0.113.7');
108
+ });
109
+
110
+ it('| should return null when the optional provider is unavailable', () => {
111
+ spyOn<any>(DyNTS_Shared, 'getGeoIpProvider').and.returnValue(null);
112
+
113
+ expect(DyNTS_Shared.getLocationByIp('203.0.113.7')).toBeNull();
114
+ });
115
+ });
116
116
 
117
117
  describe('| prompt', () => {
118
118
  it('| should be accessible', () => {
@@ -1,16 +1,16 @@
1
1
 
2
- import * as ReadLine from 'readline';
3
- import { createRequire } from 'module';
4
- import { Request } from 'express';
2
+ import * as ReadLine from 'readline';
3
+ import { createRequire } from 'module';
4
+ import { Request } from 'express';
5
5
 
6
6
  import { DyFM_Object } from '@futdevpro/fsm-dynamo';
7
- import { DyFM_GeoIpLocation } from '@futdevpro/fsm-dynamo/location';
8
-
9
- interface DyNTS_GeoIpProvider {
10
- lookup(ip: string): DyFM_GeoIpLocation | null;
11
- }
12
-
13
- const DyNTS_optionalRequire: NodeJS.Require = createRequire(__filename);
7
+ import { DyFM_GeoIpLocation } from '@futdevpro/fsm-dynamo/location';
8
+
9
+ interface DyNTS_GeoIpProvider {
10
+ lookup(ip: string): DyFM_GeoIpLocation | null;
11
+ }
12
+
13
+ const DyNTS_optionalRequire: NodeJS.Require = createRequire(__filename);
14
14
 
15
15
  /**
16
16
  * Collection of static helper utilities shared across modules.
@@ -26,10 +26,10 @@ export class DyNTS_Shared extends DyFM_Object {
26
26
  static getIpFromRequest(request: Request): string {
27
27
  let ip: string;
28
28
 
29
- if (request?.headers?.['x-forwarded-for']) {
30
- const route: string[] = (request.headers['x-forwarded-for'] as string).split(', ');
31
-
32
- ip = route[route.length - 1];
29
+ if (request?.headers?.['x-forwarded-for']) {
30
+ const route: string[] = (request.headers['x-forwarded-for'] as string).split(', ');
31
+
32
+ ip = route[route.length - 1];
33
33
  } else {
34
34
  ip = request.socket.remoteAddress;
35
35
  }
@@ -41,45 +41,45 @@ export class DyNTS_Shared extends DyFM_Object {
41
41
  * Lookup the Geo location of a request based on its IP address.
42
42
  *
43
43
  * @param request Incoming request
44
- * The optional GeoIP provider is loaded only for this capability. When it is not installed,
45
- * the method returns `null` and does not transmit or log the address.
46
- *
47
- * @returns Resolved geo location information, or `null` when unavailable
48
- */
49
- static getLocationDataByRequest(request: Request): DyFM_GeoIpLocation | null {
50
- return this.getLocationByIp(this.getIpFromRequest(request));
51
- }
44
+ * The optional GeoIP provider is loaded only for this capability. When it is not installed,
45
+ * the method returns `null` and does not transmit or log the address.
46
+ *
47
+ * @returns Resolved geo location information, or `null` when unavailable
48
+ */
49
+ static getLocationDataByRequest(request: Request): DyFM_GeoIpLocation | null {
50
+ return this.getLocationByIp(this.getIpFromRequest(request));
51
+ }
52
52
 
53
53
  /**
54
54
  * Lookup the Geo location of a raw IP address.
55
55
  *
56
56
  * @param ip IP address string
57
- * The lookup is local-only: the IP address is never sent to an external service. The optional
58
- * provider may be omitted by consumers that do not use geolocation.
59
- *
60
- * @returns Geo location information, or `null` when unavailable
61
- */
62
- static getLocationByIp(ip: string): DyFM_GeoIpLocation | null {
63
- const geoIpProvider: DyNTS_GeoIpProvider | null = this.getGeoIpProvider();
64
-
65
- return geoIpProvider?.lookup(ip) ?? null;
66
- }
67
-
68
- private static getGeoIpProvider(): DyNTS_GeoIpProvider | null {
69
- let geoIpModulePath: string;
70
-
71
- try {
72
- geoIpModulePath = DyNTS_optionalRequire.resolve('geoip-lite');
73
- } catch (error: unknown) {
74
- if (error instanceof Error && 'code' in error && error.code === 'MODULE_NOT_FOUND') {
75
- return null;
76
- }
77
-
78
- throw error;
79
- }
80
-
81
- return DyNTS_optionalRequire(geoIpModulePath);
82
- }
57
+ * The lookup is local-only: the IP address is never sent to an external service. The optional
58
+ * provider may be omitted by consumers that do not use geolocation.
59
+ *
60
+ * @returns Geo location information, or `null` when unavailable
61
+ */
62
+ static getLocationByIp(ip: string): DyFM_GeoIpLocation | null {
63
+ const geoIpProvider: DyNTS_GeoIpProvider | null = this.getGeoIpProvider();
64
+
65
+ return geoIpProvider?.lookup(ip) ?? null;
66
+ }
67
+
68
+ private static getGeoIpProvider(): DyNTS_GeoIpProvider | null {
69
+ let geoIpModulePath: string;
70
+
71
+ try {
72
+ geoIpModulePath = DyNTS_optionalRequire.resolve('geoip-lite');
73
+ } catch (error: unknown) {
74
+ if (error instanceof Error && 'code' in error && error.code === 'MODULE_NOT_FOUND') {
75
+ return null;
76
+ }
77
+
78
+ throw error;
79
+ }
80
+
81
+ return DyNTS_optionalRequire(geoIpModulePath);
82
+ }
83
83
 
84
84
  /**
85
85
  * Simple CLI helper to prompt the user for input.
package/src/index.ts CHANGED
@@ -54,7 +54,9 @@ export * from './_models/interfaces/signed-url-verify-result.interface';
54
54
  export * from './_models/interfaces/static-client-settings.interface';
55
55
  export * from './_models/interfaces/cors-settings.interface';
56
56
  export * from './_models/interfaces/security-headers-settings.interface';
57
- export * from './_models/interfaces/app-version-header-settings.interface';
57
+ export * from './_models/interfaces/app-version-header-settings.interface';
58
+ export * from './_models/interfaces/request-telemetry-settings.interface';
59
+ export * from './_models/interfaces/request-telemetry-snapshot.interface';
58
60
  export * from './_models/interfaces/db-query-options.interface';
59
61
  export * from './_models/interfaces/migration-entry.interface';
60
62
  export * from './_models/interfaces/mongo-transaction-settings.interface';
@@ -92,7 +94,8 @@ export * from './_services/core/auth.service';
92
94
  export * from './_services/core/email.service';
93
95
  export * from './_services/core/collection-growth-monitor.service';
94
96
  export * from './_services/core/global.service';
95
- export * from './_services/core/memory-guard.service';
97
+ export * from './_services/core/memory-guard.service';
98
+ export * from './_services/core/request-telemetry.control-service';
96
99
 
97
100
  export * from './_services/core/service-collection.service';
98
101
  export * from './_services/core/migration-runner.service';