@futdevpro/nts-dynamo 1.15.8 → 1.15.9

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 (83) hide show
  1. package/__documentations/nts-integration-tests-2026-03-17.md +26 -0
  2. package/build/_collections/default-fallback-cache-max-age.const.d.ts +3 -0
  3. package/build/_collections/default-fallback-cache-max-age.const.d.ts.map +1 -0
  4. package/build/_collections/default-fallback-cache-max-age.const.js +6 -0
  5. package/build/_collections/default-fallback-cache-max-age.const.js.map +1 -0
  6. package/build/_collections/default-not-found-page.const.d.ts +6 -0
  7. package/build/_collections/default-not-found-page.const.d.ts.map +1 -0
  8. package/build/_collections/default-not-found-page.const.js +25 -0
  9. package/build/_collections/default-not-found-page.const.js.map +1 -0
  10. package/build/_collections/default-socket-path.const.d.ts +3 -0
  11. package/build/_collections/default-socket-path.const.d.ts.map +1 -0
  12. package/build/_collections/default-socket-path.const.js +6 -0
  13. package/build/_collections/default-socket-path.const.js.map +1 -0
  14. package/build/_models/control-models/http-settings.control-model.d.ts +7 -0
  15. package/build/_models/control-models/http-settings.control-model.d.ts.map +1 -1
  16. package/build/_models/control-models/http-settings.control-model.js +7 -0
  17. package/build/_models/control-models/http-settings.control-model.js.map +1 -1
  18. package/build/_models/interfaces/static-client-settings.interface.d.ts +29 -0
  19. package/build/_models/interfaces/static-client-settings.interface.d.ts.map +1 -0
  20. package/build/_models/interfaces/static-client-settings.interface.js +3 -0
  21. package/build/_models/interfaces/static-client-settings.interface.js.map +1 -0
  22. package/build/_modules/mock/app-extended-server.mock.js +2 -2
  23. package/build/_modules/mock/app-extended-server.mock.js.map +1 -1
  24. package/build/_modules/mock/app-integration-test.mock.d.ts +20 -0
  25. package/build/_modules/mock/app-integration-test.mock.d.ts.map +1 -0
  26. package/build/_modules/mock/app-integration-test.mock.js +46 -0
  27. package/build/_modules/mock/app-integration-test.mock.js.map +1 -0
  28. package/build/_modules/mock/app-server.mock.js +2 -2
  29. package/build/_modules/mock/app-server.mock.js.map +1 -1
  30. package/build/_modules/mock/socket-client.mock.js +1 -1
  31. package/build/_modules/mock/socket-client.mock.js.map +1 -1
  32. package/build/_modules/mock/socket-server.mock.d.ts +1 -1
  33. package/build/_modules/mock/socket-server.mock.d.ts.map +1 -1
  34. package/build/_modules/mock/socket-server.mock.js +2 -8
  35. package/build/_modules/mock/socket-server.mock.js.map +1 -1
  36. package/build/_modules/socket/_services/socket-server.service.d.ts.map +1 -1
  37. package/build/_modules/socket/_services/socket-server.service.js +3 -1
  38. package/build/_modules/socket/_services/socket-server.service.js.map +1 -1
  39. package/build/_modules/socket/app-extended.server.d.ts +1 -0
  40. package/build/_modules/socket/app-extended.server.d.ts.map +1 -1
  41. package/build/_modules/socket/app-extended.server.js +6 -2
  42. package/build/_modules/socket/app-extended.server.js.map +1 -1
  43. package/build/_services/base/data.service.d.ts.map +1 -1
  44. package/build/_services/base/data.service.js +4 -5
  45. package/build/_services/base/data.service.js.map +1 -1
  46. package/build/_services/base/db.service.d.ts.map +1 -1
  47. package/build/_services/base/db.service.js +8 -0
  48. package/build/_services/base/db.service.js.map +1 -1
  49. package/build/_services/server/app.server.d.ts +18 -0
  50. package/build/_services/server/app.server.d.ts.map +1 -1
  51. package/build/_services/server/app.server.js +74 -2
  52. package/build/_services/server/app.server.js.map +1 -1
  53. package/build/index.d.ts +4 -0
  54. package/build/index.d.ts.map +1 -1
  55. package/build/index.js +4 -0
  56. package/build/index.js.map +1 -1
  57. package/nodemon.json +2 -1
  58. package/package.json +1 -1
  59. package/src/_collections/default-fallback-cache-max-age.const.spec.ts +11 -0
  60. package/src/_collections/default-fallback-cache-max-age.const.ts +2 -0
  61. package/src/_collections/default-not-found-page.const.spec.ts +19 -0
  62. package/src/_collections/default-not-found-page.const.ts +22 -0
  63. package/src/_collections/default-socket-path.const.spec.ts +12 -0
  64. package/src/_collections/default-socket-path.const.ts +2 -0
  65. package/src/_models/control-models/http-settings.control-model.spec.ts +11 -0
  66. package/src/_models/control-models/http-settings.control-model.ts +8 -0
  67. package/src/_models/interfaces/static-client-settings.interface.spec.ts +29 -0
  68. package/src/_models/interfaces/static-client-settings.interface.ts +28 -0
  69. package/src/_modules/mock/app-extended-server.mock.ts +2 -2
  70. package/src/_modules/mock/app-integration-test.mock.ts +51 -0
  71. package/src/_modules/mock/app-server.mock.ts +2 -2
  72. package/src/_modules/mock/socket-client.mock.spec.ts +1 -1
  73. package/src/_modules/mock/socket-client.mock.ts +1 -1
  74. package/src/_modules/mock/socket-server.mock.spec.ts +1 -1
  75. package/src/_modules/mock/socket-server.mock.ts +5 -13
  76. package/src/_modules/socket/_services/socket-server.service.ts +6 -2
  77. package/src/_modules/socket/app-extended.integration.spec.ts +85 -0
  78. package/src/_modules/socket/app-extended.server.ts +6 -2
  79. package/src/_services/base/data.service.ts +4 -7
  80. package/src/_services/base/db.service.ts +11 -3
  81. package/src/_services/route/routing-module.service.spec.ts +15 -0
  82. package/src/_services/server/app.server.ts +107 -2
  83. package/src/index.ts +4 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Alapértelmezett "Page not found" (404) HTML, amit a static client default fallbackjaként
