@futdevpro/nts-dynamo 1.15.153 → 1.15.155

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 (52) hide show
  1. package/README.md +25 -6
  2. package/__documentations/2026-08-22-content-free-process-error-boundary.md +91 -0
  3. package/build/_models/control-models/app-params.control-model.d.ts.map +1 -1
  4. package/build/_models/control-models/app-params.control-model.js +1 -2
  5. package/build/_models/control-models/app-params.control-model.js.map +1 -1
  6. package/build/_modules/server/index.d.ts +4 -0
  7. package/build/_modules/server/index.d.ts.map +1 -1
  8. package/build/_modules/server/index.js +5 -0
  9. package/build/_modules/server/index.js.map +1 -1
  10. package/build/_modules/server/safe-diagnostic/safe-diagnostic-cause.type-enum.d.ts +9 -0
  11. package/build/_modules/server/safe-diagnostic/safe-diagnostic-cause.type-enum.d.ts.map +1 -0
  12. package/build/_modules/server/safe-diagnostic/safe-diagnostic-cause.type-enum.js +13 -0
  13. package/build/_modules/server/safe-diagnostic/safe-diagnostic-cause.type-enum.js.map +1 -0
  14. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.d.ts +20 -0
  15. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.d.ts.map +1 -0
  16. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.js +24 -0
  17. package/build/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.js.map +1 -0
  18. package/build/_modules/server/safe-diagnostic/safe-diagnostic.control-service.d.ts +19 -0
  19. package/build/_modules/server/safe-diagnostic/safe-diagnostic.control-service.d.ts.map +1 -0
  20. package/build/_modules/server/safe-diagnostic/safe-diagnostic.control-service.js +83 -0
  21. package/build/_modules/server/safe-diagnostic/safe-diagnostic.control-service.js.map +1 -0
  22. package/build/_modules/server/safe-diagnostic/safe-diagnostic.interface.d.ts +19 -0
  23. package/build/_modules/server/safe-diagnostic/safe-diagnostic.interface.d.ts.map +1 -0
  24. package/build/_modules/server/safe-diagnostic/safe-diagnostic.interface.js +3 -0
  25. package/build/_modules/server/safe-diagnostic/safe-diagnostic.interface.js.map +1 -0
  26. package/build/_services/core/global.service.d.ts +3 -3
  27. package/build/_services/core/global.service.d.ts.map +1 -1
  28. package/build/_services/core/global.service.js +24 -18
  29. package/build/_services/core/global.service.js.map +1 -1
  30. package/build/_services/server/app.server.d.ts +2 -0
  31. package/build/_services/server/app.server.d.ts.map +1 -1
  32. package/build/_services/server/app.server.js +71 -199
  33. package/build/_services/server/app.server.js.map +1 -1
  34. package/build/_services/shared.static-service.d.ts +11 -4
  35. package/build/_services/shared.static-service.d.ts.map +1 -1
  36. package/build/_services/shared.static-service.js +26 -6
  37. package/build/_services/shared.static-service.js.map +1 -1
  38. package/package.json +15 -9
  39. package/src/_models/control-models/app-params.control-model.spec.ts +9 -5
  40. package/src/_models/control-models/app-params.control-model.ts +4 -3
  41. package/src/_modules/server/index.ts +6 -0
  42. package/src/_modules/server/safe-diagnostic/safe-diagnostic-cause.type-enum.ts +8 -0
  43. package/src/_modules/server/safe-diagnostic/safe-diagnostic-stage.type-enum.ts +19 -0
  44. package/src/_modules/server/safe-diagnostic/safe-diagnostic.control-service.spec.ts +124 -0
  45. package/src/_modules/server/safe-diagnostic/safe-diagnostic.control-service.ts +99 -0
  46. package/src/_modules/server/safe-diagnostic/safe-diagnostic.interface.ts +20 -0
  47. package/src/_modules/server/server-status/db-readiness-probe.control-service.spec.ts +2 -2
  48. package/src/_services/core/global.service.ts +34 -33
  49. package/src/_services/server/app-safe-diagnostic.spec.ts +124 -0
  50. package/src/_services/server/app.server.ts +209 -262
  51. package/src/_services/shared.static-service.spec.ts +57 -23
  52. package/src/_services/shared.static-service.ts +48 -19
