@nimbus-cqrs/core 2.0.0-beta.0
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/LICENSE +85 -0
- package/README.md +56 -0
- package/esm/_dnt.shims.d.ts +2 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/_dnt.shims.js +57 -0
- package/esm/deps/jsr.io/@std/fmt/1.0.10/colors.d.ts +700 -0
- package/esm/deps/jsr.io/@std/fmt/1.0.10/colors.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fmt/1.0.10/colors.js +903 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/_util.d.ts +14 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/_util.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/_util.js +65 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/decode_time.d.ts +20 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/decode_time.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/decode_time.js +43 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/mod.d.ts +44 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/mod.js +47 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/monotonic_ulid.d.ts +44 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/monotonic_ulid.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/monotonic_ulid.js +51 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/ulid.d.ts +31 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/ulid.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/ulid/1.0.0/ulid.js +37 -0
- package/esm/index.d.ts +18 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +17 -0
- package/esm/lib/eventBus/eventBus.d.ts +329 -0
- package/esm/lib/eventBus/eventBus.d.ts.map +1 -0
- package/esm/lib/eventBus/eventBus.js +473 -0
- package/esm/lib/exception/exception.d.ts +10 -0
- package/esm/lib/exception/exception.d.ts.map +1 -0
- package/esm/lib/exception/exception.js +26 -0
- package/esm/lib/exception/forbiddenException.d.ts +8 -0
- package/esm/lib/exception/forbiddenException.d.ts.map +1 -0
- package/esm/lib/exception/forbiddenException.js +9 -0
- package/esm/lib/exception/genericException.d.ts +8 -0
- package/esm/lib/exception/genericException.d.ts.map +1 -0
- package/esm/lib/exception/genericException.js +9 -0
- package/esm/lib/exception/invalidInputException.d.ts +18 -0
- package/esm/lib/exception/invalidInputException.d.ts.map +1 -0
- package/esm/lib/exception/invalidInputException.js +28 -0
- package/esm/lib/exception/notFoundException.d.ts +8 -0
- package/esm/lib/exception/notFoundException.d.ts.map +1 -0
- package/esm/lib/exception/notFoundException.js +9 -0
- package/esm/lib/exception/unauthorizedException.d.ts +8 -0
- package/esm/lib/exception/unauthorizedException.d.ts.map +1 -0
- package/esm/lib/exception/unauthorizedException.js +9 -0
- package/esm/lib/log/logFormatter.d.ts +26 -0
- package/esm/lib/log/logFormatter.d.ts.map +1 -0
- package/esm/lib/log/logFormatter.js +59 -0
- package/esm/lib/log/logLevel.d.ts +24 -0
- package/esm/lib/log/logLevel.d.ts.map +1 -0
- package/esm/lib/log/logLevel.js +27 -0
- package/esm/lib/log/logger.d.ts +377 -0
- package/esm/lib/log/logger.d.ts.map +1 -0
- package/esm/lib/log/logger.js +394 -0
- package/esm/lib/log/options.d.ts +34 -0
- package/esm/lib/log/options.d.ts.map +1 -0
- package/esm/lib/log/options.js +9 -0
- package/esm/lib/message/command.d.ts +100 -0
- package/esm/lib/message/command.d.ts.map +1 -0
- package/esm/lib/message/command.js +47 -0
- package/esm/lib/message/event.d.ts +103 -0
- package/esm/lib/message/event.d.ts.map +1 -0
- package/esm/lib/message/event.js +47 -0
- package/esm/lib/message/message.d.ts +18 -0
- package/esm/lib/message/message.d.ts.map +1 -0
- package/esm/lib/message/message.js +1 -0
- package/esm/lib/message/query.d.ts +95 -0
- package/esm/lib/message/query.d.ts.map +1 -0
- package/esm/lib/message/query.js +45 -0
- package/esm/lib/message/router.d.ts +233 -0
- package/esm/lib/message/router.d.ts.map +1 -0
- package/esm/lib/message/router.js +304 -0
- package/esm/lib/tracing/withSpan.d.ts +67 -0
- package/esm/lib/tracing/withSpan.d.ts.map +1 -0
- package/esm/lib/tracing/withSpan.js +87 -0
- package/esm/package.json +3 -0
- package/package.json +33 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { blue, bold, red, yellow } from '../../deps/jsr.io/@std/fmt/1.0.10/colors.js';
|
|
2
|
+
import { numericLogLevel } from './logLevel.js';
|
|
3
|
+
import { defaultLogOptions } from './options.js';
|
|
4
|
+
/**
|
|
5
|
+
* The Logger provides structured logging with configurable log levels, formatters, and console colors.
|
|
6
|
+
*
|
|
7
|
+
* The Logger is a singleton that should be configured once at application startup using
|
|
8
|
+
* {@link setupLogger}, then accessed throughout the application using {@link getLogger}.
|
|
9
|
+
*
|
|
10
|
+
* Log levels in order of severity: debug < info < warn < error < critical.
|
|
11
|
+
* Messages below the configured log level are silently ignored.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import {
|
|
16
|
+
* getLogger,
|
|
17
|
+
* jsonLogFormatter,
|
|
18
|
+
* parseLogLevel,
|
|
19
|
+
* prettyLogFormatter,
|
|
20
|
+
* setupLogger,
|
|
21
|
+
* } from '@nimbus/core';
|
|
22
|
+
*
|
|
23
|
+
* // Configure the logger at application startup
|
|
24
|
+
* setupLogger({
|
|
25
|
+
* logLevel: parseLogLevel(process.env.LOG_LEVEL),
|
|
26
|
+
* formatter: process.env.NODE_ENV === 'production'
|
|
27
|
+
* ? jsonLogFormatter
|
|
28
|
+
* : prettyLogFormatter,
|
|
29
|
+
* useConsoleColors: process.env.NODE_ENV !== 'production',
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* // Use the logger throughout your application
|
|
33
|
+
* const logger = getLogger();
|
|
34
|
+
*
|
|
35
|
+
* logger.info({
|
|
36
|
+
* message: 'Application started',
|
|
37
|
+
* category: 'App',
|
|
38
|
+
* data: { port: 3000, environment: 'production' },
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* logger.error({
|
|
42
|
+
* message: 'Failed to connect to database',
|
|
43
|
+
* category: 'Database',
|
|
44
|
+
* error: new Error('Connection timeout'),
|
|
45
|
+
* correlationId: '550e8400-e29b-41d4-a716-446655440000',
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class Logger {
|
|
50
|
+
static _instance;
|
|
51
|
+
_logLevel;
|
|
52
|
+
_formatter;
|
|
53
|
+
_useConsoleColors;
|
|
54
|
+
constructor(options) {
|
|
55
|
+
this._logLevel = options.logLevel ?? defaultLogOptions.logLevel;
|
|
56
|
+
this._formatter = options.formatter ?? defaultLogOptions.formatter;
|
|
57
|
+
this._useConsoleColors = options.useConsoleColors ??
|
|
58
|
+
defaultLogOptions.useConsoleColors;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Configure the Logger.
|
|
62
|
+
*
|
|
63
|
+
* @param {LogOptions} options - The options for the Logger
|
|
64
|
+
* @param {LogLevel} options.logLevel - The log level to use for the Logger
|
|
65
|
+
* @param {LogFormatter} options.formatter - The formatter to use for the Logger
|
|
66
|
+
*/
|
|
67
|
+
static configure(options) {
|
|
68
|
+
Logger._instance = new Logger(options);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the Logger instance.
|
|
72
|
+
*
|
|
73
|
+
* @returns {Logger} The Logger instance
|
|
74
|
+
*/
|
|
75
|
+
static getInstance() {
|
|
76
|
+
if (!Logger._instance) {
|
|
77
|
+
Logger._instance = new Logger(defaultLogOptions);
|
|
78
|
+
}
|
|
79
|
+
return Logger._instance;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Log a message at the debug level.
|
|
83
|
+
*
|
|
84
|
+
* @param {LogInput} logInput - The log input
|
|
85
|
+
* @param {string} logInput.message - The message
|
|
86
|
+
* @param {string} logInput.category - An optional category
|
|
87
|
+
* @param {string} logInput.correlationId - An optional correlation ID
|
|
88
|
+
* @param {Record<string, unknown>} logInput.data - An optional data object
|
|
89
|
+
* @param {Error | Exception} logInput.error - An optional error
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* import { getLogger } from "@nimbus/core";
|
|
94
|
+
*
|
|
95
|
+
* getLogger().debug({
|
|
96
|
+
* message: 'Hello World!',
|
|
97
|
+
* category: 'MyCategory',
|
|
98
|
+
* correlationId: '1234567890',
|
|
99
|
+
* data: {
|
|
100
|
+
* foo: 'bar',
|
|
101
|
+
* },
|
|
102
|
+
* error: new Error('Something went wrong!'),
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
debug(logInput) {
|
|
107
|
+
if (numericLogLevel['debug'] >= numericLogLevel[this._logLevel]) {
|
|
108
|
+
this._log(logInput, 'debug', console.debug);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Log a message at the info level.
|
|
113
|
+
*
|
|
114
|
+
* @param {LogInput} logInput - The log input
|
|
115
|
+
* @param {string} logInput.message - The message
|
|
116
|
+
* @param {string} logInput.category - An optional category
|
|
117
|
+
* @param {string} logInput.correlationId - An optional correlation ID
|
|
118
|
+
* @param {Record<string, unknown>} logInput.data - An optional data object
|
|
119
|
+
* @param {Error | Exception} logInput.error - An optional error
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* import { getLogger } from "@nimbus/core";
|
|
124
|
+
*
|
|
125
|
+
* getLogger().info({
|
|
126
|
+
* message: 'Hello World!',
|
|
127
|
+
* category: 'MyCategory',
|
|
128
|
+
* correlationId: '1234567890',
|
|
129
|
+
* data: {
|
|
130
|
+
* foo: 'bar',
|
|
131
|
+
* },
|
|
132
|
+
* error: new Error('Something went wrong!'),
|
|
133
|
+
* });
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
info(logInput) {
|
|
137
|
+
if (numericLogLevel['info'] >= numericLogLevel[this._logLevel]) {
|
|
138
|
+
this._log(logInput, 'info', console.info);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Log a message at the warn level.
|
|
143
|
+
*
|
|
144
|
+
* @param {LogInput} logInput - The log input
|
|
145
|
+
* @param {string} logInput.message - The message
|
|
146
|
+
* @param {string} logInput.category - An optional category
|
|
147
|
+
* @param {string} logInput.correlationId - An optional correlation ID
|
|
148
|
+
* @param {Record<string, unknown>} logInput.data - An optional data object
|
|
149
|
+
* @param {Error | Exception} logInput.error - An optional error
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* import { getLogger } from "@nimbus/core";
|
|
154
|
+
*
|
|
155
|
+
* getLogger().warn({
|
|
156
|
+
* message: 'Hello World!',
|
|
157
|
+
* category: 'MyCategory',
|
|
158
|
+
* correlationId: '1234567890',
|
|
159
|
+
* data: {
|
|
160
|
+
* foo: 'bar',
|
|
161
|
+
* },
|
|
162
|
+
* error: new Error('Something went wrong!'),
|
|
163
|
+
* });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
warn(logInput) {
|
|
167
|
+
if (numericLogLevel['warn'] >= numericLogLevel[this._logLevel]) {
|
|
168
|
+
this._log(logInput, 'warn', console.warn);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Log a message at the error level.
|
|
173
|
+
*
|
|
174
|
+
* @param {LogInput} logInput - The log input
|
|
175
|
+
* @param {string} logInput.message - The message
|
|
176
|
+
* @param {string} logInput.category - An optional category
|
|
177
|
+
* @param {string} logInput.correlationId - An optional correlation ID
|
|
178
|
+
* @param {Record<string, unknown>} logInput.data - An optional data object
|
|
179
|
+
* @param {Error | Exception} logInput.error - An optional error
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* import { getLogger } from "@nimbus/core";
|
|
184
|
+
*
|
|
185
|
+
* getLogger().error({
|
|
186
|
+
* message: 'Hello World!',
|
|
187
|
+
* category: 'MyCategory',
|
|
188
|
+
* correlationId: '1234567890',
|
|
189
|
+
* data: {
|
|
190
|
+
* foo: 'bar',
|
|
191
|
+
* },
|
|
192
|
+
* error: new Error('Something went wrong!'),
|
|
193
|
+
* });
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
error(logInput) {
|
|
197
|
+
if (numericLogLevel['error'] >= numericLogLevel[this._logLevel]) {
|
|
198
|
+
this._log(logInput, 'error', console.error);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Log a message at the critical level.
|
|
203
|
+
*
|
|
204
|
+
* @param {LogInput} logInput - The log input
|
|
205
|
+
* @param {string} logInput.message - The message
|
|
206
|
+
* @param {string} logInput.category - An optional category
|
|
207
|
+
* @param {string} logInput.correlationId - An optional correlation ID
|
|
208
|
+
* @param {Record<string, unknown>} logInput.data - An optional data object
|
|
209
|
+
* @param {Error | Exception} logInput.error - An optional error
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* import { getLogger } from "@nimbus/core";
|
|
214
|
+
*
|
|
215
|
+
* getLogger().critical({
|
|
216
|
+
* message: 'Hello World!',
|
|
217
|
+
* category: 'MyCategory',
|
|
218
|
+
* correlationId: '1234567890',
|
|
219
|
+
* data: {
|
|
220
|
+
* foo: 'bar',
|
|
221
|
+
* },
|
|
222
|
+
* error: new Error('Something went wrong!'),
|
|
223
|
+
* });
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
critical(logInput) {
|
|
227
|
+
if (numericLogLevel['critical'] >= numericLogLevel[this._logLevel]) {
|
|
228
|
+
this._log(logInput, 'critical', console.error);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Produce a log record.
|
|
233
|
+
*
|
|
234
|
+
* @param {LogInput} logInput - The log input
|
|
235
|
+
* @param {LogLevel} level - The log level
|
|
236
|
+
*
|
|
237
|
+
* @returns {LogRecord} The log record
|
|
238
|
+
*/
|
|
239
|
+
_produceLogRecord(logInput, level) {
|
|
240
|
+
return {
|
|
241
|
+
timestamp: new Date(),
|
|
242
|
+
level,
|
|
243
|
+
category: logInput.category ?? 'Default',
|
|
244
|
+
message: logInput.message,
|
|
245
|
+
...(logInput.data && { data: logInput.data }),
|
|
246
|
+
...(logInput.error && { error: logInput.error }),
|
|
247
|
+
...(logInput.correlationId &&
|
|
248
|
+
{ correlationId: logInput.correlationId }),
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Format a log record.
|
|
253
|
+
*
|
|
254
|
+
* @param {LogRecord} logRecord - The log record
|
|
255
|
+
*
|
|
256
|
+
* @returns {string} The formatted log record
|
|
257
|
+
*/
|
|
258
|
+
_formatLogRecord(logRecord) {
|
|
259
|
+
return this._formatter(logRecord);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Colorize a string.
|
|
263
|
+
*
|
|
264
|
+
* @param {string} string - The string to colorize
|
|
265
|
+
* @param {LogLevel} logLevel - The log level to determine the color
|
|
266
|
+
*
|
|
267
|
+
* @returns {string} The colorized string
|
|
268
|
+
*/
|
|
269
|
+
_colorizeString(string, logLevel) {
|
|
270
|
+
switch (logLevel) {
|
|
271
|
+
case 'info':
|
|
272
|
+
string = blue(string);
|
|
273
|
+
break;
|
|
274
|
+
case 'warn':
|
|
275
|
+
string = yellow(string);
|
|
276
|
+
break;
|
|
277
|
+
case 'error':
|
|
278
|
+
string = red(string);
|
|
279
|
+
break;
|
|
280
|
+
case 'critical':
|
|
281
|
+
string = bold(red(string));
|
|
282
|
+
break;
|
|
283
|
+
default:
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
return string;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Log a message.
|
|
290
|
+
*
|
|
291
|
+
* @param {LogInput} logInput - The log input
|
|
292
|
+
* @param {LogLevel} logLevel - The log level
|
|
293
|
+
* @param {Function} logFunction - The log function
|
|
294
|
+
*/
|
|
295
|
+
_log(logInput, logLevel, logFunction) {
|
|
296
|
+
const logRecord = this._produceLogRecord(logInput, logLevel);
|
|
297
|
+
const formattedLogRecord = this._formatLogRecord(logRecord);
|
|
298
|
+
if (Array.isArray(formattedLogRecord)) {
|
|
299
|
+
if (this._useConsoleColors) {
|
|
300
|
+
const coloredLogs = formattedLogRecord.map((log) => this._colorizeString(log, logLevel));
|
|
301
|
+
logFunction(...coloredLogs);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
logFunction(...formattedLogRecord);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
else if (this._useConsoleColors) {
|
|
308
|
+
logFunction(this._colorizeString(formattedLogRecord, logLevel));
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
logFunction(formattedLogRecord);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Configure the Logger.
|
|
317
|
+
*
|
|
318
|
+
* @param {LogOptions} options - The options for the Logger
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```ts
|
|
322
|
+
* import {
|
|
323
|
+
* jsonLogFormatter,
|
|
324
|
+
* parseLogLevel,
|
|
325
|
+
* prettyLogFormatter,
|
|
326
|
+
* setupLogger,
|
|
327
|
+
* } from "@nimbus/core";
|
|
328
|
+
*
|
|
329
|
+
* setupLogger({
|
|
330
|
+
* logLevel: parseLogLevel(process.env.LOG_LEVEL),
|
|
331
|
+
* formatter:
|
|
332
|
+
* process.env.NODE_ENV === "development"
|
|
333
|
+
* ? prettyLogFormatter
|
|
334
|
+
* : jsonLogFormatter,
|
|
335
|
+
* useConsoleColors: process.env.NODE_ENV === "development",
|
|
336
|
+
* });
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
export const setupLogger = (options) => {
|
|
340
|
+
Logger.configure(options);
|
|
341
|
+
};
|
|
342
|
+
/**
|
|
343
|
+
* Get the Logger instance.
|
|
344
|
+
*
|
|
345
|
+
* Returns the singleton Logger instance. If the logger has not been configured
|
|
346
|
+
* via {@link setupLogger}, a default logger with silent log level is returned.
|
|
347
|
+
*
|
|
348
|
+
* @returns The Logger instance.
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```ts
|
|
352
|
+
* import { getLogger } from '@nimbus/core';
|
|
353
|
+
*
|
|
354
|
+
* const logger = getLogger();
|
|
355
|
+
*
|
|
356
|
+
* // Log at different levels with all available options
|
|
357
|
+
* logger.debug({
|
|
358
|
+
* message: 'Processing request',
|
|
359
|
+
* category: 'API',
|
|
360
|
+
* data: { method: 'POST', path: '/orders' },
|
|
361
|
+
* correlationId: '550e8400-e29b-41d4-a716-446655440000',
|
|
362
|
+
* });
|
|
363
|
+
*
|
|
364
|
+
* logger.info({
|
|
365
|
+
* message: 'Order created successfully',
|
|
366
|
+
* category: 'Orders',
|
|
367
|
+
* data: { orderId: '12345', customerId: '67890' },
|
|
368
|
+
* correlationId: '550e8400-e29b-41d4-a716-446655440000',
|
|
369
|
+
* });
|
|
370
|
+
*
|
|
371
|
+
* logger.warn({
|
|
372
|
+
* message: 'Rate limit approaching',
|
|
373
|
+
* category: 'API',
|
|
374
|
+
* data: { currentRate: 95, maxRate: 100 },
|
|
375
|
+
* });
|
|
376
|
+
*
|
|
377
|
+
* logger.error({
|
|
378
|
+
* message: 'Failed to process payment',
|
|
379
|
+
* category: 'Payments',
|
|
380
|
+
* data: { orderId: '12345' },
|
|
381
|
+
* error: new Error('Payment gateway timeout'),
|
|
382
|
+
* correlationId: '550e8400-e29b-41d4-a716-446655440000',
|
|
383
|
+
* });
|
|
384
|
+
*
|
|
385
|
+
* logger.critical({
|
|
386
|
+
* message: 'Database connection lost',
|
|
387
|
+
* category: 'Database',
|
|
388
|
+
* error: new Error('Connection refused'),
|
|
389
|
+
* });
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
export const getLogger = () => {
|
|
393
|
+
return Logger.getInstance();
|
|
394
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type LogFormatter } from './logFormatter.js';
|
|
2
|
+
import type { LogLevel } from './logLevel.js';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the Logger.
|
|
5
|
+
*
|
|
6
|
+
* Use these options with {@link setupLogger} to configure the logger at application startup.
|
|
7
|
+
*/
|
|
8
|
+
export type LogOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* The minimum log level to output. Messages below this level are silently ignored.
|
|
11
|
+
* Levels in order of severity: debug < info < warn < error < critical.
|
|
12
|
+
* Defaults to 'silent' (no logs output).
|
|
13
|
+
*/
|
|
14
|
+
logLevel?: LogLevel;
|
|
15
|
+
/**
|
|
16
|
+
* The formatter function used to convert LogRecord objects into output strings.
|
|
17
|
+
* Use `jsonLogFormatter` for structured JSON output (recommended for production),
|
|
18
|
+
* or `prettyLogFormatter` for human-readable output (recommended for development).
|
|
19
|
+
* Defaults to `jsonLogFormatter`.
|
|
20
|
+
*/
|
|
21
|
+
formatter?: LogFormatter;
|
|
22
|
+
/**
|
|
23
|
+
* Whether to apply ANSI color codes to the console output based on log level.
|
|
24
|
+
* Set to true for colored output in development terminals.
|
|
25
|
+
* Set to false for production or when outputting to log aggregation systems.
|
|
26
|
+
* Defaults to false.
|
|
27
|
+
*/
|
|
28
|
+
useConsoleColors?: boolean;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The default log options.
|
|
32
|
+
*/
|
|
33
|
+
export declare const defaultLogOptions: Required<LogOptions>;
|
|
34
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/log/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,UAAU,CAIlD,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* A command is a message that is sent to tell the system
|
|
4
|
+
* to perform an action. Typically commands come in via an API
|
|
5
|
+
* like HTTP POST requests, gRPC calls, or similar inbound traffic.
|
|
6
|
+
*
|
|
7
|
+
* Nimbus sticks to the CloudEvents specifications for all messages
|
|
8
|
+
* to make it easier to work with these messages across multiple systems.
|
|
9
|
+
*
|
|
10
|
+
* @see https://cloudevents.io/ for more information.
|
|
11
|
+
*
|
|
12
|
+
* @property {string} specversion - The version of the CloudEvents specification which the event uses.
|
|
13
|
+
* @property {string} id - A globally unique identifier of the event.
|
|
14
|
+
* @property {string} correlationid - A globally unique identifier that indicates a correlation to previous and subsequent messages.
|
|
15
|
+
* @property {string} time - The time when the command was created.
|
|
16
|
+
* @property {string} source - A URI reference that identifies the system that is constructing the command.
|
|
17
|
+
* @property {string} type - The type must follow the CloudEvents naming convention, which uses a reversed domain name as a namespace, followed by a domain-specific name.
|
|
18
|
+
* @property {string} subject - An identifier for an object or entity the command is about (optional).
|
|
19
|
+
* @property {TData} data - The actual data, containing the specific business payload.
|
|
20
|
+
* @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
|
|
21
|
+
* @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
|
|
22
|
+
*
|
|
23
|
+
* @template TData - The type of the data.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const submitOrderCommand: Command<SubmitOrderPayload> = {
|
|
27
|
+
* specversion: '1.0',
|
|
28
|
+
* id: '123',
|
|
29
|
+
* correlationid: '456',
|
|
30
|
+
* time: '2025-01-01T00:00:00Z',
|
|
31
|
+
* source: 'https://nimbus.overlap.at',
|
|
32
|
+
* type: 'at.overlap.nimbus.submit-order',
|
|
33
|
+
* data: {
|
|
34
|
+
* customerId: '666',
|
|
35
|
+
* cartId: '123',
|
|
36
|
+
* },
|
|
37
|
+
* datacontenttype: 'application/json',
|
|
38
|
+
* };
|
|
39
|
+
*/
|
|
40
|
+
export type Command<TData = unknown> = {
|
|
41
|
+
specversion: '1.0';
|
|
42
|
+
id: string;
|
|
43
|
+
correlationid: string;
|
|
44
|
+
time: string;
|
|
45
|
+
source: string;
|
|
46
|
+
type: string;
|
|
47
|
+
subject?: string;
|
|
48
|
+
data: TData;
|
|
49
|
+
datacontenttype?: string;
|
|
50
|
+
dataschema?: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Type alias for the command data field schema.
|
|
54
|
+
*/
|
|
55
|
+
type CommandDataSchema = z.ZodUnion<[
|
|
56
|
+
z.ZodRecord<z.ZodString, z.ZodUnknown>,
|
|
57
|
+
z.ZodString,
|
|
58
|
+
z.ZodNumber,
|
|
59
|
+
z.ZodArray<z.ZodUnknown>,
|
|
60
|
+
z.ZodBoolean
|
|
61
|
+
]>;
|
|
62
|
+
/**
|
|
63
|
+
* Type alias for the command schema shape.
|
|
64
|
+
*/
|
|
65
|
+
export type CommandSchemaType = z.ZodObject<{
|
|
66
|
+
specversion: z.ZodLiteral<'1.0'>;
|
|
67
|
+
id: z.ZodString;
|
|
68
|
+
correlationid: z.ZodString;
|
|
69
|
+
time: z.ZodISODateTime;
|
|
70
|
+
source: z.ZodString;
|
|
71
|
+
type: z.ZodString;
|
|
72
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
73
|
+
data: CommandDataSchema;
|
|
74
|
+
datacontenttype: z.ZodOptional<z.ZodString>;
|
|
75
|
+
dataschema: z.ZodOptional<z.ZodURL>;
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* The Zod schema matching the Command type.
|
|
79
|
+
*
|
|
80
|
+
* Zod is the default for validating incomming messages.
|
|
81
|
+
*
|
|
82
|
+
* We do not infer the Command type from this schema because of
|
|
83
|
+
* slow type issues see https://jsr.io/docs/about-slow-types for more details.
|
|
84
|
+
*/
|
|
85
|
+
export declare const commandSchema: CommandSchemaType;
|
|
86
|
+
/**
|
|
87
|
+
* Input for creating a command.
|
|
88
|
+
*
|
|
89
|
+
* When a specific command type is provided via the generic parameter,
|
|
90
|
+
* the input is validated against that type. This means fields like
|
|
91
|
+
* `type` and `data` must match the narrower types of `TCommand`.
|
|
92
|
+
*/
|
|
93
|
+
export type CreateCommandInput<TCommand extends Command = Command> = Partial<Pick<TCommand, 'id' | 'correlationid' | 'time' | 'subject' | 'datacontenttype' | 'dataschema'>> & Pick<TCommand, 'type' | 'source' | 'data'>;
|
|
94
|
+
/**
|
|
95
|
+
* Creates a command based on input data with the convenience
|
|
96
|
+
* to skip properties and use the defaults for the rest.
|
|
97
|
+
*/
|
|
98
|
+
export declare const createCommand: <TCommand extends Command>(input: CreateCommandInput<TCommand>) => TCommand;
|
|
99
|
+
export {};
|
|
100
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/lib/message/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAAI;IACnC,WAAW,EAAE,KAAK,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,iBAAiB,GAAG,CAAC,CAAC,QAAQ,CAC/B;IACI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;IACtC,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IACxB,CAAC,CAAC,UAAU;CACf,CACJ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,SAAS,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,CAAC,SAAS,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC;IACvB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,EAAE,iBAAiB,CAAC;IACxB,eAAe,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,iBAiB1B,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,OAAO,GAAG,OAAO,IAC3D,OAAO,CACL,IAAI,CACA,QAAQ,EACN,IAAI,GACJ,eAAe,GACf,MAAM,GACN,SAAS,GACT,iBAAiB,GACjB,YAAY,CACjB,CACJ,GACC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,SAAS,OAAO,EAClD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,KACpC,QAeF,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* The Zod schema matching the Command type.
|
|
5
|
+
*
|
|
6
|
+
* Zod is the default for validating incomming messages.
|
|
7
|
+
*
|
|
8
|
+
* We do not infer the Command type from this schema because of
|
|
9
|
+
* slow type issues see https://jsr.io/docs/about-slow-types for more details.
|
|
10
|
+
*/
|
|
11
|
+
export const commandSchema = z.object({
|
|
12
|
+
specversion: z.literal('1.0'),
|
|
13
|
+
id: z.string(),
|
|
14
|
+
correlationid: z.string(),
|
|
15
|
+
time: z.iso.datetime(),
|
|
16
|
+
source: z.string(),
|
|
17
|
+
type: z.string(),
|
|
18
|
+
subject: z.string().optional(),
|
|
19
|
+
data: z.union([
|
|
20
|
+
z.record(z.string(), z.unknown()),
|
|
21
|
+
z.string(),
|
|
22
|
+
z.number(),
|
|
23
|
+
z.array(z.unknown()),
|
|
24
|
+
z.boolean(),
|
|
25
|
+
]),
|
|
26
|
+
datacontenttype: z.string().optional(),
|
|
27
|
+
dataschema: z.url().optional(),
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Creates a command based on input data with the convenience
|
|
31
|
+
* to skip properties and use the defaults for the rest.
|
|
32
|
+
*/
|
|
33
|
+
export const createCommand = (input) => {
|
|
34
|
+
const command = {
|
|
35
|
+
specversion: '1.0',
|
|
36
|
+
id: input.id ?? ulid(),
|
|
37
|
+
correlationid: input.correlationid ?? ulid(),
|
|
38
|
+
time: input.time ?? new Date().toISOString(),
|
|
39
|
+
source: input.source,
|
|
40
|
+
type: input.type,
|
|
41
|
+
...(input.subject && { subject: input.subject }),
|
|
42
|
+
data: input.data,
|
|
43
|
+
datacontenttype: input.datacontenttype ?? 'application/json',
|
|
44
|
+
...(input.dataschema && { dataschema: input.dataschema }),
|
|
45
|
+
};
|
|
46
|
+
return command;
|
|
47
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* An event is a message that is emitted by the system to notify
|
|
4
|
+
* subscribers that something has happened. Typically events are
|
|
5
|
+
* the result of a command that was executed before.
|
|
6
|
+
*
|
|
7
|
+
* Nimbus sticks to the CloudEvents specifications for all messages
|
|
8
|
+
* to make it easier to work with these messages across multiple systems.
|
|
9
|
+
*
|
|
10
|
+
* @see https://cloudevents.io/ for more information.
|
|
11
|
+
*
|
|
12
|
+
* @property {string} specversion - The version of the CloudEvents specification which the event uses.
|
|
13
|
+
* @property {string} id - A globally unique identifier of the event.
|
|
14
|
+
* @property {string} correlationid - A globally unique identifier that indicates a correlation to previous and subsequent messages to this event.
|
|
15
|
+
* @property {string} time - The time when the event was created.
|
|
16
|
+
* @property {string} source - A URI reference that identifies the system that is constructing the event.
|
|
17
|
+
* @property {string} type - The type must follow the CloudEvents naming convention, which uses a reversed domain name as a namespace, followed by a domain-specific name.
|
|
18
|
+
* @property {string} subject - An identifier for an object or entity the event is about (optional).
|
|
19
|
+
* @property {TData} data - The actual data, containing the specific business payload.
|
|
20
|
+
* @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
|
|
21
|
+
* @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
|
|
22
|
+
*
|
|
23
|
+
* @template TData - The type of the data.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const orderSubmittedEvent: Event<Order> = {
|
|
27
|
+
* specversion: '1.0',
|
|
28
|
+
* id: '123',
|
|
29
|
+
* correlationid: '456',
|
|
30
|
+
* time: '2025-01-01T00:00:00Z',
|
|
31
|
+
* source: 'https://nimbus.overlap.at',
|
|
32
|
+
* type: 'at.overlap.nimbus.submit-order',
|
|
33
|
+
* subject: '/orders/42',
|
|
34
|
+
* data: {
|
|
35
|
+
* orderId: '42',
|
|
36
|
+
* customerId: '666',
|
|
37
|
+
* cartId: '123',
|
|
38
|
+
* status: 'submitted',
|
|
39
|
+
* },
|
|
40
|
+
* datacontenttype: 'application/json',
|
|
41
|
+
* };
|
|
42
|
+
*/
|
|
43
|
+
export type Event<TData = unknown> = {
|
|
44
|
+
specversion: '1.0';
|
|
45
|
+
id: string;
|
|
46
|
+
correlationid: string;
|
|
47
|
+
time: string;
|
|
48
|
+
source: string;
|
|
49
|
+
type: string;
|
|
50
|
+
subject: string;
|
|
51
|
+
data: TData;
|
|
52
|
+
datacontenttype?: string;
|
|
53
|
+
dataschema?: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Type alias for the event data field schema.
|
|
57
|
+
*/
|
|
58
|
+
type EventDataSchema = z.ZodUnion<[
|
|
59
|
+
z.ZodRecord<z.ZodString, z.ZodUnknown>,
|
|
60
|
+
z.ZodString,
|
|
61
|
+
z.ZodNumber,
|
|
62
|
+
z.ZodArray<z.ZodUnknown>,
|
|
63
|
+
z.ZodBoolean
|
|
64
|
+
]>;
|
|
65
|
+
/**
|
|
66
|
+
* Type alias for the event schema shape.
|
|
67
|
+
*/
|
|
68
|
+
export type EventSchemaType = z.ZodObject<{
|
|
69
|
+
specversion: z.ZodLiteral<'1.0'>;
|
|
70
|
+
id: z.ZodString;
|
|
71
|
+
correlationid: z.ZodString;
|
|
72
|
+
time: z.ZodISODateTime;
|
|
73
|
+
source: z.ZodString;
|
|
74
|
+
type: z.ZodString;
|
|
75
|
+
subject: z.ZodString;
|
|
76
|
+
data: EventDataSchema;
|
|
77
|
+
datacontenttype: z.ZodOptional<z.ZodString>;
|
|
78
|
+
dataschema: z.ZodOptional<z.ZodURL>;
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* The Zod schema matching the Event type.
|
|
82
|
+
*
|
|
83
|
+
* Zod is the default for validating incoming messages.
|
|
84
|
+
*
|
|
85
|
+
* We do not infer the Event type from this schema because of
|
|
86
|
+
* slow type issues see https://jsr.io/docs/about-slow-types for more details.
|
|
87
|
+
*/
|
|
88
|
+
export declare const eventSchema: EventSchemaType;
|
|
89
|
+
/**
|
|
90
|
+
* Input for creating an event.
|
|
91
|
+
*
|
|
92
|
+
* When a specific event type is provided via the generic parameter,
|
|
93
|
+
* the input is validated against that type. This means fields like
|
|
94
|
+
* `type` and `data` must match the narrower types of `TEvent`.
|
|
95
|
+
*/
|
|
96
|
+
export type CreateEventInput<TEvent extends Event = Event> = Partial<Pick<TEvent, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TEvent, 'type' | 'source' | 'subject' | 'data'>;
|
|
97
|
+
/**
|
|
98
|
+
* Creates an event based on input data with the convenience
|
|
99
|
+
* to skip properties and use the defaults for the rest.
|
|
100
|
+
*/
|
|
101
|
+
export declare const createEvent: <TEvent extends Event>(input: CreateEventInput<TEvent>) => TEvent;
|
|
102
|
+
export {};
|
|
103
|
+
//# sourceMappingURL=event.d.ts.map
|