@futdevpro/nts-dynamo 1.15.17 → 1.15.19

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 (37) hide show
  1. package/_specifications/BACKLOG.md +2 -2
  2. package/build/_models/interfaces/global-log-settings.interface.d.ts +35 -0
  3. package/build/_models/interfaces/global-log-settings.interface.d.ts.map +1 -1
  4. package/build/_modules/logs/file-log.service.d.ts +87 -0
  5. package/build/_modules/logs/file-log.service.d.ts.map +1 -0
  6. package/build/_modules/logs/file-log.service.js +267 -0
  7. package/build/_modules/logs/file-log.service.js.map +1 -0
  8. package/build/_modules/logs/get-logs-routing-module.util.d.ts +19 -0
  9. package/build/_modules/logs/get-logs-routing-module.util.d.ts.map +1 -0
  10. package/build/_modules/logs/get-logs-routing-module.util.js +32 -0
  11. package/build/_modules/logs/get-logs-routing-module.util.js.map +1 -0
  12. package/build/_modules/logs/index.d.ts +5 -0
  13. package/build/_modules/logs/index.d.ts.map +1 -0
  14. package/build/_modules/logs/index.js +12 -0
  15. package/build/_modules/logs/index.js.map +1 -0
  16. package/build/_modules/logs/log-buffer.service.d.ts +38 -0
  17. package/build/_modules/logs/log-buffer.service.d.ts.map +1 -0
  18. package/build/_modules/logs/log-buffer.service.js +97 -0
  19. package/build/_modules/logs/log-buffer.service.js.map +1 -0
  20. package/build/_modules/logs/logs.controller.d.ts +27 -0
  21. package/build/_modules/logs/logs.controller.d.ts.map +1 -0
  22. package/build/_modules/logs/logs.controller.js +90 -0
  23. package/build/_modules/logs/logs.controller.js.map +1 -0
  24. package/build/_modules/logs/logs.service.d.ts +40 -0
  25. package/build/_modules/logs/logs.service.d.ts.map +1 -0
  26. package/build/_modules/logs/logs.service.js +97 -0
  27. package/build/_modules/logs/logs.service.js.map +1 -0
  28. package/package.json +1 -1
  29. package/pipeline.cicd.config.json +3 -1
  30. package/src/_models/interfaces/global-log-settings.interface.ts +36 -0
  31. package/src/_modules/logs/file-log.service.spec.ts +202 -0
  32. package/src/_modules/logs/file-log.service.ts +283 -0
  33. package/src/_modules/logs/get-logs-routing-module.util.ts +36 -0
  34. package/src/_modules/logs/index.ts +4 -0
  35. package/src/_modules/logs/log-buffer.service.ts +101 -0
  36. package/src/_modules/logs/logs.controller.ts +109 -0
  37. package/src/_modules/logs/logs.service.ts +100 -0
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DyNTS_LogBuffer_Service = void 0;
4
+ const singleton_service_1 = require("../../_services/base/singleton.service");
5
+ /**
6
+ * In-memory ring buffer a szerver console kimenethez.
7
+ * Interceptalja a console.log/error/warn/info hivasokat es eltarolja az utolso N sort.
8
+ *
9
+ * Hasznalat:
10
+ * DyNTS_LogBuffer_Service.getInstance().install(); // app startup-nal
11
+ * DyNTS_LogBuffer_Service.getInstance().getLines(100); // utolso 100 sor
12
+ */
13
+ class DyNTS_LogBuffer_Service extends singleton_service_1.DyNTS_SingletonService {
14
+ static getInstance() {
15
+ return DyNTS_LogBuffer_Service.getSingletonInstance();
16
+ }
17
+ maxLines = 2000;
18
+ buffer = [];
19
+ installed = false;
20
+ /**
21
+ * Interceptalja a console.log/error/warn/info kimeneteket es a bufferbe irja.
22
+ * Egyszer kell hivni, a szerver indulasakor (lehetoleg a legelso muvelet).
23
+ */
24
+ install() {
25
+ if (this.installed) {
26
+ return;
27
+ }
28
+ this.installed = true;
29
+ const self = this;
30
+ const originalLog = console.log.bind(console);
31
+ const originalError = console.error.bind(console);
32
+ const originalWarn = console.warn.bind(console);
33
+ const originalInfo = console.info.bind(console);
34
+ console.log = (...args) => {
35
+ self.addLine('LOG', args);
36
+ originalLog(...args);
37
+ };
38
+ console.error = (...args) => {
39
+ self.addLine('ERR', args);
40
+ originalError(...args);
41
+ };
42
+ console.warn = (...args) => {
43
+ self.addLine('WRN', args);
44
+ originalWarn(...args);
45
+ };
46
+ console.info = (...args) => {
47
+ self.addLine('INF', args);
48
+ originalInfo(...args);
49
+ };
50
+ }
51
+ /**
52
+ * A log buffer be van-e kapcsolva (install megtortent-e).
53
+ */
54
+ isInstalled() {
55
+ return this.installed;
56
+ }
57
+ /**
58
+ * Az utolso N sor lekerdezese.
59
+ */
60
+ getLines(count = 200) {
61
+ const start = Math.max(0, this.buffer.length - count);
62
+ return this.buffer.slice(start);
63
+ }
64
+ /**
65
+ * Az osszes buffered sor szama.
66
+ */
67
+ getLineCount() {
68
+ return this.buffer.length;
69
+ }
70
+ /**
71
+ * Buffer uritese.
72
+ */
73
+ clear() {
74
+ this.buffer.length = 0;
75
+ }
76
+ addLine(level, args) {
77
+ const timestamp = new Date().toISOString();
78
+ const message = args.map(formatArg).join(' ');
79
+ this.buffer.push(`${timestamp} [${level}] ${message}`);
80
+ if (this.buffer.length > this.maxLines) {
81
+ this.buffer.shift();
82
+ }
83
+ }
84
+ }
85
+ exports.DyNTS_LogBuffer_Service = DyNTS_LogBuffer_Service;
86
+ function formatArg(arg) {
87
+ if (typeof arg === 'string') {
88
+ return arg;
89
+ }
90
+ try {
91
+ return JSON.stringify(arg);
92
+ }
93
+ catch {
94
+ return String(arg);
95
+ }
96
+ }
97
+ //# sourceMappingURL=log-buffer.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-buffer.service.js","sourceRoot":"","sources":["../../../src/_modules/logs/log-buffer.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { Request, Response } from 'express';
2
+ import { DyNTS_Controller } from '../../_services/route/controller.service';
3
+ /**
4
+ * Overseer-szintu log parameter tipus.
5
+ * Az authPreProcess opcionalis — ha megadod, a /get endpoint vedett lesz.
6
+ */
7
+ export interface DyNTS_LogsController_Config {
8
+ /** Opcionalis auth preprocess. Ha nincs megadva → nyilt hozzaferes. */
9
+ authPreProcess?: (req: Request, res: Response) => Promise<void>;
10
+ }
11
+ /**
12
+ * NTS Logs Controller — beepitett /logs/get endpoint a szerver logok lekeresehez.
13
+ *
14
+ * Hasznalat:
15
+ * DyNTS_getLogsRoutingModule() — auth nelkul
16
+ * DyNTS_getLogsRoutingModule({ authPreProcess: myAuth }) — auth-tal
17
+ *
18
+ * Ha a logs_endpoint.enabled === false, a controller 503-at dob.
19
+ */
20
+ export declare class DyNTS_Logs_Controller extends DyNTS_Controller {
21
+ private static config;
22
+ static configure(config: DyNTS_LogsController_Config): void;
23
+ static getInstance(): DyNTS_Logs_Controller;
24
+ private readonly logsService;
25
+ setupEndpoints(): void;
26
+ }
27
+ //# sourceMappingURL=logs.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.controller.d.ts","sourceRoot":"","sources":["../../../src/_modules/logs/logs.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAI5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAK5E;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC1C,uEAAuE;IACvE,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE;AAED;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,gBAAgB;IAEzD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAmC;IAExD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,2BAA2B,GAAG,IAAI;IAI3D,MAAM,CAAC,WAAW,IAAI,qBAAqB;IAI3C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwD;IAEpF,cAAc,IAAI,IAAI;CAmEvB"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DyNTS_Logs_Controller = void 0;
4
+ const fsm_dynamo_1 = require("@futdevpro/fsm-dynamo");
5
+ const controller_service_1 = require("../../_services/route/controller.service");
6
+ const endpoint_params_control_model_1 = require("../../_models/control-models/endpoint-params.control-model");
7
+ const global_settings_const_1 = require("../../_collections/global-settings.const");
8
+ const logs_service_1 = require("./logs.service");
9
+ /**
10
+ * NTS Logs Controller — beepitett /logs/get endpoint a szerver logok lekeresehez.
11
+ *
12
+ * Hasznalat:
13
+ * DyNTS_getLogsRoutingModule() — auth nelkul
14
+ * DyNTS_getLogsRoutingModule({ authPreProcess: myAuth }) — auth-tal
15
+ *
16
+ * Ha a logs_endpoint.enabled === false, a controller 503-at dob.
17
+ */
18
+ class DyNTS_Logs_Controller extends controller_service_1.DyNTS_Controller {
19
+ static config = {};
20
+ static configure(config) {
21
+ DyNTS_Logs_Controller.config = config;
22
+ }
23
+ static getInstance() {
24
+ return DyNTS_Logs_Controller.getSingletonInstance();
25
+ }
26
+ logsService = logs_service_1.DyNTS_Logs_Service.getInstance();
27
+ setupEndpoints() {
28
+ const preProcesses = [];
29
+ if (DyNTS_Logs_Controller.config.authPreProcess) {
30
+ preProcesses.push(DyNTS_Logs_Controller.config.authPreProcess);
31
+ }
32
+ this.endpoints = [
33
+ // GET /get?tail=200 — utolso N sor a log bufferbol
34
+ new endpoint_params_control_model_1.DyNTS_Endpoint_Params({
35
+ name: 'getLogs',
36
+ type: fsm_dynamo_1.DyFM_HttpCallType.get,
37
+ endpoint: '/get',
38
+ preProcesses: preProcesses,
39
+ logRequest: false,
40
+ tasks: [
41
+ async (req, res) => {
42
+ // Ellenorzes: be van-e kapcsolva a logs endpoint
43
+ if (!global_settings_const_1.DyNTS_global_settings.log_settings?.logs_endpoint?.enabled) {
44
+ res.status(503).send({
45
+ error: 'Logs endpoint is not enabled on this server.',
46
+ hint: 'Set DyNTS_global_settings.log_settings.logs_endpoint.enabled = true',
47
+ });
48
+ return;
49
+ }
50
+ // Ellenorzes: install megtortent-e
51
+ if (!this.logsService.isInstalled()) {
52
+ res.status(503).send({
53
+ error: 'Log buffer is not installed. Call DyNTS_Logs_Service.getInstance().install() at server startup.',
54
+ });
55
+ return;
56
+ }
57
+ const tail = Math.min(parseInt(req.query.tail) || 200, 2000);
58
+ const lines = this.logsService.getLines(tail);
59
+ res.send({
60
+ totalBuffered: this.logsService.getLineCount(),
61
+ returned: lines.length,
62
+ lines: lines,
63
+ });
64
+ },
65
+ ],
66
+ }),
67
+ // DELETE /clear — buffer uritese
68
+ new endpoint_params_control_model_1.DyNTS_Endpoint_Params({
69
+ name: 'clearLogs',
70
+ type: fsm_dynamo_1.DyFM_HttpCallType.delete,
71
+ endpoint: '/clear',
72
+ preProcesses: preProcesses,
73
+ logRequest: false,
74
+ tasks: [
75
+ async (req, res) => {
76
+ if (!global_settings_const_1.DyNTS_global_settings.log_settings?.logs_endpoint?.enabled) {
77
+ res.status(503).send({ error: 'Logs endpoint is not enabled.' });
78
+ return;
79
+ }
80
+ const count = this.logsService.getLineCount();
81
+ this.logsService.clear();
82
+ res.send({ result: 'Log buffer cleared', clearedLines: count });
83
+ },
84
+ ],
85
+ }),
86
+ ];
87
+ }
88
+ }
89
+ exports.DyNTS_Logs_Controller = DyNTS_Logs_Controller;
90
+ //# sourceMappingURL=logs.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.controller.js","sourceRoot":"","sources":["../../../src/_modules/logs/logs.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { DyNTS_SingletonServiceBase } from '../../_services/base/singleton.service-base';
2
+ /**
3
+ * In-memory ring buffer a szerver logokhoz.
4
+ * Interceptalja a console.log/error/warn kimeneteket es tarolja oket.
5
+ * Max entryszam a log_settings.logs_endpoint.maxEntries-bol jon (default: 2000).
6
+ *
7
+ * Hasznalat:
8
+ * DyNTS_Logs_Service.getInstance().install() — egyszer, szerver indulasakor
9
+ * DyNTS_Logs_Service.getInstance().getLines(200) — utolso N sor
10
+ */
11
+ export declare class DyNTS_Logs_Service extends DyNTS_SingletonServiceBase {
12
+ static getInstance(): DyNTS_Logs_Service;
13
+ private readonly maxEntries;
14
+ private readonly buffer;
15
+ private installed;
16
+ protected constructor();
17
+ /**
18
+ * Interceptalja a console.log/error/warn kimeneteket es a bufferbe irja.
19
+ * Egyszer kell hivni, a szerver indulasakor. Tobbszori hivas no-op.
20
+ */
21
+ install(): void;
22
+ /**
23
+ * Az utolso N sor lekerdezese.
24
+ */
25
+ getLines(count?: number): string[];
26
+ /**
27
+ * Osszes bufferelt sor szama.
28
+ */
29
+ getLineCount(): number;
30
+ /**
31
+ * Buffer uritese.
32
+ */
33
+ clear(): void;
34
+ /**
35
+ * Telepitve van-e mar a console intercept.
36
+ */
37
+ isInstalled(): boolean;
38
+ private addLine;
39
+ }
40
+ //# sourceMappingURL=logs.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.service.d.ts","sourceRoot":"","sources":["../../../src/_modules/logs/logs.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAC;AAGzF;;;;;;;;GAQG;AACH,qBAAa,kBAAmB,SAAQ,0BAA0B;IAEhE,MAAM,CAAC,WAAW,IAAI,kBAAkB;IAIxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,SAAS,CAAkB;IAEnC,SAAS;IAKT;;;OAGG;IACH,OAAO,IAAI,IAAI;IA0Bf;;OAEG;IACH,QAAQ,CAAC,KAAK,GAAE,MAAY,GAAG,MAAM,EAAE;IAKvC;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,OAAO;CAahB"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DyNTS_Logs_Service = void 0;
4
+ const singleton_service_base_1 = require("../../_services/base/singleton.service-base");
5
+ const global_settings_const_1 = require("../../_collections/global-settings.const");
6
+ /**
7
+ * In-memory ring buffer a szerver logokhoz.
8
+ * Interceptalja a console.log/error/warn kimeneteket es tarolja oket.
9
+ * Max entryszam a log_settings.logs_endpoint.maxEntries-bol jon (default: 2000).
10
+ *
11
+ * Hasznalat:
12
+ * DyNTS_Logs_Service.getInstance().install() — egyszer, szerver indulasakor
13
+ * DyNTS_Logs_Service.getInstance().getLines(200) — utolso N sor
14
+ */
15
+ class DyNTS_Logs_Service extends singleton_service_base_1.DyNTS_SingletonServiceBase {
16
+ static getInstance() {
17
+ return DyNTS_Logs_Service.getSingletonInstance();
18
+ }
19
+ maxEntries;
20
+ buffer = [];
21
+ installed = false;
22
+ constructor() {
23
+ super();
24
+ this.maxEntries = global_settings_const_1.DyNTS_global_settings.log_settings?.logs_endpoint?.maxEntries ?? 2000;
25
+ }
26
+ /**
27
+ * Interceptalja a console.log/error/warn kimeneteket es a bufferbe irja.
28
+ * Egyszer kell hivni, a szerver indulasakor. Tobbszori hivas no-op.
29
+ */
30
+ install() {
31
+ if (this.installed) {
32
+ return;
33
+ }
34
+ this.installed = true;
35
+ const originalLog = console.log.bind(console);
36
+ const originalError = console.error.bind(console);
37
+ const originalWarn = console.warn.bind(console);
38
+ const self = this;
39
+ console.log = (...args) => {
40
+ self.addLine('LOG', args);
41
+ originalLog(...args);
42
+ };
43
+ console.error = (...args) => {
44
+ self.addLine('ERR', args);
45
+ originalError(...args);
46
+ };
47
+ console.warn = (...args) => {
48
+ self.addLine('WRN', args);
49
+ originalWarn(...args);
50
+ };
51
+ }
52
+ /**
53
+ * Az utolso N sor lekerdezese.
54
+ */
55
+ getLines(count = 200) {
56
+ const start = Math.max(0, this.buffer.length - count);
57
+ return this.buffer.slice(start);
58
+ }
59
+ /**
60
+ * Osszes bufferelt sor szama.
61
+ */
62
+ getLineCount() {
63
+ return this.buffer.length;
64
+ }
65
+ /**
66
+ * Buffer uritese.
67
+ */
68
+ clear() {
69
+ this.buffer.length = 0;
70
+ }
71
+ /**
72
+ * Telepitve van-e mar a console intercept.
73
+ */
74
+ isInstalled() {
75
+ return this.installed;
76
+ }
77
+ addLine(level, args) {
78
+ const message = args.map((arg) => {
79
+ if (typeof arg === 'string') {
80
+ return arg;
81
+ }
82
+ try {
83
+ return JSON.stringify(arg);
84
+ }
85
+ catch {
86
+ return String(arg);
87
+ }
88
+ }).join(' ');
89
+ const timestamped = `${new Date().toISOString()} [${level}] ${message}`;
90
+ this.buffer.push(timestamped);
91
+ if (this.buffer.length > this.maxEntries) {
92
+ this.buffer.shift();
93
+ }
94
+ }
95
+ }
96
+ exports.DyNTS_Logs_Service = DyNTS_Logs_Service;
97
+ //# sourceMappingURL=logs.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.service.js","sourceRoot":"","sources":["../../../src/_modules/logs/logs.service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@futdevpro/nts-dynamo",
3
- "version": "01.15.17",
3
+ "version": "01.15.19",
4
4
  "description": "Dynamic NodeTS (NodeJS-Typescript), MongoDB Backend System Framework by Future Development Program Ltd.",
