@adatechnology/logger 0.0.2
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.
- package/CHANGELOG.md +7 -0
- package/README.md +151 -0
- package/agents/skills/SKILL.md +47 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.js +567 -0
- package/package.json +27 -0
- package/src/context/async-context.service.ts +17 -0
- package/src/context/async-context.types.ts +1 -0
- package/src/implementations/winston/winston.logger.constants.ts +1 -0
- package/src/implementations/winston/winston.logger.module.ts +305 -0
- package/src/implementations/winston/winston.logger.provider.ts +98 -0
- package/src/implementations/winston/winston.logger.token.ts +3 -0
- package/src/implementations/winston/winston.logger.types.ts +16 -0
- package/src/index.ts +11 -0
- package/src/logger.config.ts +57 -0
- package/src/logger.constant.ts +32 -0
- package/src/logger.interface.ts +25 -0
- package/src/logger.module.ts +50 -0
- package/src/logger.provider.ts +53 -0
- package/src/logger.token.ts +1 -0
- package/src/middleware/request-context.middleware.ts +26 -0
- package/src/middleware/request-context.types.ts +11 -0
- package/src/obfuscator.ts +96 -0
- package/src/obfuscator.types.ts +6 -0
- package/src/request-id.constants.ts +7 -0
- package/tsconfig.json +14 -0
- package/tsconfig.tsup.json +6 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
19
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
20
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
21
|
+
if (decorator = decorators[i])
|
|
22
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
23
|
+
if (kind && result) __defProp(target, key, result);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
27
|
+
|
|
28
|
+
// src/index.ts
|
|
29
|
+
var index_exports = {};
|
|
30
|
+
__export(index_exports, {
|
|
31
|
+
DEFAULT_LOGGER_CONFIG: () => DEFAULT_LOGGER_CONFIG,
|
|
32
|
+
LOGGER_PROVIDER: () => LOGGER_PROVIDER,
|
|
33
|
+
LoggerModule: () => LoggerModule,
|
|
34
|
+
RequestContextMiddleware: () => RequestContextMiddleware,
|
|
35
|
+
getContext: () => getContext,
|
|
36
|
+
runWithContext: () => runWithContext
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
|
+
|
|
40
|
+
// src/logger.module.ts
|
|
41
|
+
var import_common4 = require("@nestjs/common");
|
|
42
|
+
|
|
43
|
+
// src/logger.provider.ts
|
|
44
|
+
var import_common = require("@nestjs/common");
|
|
45
|
+
|
|
46
|
+
// src/implementations/winston/winston.logger.token.ts
|
|
47
|
+
var WINSTON_LOGGER = "WINSTON_LOGGER";
|
|
48
|
+
var WINSTON_RAW = "WINSTON_RAW";
|
|
49
|
+
var WINSTON_OBFUSCATOR = "WINSTON_OBFUSCATOR";
|
|
50
|
+
|
|
51
|
+
// src/logger.provider.ts
|
|
52
|
+
var LoggerProvider = class {
|
|
53
|
+
constructor(implementation) {
|
|
54
|
+
this.implementation = implementation;
|
|
55
|
+
}
|
|
56
|
+
debug(...args) {
|
|
57
|
+
return this.implementation.debug(...args);
|
|
58
|
+
}
|
|
59
|
+
info(...args) {
|
|
60
|
+
return this.implementation.info(...args);
|
|
61
|
+
}
|
|
62
|
+
warn(...args) {
|
|
63
|
+
return this.implementation.warn(...args);
|
|
64
|
+
}
|
|
65
|
+
error(...args) {
|
|
66
|
+
return this.implementation.error(...args);
|
|
67
|
+
}
|
|
68
|
+
setContext(context) {
|
|
69
|
+
if (typeof this.implementation.setContext === "function") {
|
|
70
|
+
return this.implementation.setContext(context);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
LoggerProvider = __decorateClass([
|
|
76
|
+
(0, import_common.Injectable)(),
|
|
77
|
+
__decorateParam(0, (0, import_common.Inject)(WINSTON_LOGGER))
|
|
78
|
+
], LoggerProvider);
|
|
79
|
+
|
|
80
|
+
// src/logger.token.ts
|
|
81
|
+
var LOGGER_PROVIDER = "LOGGER_PROVIDER";
|
|
82
|
+
|
|
83
|
+
// src/implementations/winston/winston.logger.module.ts
|
|
84
|
+
var import_common3 = require("@nestjs/common");
|
|
85
|
+
var import_winston = require("winston");
|
|
86
|
+
var import_util = require("util");
|
|
87
|
+
|
|
88
|
+
// src/implementations/winston/winston.logger.provider.ts
|
|
89
|
+
var import_common2 = require("@nestjs/common");
|
|
90
|
+
|
|
91
|
+
// src/context/async-context.service.ts
|
|
92
|
+
var import_async_hooks = require("async_hooks");
|
|
93
|
+
var asyncLocalStorage = new import_async_hooks.AsyncLocalStorage();
|
|
94
|
+
function getContext() {
|
|
95
|
+
return asyncLocalStorage.getStore();
|
|
96
|
+
}
|
|
97
|
+
function runWithContext(ctx, fn) {
|
|
98
|
+
return asyncLocalStorage.run(ctx, fn);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/logger.constant.ts
|
|
102
|
+
var DEFAULT_SENSITIVE_KEYS = [
|
|
103
|
+
"password",
|
|
104
|
+
"pass",
|
|
105
|
+
"pwd",
|
|
106
|
+
"token",
|
|
107
|
+
"accessToken",
|
|
108
|
+
"refreshToken",
|
|
109
|
+
"authorization",
|
|
110
|
+
"auth",
|
|
111
|
+
"secret",
|
|
112
|
+
"ssn",
|
|
113
|
+
"creditCard"
|
|
114
|
+
];
|
|
115
|
+
var EMPTY_STRING = "";
|
|
116
|
+
var MASK = {
|
|
117
|
+
REPLACEMENT: "****",
|
|
118
|
+
MIN_LENGTH: 4,
|
|
119
|
+
EDGE_CHARS: 2
|
|
120
|
+
};
|
|
121
|
+
var MASK_REPLACEMENT = MASK.REPLACEMENT;
|
|
122
|
+
var MASK_MIN_LENGTH = MASK.MIN_LENGTH;
|
|
123
|
+
var MASK_EDGE_CHARS = MASK.EDGE_CHARS;
|
|
124
|
+
var ID_FALLBACK_SEPARATOR = "-";
|
|
125
|
+
|
|
126
|
+
// src/implementations/winston/winston.logger.provider.ts
|
|
127
|
+
var WinstonLoggerProvider = class {
|
|
128
|
+
constructor(logger, obfuscator) {
|
|
129
|
+
this.logger = logger;
|
|
130
|
+
this.obfuscator = obfuscator;
|
|
131
|
+
}
|
|
132
|
+
context;
|
|
133
|
+
debug(messageOrPayload, meta, context) {
|
|
134
|
+
this.handleLog("debug" /* DEBUG */, messageOrPayload, meta, context);
|
|
135
|
+
}
|
|
136
|
+
info(messageOrPayload, meta, context) {
|
|
137
|
+
this.handleLog("info" /* INFO */, messageOrPayload, meta, context);
|
|
138
|
+
}
|
|
139
|
+
warn(messageOrPayload, meta, context) {
|
|
140
|
+
this.handleLog("warn" /* WARN */, messageOrPayload, meta, context);
|
|
141
|
+
}
|
|
142
|
+
error(messageOrPayload, meta, context) {
|
|
143
|
+
this.handleLog("error" /* ERROR */, messageOrPayload, meta, context);
|
|
144
|
+
}
|
|
145
|
+
setContext(context) {
|
|
146
|
+
this.context = context;
|
|
147
|
+
}
|
|
148
|
+
handleLog(level, messageOrPayload, meta, context) {
|
|
149
|
+
let payload;
|
|
150
|
+
if (typeof messageOrPayload === "string") {
|
|
151
|
+
payload = {
|
|
152
|
+
message: messageOrPayload,
|
|
153
|
+
meta,
|
|
154
|
+
context: context || this.context
|
|
155
|
+
};
|
|
156
|
+
} else {
|
|
157
|
+
payload = {
|
|
158
|
+
...messageOrPayload,
|
|
159
|
+
context: messageOrPayload.context || context || this.context,
|
|
160
|
+
meta: { ...messageOrPayload.meta, ...meta }
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
this.log({ level, payload });
|
|
164
|
+
}
|
|
165
|
+
log(params) {
|
|
166
|
+
const { level, payload } = params;
|
|
167
|
+
const { message, context, meta, ...rest } = payload;
|
|
168
|
+
const messageText = message ?? EMPTY_STRING;
|
|
169
|
+
const messageContext = context ?? this.context;
|
|
170
|
+
const obfuscatedMeta = this.obfuscator ? this.obfuscator(meta) : meta;
|
|
171
|
+
const requestContext = getContext();
|
|
172
|
+
const requestIdFromContext = requestContext?.requestId;
|
|
173
|
+
const logInfo = {
|
|
174
|
+
...rest,
|
|
175
|
+
context: messageContext,
|
|
176
|
+
requestId: requestIdFromContext || payload.requestId,
|
|
177
|
+
meta: obfuscatedMeta
|
|
178
|
+
};
|
|
179
|
+
this.logger.log(level, messageText, logInfo);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
WinstonLoggerProvider = __decorateClass([
|
|
183
|
+
(0, import_common2.Injectable)(),
|
|
184
|
+
__decorateParam(0, (0, import_common2.Inject)(WINSTON_RAW)),
|
|
185
|
+
__decorateParam(1, (0, import_common2.Inject)(WINSTON_OBFUSCATOR))
|
|
186
|
+
], WinstonLoggerProvider);
|
|
187
|
+
|
|
188
|
+
// src/implementations/winston/winston.logger.constants.ts
|
|
189
|
+
var DEFAULT_LOG_LEVEL = "info";
|
|
190
|
+
|
|
191
|
+
// src/obfuscator.ts
|
|
192
|
+
function isObject(value) {
|
|
193
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
194
|
+
}
|
|
195
|
+
function maskString(str) {
|
|
196
|
+
if (str.length <= MASK.MIN_LENGTH) return MASK.REPLACEMENT;
|
|
197
|
+
return str.slice(0, MASK.EDGE_CHARS) + MASK.REPLACEMENT + str.slice(-MASK.EDGE_CHARS);
|
|
198
|
+
}
|
|
199
|
+
function normalizeEntries(entries) {
|
|
200
|
+
const keys = [];
|
|
201
|
+
const custom = /* @__PURE__ */ new Map();
|
|
202
|
+
if (!entries || entries.length === 0) return { keys, custom };
|
|
203
|
+
for (const entry of entries) {
|
|
204
|
+
if (typeof entry === "string") {
|
|
205
|
+
keys.push(entry);
|
|
206
|
+
} else if (entry && typeof entry === "object" && "key" in entry && typeof entry.key === "string" && typeof entry.obfuscator === "function") {
|
|
207
|
+
custom.set(entry.key.toLowerCase(), entry.obfuscator);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return { keys, custom };
|
|
211
|
+
}
|
|
212
|
+
function defaultObfuscator(params) {
|
|
213
|
+
const { obj, entries } = params;
|
|
214
|
+
if (obj == null) return obj;
|
|
215
|
+
if (Array.isArray(obj)) {
|
|
216
|
+
return obj.map((item) => defaultObfuscator({ obj: item, entries }));
|
|
217
|
+
}
|
|
218
|
+
if (!isObject(obj)) return obj;
|
|
219
|
+
const { keys: extraKeys, custom } = normalizeEntries(entries);
|
|
220
|
+
const keys = DEFAULT_SENSITIVE_KEYS.concat(extraKeys || []);
|
|
221
|
+
function splitIntoWords(k) {
|
|
222
|
+
const withSpaces = k.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_\-.]+/g, " ");
|
|
223
|
+
return withSpaces.split(/\s+/).filter(Boolean);
|
|
224
|
+
}
|
|
225
|
+
const out = {};
|
|
226
|
+
for (const key of Object.keys(obj)) {
|
|
227
|
+
const value = obj[key];
|
|
228
|
+
const lowerKey = key.toLowerCase();
|
|
229
|
+
if (custom.has(lowerKey)) {
|
|
230
|
+
try {
|
|
231
|
+
out[key] = custom.get(lowerKey)(value);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
out[key] = MASK.REPLACEMENT;
|
|
234
|
+
}
|
|
235
|
+
} else if (
|
|
236
|
+
// match when key exactly equals a sensitive token OR
|
|
237
|
+
// when any token equals one of the camelCase/sep-separated words
|
|
238
|
+
keys.some((s) => {
|
|
239
|
+
const sens = s.toLowerCase();
|
|
240
|
+
if (lowerKey === sens) return true;
|
|
241
|
+
const words = splitIntoWords(lowerKey);
|
|
242
|
+
return words.some((w) => w === sens);
|
|
243
|
+
})
|
|
244
|
+
) {
|
|
245
|
+
if (typeof value === "string") out[key] = maskString(value);
|
|
246
|
+
else out[key] = MASK.REPLACEMENT;
|
|
247
|
+
} else if (isObject(value) || Array.isArray(value)) {
|
|
248
|
+
out[key] = defaultObfuscator({ obj: value, entries });
|
|
249
|
+
} else {
|
|
250
|
+
out[key] = value;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return out;
|
|
254
|
+
}
|
|
255
|
+
function buildDefaultObfuscator(additional) {
|
|
256
|
+
return (v) => defaultObfuscator({ obj: v, entries: additional });
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// src/implementations/winston/winston.logger.module.ts
|
|
260
|
+
var WinstonImplementationModule = class {
|
|
261
|
+
static forRoot(config) {
|
|
262
|
+
const providers = this.createProviders(config);
|
|
263
|
+
return {
|
|
264
|
+
module: WinstonImplementationModule,
|
|
265
|
+
providers,
|
|
266
|
+
exports: [WINSTON_LOGGER]
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
static forRootAsync(options) {
|
|
270
|
+
return {
|
|
271
|
+
module: WinstonImplementationModule,
|
|
272
|
+
imports: options.imports || [],
|
|
273
|
+
providers: [
|
|
274
|
+
{
|
|
275
|
+
provide: "LOGGER_CONFIG",
|
|
276
|
+
useFactory: options.useFactory,
|
|
277
|
+
inject: options.inject || []
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
provide: WINSTON_RAW,
|
|
281
|
+
useFactory: (config) => {
|
|
282
|
+
return this.createWinstonLogger(config);
|
|
283
|
+
},
|
|
284
|
+
inject: ["LOGGER_CONFIG"]
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
provide: WINSTON_OBFUSCATOR,
|
|
288
|
+
useFactory: (config) => {
|
|
289
|
+
return config?.obfuscator ?? buildDefaultObfuscator(config?.obfuscatorKeys);
|
|
290
|
+
},
|
|
291
|
+
inject: ["LOGGER_CONFIG"]
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
provide: WINSTON_LOGGER,
|
|
295
|
+
useClass: WinstonLoggerProvider
|
|
296
|
+
}
|
|
297
|
+
],
|
|
298
|
+
exports: [WINSTON_LOGGER]
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
static createProviders(config) {
|
|
302
|
+
const winstonLogger = this.createWinstonLogger(config);
|
|
303
|
+
const obfuscator = config?.obfuscator ?? buildDefaultObfuscator(config?.obfuscatorKeys);
|
|
304
|
+
return [
|
|
305
|
+
{
|
|
306
|
+
provide: WINSTON_RAW,
|
|
307
|
+
useValue: winstonLogger
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
provide: WINSTON_OBFUSCATOR,
|
|
311
|
+
useValue: obfuscator
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
provide: WINSTON_LOGGER,
|
|
315
|
+
useClass: WinstonLoggerProvider
|
|
316
|
+
}
|
|
317
|
+
];
|
|
318
|
+
}
|
|
319
|
+
static createWinstonLogger(config) {
|
|
320
|
+
const isProduction = config?.isProduction ?? process.env.NODE_ENV === "production";
|
|
321
|
+
const useColors = config?.colorize !== false;
|
|
322
|
+
const standardFields = (0, import_winston.format)((info) => {
|
|
323
|
+
const meta = info.meta;
|
|
324
|
+
if (meta) {
|
|
325
|
+
if (meta.requestId && !info.requestId) {
|
|
326
|
+
info.requestId = meta.requestId;
|
|
327
|
+
delete meta.requestId;
|
|
328
|
+
}
|
|
329
|
+
if (meta.context && !info.context) {
|
|
330
|
+
info.context = meta.context;
|
|
331
|
+
delete meta.context;
|
|
332
|
+
}
|
|
333
|
+
if (meta.source && !info.source) {
|
|
334
|
+
info.source = meta.source;
|
|
335
|
+
delete meta.source;
|
|
336
|
+
}
|
|
337
|
+
if (meta.lib && !info.lib) {
|
|
338
|
+
info.lib = meta.lib;
|
|
339
|
+
delete meta.lib;
|
|
340
|
+
}
|
|
341
|
+
if (meta.libVersion && !info.libVersion) {
|
|
342
|
+
info.libVersion = meta.libVersion;
|
|
343
|
+
delete meta.libVersion;
|
|
344
|
+
}
|
|
345
|
+
if (meta.libMethod && !info.libMethod) {
|
|
346
|
+
info.libMethod = meta.libMethod;
|
|
347
|
+
delete meta.libMethod;
|
|
348
|
+
}
|
|
349
|
+
if (meta.appName && !info.appName) {
|
|
350
|
+
info.appName = meta.appName;
|
|
351
|
+
delete meta.appName;
|
|
352
|
+
}
|
|
353
|
+
if (meta.appVersion && !info.appVersion) {
|
|
354
|
+
info.appVersion = meta.appVersion;
|
|
355
|
+
delete meta.appVersion;
|
|
356
|
+
}
|
|
357
|
+
if (meta.logContext && !info.source) {
|
|
358
|
+
const lc = meta.logContext;
|
|
359
|
+
if (lc.className && lc.methodName) {
|
|
360
|
+
info.source = `${lc.className}.${lc.methodName}`;
|
|
361
|
+
} else if (lc.className) {
|
|
362
|
+
info.source = lc.className;
|
|
363
|
+
} else if (lc.methodName) {
|
|
364
|
+
info.source = lc.methodName;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
info.requestId = info.requestId || "no-request-id";
|
|
369
|
+
info.context = info.context || config?.context || "App";
|
|
370
|
+
info.appName = info.appName || config?.appName;
|
|
371
|
+
info.appVersion = info.appVersion || config?.appVersion;
|
|
372
|
+
info.lib = info.lib || config?.lib;
|
|
373
|
+
info.libVersion = info.libVersion || config?.libVersion;
|
|
374
|
+
return info;
|
|
375
|
+
});
|
|
376
|
+
const levelColorizer = import_winston.format.colorize();
|
|
377
|
+
const developmentFormat = import_winston.format.printf(
|
|
378
|
+
(info) => {
|
|
379
|
+
const {
|
|
380
|
+
level,
|
|
381
|
+
message,
|
|
382
|
+
timestamp,
|
|
383
|
+
requestId,
|
|
384
|
+
context,
|
|
385
|
+
source,
|
|
386
|
+
meta,
|
|
387
|
+
stack,
|
|
388
|
+
appName,
|
|
389
|
+
appVersion,
|
|
390
|
+
lib,
|
|
391
|
+
libMethod,
|
|
392
|
+
libVersion
|
|
393
|
+
} = info;
|
|
394
|
+
const colors = {
|
|
395
|
+
reset: "\x1B[0m",
|
|
396
|
+
gray: "\x1B[90m",
|
|
397
|
+
cyan: "\x1B[36m",
|
|
398
|
+
magenta: "\x1B[35m",
|
|
399
|
+
yellow: "\x1B[33m",
|
|
400
|
+
red: "\x1B[31m",
|
|
401
|
+
green: "\x1B[32m",
|
|
402
|
+
bold: "\x1B[1m"
|
|
403
|
+
};
|
|
404
|
+
const colorize = (color, text) => useColors ? `${color}${text}${colors.reset}` : text;
|
|
405
|
+
const coloredLevel = useColors ? levelColorizer.colorize(level, level.toUpperCase()) : level.toUpperCase();
|
|
406
|
+
const coloredTime = colorize(colors.gray, timestamp);
|
|
407
|
+
const coloredRequestId = colorize(colors.cyan, requestId);
|
|
408
|
+
let appDisplay = "";
|
|
409
|
+
if (appName) {
|
|
410
|
+
const appText = appVersion ? `${appName}@${appVersion}` : appName;
|
|
411
|
+
appDisplay = `[${colorize(colors.green, `App-${appText}`)}]`;
|
|
412
|
+
}
|
|
413
|
+
let libDisplay = "";
|
|
414
|
+
if (lib) {
|
|
415
|
+
const libText = libVersion ? `${lib}:${libVersion}` : lib;
|
|
416
|
+
libDisplay = `[${colorize(colors.yellow, libText)}]`;
|
|
417
|
+
}
|
|
418
|
+
const mag = colors.magenta;
|
|
419
|
+
let sourceDisplay = "";
|
|
420
|
+
let libMethodDisplay = "";
|
|
421
|
+
if (source) {
|
|
422
|
+
sourceDisplay = `[${colorize(mag, source)}]`;
|
|
423
|
+
}
|
|
424
|
+
if (lib) {
|
|
425
|
+
const methodPath = libMethod ? `${context}.${libMethod}` : context;
|
|
426
|
+
libMethodDisplay = `[${colorize(mag, methodPath)}]`;
|
|
427
|
+
if (source === context || source === methodPath) {
|
|
428
|
+
sourceDisplay = "";
|
|
429
|
+
}
|
|
430
|
+
} else if (!source) {
|
|
431
|
+
libMethodDisplay = `[${colorize(mag, context)}]`;
|
|
432
|
+
} else if (source.startsWith(`${context}.`) || source === context) {
|
|
433
|
+
libMethodDisplay = `[${colorize(mag, source)}]`;
|
|
434
|
+
sourceDisplay = "";
|
|
435
|
+
} else {
|
|
436
|
+
libMethodDisplay = `[${colorize(mag, context)}]`;
|
|
437
|
+
sourceDisplay = `[${colorize(mag, source)}]`;
|
|
438
|
+
}
|
|
439
|
+
let output = `${appDisplay}${libDisplay}[${coloredRequestId}][${coloredTime}]${sourceDisplay}${libMethodDisplay}[${coloredLevel}] - ${message}`;
|
|
440
|
+
if (meta && typeof meta === "object" && Object.keys(meta).length > 0) {
|
|
441
|
+
const inspectedMeta = (0, import_util.inspect)(meta, {
|
|
442
|
+
colors: useColors,
|
|
443
|
+
depth: null,
|
|
444
|
+
compact: true,
|
|
445
|
+
sorted: true,
|
|
446
|
+
breakLength: Infinity
|
|
447
|
+
});
|
|
448
|
+
output += ` - ${inspectedMeta}`;
|
|
449
|
+
}
|
|
450
|
+
if (stack) {
|
|
451
|
+
output += `
|
|
452
|
+
${colorize(colors.red, stack)}`;
|
|
453
|
+
}
|
|
454
|
+
return output;
|
|
455
|
+
}
|
|
456
|
+
);
|
|
457
|
+
const formats = [
|
|
458
|
+
import_winston.format.timestamp(),
|
|
459
|
+
import_winston.format.errors({ stack: true }),
|
|
460
|
+
import_winston.format.splat(),
|
|
461
|
+
standardFields()
|
|
462
|
+
];
|
|
463
|
+
if (isProduction) {
|
|
464
|
+
formats.push(import_winston.format.json());
|
|
465
|
+
} else {
|
|
466
|
+
formats.push(developmentFormat);
|
|
467
|
+
}
|
|
468
|
+
const defaultFormat = import_winston.format.combine(...formats);
|
|
469
|
+
const consoleTransport = new import_winston.transports.Console({
|
|
470
|
+
format: defaultFormat
|
|
471
|
+
});
|
|
472
|
+
const defaultOptions = {
|
|
473
|
+
level: config?.level || process.env.LOG_LEVEL || DEFAULT_LOG_LEVEL,
|
|
474
|
+
format: defaultFormat,
|
|
475
|
+
transports: [consoleTransport]
|
|
476
|
+
};
|
|
477
|
+
const mergedOptions = Object.assign(
|
|
478
|
+
{},
|
|
479
|
+
defaultOptions,
|
|
480
|
+
config?.loggerOptions || {}
|
|
481
|
+
);
|
|
482
|
+
return (0, import_winston.createLogger)(mergedOptions);
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
WinstonImplementationModule = __decorateClass([
|
|
486
|
+
(0, import_common3.Module)({})
|
|
487
|
+
], WinstonImplementationModule);
|
|
488
|
+
|
|
489
|
+
// src/logger.module.ts
|
|
490
|
+
var LoggerModule = class {
|
|
491
|
+
static forRoot(config) {
|
|
492
|
+
const implModule = WinstonImplementationModule.forRoot(config);
|
|
493
|
+
const provider = {
|
|
494
|
+
provide: LOGGER_PROVIDER,
|
|
495
|
+
useClass: LoggerProvider
|
|
496
|
+
};
|
|
497
|
+
if (config && config.requestScoped) {
|
|
498
|
+
provider.scope = import_common4.Scope.REQUEST;
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
module: LoggerModule,
|
|
502
|
+
imports: [implModule],
|
|
503
|
+
providers: [provider],
|
|
504
|
+
exports: [LOGGER_PROVIDER]
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
static forRootAsync(options) {
|
|
508
|
+
return {
|
|
509
|
+
module: LoggerModule,
|
|
510
|
+
imports: [
|
|
511
|
+
...options.imports || [],
|
|
512
|
+
WinstonImplementationModule.forRootAsync(options)
|
|
513
|
+
],
|
|
514
|
+
providers: [
|
|
515
|
+
{
|
|
516
|
+
provide: LOGGER_PROVIDER,
|
|
517
|
+
useClass: LoggerProvider
|
|
518
|
+
}
|
|
519
|
+
],
|
|
520
|
+
exports: [LOGGER_PROVIDER]
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
LoggerModule = __decorateClass([
|
|
525
|
+
(0, import_common4.Global)(),
|
|
526
|
+
(0, import_common4.Module)({})
|
|
527
|
+
], LoggerModule);
|
|
528
|
+
|
|
529
|
+
// src/middleware/request-context.middleware.ts
|
|
530
|
+
var import_common5 = require("@nestjs/common");
|
|
531
|
+
var import_crypto = require("crypto");
|
|
532
|
+
|
|
533
|
+
// src/request-id.constants.ts
|
|
534
|
+
var DEFAULT_HTTP_REQUEST_ID_HEADER = "x-request-id";
|
|
535
|
+
var DEFAULT_HTTP_REQUEST_ID_FALLBACKS = ["x-correlation-id"];
|
|
536
|
+
var HEADERS_PARAMS = {
|
|
537
|
+
REQUEST_ID: DEFAULT_HTTP_REQUEST_ID_HEADER,
|
|
538
|
+
FALLBACKS: DEFAULT_HTTP_REQUEST_ID_FALLBACKS
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
// src/middleware/request-context.middleware.ts
|
|
542
|
+
var RequestContextMiddleware = class {
|
|
543
|
+
use(req, _res, next) {
|
|
544
|
+
const existing = req.headers?.[HEADERS_PARAMS.REQUEST_ID] || req.headers?.[HEADERS_PARAMS.FALLBACKS[0]];
|
|
545
|
+
const id = existing || (typeof import_crypto.randomUUID === "function" ? (0, import_crypto.randomUUID)() : `${Date.now()}${ID_FALLBACK_SEPARATOR}${Math.random()}`);
|
|
546
|
+
asyncLocalStorage.run({ requestId: id }, () => next());
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
RequestContextMiddleware = __decorateClass([
|
|
550
|
+
(0, import_common5.Injectable)()
|
|
551
|
+
], RequestContextMiddleware);
|
|
552
|
+
|
|
553
|
+
// src/logger.config.ts
|
|
554
|
+
var DEFAULT_LOGGER_CONFIG = {
|
|
555
|
+
requestScoped: false,
|
|
556
|
+
level: "info",
|
|
557
|
+
colorize: true
|
|
558
|
+
};
|
|
559
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
560
|
+
0 && (module.exports = {
|
|
561
|
+
DEFAULT_LOGGER_CONFIG,
|
|
562
|
+
LOGGER_PROVIDER,
|
|
563
|
+
LoggerModule,
|
|
564
|
+
RequestContextMiddleware,
|
|
565
|
+
getContext,
|
|
566
|
+
runWithContext
|
|
567
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adatechnology/logger",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"@nestjs/common": "^11.0.16",
|
|
12
|
+
"@nestjs/core": "^11"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@esbuild-plugins/tsconfig-paths": "^0.1.2",
|
|
16
|
+
"tsup": "^8.5.1"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"winston": "^3.9.0"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"prebuild": "rm -rf dist",
|
|
23
|
+
"build": "tsup src/index.ts --dts --tsconfig tsconfig.tsup.json",
|
|
24
|
+
"build:watch": "tsup src/index.ts --watch --dts --tsconfig tsconfig.tsup.json",
|
|
25
|
+
"check": "tsc -p tsconfig.json --noEmit"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2
|
+
import { RequestContext } from "./async-context.types";
|
|
3
|
+
|
|
4
|
+
export const asyncLocalStorage = new AsyncLocalStorage<
|
|
5
|
+
Record<string, unknown>
|
|
6
|
+
>();
|
|
7
|
+
|
|
8
|
+
export function getContext(): RequestContext {
|
|
9
|
+
return asyncLocalStorage.getStore();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function runWithContext<T>(
|
|
13
|
+
ctx: Record<string, unknown>,
|
|
14
|
+
fn: () => T,
|
|
15
|
+
): T {
|
|
16
|
+
return asyncLocalStorage.run(ctx, fn as any);
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type RequestContext = Record<string, unknown> | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_LOG_LEVEL = "info";
|