3
+ * szolgálunk ki, ha nincs fallbackPath (nem-SPA mód) és a kérés nem egy létező static fájlra mutat.
4
+ */
5
+ export const DyNTS_defaultNotFoundPageHtml: string =
6
+ '<!DOCTYPE html>\n' +
7
+ '<html lang="en">\n' +
8
+ '<head>\n' +
9
+ ' <meta charset="utf-8">\n' +
10
+ ' <meta name="viewport" content="width=device-width, initial-scale=1">\n' +
11
+ ' <title>Page not found</title>\n' +
12
+ ' <style>\n' +
13
+ ' body { font-family: system-ui, sans-serif; margin: 2rem; text-align: center; }\n' +
14
+ ' h1 { font-size: 1.5rem; color: #333; }\n' +
15
+ ' p { color: #666; }\n' +
16
+ ' </style>\n' +
17
+ '</head>\n' +
18
+ '<body>\n' +
19
+ ' <h1>Page not found</h1>\n' +
20
+ ' <p>The requested resource could not be found.</p>\n' +
21
+ '</body>\n' +
22
+ '</html>\n';
@@ -0,0 +1,12 @@
1
+ import { DyNTS_defaultSocketPath } from './default-socket-path.const';
2
+
3
+ describe('| DyNTS_defaultSocketPath', () => {
4
+ it('| should export default socket path as \'/socket\'', () => {
5
+ expect(DyNTS_defaultSocketPath).toBe('/socket');
6
+ });
7
+
8
+ it('| should be a non-empty string', () => {
9
+ expect(typeof DyNTS_defaultSocketPath).toBe('string');
10
+ expect(DyNTS_defaultSocketPath.length).toBeGreaterThan(0);
11
+ });
12
+ });
@@ -0,0 +1,2 @@
1
+ /** Default Socket.IO path, ha a portSettings.socketPath nincs megadva. */
2
+ export const DyNTS_defaultSocketPath: string = '/socket';
@@ -8,6 +8,7 @@ describe('| DyNTS_Http_Settings', () => {
8
8
 
9
9
  expect(settings.httpPort).toBeUndefined();
10
10
  expect(settings.httpsPort).toBeUndefined();
11
+ expect(settings.socketPath).toBeUndefined();
11
12
  expect(settings.httpUrlencoded).toEqual({
12
13
  limit: '50mb',
13
14
  extended: true,
@@ -63,4 +64,14 @@ describe('| DyNTS_Http_Settings', () => {
63
64
  limit: '100mb',
64
65
  } as BodyParser.OptionsJson);
65
66
  });
67
+
68
+ it('| should have socketPath undefined when not provided', () => {
69
+ const settings = new DyNTS_Http_Settings();
70
+ expect(settings.socketPath).toBeUndefined();
71
+ });
72
+
73
+ it('| should set socketPath when provided in constructor', () => {
74
+ const settings = new DyNTS_Http_Settings({ socketPath: '/ws' });
75
+ expect(settings.socketPath).toBe('/ws');
76
+ });
66
77
  });
