@likec4/log 1.43.0 → 1.45.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/dist/index.d.mts CHANGED
@@ -14,6 +14,41 @@ declare function getConsoleSink(options?: ConsoleSinkOptions): Sink;
14
14
  declare function getConsoleStderrSink(options?: ConsoleSinkOptions): Sink;
15
15
 
16
16
  declare function loggable(error: unknown): string;
17
+ type NormalizeError<ErrorArg> = ErrorArg extends Error ? ErrorArg : Error;
18
+ /**
19
+ * Appends `message` to `error.message`. If `message` ends with `:` or `:\n`,
20
+ * prepends it instead.
21
+ *
22
+ * Returns `error`. If `error` is not an `Error` instance, it is converted to
23
+ * one.
24
+ *
25
+ * @example
26
+ * ```js
27
+ * wrapErrorMessage(new Error('Message.'), 'Additional message.')
28
+ * // Error: Message.
29
+ * // Additional message.
30
+ *
31
+ * wrapErrorMessage(new Error('Message.'), 'Additional message:')
32
+ * // Error: Additional message: Message.
33
+ *
34
+ * wrapErrorMessage(new Error('Message.'), 'Additional message:\n')
35
+ * // Error: Additional message:
36
+ * // Message.
37
+ *
38
+ * wrapErrorMessage(new Error('Message.'), '')
39
+ * // Error: Message.
40
+ *
41
+ * const invalidError = 'Message.'
42
+ * wrapErrorMessage(invalidError, 'Additional message.')
43
+ * // Error: Message.
44
+ * // Additional message.
45
+ *
46
+ * wrapErrorMessage(new Error(' Message with spaces '), ' Additional message ')
47
+ * // Error: Message with spaces
48
+ * // Additional message
49
+ * ```
50
+ */
51
+ declare function wrapError<ErrorArg>(error: ErrorArg, newMessage: string): NormalizeError<ErrorArg>;
17
52
 
18
53
  declare const logger: _logtape_logtape.Logger;
19
54
 
@@ -26,4 +61,4 @@ declare const logger: _logtape_logtape.Logger;
26
61
  declare function createLogger(subcategory: string | readonly [string] | readonly [string, ...string[]]): _logtape_logtape.Logger;
27
62
  declare function configureLogger<TSinkId extends string, TFilterId extends string>(config?: Partial<Config<TSinkId, TFilterId>>): void;
28
63
 
29
- export { configureLogger, logger as consola, createLogger, errorFromLogRecord, getAnsiColorFormatter, getConsoleSink, getConsoleStderrSink, getMessageOnlyFormatter, getTextFormatter, loggable, logger, logger as rootLogger };
64
+ export { configureLogger, logger as consola, createLogger, errorFromLogRecord, getAnsiColorFormatter, getConsoleSink, getConsoleStderrSink, getMessageOnlyFormatter, getTextFormatter, loggable, logger, logger as rootLogger, wrapError };
package/dist/index.mjs CHANGED
@@ -1283,9 +1283,10 @@ const parseStack = (stack) => {
1283
1283
  });
1284
1284
  return lines;
1285
1285
  };
