@loglayer/mixin-wide-events 1.0.0 → 1.0.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Theo Gravity / [Disaresta](https://disaresta.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs CHANGED
@@ -1,5 +1,4 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
2
  //#region ../../core/plugin/dist/index.js
4
3
  /**
5
4
  * List of plugin callbacks that can be called by the plugin manager.
@@ -20,17 +19,7 @@ let PluginCallbackType = /* @__PURE__ */ function(PluginCallbackType) {
20
19
  PluginCallbackType["onContextCalled"] = "onContextCalled";
21
20
  return PluginCallbackType;
22
21
  }({});
23
-
24
- //#endregion
25
- //#region ../../core/loglayer/dist/index.js
26
- const CALLBACK_LIST = [
27
- PluginCallbackType.onBeforeDataOut,
28
- PluginCallbackType.onMetadataCalled,
29
- PluginCallbackType.onBeforeMessageOut,
30
- PluginCallbackType.transformLogLevel,
31
- PluginCallbackType.shouldSendToLogger,
32
- PluginCallbackType.onContextCalled
33
- ];
22
+ PluginCallbackType.onBeforeDataOut, PluginCallbackType.onMetadataCalled, PluginCallbackType.onBeforeMessageOut, PluginCallbackType.transformLogLevel, PluginCallbackType.shouldSendToLogger, PluginCallbackType.onContextCalled;
34
23
  /**
35
24
  * The class that the mixin extends
36
25
  */
@@ -45,7 +34,6 @@ let LogLayerMixinAugmentType = /* @__PURE__ */ function(LogLayerMixinAugmentType
45
34
  LogLayerMixinAugmentType["LogLayer"] = "LogLayer";
46
35
  return LogLayerMixinAugmentType;
47
36
  }({});
48
-
49
37
  //#endregion
50
38
  //#region src/mixin.ts
51
39
  /**
@@ -95,6 +83,21 @@ function createWideEventMixin(options) {
95
83
  const asyncContext = options.asyncContext;
96
84
  const includeContext = options.includeContext ?? true;
97
85
  const wideEventField = options.wideEventField;
86
+ const errorsAsArray = options.errorsAsArray ?? false;
87
+ const errorField = options.errorField ?? (errorsAsArray ? "errors" : "error");
88
+ function defaultErrorSerializer(err) {
89
+ if (err instanceof Error) return {
90
+ name: err.name,
91
+ message: err.message,
92
+ stack: err.stack
93
+ };
94
+ return { message: String(err) };
95
+ }
96
+ function getErrorSerializer(self) {
97
+ const config = self.getConfig?.();
98
+ if (config?.errorSerializer) return config.errorSerializer;
99
+ return defaultErrorSerializer;
100
+ }
98
101
  /**
99
102
  * Context tracker plugin - stores context in async storage
100
103
  * for inclusion in wide events (only if includeContext is true)
@@ -160,6 +163,21 @@ function createWideEventMixin(options) {
160
163
  return self;
161
164
  }
162
165
  /**
166
+ * Implementation for withWideEventError
167
+ */
168
+ function withWideEventErrorImpl(error, self) {
169
+ const store = asyncContext.getStore();
170
+ if (store) {
171
+ const serializedError = getErrorSerializer(self)(error);
172
+ if (errorsAsArray) {
173
+ if (!store._llWideEvents) store._llWideEvents = {};
174
+ if (!store._llWideEvents[errorField]) store._llWideEvents[errorField] = [];
175
+ store._llWideEvents[errorField].push(serializedError);
176
+ } else withWideEventsImpl({ [errorField]: serializedError }, self);
177
+ }
178
+ return self;
179
+ }
180
+ /**
163
181
  * Implementation for emitWideEvent
164
182
  */
165
183
  function emitWideEventImpl(config, self) {
@@ -167,11 +185,9 @@ function createWideEventMixin(options) {
167
185
  const wideEventData = {};
168
186
  if (includeContext && store?._llContext) Object.assign(wideEventData, store._llContext);
169
187
  if (store?._llWideEvents) Object.assign(wideEventData, store._llWideEvents);
170
- if (config.metadata) Object.assign(wideEventData, config.metadata);
171
188
  const level = config.level ?? "info";
172
189
  const metadataToEmit = wideEventField ? { [wideEventField]: wideEventData } : wideEventData;
173
190
  self.withMetadata(metadataToEmit)[level](config.message);
174
- return self;
175
191
  }
176
192
  return {
177
193
  mixinsToAdd: [{
@@ -189,6 +205,9 @@ function createWideEventMixin(options) {
189
205
  prototype.emitWideEvent = function(config) {
190
206
  return emitWideEventImpl(config, this);
191
207
  };
208
+ prototype.withWideEventError = function(error) {
209
+ return withWideEventErrorImpl(error, this);
210
+ };
192
211
  },
193
212
  augmentMock: (prototype) => {
194
213
  prototype.withWideEvents = function(data) {
@@ -203,11 +222,13 @@ function createWideEventMixin(options) {
203
222
  prototype.emitWideEvent = function(config) {
204
223
  return emitWideEventImpl(config, this);
205
224
  };
225
+ prototype.withWideEventError = function(error) {
226
+ return withWideEventErrorImpl(error, this);
227
+ };
206
228
  }
207
229
  }],
208
230
  pluginsToAdd: [contextTrackerPlugin]
209
231
  };
210
232
  }
211
-
212
233
  //#endregion
213
- exports.createWideEventMixin = createWideEventMixin;
234
+ exports.createWideEventMixin = createWideEventMixin;
package/dist/index.d.cts CHANGED
@@ -2089,6 +2089,18 @@ interface WideEventMixinOptions {
2089
2089
  * { "userId": "123", "orderId": "456", "msg": "done" }
2090
2090
  */
2091
2091
  wideEventField?: string;
2092
+ /**
2093
+ * Optional: Field name to use for error data in wide events.
2094
+ * @default "error" (single mode) or "errors" (array mode)
2095
+ */
2096
+ errorField?: string;
2097
+ /**
2098
+ * Optional: When true, errors are collected as an array.
2099
+ * Each call to withWideEventError() appends to the array.
2100
+ * When false, each call replaces the previous error.
2101
+ * @default false
2102
+ */
2103
+ errorsAsArray?: boolean;
2092
2104
  }
2093
2105
  /**
2094
2106
  * Configuration for emitting a wide event.
@@ -2102,11 +2114,6 @@ interface EmitWideEventConfig {
2102
2114
  * Optional: Log level (defaults to "info").
2103
2115
  */
2104
2116
  level?: LogLevelType;
2105
- /**
2106
- * Optional: Additional metadata to include in this specific emission.
2107
- * This is merged with the accumulated wide event data.
2108
- */
2109
- metadata?: Record<string, any>;
2110
2117
  }
2111
2118
  /**
2112
2119
  * Interface for wide event mixin functionality.
@@ -2183,22 +2190,41 @@ interface IWideEventMixin {
2183
2190
  * and logs at the specified level.
2184
2191
  *
2185
2192
  * @param config - Configuration for the wide event emission
2186
- * @returns This logger instance for chaining
2187
2193
  *
2188
2194
  * @example
2189
2195
  * ```typescript
2190
2196
  * // Emit as info log
2191
2197
  * logger.emitWideEvent({ message: "Order processed" });
2192
2198
  *
2193
- * // Emit as error with additional metadata
2199
+ * // Emit as error
2194
2200
  * logger.emitWideEvent({
2195
2201
  * message: "Order failed",
2196
2202
  * level: "error",
2197
- * metadata: { reason: "payment_declined" }
2198
2203
  * });
2199
2204
  * ```
2200
2205
  */
2201
- emitWideEvent(config: EmitWideEventConfig): this;
2206
+ emitWideEvent(config: EmitWideEventConfig): void;
2207
+ /**
2208
+ * Captures an error for inclusion in the wide event.
2209
+ * Serializes the error using the configured errorSerializer (or default).
2210
+ *
2211
+ * @param error - The error to capture
2212
+ * @returns This logger instance for chaining
2213
+ *
2214
+ * @example
2215
+ * ```typescript
2216
+ * try {
2217
+ * await doSomething();
2218
+ * } catch (err) {
2219
+ * // For single error (replaces previous)
2220
+ * logger.withWideEventError(err);
2221
+ *
2222
+ * // With errorsAsArray: true - errors accumulate
2223
+ * logger.withWideEventError(err).withWideEventError(otherErr);
2224
+ * }
2225
+ * ```
2226
+ */
2227
+ withWideEventError(error: any): this;
2202
2228
  }
2203
2229
  declare module "loglayer" {
2204
2230
  interface LogLayer extends IWideEventMixin {}
package/dist/index.d.mts CHANGED
@@ -2089,6 +2089,18 @@ interface WideEventMixinOptions {
2089
2089
  * { "userId": "123", "orderId": "456", "msg": "done" }
2090
2090
  */
2091
2091
  wideEventField?: string;
2092
+ /**
2093
+ * Optional: Field name to use for error data in wide events.
2094
+ * @default "error" (single mode) or "errors" (array mode)
2095
+ */
2096
+ errorField?: string;
2097
+ /**
2098
+ * Optional: When true, errors are collected as an array.
2099
+ * Each call to withWideEventError() appends to the array.
2100
+ * When false, each call replaces the previous error.
2101
+ * @default false
2102
+ */
2103
+ errorsAsArray?: boolean;
2092
2104
  }
2093
2105
  /**
2094
2106
  * Configuration for emitting a wide event.
@@ -2102,11 +2114,6 @@ interface EmitWideEventConfig {
2102
2114
  * Optional: Log level (defaults to "info").
2103
2115
  */
2104
2116
  level?: LogLevelType;
2105
- /**
2106
- * Optional: Additional metadata to include in this specific emission.
2107
- * This is merged with the accumulated wide event data.
2108
- */
2109
- metadata?: Record<string, any>;
2110
2117
  }
2111
2118
  /**
2112
2119
  * Interface for wide event mixin functionality.
@@ -2183,22 +2190,41 @@ interface IWideEventMixin {
2183
2190
  * and logs at the specified level.
2184
2191
  *
2185
2192
  * @param config - Configuration for the wide event emission
2186
- * @returns This logger instance for chaining
2187
2193
  *
2188
2194
  * @example
2189
2195
  * ```typescript
2190
2196
  * // Emit as info log
2191
2197
  * logger.emitWideEvent({ message: "Order processed" });
2192
2198
  *
2193
- * // Emit as error with additional metadata
2199
+ * // Emit as error
2194
2200
  * logger.emitWideEvent({
2195
2201
  * message: "Order failed",
2196
2202
  * level: "error",
2197
- * metadata: { reason: "payment_declined" }
2198
2203
  * });
2199
2204
  * ```
2200
2205
  */
2201
- emitWideEvent(config: EmitWideEventConfig): this;
2206
+ emitWideEvent(config: EmitWideEventConfig): void;
2207
+ /**
2208
+ * Captures an error for inclusion in the wide event.
2209
+ * Serializes the error using the configured errorSerializer (or default).
2210
+ *
2211
+ * @param error - The error to capture
2212
+ * @returns This logger instance for chaining
2213
+ *
2214
+ * @example
2215
+ * ```typescript
2216
+ * try {
2217
+ * await doSomething();
2218
+ * } catch (err) {
2219
+ * // For single error (replaces previous)
2220
+ * logger.withWideEventError(err);
2221
+ *
2222
+ * // With errorsAsArray: true - errors accumulate
2223
+ * logger.withWideEventError(err).withWideEventError(otherErr);
2224
+ * }
2225
+ * ```
2226
+ */
2227
+ withWideEventError(error: any): this;
2202
2228
  }
