b2b-platform-utils 1.1.3 → 1.1.5

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 (3) hide show
  1. package/logger.js +136 -28
  2. package/objectWrapper.js +48 -0
  3. package/package.json +1 -1
package/logger.js CHANGED
@@ -1,33 +1,141 @@
1
1
  'use strict';
2
2
 
3
- // Purpose: Colorized console logging helpers for quick CLI visibility.
3
+ /**
4
+ * @module logger
5
+ * @description
6
+ * Non-blocking logger that reads environment and service name from localCache.
7
+ * - Production (environment === "production"): newline-delimited JSON to stdout/stderr.
8
+ * - Non-production: colorized console output with icons.
9
+ * - Uses async writes to avoid blocking hot paths.
10
+ *
11
+ * Dependencies:
12
+ * - localCache module must export: getValue(key), getService().
13
+ */
4
14
 
5
- module.exports = {
6
- /**
7
- * Print a debug payload as magenta JSON.
8
- */
9
- debug: (data) => {
10
- console.log(`\x1b[35m❗ ${JSON.stringify(data)} [DEBUG] \x1b[0m`);
11
- },
12
-
13
- /**
14
- * Print a green success note.
15
- */
16
- successNote: (message) => {
17
- console.info(`\x1b[32m✅ ${message?.toString()} \x1b[0m`);
18
- },
19
-
20
- /**
21
- * Print a red critical note.
22
- */
23
- criticalNote: (message) => {
24
- console.info(`\x1b[31m⛔ ${message?.toString()} ⛔\x1b[0m`);
25
- },
26
-
27
- /**
28
- * Print a yellow warning note.
29
- */
30
- warningNote: (message) => {
31
- console.warn(`\x1b[33m❗ ${message?.toString()} ❗\x1b[0m`);
15
+ let cache;
16
+ try {
17
+ // NOTE: Adjust the path if your cache module lives elsewhere.
18
+ cache = require('./localCache');
19
+ } catch (_) {
20
+ // NOTE: Safe fallback stub to keep logger functional if cache is not available.
21
+ cache = {
22
+ getValue: () => null,
23
+ getService: () => 'not_set_service'
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Resolve current environment and service on each call.
29
+ * This allows dynamic changes at runtime (if your cache updates).
30
+ */
31
+ function resolveContext() {
32
+ const env = cache.getValue('environment') || 'development';
33
+ const service = cache.getService ? cache.getService() : 'not_set_service';
34
+ const isProd = env === 'production';
35
+ return { env, service, isProd };
36
+ }
37
+
38
+ /**
39
+ * Internal async writer using setImmediate to offload writes from the hot path.
40
+ * @param {'stdout'|'stderr'} stream
41
+ * @param {string} message
42
+ */
43
+ function asyncWrite(stream, message) {
44
+ setImmediate(() => {
45
+ process[stream].write(message + '\n');
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Serialize a structured JSON log line for production.
51
+ * @param {string} level
52
+ * @param {string} message
53
+ * @param {Record<string, any>=} extra
54
+ */
55
+ function serializeJSON(level, message, extra = {}) {
56
+ const { env, service } = resolveContext();
57
+ return JSON.stringify({
58
+ ts: new Date().toISOString(),
59
+ level,
60
+ service,
61
+ env,
62
+ msg: message,
63
+ ...extra
64
+ });
65
+ }
66
+
67
+ /**
68
+ * Build a colorized single-line message for non-production.
69
+ * @param {string} colorCode
70
+ * @param {string} icon
71
+ * @param {string} message
72
+ * @param {string} label
73
+ */
74
+ function colorize(colorCode, icon, message, label) {
75
+ return `${colorCode}${icon} ${message} [${label}] \x1b[0m`;
76
+ }
77
+
78
+ /**
79
+ * Print a debug payload (object) as magenta JSON or structured JSON in prod.
80
+ * @param {any} data
81
+ */
82
+ function debug(data) {
83
+ const { isProd } = resolveContext();
84
+ if (isProd) {
85
+ asyncWrite('stdout', serializeJSON('debug', 'debug payload', { data }));
86
+ } else {
87
+ const payload = (() => {
88
+ try { return JSON.stringify(data); } catch { return String(data); }
89
+ })();
90
+ asyncWrite('stdout', colorize('\x1b[35m', '🐛', payload, 'DEBUG'));
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Print a green success note.
96
+ * @param {string|number|boolean} message
97
+ */
98
+ function successNote(message) {
99
+ const { isProd } = resolveContext();
100
+ const msg = message != null ? message.toString() : '';
101
+ if (isProd) {
102
+ asyncWrite('stdout', serializeJSON('info', msg));
103
+ } else {
104
+ asyncWrite('stdout', colorize('\x1b[32m', '✅', msg, 'SUCCESS'));
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Print a red critical note.
110
+ * @param {string|number|boolean} message
111
+ */
112
+ function criticalNote(message) {
113
+ const { isProd } = resolveContext();
114
+ const msg = message != null ? message.toString() : '';
115
+ if (isProd) {
116
+ asyncWrite('stderr', serializeJSON('error', msg));
117
+ } else {
118
+ asyncWrite('stderr', colorize('\x1b[31m', '⛔', msg, 'CRITICAL'));
32
119
  }
120
+ }
121
+
122
+ /**
123
+ * Print a yellow warning note.
124
+ * @param {string|number|boolean} message
125
+ */
126
+ function warningNote(message) {
127
+ const { isProd } = resolveContext();
128
+ const msg = message != null ? message.toString() : '';
129
+ if (isProd) {
130
+ asyncWrite('stderr', serializeJSON('warn', msg));
131
+ } else {
132
+ asyncWrite('stderr', colorize('\x1b[33m', '⚠️', msg, 'WARNING'));
133
+ }
134
+ }
135
+
136
+ module.exports = {
137
+ debug,
138
+ successNote,
139
+ criticalNote,
140
+ warningNote
33
141
  };
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Merges multiple arrays of objects by `date_time` key.
5
+ * If objects share the same `date_time`, their properties are combined into one.
6
+ *
7
+ * @param {Array<Array<Object>>} arrayOfArrays - Array of arrays containing objects with a `date_time` field
8
+ * @returns {Array<Object>} Merged array of objects
9
+ */
10
+ function mergeArraysByDateTime(arrayOfArrays) {
11
+ const resultMap = new Map();
12
+
13
+ for (const array of arrayOfArrays) {
14
+ for (const item of array) {
15
+ const { date_time } = item;
16
+ if (!resultMap.has(date_time)) {
17
+ resultMap.set(date_time, { date_time });
18
+ }
19
+ Object.assign(resultMap.get(date_time), item);
20
+ }
21
+ }
22
+
23
+ return Array.from(resultMap.values());
24
+ }
25
+
26
+ /**
27
+ * Groups objects by `date_time` and merges their non-date properties into an `items` array.
28
+ *
29
+ * @param {Array<Object>} arrayOfObjects - Array of objects containing a `date_time` field
30
+ * @returns {Array<Object>} Array of grouped objects: { date_time, items: [...] }
31
+ */
32
+ function mergeItemsByDateTime(arrayOfObjects) {
33
+ const grouped = arrayOfObjects.reduce((acc, obj) => {
34
+ const { date_time, ...rest } = obj;
35
+ if (!acc[date_time]) {
36
+ acc[date_time] = { date_time, items: [] };
37
+ }
38
+ acc[date_time].items.push(rest);
39
+ return acc;
40
+ }, {});
41
+
42
+ return Object.values(grouped);
43
+ }
44
+
45
+ module.exports = {
46
+ mergeArraysByDateTime,
47
+ mergeItemsByDateTime,
48
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "b2b-platform-utils",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Shared utilities for Node.js microservices: errors map, local cache, logger, numbers, dates, filesystem, media optimization, paginator, slugger, crypto wrapper, sanitize HTML, sorting.",
5
5
  "type": "commonjs",
6
6
  "license": "KingSizer",