1286
- function ident(value, identation = 2) {
1286
+ function indent(value, indentation = 2) {
1287
1287
  value = Array.isArray(value) ? value : value.split("\n");
1288
- return value.map((l) => `${" ".repeat(identation)}${l}`).join("\n");
1288
+ const prefix = " ".repeat(indentation);
1289
+ return value.map((l) => `${prefix}${l}`).join("\n");
1289
1290
  }
1290
1291
  function loggable(error) {
1291
1292
  if (typeof error === "string") {
@@ -1295,20 +1296,29 @@ function loggable(error) {
1295
1296
  const mergedErr = mergeErrorCause(error);
1296
1297
  if (mergedErr.stack) {
1297
1298
  const stack = parseStack(mergedErr.stack);
1298
- return mergedErr.message + "\n" + ident(stack.slice(1));
1299
+ return mergedErr.message + "\n" + indent(stack.slice(1));
1299
1300
  }
1300
1301
  return mergedErr.message;
1301
1302
  }
1302
- return safeStringify(error);
1303
+ return safeStringify(error, { indentation: " " });
1304
+ }
1305
+ function wrapError(error, newMessage) {
1306
+ return wrapErrorMessage(error, newMessage);
1303
1307
  }
1304
1308
 
1305
1309
  function gerErrorFromLogRecord(record) {
1306
- const errors = Object.values(record.properties).filter((v) => v instanceof Error).map((err) => {
1307
- const mergedErr = mergeErrorCause(err);
1308
- if (mergedErr.stack) {
1309
- mergedErr.stack = parseStack(mergedErr.stack).join("\n");
1310
+ const errors = Object.entries(record.properties).flatMap(([k, err]) => {
1311
+ if (err instanceof Error) {
1312
+ const mergedErr = mergeErrorCause(err);
1313
+ if (mergedErr.stack) {
1314
+ mergedErr.stack = parseStack(mergedErr.stack).join("\n");
1315
+ }
1316
+ return [mergedErr];
1317
+ }
1318
+ if (k === "error" || k === "err") {
1319
+ return [new Error(`${err}`)];
1310
1320
  }
1311
- return mergedErr;
1321
+ return [];
1312
1322
  });
1313
1323
  if (errors.length === 0) {
1314
1324
  return null;
@@ -1322,19 +1332,19 @@ function errorFromLogRecord(record) {
1322
1332
  }
1323
1333
  return error;
1324
1334
  }
1325
- function appendErrorToMessage(values, color) {
1335
+ function appendErrorToMessage(values, color = false) {
1326
1336
  const error = gerErrorFromLogRecord(values.record);
1327
1337
  if (error) {
1328
1338
  let errorMessge = error.message;
1329
1339
  if (error.stack) {
1330
- errorMessge = errorMessge + "\n" + ident(error.stack.split("\n").slice(1));
1340
+ errorMessge = errorMessge + "\n" + indent(error.stack.split("\n").slice(1));
1331
1341
  }
1332
1342
  if (color) {
1333
1343
  errorMessge = `${ansiColors.red}${errorMessge}${RESET}`;
1334
1344
  }
1335
1345
  return {
1336
1346
  ...values,
1337
- message: values.message + "\n" + ident(errorMessge)
1347
+ message: values.message + "\n" + indent(errorMessge)
1338
1348
  };
1339
1349
  }
1340
1350
  return values;
@@ -1445,4 +1455,4 @@ function configureLogger(config) {
1445
1455
  }
1446
1456
  }
1447
1457
 
1448
- export { configureLogger, logger as consola, createLogger, errorFromLogRecord, getAnsiColorFormatter, getConsoleSink, getConsoleStderrSink, getMessageOnlyFormatter, getTextFormatter, loggable, logger, logger as rootLogger };
1458
+ export { configureLogger, logger as consola, createLogger, errorFromLogRecord, getAnsiColorFormatter, getConsoleSink, getConsoleStderrSink, getMessageOnlyFormatter, getTextFormatter, loggable, logger, logger as rootLogger, wrapError };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@likec4/log",
3
3
  "description": "Shared interface for logging",
4
4
  "license": "MIT",
5
- "version": "1.43.0",
5
+ "version": "1.45.0",
6
6
  "bugs": "https://github.com/likec4/likec4/issues",
7
7
  "homepage": "https://likec4.dev",
8
8
  "author": "Denis Davydkov <denis@davydkov.com>",
@@ -38,11 +38,11 @@
38
38
  "@types/node": "~20.19.22",
39
39
  "merge-error-cause": "^5.0.2",
40
40
  "safe-stringify": "^1.2.0",
41
- "std-env": "^3.9.0",
41
+ "std-env": "^3.10.0",
42
42
  "typescript": "5.9.3",
43
43
  "unbuild": "3.5.0",
44
44
  "wrap-error-message": "^3.0.1",
45
- "@likec4/tsconfig": "1.43.0",
45
+ "@likec4/tsconfig": "1.45.0",
46
46
  "@likec4/devops": "1.42.0"
47
47
  },
48
48
  "scripts": {
package/src/formatters.ts CHANGED
@@ -13,18 +13,23 @@ import {
13
13
  } from '@logtape/logtape'
14
14
  import mergeErrorCause from 'merge-error-cause'
15
15
  import wrapErrorMessage from 'wrap-error-message'
16
- import { ident, parseStack } from './utils'
16
+ import { indent, parseStack } from './utils'
17
17
 
18
18
  function gerErrorFromLogRecord(record: LogRecord): Error | null {
19
19
  const errors = Object
20
- .values(record.properties)
21
- .filter((v) => v instanceof Error)
22
- .map(err => {
23
- const mergedErr = mergeErrorCause(err)
24
- if (mergedErr.stack) {
25
- mergedErr.stack = parseStack(mergedErr.stack).join('\n')
20
+ .entries(record.properties)
21
+ .flatMap(([k, err]) => {
22
+ if (err instanceof Error) {
23
+ const mergedErr = mergeErrorCause(err)
24
+ if (mergedErr.stack) {
25
+ mergedErr.stack = parseStack(mergedErr.stack).join('\n')
26
+ }
27
+ return [mergedErr]
26
28
  }
27
- return mergedErr
29
+ if (k === 'error' || k === 'err') {
30
+ return [new Error(`${err}`)]
31
+ }
32
+ return []
28
33
  })
29
34
  if (errors.length === 0) {
30
35
  return null
@@ -40,19 +45,19 @@ export function errorFromLogRecord(record: LogRecord): Error | null {
40
45
  return error
41
46
  }
42
47
 
43
- export function appendErrorToMessage(values: FormattedValues, color?: boolean): FormattedValues {
48
+ export function appendErrorToMessage(values: FormattedValues, color = false): FormattedValues {
44
49
  const error = gerErrorFromLogRecord(values.record)
45
50
  if (error) {
46
51
  let errorMessge = error.message
47
52
  if (error.stack) {
48
- errorMessge = errorMessge + '\n' + ident(error.stack.split('\n').slice(1))
53
+ errorMessge = errorMessge + '\n' + indent(error.stack.split('\n').slice(1))
49
54
  }
50
55
  if (color) {
51
56
  errorMessge = `${ansiColors.red}${errorMessge}${RESET}`
52
57
  }
53
58
  return {
54
59
  ...values,
55
- message: values.message + '\n' + ident(errorMessge),
60
+ message: values.message + '\n' + indent(errorMessge),
56
61
  }
57
62
  }
58
63
  return values
package/src/index.ts CHANGED
@@ -34,7 +34,10 @@ export {
34
34
  logger as rootLogger,
35
35
  }
36
36
 
37
- export { loggable } from './utils'
37
+ export {
38
+ loggable,
39
+ wrapError,
40
+ } from './utils'
38
41
 
39
42
  /**
40
43
  * Get a child logger with the given subcategory.
package/src/utils.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import mergeErrorCause from 'merge-error-cause'
2
2
  import safeStringify from 'safe-stringify'
3
+ import wrapErrorMessage from 'wrap-error-message'
3
4
 
4
5
  export const parseStack = (stack: string): string[] => {
5
6
  const lines = stack
@@ -16,9 +17,10 @@ export const parseStack = (stack: string): string[] => {
16
17
  return lines
17
18
  }
18
19
 
19
- export function ident(value: string | string[], identation = 2): string {
20
+ export function indent(value: string | string[], indentation = 2): string {
20
21
  value = Array.isArray(value) ? value : value.split('\n')
21
- return value.map((l) => `${' '.repeat(identation)}${l}`).join('\n')
22
+ const prefix = ' '.repeat(indentation)
23
+ return value.map((l) => `${prefix}${l}`).join('\n')
22
24
  }
23
25
 
24
26
  export function loggable(error: unknown): string {
@@ -29,9 +31,48 @@ export function loggable(error: unknown): string {
29
31
  const mergedErr = mergeErrorCause(error)
30
32
  if (mergedErr.stack) {
31
33
  const stack = parseStack(mergedErr.stack)
32
- return mergedErr.message + '\n' + ident(stack.slice(1))
34
+ return mergedErr.message + '\n' + indent(stack.slice(1))
33
35
  }
34
36
  return mergedErr.message
35
37
  }
36
- return safeStringify(error)
38
+ return safeStringify(error, { indentation: '\t' })
39
+ }
40
+
41
+ type NormalizeError<ErrorArg> = ErrorArg extends Error ? ErrorArg : Error
42
+
43
+ /**
44
+ * Appends `message` to `error.message`. If `message` ends with `:` or `:\n`,
45
+ * prepends it instead.
46
+ *
47
+ * Returns `error`. If `error` is not an `Error` instance, it is converted to
48
+ * one.
49
+ *
50
+ * @example
51
+ * ```js
52
+ * wrapErrorMessage(new Error('Message.'), 'Additional message.')
53
+ * // Error: Message.
54
+ * // Additional message.
55
+ *
56
+ * wrapErrorMessage(new Error('Message.'), 'Additional message:')
57
+ * // Error: Additional message: Message.
58
+ *
59
+ * wrapErrorMessage(new Error('Message.'), 'Additional message:\n')
60
+ * // Error: Additional message:
61
+ * // Message.
62
+ *
63
+ * wrapErrorMessage(new Error('Message.'), '')
64
+ * // Error: Message.
65
+ *
66
+ * const invalidError = 'Message.'
67
+ * wrapErrorMessage(invalidError, 'Additional message.')
68
+ * // Error: Message.
69
+ * // Additional message.
70
+ *
71
+ * wrapErrorMessage(new Error(' Message with spaces '), ' Additional message ')
72
+ * // Error: Message with spaces
73
+ * // Additional message
74
+ * ```
75
+ */
76
+ export function wrapError<ErrorArg>(error: ErrorArg, newMessage: string): NormalizeError<ErrorArg> {
77
+ return wrapErrorMessage(error, newMessage)
37
78
  }