@futdevpro/fsm-dynamo 1.16.9 → 1.16.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.
@@ -1,6 +1,39 @@
1
1
  import { DyFM_DataModel_Type } from '../../_enums/data-model-type.enum';
2
2
  import { DyFM_Metadata } from '../data-models/metadata.data-model';
3
3
  import { DyFM_DataProperties, DyFM_DataProperty_Params } from './data-property-params.control-model';
4
+ /**
5
+ * FR-258 / SR-1 — declarative automatic document retention.
6
+ *
7
+ * When a data-model declares `retention`, `DyNTS_App` startup installs a MongoDB TTL index on
8
+ * the record's `__created` Date field, so MongoDB NATIVELY auto-deletes documents older than the
9
+ * configured age. This is the fleet-wide defense against the unbounded-collection-growth class:
10
+ * a collection that grows without bound (logs / history / events / metrics / reports / archives)
11
+ * and is then loaded by an unbounded find pulls 100s of MB into heap → GC-thrash → OOM. TTL keeps
12
+ * the collection bounded with ZERO app-level loading.
13
+ *
14
+ * Declare EITHER `retentionDays` OR `ttlSeconds` (`ttlSeconds` wins if both are set).
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const params = new DyFM_DataModel_Params<MyLog>({
19
+ * dataName: 'my_log',
20
+ * retention: { retentionDays: 14 }, // auto-delete 14 days after creation
21
+ * properties: { ... },
22
+ * });
23
+ * ```
24
+ */
25
+ export interface DyFM_RetentionSettings {
26
+ /** Auto-delete documents this many days after their `__created` timestamp. */
27
+ retentionDays?: number;
28
+ /** Explicit TTL in seconds; takes precedence over `retentionDays`. */
29
+ ttlSeconds?: number;
30
+ }
31
+ /**
32
+ * Resolve a {@link DyFM_RetentionSettings} to a positive integer TTL in seconds, or `undefined`
33
+ * when no valid retention is configured (→ no TTL index is installed). `ttlSeconds` wins over
34
+ * `retentionDays`; non-finite or ≤ 0 values are rejected. Pure + side-effect-free (unit-tested).
35
+ */
36
+ export declare function DyFM_resolveRetentionTtlSeconds(retention?: DyFM_RetentionSettings): number | undefined;
4
37
  export declare class DyFM_DataModel_Settings<T extends DyFM_Metadata> extends DyFM_Metadata {
5
38
  /** this will be used as db table name, therefore it should be in snake_case,
6
39
  * this also will be used in logs and errors
@@ -20,6 +53,14 @@ export declare class DyFM_DataModel_Settings<T extends DyFM_Metadata> extends Dy
20
53
  * @default false
21
54
  */
22
55
  forbidDelete?: boolean;
56
+ /**
57
+ * FR-258 / SR-1 — declarative automatic retention. If set, `DyNTS_App` startup creates a
58
+ * MongoDB TTL index on `__created`, so MongoDB auto-deletes documents older than the configured
59
+ * age (no app-level load → prevents the unbounded-growth → OOM class). See {@link DyFM_RetentionSettings}.
60
+ *
61
+ * @example { retentionDays: 14 }
62
+ */
63
+ retention?: DyFM_RetentionSettings;
23
64
  /**
24
65
  * from these settings we will set the data model properties for the DB.
25
66
  * metadata properties will be added automatically to the data model.
@@ -1 +1 @@
1
- {"version":3,"file":"data-model-params.control-model.d.ts","sourceRoot":"","sources":["../../../src/_models/control-models/data-model-params.control-model.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAKrG,qBAAa,uBAAuB,CAAC,CAAC,SAAS,aAAa,CAAE,SAAQ,aAAa;IACjF;;OAEG;IACH,QAAQ,EAAG,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAEhC,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,UAAU,EAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;CACrC;AAcD,qBAAa,qBAAqB,CAAC,CAAC,SAAS,aAAa,CAAE,SAAQ,uBAAuB,CAAC,CAAC,CAAC;IAG5F,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;gBAG9B,GAAG,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAiNjC,WAAW,CAAC,IAAI,OAAO;IAIvB,yBAAyB,CAAC,CAAC,QAAQ,EAAE,wBAAwB,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI;CA0B7E"}
1
+ {"version":3,"file":"data-model-params.control-model.d.ts","sourceRoot":"","sources":["../../../src/_models/control-models/data-model-params.control-model.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAGrG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,sBAAsB;IACrC,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,CAAC,EAAE,sBAAsB,GAAG,MAAM,GAAG,SAAS,CAQtG;AAID,qBAAa,uBAAuB,CAAC,CAAC,SAAS,aAAa,CAAE,SAAQ,aAAa;IACjF;;OAEG;IACH,QAAQ,EAAG,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAEhC,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,sBAAsB,CAAC;IAEnC;;;OAGG;IACH,UAAU,EAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;CACrC;AAcD,qBAAa,qBAAqB,CAAC,CAAC,SAAS,aAAa,CAAE,SAAQ,uBAAuB,CAAC,CAAC,CAAC;IAG5F,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;gBAG9B,GAAG,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAiNjC,WAAW,CAAC,IAAI,OAAO;IAIvB,yBAAyB,CAAC,CAAC,QAAQ,EAAE,wBAAwB,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI;CA0B7E"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DyFM_DataModel_Params = exports.DyFM_DataModel_Settings = void 0;
4
+ exports.DyFM_resolveRetentionTtlSeconds = DyFM_resolveRetentionTtlSeconds;
4
5
  const log_util_1 = require("../../_collections/utils/log.util");
5
6
  const object_util_1 = require("../../_collections/utils/object.util");
6
7
  const stack_util_1 = require("../../_collections/utils/stack.util");
@@ -10,6 +11,23 @@ const data_model_type_enum_1 = require("../../_enums/data-model-type.enum");
10
11
  const metadata_data_model_1 = require("../data-models/metadata.data-model");
11
12
  const data_property_params_control_model_1 = require("./data-property-params.control-model");
12
13
  const error_control_model_1 = require("./error.control-model");
14
+ /**
15
+ * Resolve a {@link DyFM_RetentionSettings} to a positive integer TTL in seconds, or `undefined`
16
+ * when no valid retention is configured (→ no TTL index is installed). `ttlSeconds` wins over
17
+ * `retentionDays`; non-finite or ≤ 0 values are rejected. Pure + side-effect-free (unit-tested).
18
+ */
19
+ function DyFM_resolveRetentionTtlSeconds(retention) {
20
+ if (!retention) {
21
+ return undefined;
22
+ }
23
+ const raw = retention.ttlSeconds !== undefined ? retention.ttlSeconds
24
+ : retention.retentionDays !== undefined ? retention.retentionDays * 86400
25
+ : undefined;
26
+ if (raw === undefined || !Number.isFinite(raw) || raw <= 0) {
27
+ return undefined;
28
+ }
29
+ return Math.floor(raw);
30
+ }
13
31
  /* export type DyFM_Data_S<T extends DyFM_Metadata> = DyFM_DataModel_Settings<T>;
14
32
  export type DyFM_Data_Settings<T extends DyFM_Metadata> = DyFM_DataModel_Settings<T>; */
15
33
  class DyFM_DataModel_Settings extends metadata_data_model_1.DyFM_Metadata {
@@ -31,6 +49,14 @@ class DyFM_DataModel_Settings extends metadata_data_model_1.DyFM_Metadata {
31
49
  * @default false
32
50
  */
33
51
  forbidDelete;
52
+ /**
53
+ * FR-258 / SR-1 — declarative automatic retention. If set, `DyNTS_App` startup creates a
54
+ * MongoDB TTL index on `__created`, so MongoDB auto-deletes documents older than the configured
55
+ * age (no app-level load → prevents the unbounded-growth → OOM class). See {@link DyFM_RetentionSettings}.
56
+ *
57
+ * @example { retentionDays: 14 }
58
+ */
59
+ retention;
34
60
  /**
35
61
  * from these settings we will set the data model properties for the DB.
36
62
  * metadata properties will be added automatically to the data model.
@@ -1 +1 @@
1
- {"version":3,"file":"data-model-params.control-model.js","sourceRoot":"","sources":["../../../src/_models/control-models/data-model-params.control-model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-model-params.control-model.js","sourceRoot":"","sources":["../../../src/_models/control-models/data-model-params.control-model.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@futdevpro/fsm-dynamo",
3
- "version": "01.16.9",
3
+ "version": "01.16.10",
4
4
  "description": "Full Stack Model Collection for Dynamic (NodeJS-Typescript) Framework called Dynamo, by Future Development Ltd.",
5
5
  "DyBu_settings": {
6
6
  "packageType": "full-stack-package",
@@ -2,7 +2,7 @@ import { DyFM_Log } from '../../_collections/utils/log.util';
2
2
  import { DyFM_BasicProperty_Type } from '../../_enums/basic-property-type.enum';
3
3
  import { DyFM_DataModel_Type } from '../../_enums/data-model-type.enum';
4
4
  import { DyFM_Metadata } from '../data-models/metadata.data-model';
5
- import { DyFM_DataModel_Params, DyFM_DataModel_Settings } from './data-model-params.control-model';
5
+ import { DyFM_DataModel_Params, DyFM_DataModel_Settings, DyFM_resolveRetentionTtlSeconds } from './data-model-params.control-model';
6
6
  import { DyFM_DataProperties } from './data-property-params.control-model';
7
7
  import { DyFM_Error } from './error.control-model';
8
8
 
@@ -82,4 +82,52 @@ describe('| DyFM_DataModel_Params', () => {
82
82
  const params = new DyFM_DataModel_Params(mockSettings);
83
83
  expect(params.constructed()).toBeTrue();
84
84
  });
85
+
86
+ // FR-258 / SR-1 — the optional `retention` declaration must survive construction so
87
+ // DyNTS_App startup can read it to install the TTL index.
88
+ it('| should carry the optional `retention` declaration through to the params instance', () => {
89
+ mockSettings.retention = { retentionDays: 14 };
90
+ const params = new DyFM_DataModel_Params(mockSettings);
91
+ expect(params.retention).toEqual({ retentionDays: 14 });
92
+ });
93
+
94
+ it('| should leave `retention` undefined when not declared (backward-compatible)', () => {
95
+ const params = new DyFM_DataModel_Params(mockSettings);
96
+ expect(params.retention).toBeUndefined();
97
+ });
98
+ });
99
+
100
+ // FR-258 / SR-1 — pure resolver: retention declaration → positive integer TTL seconds (or undefined).
101
+ describe('| DyFM_resolveRetentionTtlSeconds (FR-258 / SR-1)', () => {
102
+ it('| undefined retention → undefined (no TTL index)', () => {
103
+ expect(DyFM_resolveRetentionTtlSeconds(undefined)).toBeUndefined();
104
+ expect(DyFM_resolveRetentionTtlSeconds({})).toBeUndefined();
105
+ });
106
+
107
+ it('| retentionDays → days * 86400', () => {
108
+ expect(DyFM_resolveRetentionTtlSeconds({ retentionDays: 14 })).toBe(14 * 86400);
109
+ expect(DyFM_resolveRetentionTtlSeconds({ retentionDays: 1 })).toBe(86400);
110
+ });
111
+
112
+ it('| ttlSeconds → passed through as-is', () => {
113
+ expect(DyFM_resolveRetentionTtlSeconds({ ttlSeconds: 3600 })).toBe(3600);
114
+ });
115
+
116
+ it('| ttlSeconds takes precedence over retentionDays when both set', () => {
117
+ expect(DyFM_resolveRetentionTtlSeconds({ ttlSeconds: 100, retentionDays: 30 })).toBe(100);
118
+ });
119
+
120
+ it('| rejects zero / negative / non-finite (→ undefined, no index)', () => {
121
+ expect(DyFM_resolveRetentionTtlSeconds({ retentionDays: 0 })).toBeUndefined();
122
+ expect(DyFM_resolveRetentionTtlSeconds({ retentionDays: -5 })).toBeUndefined();
123
+ expect(DyFM_resolveRetentionTtlSeconds({ ttlSeconds: 0 })).toBeUndefined();
124
+ expect(DyFM_resolveRetentionTtlSeconds({ ttlSeconds: -1 })).toBeUndefined();
125
+ expect(DyFM_resolveRetentionTtlSeconds({ ttlSeconds: Number.NaN })).toBeUndefined();
126
+ expect(DyFM_resolveRetentionTtlSeconds({ ttlSeconds: Number.POSITIVE_INFINITY })).toBeUndefined();
127
+ });
128
+
129
+ it('| floors fractional results to a whole number of seconds', () => {
130
+ expect(DyFM_resolveRetentionTtlSeconds({ ttlSeconds: 99.9 })).toBe(99);
131
+ expect(DyFM_resolveRetentionTtlSeconds({ retentionDays: 0.5 })).toBe(43200);
132
+ });
85
133
  });
@@ -8,6 +8,49 @@ import { DyFM_Metadata } from '../data-models/metadata.data-model';
8
8
  import { DyFM_DataProperties, DyFM_DataProperty_Params } from './data-property-params.control-model';
9
9
  import { DyFM_Error } from './error.control-model';
10
10
 
11
+ /**
12
+ * FR-258 / SR-1 — declarative automatic document retention.
13
+ *
14
+ * When a data-model declares `retention`, `DyNTS_App` startup installs a MongoDB TTL index on
15
+ * the record's `__created` Date field, so MongoDB NATIVELY auto-deletes documents older than the
16
+ * configured age. This is the fleet-wide defense against the unbounded-collection-growth class:
17
+ * a collection that grows without bound (logs / history / events / metrics / reports / archives)
18
+ * and is then loaded by an unbounded find pulls 100s of MB into heap → GC-thrash → OOM. TTL keeps
19
+ * the collection bounded with ZERO app-level loading.
20
+ *
21
+ * Declare EITHER `retentionDays` OR `ttlSeconds` (`ttlSeconds` wins if both are set).
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const params = new DyFM_DataModel_Params<MyLog>({
26
+ * dataName: 'my_log',
27
+ * retention: { retentionDays: 14 }, // auto-delete 14 days after creation
28
+ * properties: { ... },
29
+ * });
30
+ * ```
31
+ */
32
+ export interface DyFM_RetentionSettings {
33
+ /** Auto-delete documents this many days after their `__created` timestamp. */
34
+ retentionDays?: number;
35
+ /** Explicit TTL in seconds; takes precedence over `retentionDays`. */
36
+ ttlSeconds?: number;
37
+ }
38
+
39
+ /**
40
+ * Resolve a {@link DyFM_RetentionSettings} to a positive integer TTL in seconds, or `undefined`
41
+ * when no valid retention is configured (→ no TTL index is installed). `ttlSeconds` wins over
42
+ * `retentionDays`; non-finite or ≤ 0 values are rejected. Pure + side-effect-free (unit-tested).
43
+ */
44
+ export function DyFM_resolveRetentionTtlSeconds(retention?: DyFM_RetentionSettings): number | undefined {
45
+ if (!retention) { return undefined; }
46
+ const raw: number | undefined =
47
+ retention.ttlSeconds !== undefined ? retention.ttlSeconds
48
+ : retention.retentionDays !== undefined ? retention.retentionDays * 86400
49
+ : undefined;
50
+ if (raw === undefined || !Number.isFinite(raw) || raw <= 0) { return undefined; }
51
+ return Math.floor(raw);
52
+ }
53
+
11
54
  /* export type DyFM_Data_S<T extends DyFM_Metadata> = DyFM_DataModel_Settings<T>;
12
55
  export type DyFM_Data_Settings<T extends DyFM_Metadata> = DyFM_DataModel_Settings<T>; */
13
56
  export class DyFM_DataModel_Settings<T extends DyFM_Metadata> extends DyFM_Metadata {
@@ -33,6 +76,15 @@ export class DyFM_DataModel_Settings<T extends DyFM_Metadata> extends DyFM_Metad
33
76
  */
34
77
  forbidDelete?: boolean;
35
78
 
79
+ /**
80
+ * FR-258 / SR-1 — declarative automatic retention. If set, `DyNTS_App` startup creates a
81
+ * MongoDB TTL index on `__created`, so MongoDB auto-deletes documents older than the configured
82
+ * age (no app-level load → prevents the unbounded-growth → OOM class). See {@link DyFM_RetentionSettings}.
83
+ *
84
+ * @example { retentionDays: 14 }
85
+ */
86
+ retention?: DyFM_RetentionSettings;
87
+
36
88
  /**
37
89
  * from these settings we will set the data model properties for the DB.
38
90
  * metadata properties will be added automatically to the data model.