5
5
  "DyBu_settings": {
6
6
  "packageType": "server-package",
@@ -76,7 +76,9 @@
76
76
  "@futdevpro/fsm-dynamo"
77
77
  ]
78
78
  }
79
- ]
79
+ ],
80
+ "fix": true,
81
+ "patchOnly": true
80
82
  }
81
83
  },
82
84
  {
@@ -105,4 +105,40 @@ export interface DyNTS_GlobalLog_Settings {
105
105
  /** Max sorok szama a bufferben. Default: 2000. */
106
106
  maxEntries?: number;
107
107
  };
108
+
109
+ /**
110
+ * File-based log kiiras konfiguracio (DyNTS_FileLog_Service).
111
+ *
112
+ * Az in-memory ring buffer (DyNTS_Logs_Service) mellett mukodik — NEM
113
+ * helyette. A szerver stdout/stderr kimeneteket egy per-session log
114
+ * fajlba duplikalja (`{logDir}/{filenamePrefix}YYYY-MM-DD_HH-MM-SS.log`).
115
+ *
116
+ * Rotation: ha az aktiv fajl meghaladja a `maxFileSizeMb`-t, uj fajl jon
117
+ * letre. Retention: az `install()` + minden rotation utan a
118
+ * `maxFiles`-nel regebbi vagy a `retentionDays`-nel idosebb fajlok
119
+ * torlodnek (ami elobb teljesul).
120
+ *
121
+ * Hasznalat:
122
+ * DyNTS_FileLog_Service.getInstance().install(); // szerver startup
123
+ */
124
+ file_log?: {
125
+ /** Engedelyezve van-e a file-based logolás. Default: false. */
126
+ enabled: boolean;
127
+ /** Log mappa abszolut vagy relativ path-ja. Default: './logs/server'. */
128
+ logDir?: string;
129
+ /** Per-session fajlnev prefix. Default: 'server-'. */
130
+ filenamePrefix?: string;
131
+ /** Rotation trigger MB-ban. Default: 50. */
132
+ maxFileSizeMb?: number;
133
+ /** Retention by count — max ennyi log fajl marad meg. Default: 10. */
134
+ maxFiles?: number;
135
+ /** Retention by age — ennyi napnal regebbi fajl torlodik. Default: 30. */
136
+ retentionDays?: number;
137
+ /** ANSI escape kodok strippelese a fajl-irasnal. Default: true. */
138
+ stripAnsi?: boolean;
139
+ /** stdout interceptalasa. Default: true. */
140
+ includeStdout?: boolean;
141
+ /** stderr interceptalasa. Default: true. */
142
+ includeStderr?: boolean;
143
+ };
108
144
  }
