@fend/firo 0.0.5 → 0.0.6

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/README.md CHANGED
@@ -239,7 +239,8 @@ log.error('Payment failed', err, {
239
239
  `error()` accepts multiple call signatures:
240
240
 
241
241
  ```ts
242
- // Message only
242
+ // Message only will be automatically wrapped in an Error object to intentionally capture and preserve the stack trace
243
+ // because stack trace with a couple of extra levels of indirection is definitely better than no stack trace at all
243
244
  log.error('Something went wrong')
244
245
 
245
246
  // Message + Error object
@@ -248,6 +249,9 @@ log.error('Query failed', new Error('timeout'))
248
249
  // Error object only
249
250
  log.error(new Error('Unhandled'))
250
251
 
252
+ // Error + extra data
253
+ log.error(new Error('DB down'), { query: 'SELECT ...', reqId: 123 })
254
+
251
255
  // Anything — will be coerced to Error
252
256
  log.error(someUnknownThing)
253
257
  ```
@@ -278,9 +282,10 @@ const log = createFiro({ transport: myTransport })
278
282
  import { FiroUtils } from '@fend/firo'
279
283
 
280
284
  FiroUtils.wrapToError(value) // coerce unknown → Error
281
- FiroUtils.serializeError(err) // Error → plain object { message, stack, name }
285
+ FiroUtils.serializeError(err) // Error → plain object { message, stack, name, cause?, ... }
282
286
  FiroUtils.safeStringify(obj) // JSON.stringify with bigint support + fallback
283
287
  FiroUtils.jsonReplacer // replacer for JSON.stringify (handles bigint)
288
+ FiroUtils.extractMessage(msg) // extract message string from string | Error | unknown
284
289
  FiroUtils.colorize(text, idx) // wrap text in ANSI color by palette index
285
290
  FiroUtils.colorizeLevel(level, t) // wrap text in level color (red/yellow/dim)
286
291
  ```
package/dist/index.cjs CHANGED
@@ -45,6 +45,7 @@ __export(utils_exports, {
45
45
  LOG_LEVELS: () => LOG_LEVELS,
46
46
  colorize: () => colorize,
47
47
  colorizeLevel: () => colorizeLevel,
48
+ extractMessage: () => extractMessage,
48
49
  getColorIndex: () => getColorIndex,
49
50
  jsonReplacer: () => jsonReplacer,
50
51
  safeStringify: () => safeStringify,
@@ -122,13 +123,18 @@ var wrapToError = (obj) => {
122
123
  };
123
124
  var serializeError = (_err) => {
124
125
  const err = wrapToError(_err);
125
- return {
126
+ const result = {
126
127
  message: err.message,
127
128
  stack: err.stack,
128
129
  name: err.name,
129
130
  ...err
130
131
  };
132
+ if (err.cause !== void 0) {
133
+ result.cause = err.cause instanceof Error ? serializeError(err.cause) : err.cause;
134
+ }
135
+ return result;
131
136
  };
137
+ var extractMessage = (msg) => typeof msg === "string" ? msg : msg instanceof Error ? msg.message : typeof msg === "object" && msg !== null ? safeStringify(msg) : String(msg);
132
138
  var colorizeLevel = (level, text) => {
133
139
  if (level === "info") return text;
134
140
  switch (level) {
@@ -196,18 +202,15 @@ var createDevTransport = (config = {}) => {
196
202
  var import_node_util3 = require("util");
197
203
  var import_node_process2 = __toESM(require("process"), 1);
198
204
  var buildRecord = (level, context, msg, getTimestamp, data) => {
199
- const contextObj = context.reduce((acc, item) => {
200
- acc[item.key] = item.value;
201
- return acc;
202
- }, {});
203
205
  const logRecord = {
204
206
  timestamp: getTimestamp(),
205
- level,
206
- ...contextObj
207
+ level
207
208
  };
209
+ for (let i = 0, len = context.length; i < len; i++) {
210
+ logRecord[context[i].key] = context[i].value;
211
+ }
212
+ logRecord.message = extractMessage(msg);
208
213
  if (level === "error") {
209
- const message = typeof msg === "string" ? msg : msg instanceof Error ? msg.message : typeof msg === "object" && msg !== null ? safeStringify(msg) : String(msg);
210
- logRecord.message = message;
211
214
  if (data instanceof Error) {
212
215
  logRecord.error = serializeError(data);
213
216
  } else if (msg instanceof Error) {
@@ -218,7 +221,9 @@ var buildRecord = (level, context, msg, getTimestamp, data) => {
218
221
  if (data !== void 0) logRecord.data = data;
219
222
  }
220
223
  } else {
221
- logRecord.message = typeof msg === "object" && msg !== null ? safeStringify(msg) : String(msg);
224
+ if (msg instanceof Error) {
225
+ logRecord.error = serializeError(msg);
226
+ }
222
227
  if (data !== void 0) {
223
228
  logRecord.data = data instanceof Error ? serializeError(data) : data;
224
229
  }
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  /** Available log severity levels. */
2
2
  type LogLevel = 'debug' | 'info' | 'warn' | 'error';
3
+ /** Numeric severity values for each log level, used for threshold filtering. */
3
4
  declare const LOG_LEVELS: {
4
5
  readonly debug: 20;
5
6
  readonly info: 30;
@@ -74,12 +75,21 @@ declare const FIRO_COLORS: {
74
75
  readonly tangerine: "38;5;208";
75
76
  readonly periwinkle: "38;5;147";
76
77
  };
78
+ /** Hash a string to a stable color palette index. Similar strings land on different colors. */
77
79
  declare const getColorIndex: (str: string, useAllColors?: boolean) => number;
80
+ /** Wrap text in an ANSI color escape sequence by palette index or raw ANSI code. */
78
81
  declare const colorize: (text: string, colorIndex: number, color?: string) => string;
82
+ /** JSON.stringify replacer that converts BigInt values to strings. */
79
83
  declare const jsonReplacer: (_key: string, value: unknown) => unknown;
84
+ /** Safely stringify any value to JSON with BigInt support. Falls back to `util.inspect` on circular references. */
80
85
  declare const safeStringify: (obj: unknown) => string;
86
+ /** Coerce any value to an Error instance. If already an Error, returns as-is. */
81
87
  declare const wrapToError: (obj: unknown) => Error;
82
- declare const serializeError: (_err: unknown) => any;
88
+ /** Serialize an error-like value to a plain object with `message`, `stack`, `name`, and recursively serialized `cause`. */
89
+ declare const serializeError: (_err: unknown) => Record<string, unknown>;
90
+ /** Extract a human-readable message string from any log input. Useful for building custom transports. */
91
+ declare const extractMessage: (msg: string | Error | unknown) => string;
92
+ /** Wrap text in an ANSI color based on log level: red for error, yellow for warn, dim for debug. */
83
93
  declare const colorizeLevel: (level: LogLevel, text: string) => string;
84
94
 
85
95
  type utils_ContextExtension = ContextExtension;
@@ -94,13 +104,14 @@ type utils_LogOptions = LogOptions;
94
104
  type utils_TransportFn = TransportFn;
95
105
  declare const utils_colorize: typeof colorize;
96
106
  declare const utils_colorizeLevel: typeof colorizeLevel;
107
+ declare const utils_extractMessage: typeof extractMessage;
97
108
  declare const utils_getColorIndex: typeof getColorIndex;
98
109
  declare const utils_jsonReplacer: typeof jsonReplacer;
99
110
  declare const utils_safeStringify: typeof safeStringify;
100
111
  declare const utils_serializeError: typeof serializeError;
101
112
  declare const utils_wrapToError: typeof wrapToError;
102
113
  declare namespace utils {
103
- export { type utils_ContextExtension as ContextExtension, type utils_ContextItem as ContextItem, type utils_ContextItemWithOptions as ContextItemWithOptions, type utils_ContextOptions as ContextOptions, type utils_ContextValue as ContextValue, utils_FIRO_COLORS as FIRO_COLORS, utils_LOG_LEVELS as LOG_LEVELS, type utils_LogLevel as LogLevel, type utils_LogOptions as LogOptions, type utils_TransportFn as TransportFn, utils_colorize as colorize, utils_colorizeLevel as colorizeLevel, utils_getColorIndex as getColorIndex, utils_jsonReplacer as jsonReplacer, utils_safeStringify as safeStringify, utils_serializeError as serializeError, utils_wrapToError as wrapToError };
114
+ export { type utils_ContextExtension as ContextExtension, type utils_ContextItem as ContextItem, type utils_ContextItemWithOptions as ContextItemWithOptions, type utils_ContextOptions as ContextOptions, type utils_ContextValue as ContextValue, utils_FIRO_COLORS as FIRO_COLORS, utils_LOG_LEVELS as LOG_LEVELS, type utils_LogLevel as LogLevel, type utils_LogOptions as LogOptions, type utils_TransportFn as TransportFn, utils_colorize as colorize, utils_colorizeLevel as colorizeLevel, utils_extractMessage as extractMessage, utils_getColorIndex as getColorIndex, utils_jsonReplacer as jsonReplacer, utils_safeStringify as safeStringify, utils_serializeError as serializeError, utils_wrapToError as wrapToError };
104
115
  }
105
116
 
106
117
  /**
@@ -174,6 +185,8 @@ interface Firo {
174
185
  warn: (msg: string, data?: unknown, opts?: LogOptions) => void;
175
186
  /** Log an error object directly. */
176
187
  error(err: Error | unknown): void;
188
+ /** Log an error object with additional data. */
189
+ error(err: Error, data?: unknown, opts?: LogOptions): void;
177
190
  /** Log a message alongside an error or custom data object. */
178
191
  error(msg: string, err?: Error | unknown, opts?: LogOptions): void;
179
192
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /** Available log severity levels. */
2
2
  type LogLevel = 'debug' | 'info' | 'warn' | 'error';
3
+ /** Numeric severity values for each log level, used for threshold filtering. */
3
4
  declare const LOG_LEVELS: {
4
5
  readonly debug: 20;
5
6
  readonly info: 30;
@@ -74,12 +75,21 @@ declare const FIRO_COLORS: {
74
75
  readonly tangerine: "38;5;208";
75
76
  readonly periwinkle: "38;5;147";
76
77
  };
78
+ /** Hash a string to a stable color palette index. Similar strings land on different colors. */
77
79
  declare const getColorIndex: (str: string, useAllColors?: boolean) => number;
80
+ /** Wrap text in an ANSI color escape sequence by palette index or raw ANSI code. */
78
81
  declare const colorize: (text: string, colorIndex: number, color?: string) => string;
82
+ /** JSON.stringify replacer that converts BigInt values to strings. */
79
83
  declare const jsonReplacer: (_key: string, value: unknown) => unknown;
84
+ /** Safely stringify any value to JSON with BigInt support. Falls back to `util.inspect` on circular references. */
80
85
  declare const safeStringify: (obj: unknown) => string;
86
+ /** Coerce any value to an Error instance. If already an Error, returns as-is. */
81
87
  declare const wrapToError: (obj: unknown) => Error;
82
- declare const serializeError: (_err: unknown) => any;
88
+ /** Serialize an error-like value to a plain object with `message`, `stack`, `name`, and recursively serialized `cause`. */
89
+ declare const serializeError: (_err: unknown) => Record<string, unknown>;
90
+ /** Extract a human-readable message string from any log input. Useful for building custom transports. */
91
+ declare const extractMessage: (msg: string | Error | unknown) => string;
92
+ /** Wrap text in an ANSI color based on log level: red for error, yellow for warn, dim for debug. */
83
93
  declare const colorizeLevel: (level: LogLevel, text: string) => string;
84
94
 
85
95
  type utils_ContextExtension = ContextExtension;
@@ -94,13 +104,14 @@ type utils_LogOptions = LogOptions;
94
104
  type utils_TransportFn = TransportFn;
95
105
  declare const utils_colorize: typeof colorize;
96
106
  declare const utils_colorizeLevel: typeof colorizeLevel;
107
+ declare const utils_extractMessage: typeof extractMessage;
97
108
  declare const utils_getColorIndex: typeof getColorIndex;
98
109
  declare const utils_jsonReplacer: typeof jsonReplacer;
99
110
  declare const utils_safeStringify: typeof safeStringify;
100
111
  declare const utils_serializeError: typeof serializeError;
101
112
  declare const utils_wrapToError: typeof wrapToError;
102
113
  declare namespace utils {
103
- export { type utils_ContextExtension as ContextExtension, type utils_ContextItem as ContextItem, type utils_ContextItemWithOptions as ContextItemWithOptions, type utils_ContextOptions as ContextOptions, type utils_ContextValue as ContextValue, utils_FIRO_COLORS as FIRO_COLORS, utils_LOG_LEVELS as LOG_LEVELS, type utils_LogLevel as LogLevel, type utils_LogOptions as LogOptions, type utils_TransportFn as TransportFn, utils_colorize as colorize, utils_colorizeLevel as colorizeLevel, utils_getColorIndex as getColorIndex, utils_jsonReplacer as jsonReplacer, utils_safeStringify as safeStringify, utils_serializeError as serializeError, utils_wrapToError as wrapToError };
114
+ export { type utils_ContextExtension as ContextExtension, type utils_ContextItem as ContextItem, type utils_ContextItemWithOptions as ContextItemWithOptions, type utils_ContextOptions as ContextOptions, type utils_ContextValue as ContextValue, utils_FIRO_COLORS as FIRO_COLORS, utils_LOG_LEVELS as LOG_LEVELS, type utils_LogLevel as LogLevel, type utils_LogOptions as LogOptions, type utils_TransportFn as TransportFn, utils_colorize as colorize, utils_colorizeLevel as colorizeLevel, utils_extractMessage as extractMessage, utils_getColorIndex as getColorIndex, utils_jsonReplacer as jsonReplacer, utils_safeStringify as safeStringify, utils_serializeError as serializeError, utils_wrapToError as wrapToError };
104
115
  }
105
116
 
106
117
  /**
@@ -174,6 +185,8 @@ interface Firo {
174
185
  warn: (msg: string, data?: unknown, opts?: LogOptions) => void;
175
186
  /** Log an error object directly. */
176
187
  error(err: Error | unknown): void;
188
+ /** Log an error object with additional data. */
189
+ error(err: Error, data?: unknown, opts?: LogOptions): void;
177
190
  /** Log a message alongside an error or custom data object. */
178
191
  error(msg: string, err?: Error | unknown, opts?: LogOptions): void;
179
192
  /**
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ __export(utils_exports, {
11
11
  LOG_LEVELS: () => LOG_LEVELS,
12
12
  colorize: () => colorize,
13
13
  colorizeLevel: () => colorizeLevel,
14
+ extractMessage: () => extractMessage,
14
15
  getColorIndex: () => getColorIndex,
15
16
  jsonReplacer: () => jsonReplacer,
16
17
  safeStringify: () => safeStringify,
@@ -88,13 +89,18 @@ var wrapToError = (obj) => {
88
89
  };
89
90
  var serializeError = (_err) => {
90
91
  const err = wrapToError(_err);
91
- return {
92
+ const result = {
92
93
  message: err.message,
93
94
  stack: err.stack,
94
95
  name: err.name,
95
96
  ...err
96
97
  };
98
+ if (err.cause !== void 0) {
99
+ result.cause = err.cause instanceof Error ? serializeError(err.cause) : err.cause;
100
+ }
101
+ return result;
97
102
  };
103
+ var extractMessage = (msg) => typeof msg === "string" ? msg : msg instanceof Error ? msg.message : typeof msg === "object" && msg !== null ? safeStringify(msg) : String(msg);
98
104
  var colorizeLevel = (level, text) => {
99
105
  if (level === "info") return text;
100
106
  switch (level) {
@@ -162,18 +168,15 @@ var createDevTransport = (config = {}) => {
162
168
  import { inspect as inspect3 } from "util";
163
169
  import process2 from "process";
164
170
  var buildRecord = (level, context, msg, getTimestamp, data) => {
165
- const contextObj = context.reduce((acc, item) => {
166
- acc[item.key] = item.value;
167
- return acc;
168
- }, {});
169
171
  const logRecord = {
170
172
  timestamp: getTimestamp(),
171
- level,
172
- ...contextObj
173
+ level
173
174
  };
175
+ for (let i = 0, len = context.length; i < len; i++) {
176
+ logRecord[context[i].key] = context[i].value;
177
+ }
178
+ logRecord.message = extractMessage(msg);
174
179
  if (level === "error") {
175
- const message = typeof msg === "string" ? msg : msg instanceof Error ? msg.message : typeof msg === "object" && msg !== null ? safeStringify(msg) : String(msg);
176
- logRecord.message = message;
177
180
  if (data instanceof Error) {
178
181
  logRecord.error = serializeError(data);
179
182
  } else if (msg instanceof Error) {
@@ -184,7 +187,9 @@ var buildRecord = (level, context, msg, getTimestamp, data) => {
184
187
  if (data !== void 0) logRecord.data = data;
185
188
  }
186
189
  } else {
187
- logRecord.message = typeof msg === "object" && msg !== null ? safeStringify(msg) : String(msg);
190
+ if (msg instanceof Error) {
191
+ logRecord.error = serializeError(msg);
192
+ }
188
193
  if (data !== void 0) {
189
194
  logRecord.data = data instanceof Error ? serializeError(data) : data;
190
195
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fend/firo",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Elegant logger for Node.js, Bun and Deno with brilliant DX.",
5
5
  "keywords": [
6
6
  "firo",
@@ -42,6 +42,7 @@
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^25.5.0",
45
+ "bumpp": "^11.0.1",
45
46
  "tsup": "^8.5.1",
46
47
  "tsx": "^4.0.0",
47
48
  "typescript": "^5.9.3"
@@ -52,6 +53,7 @@
52
53
  "check": "tsc --noEmit && node --import tsx --test test/*.test.ts",
53
54
  "typecheck": "tsc --noEmit",
54
55
  "demo": "tsx demo.ts",
55
- "bench": "tsx benchmark/prod.ts > /dev/null"
56
+ "bench": "tsx benchmark/prod.ts > /dev/null",
57
+ "bump": "bumpp --files package.json --files jsr.json --execute \"pnpm check && pnpm build && npm publish --dry-run --access public && deno publish --dry-run\" --commit \"v%s\" --no-push"
56
58
  }
57
59
  }