sm-utility 2.4.9 → 2.4.12

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.
@@ -0,0 +1,112 @@
1
+ import { MetadataModel } from './metadata.model';
2
+ import { LeveledLogMethod } from 'winston';
3
+ type LogData<T> = {
4
+ context?: T;
5
+ };
6
+ type EnhancedLogParams<T, E> = {
7
+ logMethod: LeveledLogMethod;
8
+ message: string;
9
+ logData?: LogData<T>;
10
+ error?: E;
11
+ };
12
+ export declare abstract class Command {
13
+ protected readonly className: string;
14
+ protected readonly metadata: MetadataModel;
15
+ protected readonly logger: import("winston").Logger;
16
+ private startTime;
17
+ /**
18
+ * Creates a new instance of the Command class.
19
+ *
20
+ * @param className - The name of the class extending the Command class. Used for logging purposes.
21
+ * @param metadata - (Optional) A metadata model containing additional information for the command.
22
+ * If not provided, a new `MetadataModel` will be created with a randomly generated `auditUuid`.
23
+ */
24
+ constructor(className: string, metadata?: MetadataModel);
25
+ /**
26
+ * Executes the command logic. This method must be implemented by any class extending the Command base class.
27
+ *
28
+ * @param params - (Optional) Parameters required to execute the command. The specific structure and type of these
29
+ * parameters depend on the implementation in the derived class.
30
+ *
31
+ * @returns A promise that resolves when the command execution is complete. If the command encounters an error during
32
+ * execution, the promise should reject with the appropriate error.
33
+ *
34
+ * @example
35
+ * // Example implementation in a derived class
36
+ * class MyCommand extends Command {
37
+ * async execute(params?: { userId: string }): Promise<void> {
38
+ * try {
39
+ * this.logInitiated({ context: params });
40
+ * // Command logic here
41
+ * await someAsyncOperation(params?.userId);
42
+ * this.logFinished({ context: params });
43
+ * } catch (error) {
44
+ * this.logUnexpectedFailed(error, { context: params });
45
+ * throw error; // Re-throw the error for further handling
46
+ * }
47
+ * }
48
+ * }
49
+ */
50
+ abstract execute(params?: any): Promise<any>;
51
+ /**
52
+ * Logs that the command has been initiated.
53
+ * @param logData Optional contextual data for the log.
54
+ */
55
+ protected logInitiated<T>(logData?: LogData<T>): void;
56
+ /**
57
+ * Logs that the command has been successfully finished.
58
+ * @param logData Optional contextual data for the log.
59
+ */
60
+ protected logFinished<T>(logData?: LogData<T>): void;
61
+ /**
62
+ * Logs that the command has failed unexpectedly.
63
+ * @param error The error that occurred.
64
+ * @param logData Optional contextual data for the log.
65
+ */
66
+ protected logUnexpectedFailed<T>(error: Error, logData?: LogData<T>): void;
67
+ /**
68
+ * Logs detailed information about the current operation, optionally including execution time and error details.
69
+ *
70
+ * @template T - The type of contextual data included in the log.
71
+ * @template E - The type of the error (if any) included in the log.
72
+ *
73
+ * @param params - The parameters for the enhanced log.
74
+ * @param params.logMethod - The logging method to be used (e.g., `logger.info` or `logger.error`).
75
+ * @param params.message - The log message to be recorded.
76
+ * @param params.logData - (Optional) Additional contextual data for the log.
77
+ * @param params.error - (Optional) An error object to include in the log.
78
+ *
79
+ * @remarks
80
+ * - If the log message does not contain the word "initiated," the method automatically appends the `executionTime` field.
81
+ * - If an error object is provided, it will be added to the log payload under the `err` property.
82
+ * - This method builds the log payload dynamically using the provided context and metadata.
83
+ *
84
+ * @example
85
+ * // Log a successful operation
86
+ * this.enhancedLog({
87
+ * logMethod: this.logger.info,
88
+ * message: 'Operation finished successfully',
89
+ * logData: { userId: '12345' },
90
+ * });
91
+ *
92
+ * @example
93
+ * // Log a failed operation with an error
94
+ * this.enhancedLog({
95
+ * logMethod: this.logger.error,
96
+ * message: 'Operation failed',
97
+ * logData: { userId: '12345' },
98
+ * error: new Error('Unexpected error'),
99
+ * });
100
+ *
101
+ * @example
102
+ * // Log an initiated operation
103
+ * this.enhancedLog({
104
+ * logMethod: this.logger.info,
105
+ * message: 'Operation initiated',
106
+ * });
107
+ */
108
+ protected enhancedLog<T, E>({ logMethod, message, logData, error, }: EnhancedLogParams<T, E>): void;
109
+ getExecutionTime(): string;
110
+ private buildLogData;
111
+ }
112
+ export {};
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Command = void 0;
4
+ const logger_1 = require("../logger");
5
+ const metadata_model_1 = require("./metadata.model");
6
+ const uuid_1 = require("uuid");
7
+ class Command {
8
+ /**
9
+ * Creates a new instance of the Command class.
10
+ *
11
+ * @param className - The name of the class extending the Command class. Used for logging purposes.
12
+ * @param metadata - (Optional) A metadata model containing additional information for the command.
13
+ * If not provided, a new `MetadataModel` will be created with a randomly generated `auditUuid`.
14
+ */
15
+ constructor(className, metadata = new metadata_model_1.MetadataModel({
16
+ auditUuid: (0, uuid_1.v4)(),
17
+ })) {
18
+ this.className = className;
19
+ this.metadata = metadata;
20
+ this.logger = logger_1.logger;
21
+ this.startTime = performance.now();
22
+ }
23
+ /**
24
+ * Logs that the command has been initiated.
25
+ * @param logData Optional contextual data for the log.
26
+ */
27
+ logInitiated(logData) {
28
+ this.enhancedLog({
29
+ logMethod: this.logger.info,
30
+ message: `${this.className} initiated`,
31
+ logData,
32
+ });
33
+ }
34
+ /**
35
+ * Logs that the command has been successfully finished.
36
+ * @param logData Optional contextual data for the log.
37
+ */
38
+ logFinished(logData) {
39
+ this.enhancedLog({
40
+ logMethod: this.logger.info,
41
+ message: `${this.className} finished`,
42
+ logData,
43
+ });
44
+ }
45
+ /**
46
+ * Logs that the command has failed unexpectedly.
47
+ * @param error The error that occurred.
48
+ * @param logData Optional contextual data for the log.
49
+ */
50
+ logUnexpectedFailed(error, logData) {
51
+ this.enhancedLog({
52
+ logMethod: this.logger.error,
53
+ message: `${this.className} failed`,
54
+ logData,
55
+ error,
56
+ });
57
+ }
58
+ /**
59
+ * Logs detailed information about the current operation, optionally including execution time and error details.
60
+ *
61
+ * @template T - The type of contextual data included in the log.
62
+ * @template E - The type of the error (if any) included in the log.
63
+ *
64
+ * @param params - The parameters for the enhanced log.
65
+ * @param params.logMethod - The logging method to be used (e.g., `logger.info` or `logger.error`).
66
+ * @param params.message - The log message to be recorded.
67
+ * @param params.logData - (Optional) Additional contextual data for the log.
68
+ * @param params.error - (Optional) An error object to include in the log.
69
+ *
70
+ * @remarks
71
+ * - If the log message does not contain the word "initiated," the method automatically appends the `executionTime` field.
72
+ * - If an error object is provided, it will be added to the log payload under the `err` property.
73
+ * - This method builds the log payload dynamically using the provided context and metadata.
74
+ *
75
+ * @example
76
+ * // Log a successful operation
77
+ * this.enhancedLog({
78
+ * logMethod: this.logger.info,
79
+ * message: 'Operation finished successfully',
80
+ * logData: { userId: '12345' },
81
+ * });
82
+ *
83
+ * @example
84
+ * // Log a failed operation with an error
85
+ * this.enhancedLog({
86
+ * logMethod: this.logger.error,
87
+ * message: 'Operation failed',
88
+ * logData: { userId: '12345' },
89
+ * error: new Error('Unexpected error'),
90
+ * });
91
+ *
92
+ * @example
93
+ * // Log an initiated operation
94
+ * this.enhancedLog({
95
+ * logMethod: this.logger.info,
96
+ * message: 'Operation initiated',
97
+ * });
98
+ */
99
+ enhancedLog({ logMethod, message, logData, error, }) {
100
+ const logPayload = {
101
+ ...this.buildLogData(logData),
102
+ };
103
+ //* Add `executionTime` if the message is not about initiation
104
+ if (!message.includes('initiated')) {
105
+ logPayload.executionTime = this.getExecutionTime();
106
+ }
107
+ //* Add error details if present
108
+ if (error) {
109
+ logPayload.err = error;
110
+ }
111
+ //* Log the message with the appropriate level
112
+ logMethod(message, logPayload);
113
+ }
114
+ getExecutionTime() {
115
+ const executionTime = performance.now() - this.startTime;
116
+ if (executionTime >= 1000) {
117
+ //* Converting to seconds if the execution time is greater than 1000ms
118
+ return `${(executionTime / 1000).toFixed(2)}s`;
119
+ }
120
+ return `${executionTime.toFixed(2)}ms`;
121
+ }
122
+ buildLogData(logData) {
123
+ var _a;
124
+ return {
125
+ metadata: (_a = this.metadata) === null || _a === void 0 ? void 0 : _a.getData(),
126
+ ...logData,
127
+ };
128
+ }
129
+ }
130
+ exports.Command = Command;
@@ -0,0 +1,4 @@
1
+ export declare function LogMethod(options?: {
2
+ logParams?: boolean;
3
+ logReturn?: boolean;
4
+ }): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogMethod = void 0;
4
+ const logger_1 = require("src/logger");
5
+ function LogMethod(options) {
6
+ return function (target, propertyKey, descriptor) {
7
+ const originalMethod = descriptor.value;
8
+ descriptor.value = async function (...args) {
9
+ var _a, _b;
10
+ const className = target.constructor.name;
11
+ const params = (options === null || options === void 0 ? void 0 : options.logParams) ? args : undefined;
12
+ const metadata = (_a = this.metadata) === null || _a === void 0 ? void 0 : _a.getData();
13
+ try {
14
+ logger_1.logger.info(`${className}.${propertyKey} Initiated`, {
15
+ metadata,
16
+ context: {
17
+ params,
18
+ },
19
+ });
20
+ const result = await originalMethod.apply(this, args);
21
+ logger_1.logger.info(`${className}.${propertyKey} Finished`, {
22
+ metadata,
23
+ context: {
24
+ params,
25
+ result: (options === null || options === void 0 ? void 0 : options.logReturn) ? result : undefined,
26
+ },
27
+ });
28
+ return result;
29
+ }
30
+ catch (error) {
31
+ if (error instanceof Error) {
32
+ // Tentativa de deixar o stack trace mais limpo
33
+ const cleanStack = (_b = error.stack) === null || _b === void 0 ? void 0 : _b.split('\n').filter((line) => !line.includes('descriptor.value') &&
34
+ !line.includes('logMethod.decorator.ts') &&
35
+ !line.includes('node:internal/process/task_queues')).join('\n');
36
+ logger_1.logger.error(`${className}.${propertyKey} Failed`, {
37
+ err: { message: error.message, stack: cleanStack },
38
+ metadata,
39
+ context: {
40
+ params,
41
+ },
42
+ });
43
+ }
44
+ else {
45
+ // Caso o erro não seja uma instância de Error, logamos como um objeto desconhecido
46
+ logger_1.logger.error(`${className}.${propertyKey} Failed`, {
47
+ err: { message: 'Unknown error', details: error },
48
+ metadata,
49
+ context: {
50
+ params,
51
+ },
52
+ });
53
+ }
54
+ throw error;
55
+ }
56
+ };
57
+ return descriptor;
58
+ };
59
+ }
60
+ exports.LogMethod = LogMethod;
@@ -38,3 +38,4 @@ export declare function shortUniqueId(): string;
38
38
  */