@@ -0,0 +1,202 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+
5
+ import { DyNTS_global_settings } from '../../_collections/global-settings.const';
6
+
7
+ import { DyNTS_FileLog_Service } from './file-log.service';
8
+
9
+
10
+ describe('| DyNTS_FileLog_Service', (): void => {
11
+ let tempDir: string;
12
+ let originalFileLogConfig: typeof DyNTS_global_settings.log_settings.file_log;
13
+
14
+ beforeEach((): void => {
15
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nts-filelog-spec-'));
16
+ originalFileLogConfig = DyNTS_global_settings.log_settings.file_log;
17
+ });
18
+
19
+ afterEach((): void => {
20
+ // Mindig allitsuk vissza az eredeti console-t es config-ot, hogy
21
+ // ne szivarogtassuk at a teszt envt.
22
+ DyNTS_FileLog_Service.getInstance()._teardownForTesting();
23
+ DyNTS_global_settings.log_settings.file_log = originalFileLogConfig;
24
+ try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch { /* swallow */ }
25
+ });
26
+
27
+ describe('| install() — gating', (): void => {
28
+ it('| no-op ha file_log config hianyzik', (): void => {
29
+ DyNTS_global_settings.log_settings.file_log = undefined;
30
+ DyNTS_FileLog_Service.getInstance().install();
31
+ expect(DyNTS_FileLog_Service.getInstance().isInstalled()).toBe(false);
32
+ });
33
+
34
+ it('| no-op ha enabled === false', (): void => {
35
+ DyNTS_global_settings.log_settings.file_log = { enabled: false, logDir: tempDir };
36
+ DyNTS_FileLog_Service.getInstance().install();
37
+ expect(DyNTS_FileLog_Service.getInstance().isInstalled()).toBe(false);
38
+ });
39
+
40
+ it('| install() idempotens — masodszorra is no-op', (): void => {
41
+ DyNTS_global_settings.log_settings.file_log = { enabled: true, logDir: tempDir };
42
+ const svc: DyNTS_FileLog_Service = DyNTS_FileLog_Service.getInstance();
43
+ svc.install();
44
+ const firstPath: string = svc.getCurrentLogPath();
45
+ svc.install(); // ismet
46
+ expect(svc.getCurrentLogPath()).toBe(firstPath);
47
+ });
48
+ });
49
+
50
+ describe('| install() — file creation + intercept', (): void => {
51
+ it('| stdout iras a fajlba is bekerul', (): void => {
52
+ DyNTS_global_settings.log_settings.file_log = {
53
+ enabled: true,
54
+ logDir: tempDir,
55
+ filenamePrefix: 'spec-',
56
+ };
57
+ const svc: DyNTS_FileLog_Service = DyNTS_FileLog_Service.getInstance();
58
+ svc.install();
59
+
60
+ const marker: string = `hello-from-spec-${Date.now()}\n`;
61
+ process.stdout.write(marker);
62
+
63
+ const logPath: string = svc.getCurrentLogPath();
64
+ expect(fs.existsSync(logPath)).toBe(true);
65
+ const contents: string = fs.readFileSync(logPath, 'utf-8');
66
+ expect(contents).toContain(marker.trim());
67
+ });
68
+
69
+ it('| stderr iras a fajlba is bekerul ha includeStderr=true', (): void => {
70
+ DyNTS_global_settings.log_settings.file_log = {
71
+ enabled: true,
72
+ logDir: tempDir,
73
+ filenamePrefix: 'spec-',
74
+ };
75
+ const svc: DyNTS_FileLog_Service = DyNTS_FileLog_Service.getInstance();
76
+ svc.install();
77
+
78
+ const marker: string = `error-marker-${Date.now()}\n`;
79
+ process.stderr.write(marker);
80
+
81
+ const contents: string = fs.readFileSync(svc.getCurrentLogPath(), 'utf-8');
82
+ expect(contents).toContain(marker.trim());
83
+ });
84
+
85
+ it('| ANSI escape kodok strippelve a fajlban ha stripAnsi=true (default)', (): void => {
86
+ DyNTS_global_settings.log_settings.file_log = {
87
+ enabled: true,
88
+ logDir: tempDir,
89
+ filenamePrefix: 'spec-',
90
+ };
91
+ const svc: DyNTS_FileLog_Service = DyNTS_FileLog_Service.getInstance();
92
+ svc.install();
93
+
94
+ process.stdout.write('\x1b[31mredtext\x1b[0m-payload\n');
95
+
96
+ const contents: string = fs.readFileSync(svc.getCurrentLogPath(), 'utf-8');
97
+ expect(contents).toContain('redtext-payload');
98
+ expect(contents).not.toContain('\x1b[31m');
99
+ expect(contents).not.toContain('\x1b[0m');
100
+ });
101
+
102
+ it('| ANSI megmarad ha stripAnsi=false', (): void => {
103
+ DyNTS_global_settings.log_settings.file_log = {
104
+ enabled: true,
105
+ logDir: tempDir,
106
+ filenamePrefix: 'spec-',
107
+ stripAnsi: false,
108
+ };
109
+ const svc: DyNTS_FileLog_Service = DyNTS_FileLog_Service.getInstance();
110
+ svc.install();
111
+
112
+ process.stdout.write('\x1b[31mraw\x1b[0m\n');
113
+
114
+ const contents: string = fs.readFileSync(svc.getCurrentLogPath(), 'utf-8');
115
+ expect(contents).toContain('\x1b[31mraw\x1b[0m');
116
+ });
117
+ });
118
+
119
+ describe('| rotation', (): void => {
120
+ it('| uj fajl jon letre ha az iras meghaladja a maxFileSizeMb-t', (): void => {
121
+ DyNTS_global_settings.log_settings.file_log = {
122
+ enabled: true,
123
+ logDir: tempDir,
124
+ filenamePrefix: 'rotspec-',
125
+ // 1 byte limit → minden iras azonnal triggereli a rotaciot
126
+ maxFileSizeMb: 1 / (1024 * 1024),
127
+ };
128
+ const svc: DyNTS_FileLog_Service = DyNTS_FileLog_Service.getInstance();
129
+ svc.install();
130
+
131
+ const firstPath: string = svc.getCurrentLogPath();
132
+ process.stdout.write('payload-1\n');
133
+ process.stdout.write('payload-2\n');
134
+
135
+ const secondPath: string = svc.getCurrentLogPath();
136
+ expect(secondPath).not.toBe(firstPath);
137
+ // Mindket fajl letezik a tempDir-ben
138
+ const files: string[] = fs.readdirSync(tempDir).filter((f: string) => f.startsWith('rotspec-'));
139
+ expect(files.length).toBeGreaterThanOrEqual(2);
140
+ });
141
+ });
142
+
143
+ describe('| retention', (): void => {
144
+ it('| install() torli a `retentionDays`-nel regebbi fajlokat (mtime backdated)', (): void => {
145
+ const oldFile: string = path.join(tempDir, 'spec-2020-01-01_00-00-00_abc.log');
146
+ fs.writeFileSync(oldFile, 'old');
147
+ const oldMs: number = Date.now() - 365 * 24 * 60 * 60 * 1000;
148
+ fs.utimesSync(oldFile, oldMs / 1000, oldMs / 1000);
149
+
150
+ DyNTS_global_settings.log_settings.file_log = {
151
+ enabled: true,
152
+ logDir: tempDir,
153
+ filenamePrefix: 'spec-',
154
+ retentionDays: 30,
155
+ maxFiles: 100, // count szabaly NE triggereljen
156
+ };
157
+ DyNTS_FileLog_Service.getInstance().install();
158
+
159
+ expect(fs.existsSync(oldFile)).toBe(false);
160
+ });
161
+
162
+ it('| install() retention by count — maxFiles-nel tobb fajl van, a legregebbi torlodik', (): void => {
163
+ // 3 fix mtime-u "regi" fajl letrehozasa (azonnali age szempontbol mind ok)
164
+ const now: number = Date.now();
165
+ const f1: string = path.join(tempDir, 'spec-2026-01-01_00-00-01_aaa.log');
166
+ const f2: string = path.join(tempDir, 'spec-2026-01-01_00-00-02_bbb.log');
167
+ const f3: string = path.join(tempDir, 'spec-2026-01-01_00-00-03_ccc.log');
168
+ fs.writeFileSync(f1, '1'); fs.utimesSync(f1, (now - 30000) / 1000, (now - 30000) / 1000);
169
+ fs.writeFileSync(f2, '2'); fs.utimesSync(f2, (now - 20000) / 1000, (now - 20000) / 1000);
170
+ fs.writeFileSync(f3, '3'); fs.utimesSync(f3, (now - 10000) / 1000, (now - 10000) / 1000);
171
+
172
+ DyNTS_global_settings.log_settings.file_log = {
173
+ enabled: true,
174
+ logDir: tempDir,
175
+ filenamePrefix: 'spec-',
176
+ maxFiles: 2, // a legregebbi (f1) torlodik
177
+ retentionDays: 36500, // age szabaly NE triggereljen
178
+ };
179
+ DyNTS_FileLog_Service.getInstance().install();
180
+
181
+ expect(fs.existsSync(f1)).toBe(false);
182
+ expect(fs.existsSync(f2)).toBe(true);
183
+ expect(fs.existsSync(f3)).toBe(true);
184
+ });
185
+ });
186
+
187
+ describe('| silent failure', (): void => {
188
+ it('| install() NEM crashel ha a logDir letrehozasa bukik', (): void => {
189
+ // Olyan path amit nem lehet letrehozni: egy meglévő fajl ALATTI subdir.
190
+ const blocker: string = path.join(tempDir, 'iam-a-file');
191
+ fs.writeFileSync(blocker, '');
192
+ const impossible: string = path.join(blocker, 'cant-create-subdir');
193
+
194
+ DyNTS_global_settings.log_settings.file_log = {
195
+ enabled: true,
196
+ logDir: impossible,
197
+ };
198
+ expect(() => DyNTS_FileLog_Service.getInstance().install()).not.toThrow();
199
+ expect(DyNTS_FileLog_Service.getInstance().isInstalled()).toBe(false);
200
+ });
201
+ });
202
+ });