@futdevpro/nts-dynamo 1.15.8 → 1.15.10

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 (89) hide show
  1. package/.cursor/rules/_ag_frontend-structure.mdc +5 -5
  2. package/__documentations/nts-integration-tests-2026-03-17.md +26 -0
  3. package/build/_collections/default-fallback-cache-max-age.const.d.ts +3 -0
  4. package/build/_collections/default-fallback-cache-max-age.const.d.ts.map +1 -0
  5. package/build/_collections/default-fallback-cache-max-age.const.js +6 -0
  6. package/build/_collections/default-fallback-cache-max-age.const.js.map +1 -0
  7. package/build/_collections/default-not-found-page.const.d.ts +6 -0
  8. package/build/_collections/default-not-found-page.const.d.ts.map +1 -0
  9. package/build/_collections/default-not-found-page.const.js +25 -0
  10. package/build/_collections/default-not-found-page.const.js.map +1 -0
  11. package/build/_collections/default-socket-path.const.d.ts +3 -0
  12. package/build/_collections/default-socket-path.const.d.ts.map +1 -0
  13. package/build/_collections/default-socket-path.const.js +6 -0
  14. package/build/_collections/default-socket-path.const.js.map +1 -0
  15. package/build/_models/control-models/http-settings.control-model.d.ts +7 -0
  16. package/build/_models/control-models/http-settings.control-model.d.ts.map +1 -1
  17. package/build/_models/control-models/http-settings.control-model.js +7 -0
  18. package/build/_models/control-models/http-settings.control-model.js.map +1 -1
  19. package/build/_models/interfaces/static-client-settings.interface.d.ts +29 -0
  20. package/build/_models/interfaces/static-client-settings.interface.d.ts.map +1 -0
  21. package/build/_models/interfaces/static-client-settings.interface.js +3 -0
  22. package/build/_models/interfaces/static-client-settings.interface.js.map +1 -0
  23. package/build/_modules/mock/app-extended-server.mock.js +2 -2
  24. package/build/_modules/mock/app-extended-server.mock.js.map +1 -1
  25. package/build/_modules/mock/app-integration-test.mock.d.ts +20 -0
  26. package/build/_modules/mock/app-integration-test.mock.d.ts.map +1 -0
  27. package/build/_modules/mock/app-integration-test.mock.js +46 -0
  28. package/build/_modules/mock/app-integration-test.mock.js.map +1 -0
  29. package/build/_modules/mock/app-server.mock.js +2 -2
  30. package/build/_modules/mock/app-server.mock.js.map +1 -1
  31. package/build/_modules/mock/socket-client.mock.js +1 -1
  32. package/build/_modules/mock/socket-client.mock.js.map +1 -1
  33. package/build/_modules/mock/socket-server.mock.d.ts +1 -1
  34. package/build/_modules/mock/socket-server.mock.d.ts.map +1 -1
  35. package/build/_modules/mock/socket-server.mock.js +2 -8
  36. package/build/_modules/mock/socket-server.mock.js.map +1 -1
  37. package/build/_modules/server/errors/errors.data-service.d.ts.map +1 -1
  38. package/build/_modules/server/errors/errors.data-service.js +20 -9
  39. package/build/_modules/server/errors/errors.data-service.js.map +1 -1
  40. package/build/_modules/socket/_services/socket-server.service.d.ts.map +1 -1
  41. package/build/_modules/socket/_services/socket-server.service.js +3 -1
  42. package/build/_modules/socket/_services/socket-server.service.js.map +1 -1
  43. package/build/_modules/socket/app-extended.server.d.ts +1 -0
  44. package/build/_modules/socket/app-extended.server.d.ts.map +1 -1
  45. package/build/_modules/socket/app-extended.server.js +6 -2
  46. package/build/_modules/socket/app-extended.server.js.map +1 -1
  47. package/build/_services/base/data.service.d.ts.map +1 -1
  48. package/build/_services/base/data.service.js +4 -5
  49. package/build/_services/base/data.service.js.map +1 -1
  50. package/build/_services/base/db.service.d.ts.map +1 -1
  51. package/build/_services/base/db.service.js +8 -0
  52. package/build/_services/base/db.service.js.map +1 -1
  53. package/build/_services/server/app.server.d.ts +18 -0
  54. package/build/_services/server/app.server.d.ts.map +1 -1
  55. package/build/_services/server/app.server.js +74 -2
  56. package/build/_services/server/app.server.js.map +1 -1
  57. package/build/index.d.ts +4 -0
  58. package/build/index.d.ts.map +1 -1
  59. package/build/index.js +4 -0
  60. package/build/index.js.map +1 -1
  61. package/nodemon.json +2 -1
  62. package/package.json +4 -4
  63. package/src/_collections/default-fallback-cache-max-age.const.spec.ts +11 -0
  64. package/src/_collections/default-fallback-cache-max-age.const.ts +2 -0
  65. package/src/_collections/default-not-found-page.const.spec.ts +19 -0
  66. package/src/_collections/default-not-found-page.const.ts +22 -0
  67. package/src/_collections/default-socket-path.const.spec.ts +12 -0
  68. package/src/_collections/default-socket-path.const.ts +2 -0
  69. package/src/_models/control-models/http-settings.control-model.spec.ts +11 -0
  70. package/src/_models/control-models/http-settings.control-model.ts +8 -0
  71. package/src/_models/interfaces/static-client-settings.interface.spec.ts +29 -0
  72. package/src/_models/interfaces/static-client-settings.interface.ts +28 -0
  73. package/src/_modules/mock/app-extended-server.mock.ts +2 -2
  74. package/src/_modules/mock/app-integration-test.mock.ts +51 -0
  75. package/src/_modules/mock/app-server.mock.ts +2 -2
  76. package/src/_modules/mock/socket-client.mock.spec.ts +1 -1
  77. package/src/_modules/mock/socket-client.mock.ts +1 -1
  78. package/src/_modules/mock/socket-server.mock.spec.ts +1 -1
  79. package/src/_modules/mock/socket-server.mock.ts +5 -13
  80. package/src/_modules/server/errors/errors.data-service.spec.ts +6 -6
  81. package/src/_modules/server/errors/errors.data-service.ts +24 -9
  82. package/src/_modules/socket/_services/socket-server.service.ts +6 -2
  83. package/src/_modules/socket/app-extended.integration.spec.ts +85 -0
  84. package/src/_modules/socket/app-extended.server.ts +6 -2
  85. package/src/_services/base/data.service.ts +4 -7
  86. package/src/_services/base/db.service.ts +11 -3
  87. package/src/_services/route/routing-module.service.spec.ts +15 -0
  88. package/src/_services/server/app.server.ts +107 -2
  89. package/src/index.ts +4 -0