@@ -1,8 +1,16 @@
1
1
 
2
2
  import * as BodyParser from 'body-parser';
3
+
4
+ /**
5
+ * HTTP/HTTPS és Socket.IO port és body parser beállítások.
6
+ * socketPath: ha nincs megadva, DyNTS_defaultSocketPath marad;
7
+ * a kliensnek ugyanazt a path-ot kell használnia.
8
+ */
3
9
  export class DyNTS_Http_Settings {
4
10
  httpPort?: number;
5
11
  httpsPort?: number;
12
+ /** Socket.IO path (pl. '/ws'); ha üres, default: DyNTS_defaultSocketPath. */
13
+ socketPath?: string;
6
14
 
7
15
  httpUrlencoded?: BodyParser.OptionsUrlencoded = {
8
16
  limit: '50mb',
@@ -0,0 +1,29 @@
1
+ import { DyNTS_StaticClient_Settings } from './static-client-settings.interface';
2
+
3
+ describe('| DyNTS_StaticClient_Settings', () => {
4
+ it('| should allow minimal settings with only root', () => {
5
+ const s: DyNTS_StaticClient_Settings = { root: '/dist' };
6
+ expect(s.root).toBe('/dist');
7
+ expect(s.fallbackPath).toBeUndefined();
8
+ });
9
+
10
+ it('| should allow optional fallbackPath', () => {
11
+ const s: DyNTS_StaticClient_Settings = {
12
+ root: '/dist',
13
+ fallbackPath: 'index.html',
14
+ };
15
+ expect(s.fallbackPath).toBe('index.html');
16
+ });
17
+
18
+ it('| should allow SPA cache options', () => {
19
+ const s: DyNTS_StaticClient_Settings = {
20
+ root: '/dist',
21
+ assetCacheMaxAge: 31536000,
22
+ assetCacheImmutable: true,
23
+ fallbackCacheMaxAge: 0,
24
+ };
25
+ expect(s.assetCacheMaxAge).toBe(31536000);
26
+ expect(s.assetCacheImmutable).toBe(true);
27
+ expect(s.fallbackCacheMaxAge).toBe(0);
28
+ });
29
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Beállítások a client static fájlok kiszolgálásához (pl. SPA) a '/' path alatt.
3
+ * Ha megadva, a getStaticClientSettings() által visszaadott értéket a base app
4
+ * a mountStaticClient() során használja (API route-ok után).
5
+ * A cache mezők SPA (pl. Angular) optimalizáláshoz opcionálisak; ha nincs kitöltve,
6
+ * viselkedés változatlan (alkalmas nem-SPA kiszolgálásra is).
7
+ */
8
+ export interface DyNTS_StaticClient_Settings {
9
+ /** A static fájlok könyvtárának path-ja (abszolút vagy process.cwd()-hez képest). */
10
+ root: string;
11
+ /** SPA fallback: ha a kérés nem egy fájlra mutat, ezt a fájlt szolgáljuk ki (pl. 'index.html'). */
12
+ fallbackPath?: string;
13
+ /**
14
+ * Static asset-ek (pl. JS, CSS) Cache-Control max-age másodpercben.
15
+ * SPA (Angular) hashed fájloknál pl. 1 év (31536000).
16
+ */
17
+ assetCacheMaxAge?: number;
18
+ /**
19
+ * Ha true és assetCacheMaxAge is megadva, Cache-Control-hoz hozzáadódik az immutable direktíva
20
+ * (Angular hashed fájlokra ideális).
21
+ */
22
+ assetCacheImmutable?: boolean;
23
+ /**
24
+ * Fallback (pl. index.html) Cache-Control max-age másodpercben.
25
+ * SPA esetén ajánlott 0, hogy a böngésző ne cache-elje az index.html-t (deploy után friss).
26
+ */
27
+ fallbackCacheMaxAge?: number;
28
+ }
@@ -96,7 +96,7 @@ export class DyNTS_AppExtendedFull_Mock extends DyNTS_AppExtended {
96
96
 
97
97
  getPortSettings(): DyNTS_Http_Settings {
98
98
  return {
99
- httpPort: 54534,
99
+ httpPort: 0,
100
100
  };
101
101
  }
102
102
 
@@ -167,7 +167,7 @@ export class DyNTS_AppWbMock_Mock extends DyNTS_AppExtended {
167
167
 
168
168
  getPortSettings(): DyNTS_Http_Settings {
169
169
  return {
170
- httpPort: 54535,
170
+ httpPort: 0,
171
171
  };
172
172
  }
173
173
 
@@ -0,0 +1,51 @@
1
+ import { DyNTS_App_Params } from '../../_models/control-models/app-params.control-model';
2
+ import { DyNTS_Http_Settings } from '../../_models/control-models/http-settings.control-model';
3
+ import { DyNTS_StaticClient_Settings } from '../../_models/interfaces/static-client-settings.interface';
4
+ import { DyNTS_AppWbMock_Mock } from './app-extended-server.mock';
5
+
6
+ /**
7
+ * Integrációs tesztekhez használt mock app: DB nélkül indul, unified host beállításokkal
8
+ * (static client root, API base path, socket path). A static root-ot a spec állítja
9
+ * beforeAll-ban az integrationStaticRoot statikus property-n keresztül.
10
+ */
11
+ export class DyNTS_AppIntegrationTest_Mock extends DyNTS_AppWbMock_Mock {
12
+
13
+ /** A spec beforeAll-ban beállítja; getStaticClientSettings() ezt használja root-ként. */
14
+ static integrationStaticRoot: string = '';
15
+
16
+ override getAppParams(): DyNTS_App_Params {
17
+ return new DyNTS_App_Params({
18
+ name: 'nts-integration-test',
19
+ version: '1.0.0',
20
+ systemShortCodeName: 'NIT',
21
+ });
22
+ }
23
+
24
+ override getPortSettings(): DyNTS_Http_Settings {
25
+ return {
26
+ httpPort: 0,
27
+ socketPath: '/socket',
28
+ };
29
+ }
30
+
31
+ /** Az OS által kiosztott tényleges port; ready() után elérhető. */
32
+ get resolvedPort(): number {
33
+ const addr = this.httpServer?.address?.();
34
+
35
+ return (typeof addr === 'object' && addr) ? addr.port : 0;
36
+ }
37
+
38
+ override getApiBasePath(): string {
39
+ return '/api';
40
+ }
41
+
42
+ override getStaticClientSettings(): DyNTS_StaticClient_Settings | undefined {
43
+ if (!DyNTS_AppIntegrationTest_Mock.integrationStaticRoot) {
44
+ return undefined;
45
+ }
46
+ return {
47
+ root: DyNTS_AppIntegrationTest_Mock.integrationStaticRoot,
48
+ fallbackPath: undefined,
49
+ };
50
+ }
51
+ }
@@ -85,7 +85,7 @@ export class DyNTS_AppFull_Mock extends DyNTS_App {
85
85
 
86
86
  getPortSettings(): DyNTS_Http_Settings {
87
87
  return {
88
- httpPort: 20101,
88
+ httpPort: 0,
89
89
  };
90
90
  }
91
91
 
@@ -172,7 +172,7 @@ export class DyNTS_AppTEST_Mock extends DyNTS_App {
172
172
 
173
173
  getPortSettings(): DyNTS_Http_Settings {
174
174
  return {
175
- httpPort: 10203,
175
+ httpPort: 0,
176
176
  };
177
177
  }
178
178
 
@@ -34,7 +34,7 @@ describe('| SocketClient_Mock', () => {
34
34
  expect(params).toEqual(jasmine.any(DyNTS_SocketClientService_Params));
35
35
  expect(params.service).toBe('-test-socket-target-');
36
36
  expect(params.name).toBe('socket-client-mock');
37
- expect(params.port).toBe(30303);
37
+ expect(params.port).toBe(0);
38
38
  expect(params.socketOptions.reconnection).toBeTrue();
39
39
  });
40
40
  });
@@ -34,7 +34,7 @@ export class SocketClient_Mock extends DyNTS_SocketClient_ServiceBase {
34
34
  return new DyNTS_SocketClientService_Params({
35
35
  service: '-test-socket-target-',
36
36
  name: 'socket-client-mock',
37
- port: 30303,
37
+ port: 0,
38
38
  socketOptions: {
39
39
  reconnection: true,
40
40
  },
@@ -20,7 +20,7 @@ describe('| DyNTS_SocketServer_Mock', () => {
20
20
 
21
21
  expect(params).toBeInstanceOf(DyNTS_SocketServerService_Params);
22
22
  expect(params.name).toBe('test');
23
- expect(params.port).toBe(19393); // Updated from 9393 to 19393
23
+ expect(params.port).toBe(0);
24
24
  });
25
25
 
26
26
  it('| should return an empty array for incoming events', () => {
@@ -1,6 +1,5 @@
1
1
  import { DyFM_SocketEvent } from '@futdevpro/fsm-dynamo/socket';
2
2
  import { Socket } from 'socket.io';
3
- import * as net from 'net';
4
3
 
5
4
  import {
6
5
  DyNTS_SocketPresence
@@ -10,28 +9,21 @@ import {
10
9
  } from '../socket/_models/socket-server-service-params.control-model';
11
10
  import { DyNTS_SocketServerService } from '../socket/_services/socket-server.service';
12
11
 
13
- /**
14
- * Utility function to find an available port starting from a base port
15
- */
16
- const findAvailablePort = (basePort: number): number => {
17
- return basePort; // For now, return the base port, but this could be enhanced
18
- };
19
-
20
12
  /**
21
13
  * Mock Socket Server Service for testing purposes
22
- * Uses a non-privileged port to avoid EACCES errors on Windows
14
+ * Uses port 0 so the OS assigns a random available port
23
15
  */
24
- export class DyNTS_SocketServer_Mock extends
16
+ export class DyNTS_SocketServer_Mock extends
25
17
  DyNTS_SocketServerService<DyNTS_SocketPresence> {
26
-
18
+
27
19
  static getInstance(): DyNTS_SocketServer_Mock {
28
20
  return DyNTS_SocketServer_Mock.getSingletonInstance();
29
21
  }
30
-
22
+
31
23
  getServiceParams(): DyNTS_SocketServerService_Params<any> {
32
24
  return new DyNTS_SocketServerService_Params({
33
25
  name: 'test',
34
- port: findAvailablePort(19393), // Changed from 9393 to 19393 (non-privileged port)
26
+ port: 0,
35
27
  });
36
28
  }
37
29
 
@@ -508,8 +508,12 @@ export abstract class DyNTS_SocketServerService<
508
508
  await this.closeSocket(socket, `${this.params.name} on connection error`, error);
509
509
  }
510
510
  });
511
-
512
- if (options?.attachedToExistingServer) {
511
+
512
+ const isAttach: boolean =
513
+ options?.attachedToExistingServer === true ||
514
+ (this.params.port === undefined && options?.effectivePort !== undefined);
515
+
516
+ if (isAttach) {
513
517
  DyFM_Log.success(
514
518
  `\nsocket server setup finished: "${this.params.name}"` +
515
519
  (effectivePort !== undefined ? ` (attached to server on port: ${effectivePort})` : ' (attached to existing server)')
@@ -0,0 +1,85 @@
1
+ import * as Fs from 'fs';
2
+ import * as Os from 'os';
3
+ import * as Path from 'path';
4
+
5
+ import Axios from 'axios';
6
+
7
+ import { DyNTS_defaultNotFoundPageHtml } from '../../_collections/default-not-found-page.const';
8
+ import { DyNTS_AppIntegrationTest_Mock } from '../mock/app-integration-test.mock';
9
+
10
+ let INTEGRATION_BASE_URL: string = '';
11
+ const INTEGRATION_READY_TIMEOUT_MS: number = 10000;
12
+
13
+ describe('| DyNTS_AppExtended (integration)', (): void => {
14
+ beforeAll((): void => {
15
+ jasmine.DEFAULT_TIMEOUT_INTERVAL = INTEGRATION_READY_TIMEOUT_MS + 5000;
16
+ });
17
+
18
+ let app: DyNTS_AppIntegrationTest_Mock;
19
+ let tempDir: string = '';
20
+
21
+ beforeAll(async (): Promise<void> => {
22
+ tempDir = Fs.mkdtempSync(Path.join(Os.tmpdir(), 'dynts-int-'));
23
+ const indexContent: string = '<!DOCTYPE html><html><body>Integration test index</body></html>';
24
+ Fs.writeFileSync(Path.join(tempDir, 'index.html'), indexContent, { encoding: 'utf-8' });
25
+
26
+ DyNTS_AppIntegrationTest_Mock.integrationStaticRoot = tempDir;
27
+ app = new DyNTS_AppIntegrationTest_Mock();
28
+ await app.ready(INTEGRATION_READY_TIMEOUT_MS);
29
+
30
+ INTEGRATION_BASE_URL = `http://localhost:${app.resolvedPort}`;
31
+ });
32
+
33
+ afterAll(async (): Promise<void> => {
34
+ try {
35
+ if (app?.started) {
36
+ await app.stop();
37
+ }
38
+ } catch {
39
+ // stop() hiba (pl. socket server már leállt) ne szakítsa meg a suite-ot
40
+ }
41
+ if (tempDir && Fs.existsSync(tempDir)) {
42
+ Fs.rmSync(tempDir, { recursive: true });
43
+ }
44
+ });
45
+
46
+ it('| app elindul és started true', (): void => {
47
+ expect(app.started).toBe(true);
48
+ });
49
+
50
+ it('| GET nem létező path -> 404 és default "Page not found" HTML', async (): Promise<void> => {
51
+ const response = await Axios.get(`${INTEGRATION_BASE_URL}/nonexistent-path-xyz`, {
52
+ validateStatus: (): boolean => true,
53
+ responseType: 'text',
54
+ });
55
+ expect(response.status).toBe(404);
56
+ expect(response.headers['content-type']).toContain('html');
57
+ expect(typeof response.data).toBe('string');
58
+ expect((response.data as string).trim()).toContain('Page not found');
59
+ expect(response.data).toBe(DyNTS_defaultNotFoundPageHtml);
60
+ });
61
+
62
+ it('| GET /index.html -> 200 és static tartalom', async (): Promise<void> => {
63
+ const response = await Axios.get(`${INTEGRATION_BASE_URL}/index.html`, {
64
+ responseType: 'text',
65
+ });
66
+ expect(response.status).toBe(200);
67
+ expect(response.data).toContain('Integration test index');
68
+ });
69
+
70
+ it('| GET API base path alatt (mock route) -> 200', async (): Promise<void> => {
71
+ const response = await Axios.get(`${INTEGRATION_BASE_URL}/api/test-0/test-base`, {
72
+ responseType: 'text',
73
+ });
74
+ expect(response.status).toBe(200);
75
+ expect(response.data).toBe('test-base');
76
+ });
77
+
78
+ it('| GET API másik endpoint -> 200', async (): Promise<void> => {
79
+ const response = await Axios.get(`${INTEGRATION_BASE_URL}/api/test-0/test-simple`, {
80
+ responseType: 'text',
81
+ });
82
+ expect(response.status).toBe(200);
83
+ expect(response.data).toBe('test-simple');
84
+ });
85
+ });
@@ -12,6 +12,7 @@ import {
12
12
  DyFM_Log,
13
13
  } from '@futdevpro/fsm-dynamo';
14
14
 
15
+ import { DyNTS_defaultSocketPath } from '../../_collections/default-socket-path.const';
15
16
  import { DyNTS_global_settings } from '../../_collections/global-settings.const';
16
17
  import { DyNTS_RouteSecurity } from '../../_enums/route-security.enum';
17
18
  import {
@@ -438,6 +439,7 @@ export abstract class DyNTS_AppExtended extends DyNTS_App {
438
439
  * ha a service.port nincs megadva, a getPortSettings() httpPort/httpsPort értékét használjuk.
439
440
  * Ha a base app már listenel (httpServer/httpsServer), arra attacholjuk a Socket.IO-t,
440
441
  * különben külön httpSocketServer-t hozunk létre és listenelünk.
442
+ * A Socket.IO path a portSettings.socketPath-ből jön (default: DyNTS_defaultSocketPath); a kliensnek ugyanazt kell használnia.
441
443
  */
442
444
  private async setupSocketServerServices(): Promise<void> {
443
445
  try {
@@ -519,9 +521,10 @@ export abstract class DyNTS_AppExtended extends DyNTS_App {
519
521
  this.httpSocketSettingUpCount++;
520
522
  this.systemControlsExt.httpSocketServer.started = false;
521
523
 
524
+ const socketPath: string = this.portSettings.socketPath ?? DyNTS_defaultSocketPath;
522
525
  this.allSocketServers.push(
523
526
  await service.setupSocketServer(
524
- new SocketIO.Server(serverForOpen),
527
+ new SocketIO.Server(serverForOpen, { path: socketPath }),
525
528
  DyNTS_SocketSecurity.open,
526
529
  (): void => {
527
530
  this.httpSocketSettingUpCount--;
@@ -546,9 +549,10 @@ export abstract class DyNTS_AppExtended extends DyNTS_App {
546
549
  this.httpsSocketSettingUpCount++;
547
550
  this.systemControlsExt.httpsSocketServer.started = false;
548
551
 
552
+ const socketPathSecure: string = this.portSettings.socketPath ?? DyNTS_defaultSocketPath;
549
553
  this.allSocketServers.push(
550
554
  await service.setupSocketServer(
551
- new SocketIO.Server(this.httpsServer),
555
+ new SocketIO.Server(this.httpsServer, { path: socketPathSecure }),
552
556
  DyNTS_SocketSecurity.secure,
553
557
  (): void => {
554
558
  this.httpsSocketSettingUpCount--;
@@ -1327,7 +1327,7 @@ export class DyNTS_DataService<T extends DyFM_Metadata> {
1327
1327
  ...this._getDefaultErrorSettings(
1328
1328
  'validateByPropertyParams',
1329
1329
  new Error(
1330
- 'Validation failed! (multiple validation errors)' +
1330
+ `Validation failed! (multiple validation errors for ${this.dataParams.dataName})` +
1331
1331
  validationErrors.map((error: DyFM_Error) => `\n ${DyFM_Error.getAnyMessage(error)}`).join('')
1332
1332
  )
1333
1333
  ),
@@ -1367,10 +1367,7 @@ export class DyNTS_DataService<T extends DyFM_Metadata> {
1367
1367
  ): void {
1368
1368
  // basic required validations
1369
1369
  if (
1370
- (
1371
- propertyParams.required ||
1372
- propertyParams.index
1373
- ) && (
1370
+ propertyParams.required && (
1374
1371
  propertyValue === null ||
1375
1372
  propertyValue === undefined
1376
1373
  )
@@ -1380,7 +1377,7 @@ export class DyNTS_DataService<T extends DyFM_Metadata> {
1380
1377
  'validateProperty',
1381
1378
  new Error(
1382
1379
  `validateProperty failed, "${this.getPropertyKey(propertyParams, isSubObjectOf)}" is missing! ` +
1383
- `(index or required in "${this.dataParams.dataName}" dataParams) ` +
1380
+ `(required in "${this.dataParams.dataName}" dataParams) ` +
1384
1381
  ((data as any)?.name ? `\n The failed data's name: ${(data as any).name}` : '')
1385
1382
  )
1386
1383
  ),
@@ -1391,7 +1388,7 @@ export class DyNTS_DataService<T extends DyFM_Metadata> {
1391
1388
  validationErrors: {
1392
1389
  [propertyParams.key]: {
1393
1390
  message: `validateProperty failed, "${this.getPropertyKey(propertyParams, isSubObjectOf)}" is missing! ` +
1394
- `(index or required in "${this.dataParams.dataName}" dataParams) ` +
1391
+ `(required in "${this.dataParams.dataName}" dataParams) ` +
1395
1392
  ((data as any)?.name ? `\n The failed data's name: ${(data as any).name}` : ''),
1396
1393
  code: `${this.ecBase}DyNTS-DS0-VP1`,
1397
1394
  userMessage: 'The property is required and must be a valid value!',
@@ -1495,11 +1495,17 @@ export class DyNTS_DBService<T extends DyFM_Metadata> {
1495
1495
  }
1496
1496
 
1497
1497
  if (!properties._deletedBy) {
1498
- properties._deletedBy = {
1498
+ properties._deletedBy = {
1499
1499
  key: '_deletedBy', type: DyFM_BasicProperty_Type.string,
1500
1500
  };
1501
1501
  }
1502
1502
 
1503
+ if (!properties._archived) {
1504
+ properties._archived = {
1505
+ key: '_archived', type: DyFM_BasicProperty_Type.date,
1506
+ };
1507
+ }
1508
+
1503
1509
  return properties;
1504
1510
  }
1505
1511
 
@@ -1521,10 +1527,12 @@ export class DyNTS_DBService<T extends DyFM_Metadata> {
1521
1527
  }
1522
1528
 
1523
1529
  if (!properties._archived) {
1524
- properties._archived = {
1530
+ properties._archived = {
1525
1531
  key: '_archived', type: DyFM_BasicProperty_Type.date,
1526
- required: true,
1532
+ required: true,
1527
1533
  };
1534
+ } else if (properties._archived.required === undefined) {
1535
+ properties._archived.required = true;
1528
1536
  }
1529
1537
 
1530
1538
  return properties;
@@ -1,6 +1,7 @@
1
1
 
2
2
  import { DyFM_Error, DyFM_HttpCallType } from '@futdevpro/fsm-dynamo';
3
3
 
4
+ import { DyNTS_global_settings } from '../../_collections/global-settings.const';
4
5
  import { DyNTS_RouteSecurity } from '../../_enums/route-security.enum';
5
6
  import { DyNTS_Endpoint_Params } from '../../_models/control-models/endpoint-params.control-model';
6
7
  import {
@@ -80,4 +81,18 @@ describe('| DyNTS_RoutingModule', () => {
80
81
  routingModule.endpoints = [ mockEndpoint, mockEndpoint ];
81
82
  expect(() => routingModule['mountRoutes']()).toThrowError(/ENDPOINT DUPLICATION/);
82
83
  });
84
+
85
+ it('| should use DyNTS_global_settings.baseUrl as route prefix', () => {
86
+ const originalBaseUrl: string = DyNTS_global_settings.baseUrl;
87
+ try {
88
+ DyNTS_global_settings.baseUrl = '/custom-api';
89
+ const moduleWithCustomBase: DyNTS_RoutingModule = new DyNTS_RoutingModule({
90
+ route: '/foo',
91
+ controllers: [ mockController ],
92
+ });
93
+ expect(moduleWithCustomBase.route).toBe('/custom-api/foo');
94
+ } finally {
95
+ DyNTS_global_settings.baseUrl = originalBaseUrl;
96
+ }
97
+ });
83
98
  });