39
39
  export declare function copy<T>(obj: T): T;
40
40
  export { MetadataModel, IMetadata } from './metadata.model';
41
+ export { Command } from './command.abstract';
package/general/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MetadataModel = exports.copy = exports.shortUniqueId = exports.mergeDeep = exports.timeout = exports.randomSixDigitNumber = exports.pipe = void 0;
3
+ exports.Command = exports.MetadataModel = exports.copy = exports.shortUniqueId = exports.mergeDeep = exports.timeout = exports.randomSixDigitNumber = exports.pipe = void 0;
4
4
  const nanoid_1 = require("nanoid");
5
5
  function pipe(...fns) {
6
6
  return (x) => fns.reduce((v, f) => f(v), x);
@@ -104,3 +104,5 @@ function copy(obj) {
104
104
  exports.copy = copy;
105
105
  var metadata_model_1 = require("./metadata.model");
106
106
  Object.defineProperty(exports, "MetadataModel", { enumerable: true, get: function () { return metadata_model_1.MetadataModel; } });
107
+ var command_abstract_1 = require("./command.abstract");
108
+ Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return command_abstract_1.Command; } });
@@ -1,9 +1,45 @@
1
- export interface IMetadata {
1
+ /**
2
+ * Represents metadata for tracking execution flow within commands.
3
+ *
4
+ * @param auditUuid - The UUID used to track the full execution flow.
5
+ * Example: The `auditUuid` from `OrderTravelCommand` will be passed to all items processed by `ProcessOrderItemCommand`.
6
+ * @param actionUuid - (Optional) The UUID used for tracking sub-flows.
7
+ * Example: `ProcessOrderItemCommand` generates its own `actionUuid` and passes it along for tracking each item.
8
+ * @param extraInfo - (Optional) Additional information related to the command.
9
+ */
10
+ export interface IMetadata<T = any> {
2
11
  auditUuid: string;
12
+ actionUuid?: string;
13
+ extraInfo?: T;
3
14
  }
15
+ /**
16
+ * @param metadata - The metadata object containing execution tracking details.
17
+ */
4
18
  export declare class MetadataModel {
5
19
  private metadata;
6
20
  constructor(metadata: IMetadata);
21
+ /**
22
+ * Retrieves the complete metadata object.
23
+ *
24
+ * @returns The metadata object.
25
+ */
7
26
  getData(): IMetadata;
27
+ /**
28
+ * Retrieves the UUID used to track the full execution flow.
29
+ *
30
+ * @returns The audit UUID.
31
+ */
8
32
  getAuditUuid(): string;
33
+ /**
34
+ * Retrieves the UUID used for tracking sub-flows.
35
+ *
36
+ * @returns The action UUID, or undefined if not set.
37
+ */
38
+ getActionUuid(): string | undefined;
39
+ /**
40
+ * Retrieves additional information related to the execution flow.
41
+ *
42
+ * @returns The extra information, or undefined if not available.
43
+ */
44
+ getExtraInfo<T = any>(): T | undefined;
9
45
  }
@@ -1,15 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MetadataModel = void 0;
4
+ /**
5
+ * @param metadata - The metadata object containing execution tracking details.
6
+ */
4
7
  class MetadataModel {
5
8
  constructor(metadata) {
6
9
  this.metadata = metadata;
7
10
  }
11
+ /**
12
+ * Retrieves the complete metadata object.
13
+ *
14
+ * @returns The metadata object.
15
+ */
8
16
  getData() {
9
17
  return this.metadata;
10
18
  }
19
+ /**
20
+ * Retrieves the UUID used to track the full execution flow.
21
+ *
22
+ * @returns The audit UUID.
23
+ */
11
24
  getAuditUuid() {
12
25
  return this.metadata.auditUuid;
13
26
  }
27
+ /**
28
+ * Retrieves the UUID used for tracking sub-flows.
29
+ *
30
+ * @returns The action UUID, or undefined if not set.
31
+ */
32
+ getActionUuid() {
33
+ return this.metadata.actionUuid;
34
+ }
35
+ /**
36
+ * Retrieves additional information related to the execution flow.
37
+ *
38
+ * @returns The extra information, or undefined if not available.
39
+ */
40
+ getExtraInfo() {
41
+ return this.metadata.extraInfo;
42
+ }
14
43
  }
15
44
  exports.MetadataModel = MetadataModel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sm-utility",
3
- "version": "2.4.9",
3
+ "version": "2.4.12",
4
4
  "description": "reusable utility codes for sm projects",
5
5
  "main": "index.js",
6
6
  "types": "./index.d.ts",