2203
2229
  declare module "loglayer" {
2204
2230
  interface LogLayer extends IWideEventMixin {}
package/dist/index.mjs CHANGED
@@ -18,17 +18,7 @@ let PluginCallbackType = /* @__PURE__ */ function(PluginCallbackType) {
18
18
  PluginCallbackType["onContextCalled"] = "onContextCalled";
19
19
  return PluginCallbackType;
20
20
  }({});
21
-
22
- //#endregion
23
- //#region ../../core/loglayer/dist/index.js
24
- const CALLBACK_LIST = [
25
- PluginCallbackType.onBeforeDataOut,
26
- PluginCallbackType.onMetadataCalled,
27
- PluginCallbackType.onBeforeMessageOut,
28
- PluginCallbackType.transformLogLevel,
29
- PluginCallbackType.shouldSendToLogger,
30
- PluginCallbackType.onContextCalled
31
- ];
21
+ PluginCallbackType.onBeforeDataOut, PluginCallbackType.onMetadataCalled, PluginCallbackType.onBeforeMessageOut, PluginCallbackType.transformLogLevel, PluginCallbackType.shouldSendToLogger, PluginCallbackType.onContextCalled;
32
22
  /**
33
23
  * The class that the mixin extends
34
24
  */
@@ -43,7 +33,6 @@ let LogLayerMixinAugmentType = /* @__PURE__ */ function(LogLayerMixinAugmentType
43
33
  LogLayerMixinAugmentType["LogLayer"] = "LogLayer";
44
34
  return LogLayerMixinAugmentType;
45
35
  }({});
46
-
47
36
  //#endregion
48
37
  //#region src/mixin.ts
49
38
  /**
@@ -93,6 +82,21 @@ function createWideEventMixin(options) {
93
82
  const asyncContext = options.asyncContext;
94
83
  const includeContext = options.includeContext ?? true;
95
84
  const wideEventField = options.wideEventField;
85
+ const errorsAsArray = options.errorsAsArray ?? false;
86
+ const errorField = options.errorField ?? (errorsAsArray ? "errors" : "error");
87
+ function defaultErrorSerializer(err) {
88
+ if (err instanceof Error) return {
89
+ name: err.name,
90
+ message: err.message,
91
+ stack: err.stack
92
+ };
93
+ return { message: String(err) };
94
+ }
95
+ function getErrorSerializer(self) {
96
+ const config = self.getConfig?.();
97
+ if (config?.errorSerializer) return config.errorSerializer;
98
+ return defaultErrorSerializer;
99
+ }
96
100
  /**
97
101
  * Context tracker plugin - stores context in async storage
98
102
  * for inclusion in wide events (only if includeContext is true)
@@ -158,6 +162,21 @@ function createWideEventMixin(options) {
158
162
  return self;
159
163
  }
160
164
  /**
165
+ * Implementation for withWideEventError
166
+ */
167
+ function withWideEventErrorImpl(error, self) {
168
+ const store = asyncContext.getStore();
169
+ if (store) {
170
+ const serializedError = getErrorSerializer(self)(error);
171
+ if (errorsAsArray) {
172
+ if (!store._llWideEvents) store._llWideEvents = {};
173
+ if (!store._llWideEvents[errorField]) store._llWideEvents[errorField] = [];
174
+ store._llWideEvents[errorField].push(serializedError);
175
+ } else withWideEventsImpl({ [errorField]: serializedError }, self);
176
+ }
177
+ return self;
178
+ }
179
+ /**
161
180
  * Implementation for emitWideEvent
162
181
  */
163
182
  function emitWideEventImpl(config, self) {
@@ -165,11 +184,9 @@ function createWideEventMixin(options) {
165
184
  const wideEventData = {};
166
185
  if (includeContext && store?._llContext) Object.assign(wideEventData, store._llContext);
167
186
  if (store?._llWideEvents) Object.assign(wideEventData, store._llWideEvents);
168
- if (config.metadata) Object.assign(wideEventData, config.metadata);
169
187
  const level = config.level ?? "info";
170
188
  const metadataToEmit = wideEventField ? { [wideEventField]: wideEventData } : wideEventData;
171
189
  self.withMetadata(metadataToEmit)[level](config.message);
172
- return self;
173
190
  }
174
191
  return {
175
192
  mixinsToAdd: [{
@@ -187,6 +204,9 @@ function createWideEventMixin(options) {
187
204
  prototype.emitWideEvent = function(config) {
188
205
  return emitWideEventImpl(config, this);
189
206
  };
207
+ prototype.withWideEventError = function(error) {
208
+ return withWideEventErrorImpl(error, this);
209
+ };
190
210
  },
191
211
  augmentMock: (prototype) => {
192
212
  prototype.withWideEvents = function(data) {
@@ -201,11 +221,13 @@ function createWideEventMixin(options) {
201
221
  prototype.emitWideEvent = function(config) {
202
222
  return emitWideEventImpl(config, this);
203
223
  };
224
+ prototype.withWideEventError = function(error) {
225
+ return withWideEventErrorImpl(error, this);
226
+ };
204
227
  }
205
228
  }],
206
229
  pluginsToAdd: [contextTrackerPlugin]
207
230
  };
208
231
  }
209
-
210
232
  //#endregion
211
- export { createWideEventMixin };
233
+ export { createWideEventMixin };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loglayer/mixin-wide-events",
3
3
  "description": "Adds wide event logging functionality to LogLayer for comprehensive, self-contained log entries.",
4
- "version": "1.0.0",
4
+ "version": "1.0.1",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.mjs",
@@ -32,22 +32,14 @@
32
32
  "wide-events",
33
33
  "canonical-log-lines"
34
34
  ],
35
- "scripts": {
36
- "build": "tsdown src/index.ts",
37
- "test": "vitest --run",
38
- "clean": "rm -rf .turbo node_modules dist",
39
- "lint": "biome check --no-errors-on-unmatched --write --unsafe src",
40
- "lint:staged": "biome check --no-errors-on-unmatched --write --unsafe --staged src",
41
- "verify-types": "tsc --noEmit"
42
- },
43
35
  "devDependencies": {
44
- "@internal/tsconfig": "workspace:*",
45
- "@loglayer/shared": "workspace:*",
46
- "@types/node": "25.2.3",
47
- "loglayer": "workspace:*",
48
- "tsdown": "0.20.3",
49
- "typescript": "5.9.3",
50
- "vitest": "4.0.18"
36
+ "@types/node": "25.9.1",
37
+ "tsdown": "0.22.0",
38
+ "typescript": "6.0.3",
39
+ "vitest": "4.1.7",
40
+ "@loglayer/shared": "4.2.0",
41
+ "@internal/tsconfig": "2.1.0",
42
+ "loglayer": "9.2.0"
51
43
  },
52
44
  "peerDependencies": {},
53
45
  "bugs": "https://github.com/loglayer/loglayer/issues",
@@ -55,5 +47,12 @@
55
47
  "dist"
56
48
  ],
57
49
  "homepage": "https://loglayer.dev",
58
- "packageManager": "pnpm@10.20.0"
59
- }
50
+ "scripts": {
51
+ "build": "tsdown src/index.ts",
52
+ "test": "vitest --run",
53
+ "clean": "rm -rf .turbo node_modules dist",
54
+ "lint": "biome check --no-errors-on-unmatched --write --unsafe src",
55
+ "lint:staged": "biome check --no-errors-on-unmatched --write --unsafe --staged src",
56
+ "verify-types": "tsc --noEmit"
57
+ }
58
+ }