@@ -1,11 +1,14 @@
1
- import { DyNTS_Shared } from './shared.static-service';
2
- import { Request } from 'express';
3
- import * as GeoIp from 'geoip-lite';
1
+ import { Request } from 'express';
2
+
3
+ import { DyFM_GeoIpLocation } from '@futdevpro/fsm-dynamo/location';
4
+
5
+ import { DyNTS_Shared } from './shared.static-service';
4
6
 
5
7
  describe('| DyNTS_Shared', () => {
6
8
  describe('| getIpFromRequest', () => {
7
- it('| should extract IP from x-forwarded-for header', () => {
8
- const mockRequest = {
9
+ it('| should extract IP from x-forwarded-for header', () => {
10
+ const consoleLogSpy: jasmine.Spy = spyOn(console, 'log');
11
+ const mockRequest = {
9
12
  headers: {
10
13
  'x-forwarded-for': '192.168.1.1, 10.0.0.1, 172.16.0.1',
11
14
  },
@@ -15,8 +18,9 @@ describe('| DyNTS_Shared', () => {
15
18
  } as any as Request;
16
19
 
17
20
  const ip = DyNTS_Shared.getIpFromRequest(mockRequest);
18
-
19
- expect(ip).toBe('172.16.0.1');
21
+
22
+ expect(ip).toBe('172.16.0.1');
23
+ expect(consoleLogSpy).not.toHaveBeenCalled();
20
24
  });
21
25
 
22
26
  it('| should extract IP from socket.remoteAddress when x-forwarded-for is not present', () => {
@@ -63,22 +67,52 @@ describe('| DyNTS_Shared', () => {
63
67
  });
64
68
  });
65
69
 
66
- // Skip geoip tests - GeoIp.lookup is not writable/mockable
67
- describe('| getLocationDataByRequest', () => {
68
- it('| should return location data for request IP', () => {
69
- // Skipped - GeoIp.lookup cannot be mocked
70
- });
71
- });
72
-
73
- describe('| getLocationByIp', () => {
74
- it('| should return location data for IP address', () => {
75
- // Skipped - GeoIp.lookup cannot be mocked
76
- });
77
-
78
- it('| should return null for invalid IP', () => {
79
- // Skipped - GeoIp.lookup cannot be mocked
80
- });
81
- });
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
+ });
82
116
 
83
117
  describe('| prompt', () => {
84
118
  it('| should be accessible', () => {
@@ -1,10 +1,16 @@
1
1
 
2
- import * as ReadLine from 'readline';
3
- import * as GeoIp from 'geoip-lite';
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';
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);
8
14
 
9
15
  /**
10
16
  * Collection of static helper utilities shared across modules.
@@ -20,11 +26,10 @@ export class DyNTS_Shared extends DyFM_Object {
20
26
  static getIpFromRequest(request: Request): string {
21
27
  let ip: string;
22
28
 
23
- if (request?.headers?.['x-forwarded-for']) {
24
- const route: string[] = (request.headers['x-forwarded-for'] as string).split(', ');
25
-
26
- console.log('TESTTTT route:', route);
27
- 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];
28
33
  } else {
29
34
  ip = request.socket.remoteAddress;
30
35
  }
@@ -36,21 +41,45 @@ export class DyNTS_Shared extends DyFM_Object {
36
41
  * Lookup the Geo location of a request based on its IP address.
37
42
  *
38
43
  * @param request Incoming request
39
- * @returns Resolved geo location information
40
- */
41
- static getLocationDataByRequest(request: Request): DyFM_GeoIpLocation {
42
- return GeoIp.lookup(this.getIpFromRequest(request));
43
- }
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
52
 
45
53
  /**
46
54
  * Lookup the Geo location of a raw IP address.
47
55
  *
48
56
  * @param ip IP address string
49
- * @returns Geo location information
50
- */
51
- static getLocationByIp(ip: string): DyFM_GeoIpLocation {
52
- return GeoIp.lookup(ip);
53
- }
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
+ }
54
83
 
55
84
  /**
56
85
  * Simple CLI helper to prompt the user for input.