@@ -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
  });
@@ -8,6 +8,7 @@ import * as BodyParser from 'body-parser';
8
8
  import * as FileSystem from 'fs';
9
9
  import * as Http from 'http';
10
10
  import * as Https from 'https';
11
+ import * as Path from 'path';
11
12
  import * as dotenv from 'dotenv'
12
13
 
13
14
  /* import { version } from '../../../package.json'; */
@@ -25,6 +26,8 @@ import {
25
26
  second
26
27
  } from '@futdevpro/fsm-dynamo';
27
28
 
29
+ import { DyNTS_defaultFallbackCacheMaxAge } from '../../_collections/default-fallback-cache-max-age.const';
30
+ import { DyNTS_defaultNotFoundPageHtml } from '../../_collections/default-not-found-page.const';
28
31
  import { DyNTS_global_settings } from '../../_collections/global-settings.const';
29
32
  import { DyNTS_RouteSecurity } from '../../_enums/route-security.enum';
30
33
  import { DyNTS_App_Params } from '../../_models/control-models/app-params.control-model';
@@ -41,6 +44,9 @@ import {
41
44
  import {
42
45
  DyNTS_GlobalService_Settings
43
46
  } from '../../_models/interfaces/global-service-settings.interface';
47
+ import {
48
+ DyNTS_StaticClient_Settings
49
+ } from '../../_models/interfaces/static-client-settings.interface';
44
50
  import { DyNTS_SingletonService } from '../base/singleton.service';
45
51
  import { DyNTS_GlobalService } from '../core/global.service';
46
52
  import { DyNTS_RoutingModule } from '../route/routing-module.service';
@@ -457,6 +463,10 @@ export abstract class DyNTS_App extends DyNTS_SingletonService {
457
463
  this._cert = this.getCertificationSettings();
458
464
  }
459
465
 
466
+ if (this.getApiBasePath) {
467
+ DyNTS_global_settings.baseUrl = this.getApiBasePath();
468
+ }
469
+
460
470
  if (this.getRoutingModules) {
461
471
  this._routingModules = this.getRoutingModules();
462
472
 
@@ -499,6 +509,8 @@ export abstract class DyNTS_App extends DyNTS_SingletonService {
499
509
  await this.mountSecureRoutes();
500
510
  }
501
511
 
512
+ await this.mountStaticClient();
513
+
502
514
  if (this.logSetup) {
503
515
  DyFM_Log.log(`\nRoutes mounted.... server using security: ${this._security}`);
504
516
  }
@@ -951,7 +963,7 @@ export abstract class DyNTS_App extends DyNTS_SingletonService {
951
963
 
952
964
  try {
953
965
  if (this._security && this._security !== DyNTS_RouteSecurity.secure) {
954
- if (!this._portSettings.httpPort) {
966
+ if (this._portSettings.httpPort === undefined || this._portSettings.httpPort === null) {
955
967
  let errorMsg: string =
956
968
  `\nYou have open routes, but httpPort is not set!` +
957
969
  `\nThere are ${this._routingModules.filter(
@@ -1151,9 +1163,19 @@ export abstract class DyNTS_App extends DyNTS_SingletonService {
1151
1163
  this.params.expressBacklog,
1152
1164
  (): void => {
1153
1165
  this.systemControls.httpServer.started = true;
1166
+
1167
+ const resolvedPort: number = this.httpServer?.address?.()?.['port'] ?? this._portSettings.httpPort;
1168
+
1169
+ if (this._portSettings.httpPort === 0) {
1170
+ DyFM_Log.H_warn(
1171
+ `\nHTTP (open) server is using a randomly selected port by the OS: ${resolvedPort}` +
1172
+ `\n (httpPort was set to 0 — this is intended for testing only)`
1173
+ );
1174
+ }
1175
+
1154
1176
  DyFM_Log.success(
1155
1177
  `\nHTTP (open) server is listening on port: ` +
1156
- `${this.params.openHost}:${this._portSettings.httpPort}`
1178
+ `${this.params.openHost}:${resolvedPort}`
1157
1179
  );
1158
1180
 
1159
1181
  resolve();
@@ -1374,6 +1396,77 @@ export abstract class DyNTS_App extends DyNTS_SingletonService {
1374
1396
  }
1375
1397
  }
1376
1398
 
1399
+ /**
1400
+ * Ha getStaticClientSettings() visszaad beállításokat, a client static fájlok a '/' alatt
1401
+ * lesznek kiszolgálva (API route-ok után). SPA fallback opcionális (fallbackPath).
1402
+ * Asset cache (assetCacheMaxAge, assetCacheImmutable) és fallback cache (fallbackCacheMaxAge)
1403
+ * opcionálisak; ha nincs megadva fallbackCacheMaxAge, DyNTS_defaultFallbackCacheMaxAge (0) marad.
1404
+ */
1405
+ private async mountStaticClient(): Promise<void> {
1406
+ const settings: DyNTS_StaticClient_Settings | undefined = this.getStaticClientSettings?.();
1407
+ if (!settings) {
1408
+ return;
1409
+ }
1410
+
1411
+ const absoluteRoot: string = Path.isAbsolute(settings.root)
1412
+ ? settings.root
1413
+ : Path.resolve(process.cwd(), settings.root);
1414
+
1415
+ const hasAssetCache: boolean =
1416
+ settings.assetCacheMaxAge !== undefined || settings.assetCacheImmutable === true;
1417
+ const staticOptions: { setHeaders: (res: Express.Response) => void } | undefined =
1418
+ hasAssetCache && settings.assetCacheMaxAge !== undefined
1419
+ ? {
1420
+ setHeaders: (res: Express.Response): void => {
1421
+ const maxAge: number = settings.assetCacheMaxAge!;
1422
+ const immutable: string =
1423
+ settings.assetCacheImmutable === true ? ', immutable' : '';
1424
+ res.setHeader('Cache-Control', `max-age=${maxAge}${immutable}`);
1425
+ },
1426
+ }
1427
+ : undefined;
1428
+
1429
+ const staticMiddleware: Express.Handler =
1430
+ staticOptions
1431
+ ? Express.static(absoluteRoot, staticOptions)
1432
+ : Express.static(absoluteRoot);
1433
+
1434
+ const fallbackMaxAge: number =
1435
+ settings.fallbackCacheMaxAge ?? DyNTS_defaultFallbackCacheMaxAge;
1436
+
1437
+ if (this.openExpress) {
1438
+ this.openExpress.use('/', staticMiddleware);
1439
+ if (settings.fallbackPath) {
1440
+ this.openExpress.get('*', (req: Express.Request, res: Express.Response): void => {
1441
+ res.setHeader('Cache-Control', `max-age=${fallbackMaxAge}`);
1442
+ res.sendFile(settings.fallbackPath!, { root: absoluteRoot });
1443
+ });
1444
+ } else {
1445
+ this.openExpress.get('*', (req: Express.Request, res: Express.Response): void => {
1446
+ res.status(404).type('html').send(DyNTS_defaultNotFoundPageHtml);
1447
+ });
1448
+ }
1449
+ }
1450
+
1451
+ if (this.secureExpress) {
1452
+ this.secureExpress.use('/', staticMiddleware);
1453
+ if (settings.fallbackPath) {
1454
+ this.secureExpress.get('*', (req: Express.Request, res: Express.Response): void => {
1455
+ res.setHeader('Cache-Control', `max-age=${fallbackMaxAge}`);
1456
+ res.sendFile(settings.fallbackPath!, { root: absoluteRoot });
1457
+ });
1458
+ } else {
1459
+ this.secureExpress.get('*', (req: Express.Request, res: Express.Response): void => {
1460
+ res.status(404).type('html').send(DyNTS_defaultNotFoundPageHtml);
1461
+ });
1462
+ }
1463
+ }
1464
+
1465
+ if (this.logSetup) {
1466
+ DyFM_Log.log(`\nStatic client mounted at / (root: ${absoluteRoot})`);
1467
+ }
1468
+ }
1469
+
1377
1470
  /**
1378
1471
  *
1379
1472
  */
@@ -1444,6 +1537,12 @@ export abstract class DyNTS_App extends DyNTS_SingletonService {
1444
1537
  */
1445
1538
  overrideDynamoNTSGlobalSettings?(): void;
1446
1539
 
1540
+ /**
1541
+ * Ha megadva, a visszaadott értéket használjuk a route prefix-ként
1542
+ * (DyNTS_global_settings.baseUrl felülírása erre az app-ra).
1543
+ */
1544
+ getApiBasePath?(): string;
1545
+
1447
1546
  /**
1448
1547
  * MISSING Description (TODO)
1449
1548
  */
@@ -1459,6 +1558,12 @@ export abstract class DyNTS_App extends DyNTS_SingletonService {
1459
1558
  */
1460
1559
  getCertificationSettings?(): DyNTS_Certification_Settings;
1461
1560
 
1561
+ /**
1562
+ * Ha megadva, a client static fájlok a '/' alatt lesznek kiszolgálva (API route-ok után).
1563
+ * Opcionális fallbackPath pl. SPA index.html-hez.
1564
+ */
1565
+ getStaticClientSettings?(): DyNTS_StaticClient_Settings | undefined;
1566
+
1462
1567
  /**
1463
1568
  * MISSING Description (TODO)
1464
1569
  */
package/src/index.ts CHANGED
@@ -27,6 +27,9 @@ try {
27
27
  // COLLECTIONS
28
28
  export * from './_collections/archive.util';
29
29
  export * from './_collections/atlas-default-db-options.const';
30
+ export * from './_collections/default-fallback-cache-max-age.const';
31
+ export * from './_collections/default-not-found-page.const';
32
+ export * from './_collections/default-socket-path.const';
30
33
  export * from './_collections/get-environment-settings.util';
31
34
  export * from './_collections/global-settings.const';
32
35
 
@@ -46,6 +49,7 @@ export * from './_models/interfaces/environment-settings.interface';
46
49
  export * from './_models/interfaces/global-service-settings.interface';
47
50
  export * from './_models/interfaces/global-settings.interface';
48
51
  export * from './_models/interfaces/routing-module-settings.interface';
52
+ export * from './_models/interfaces/static-client-settings.interface';
49
53
 
50
54
  // models/CONTROL MODELS
51
55
  export * from './_models/control-models/api-call-params.control-model';