widelogger 0.2.1 → 0.3.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/README.md CHANGED
@@ -41,7 +41,7 @@ npm install widelogger
41
41
  ```ts
42
42
  import { widelogger } from "widelogger";
43
43
 
44
- const { widelog, destroy } = widelogger({
44
+ const { context, destroy } = widelogger({
45
45
  service: "checkout-api",
46
46
  defaultEventName: "http_request",
47
47
  version: "1.0.0",
@@ -49,15 +49,23 @@ const { widelog, destroy } = widelogger({
49
49
  });
50
50
  ```
51
51
 
52
+ `widelogger()` returns a `context` function to wrap request lifecycles and a `destroy` function for graceful shutdown. To log fields, import `widelog` directly from the package — it works anywhere inside a `context()` call thanks to `AsyncLocalStorage`.
53
+
54
+ ```ts
55
+ import { widelog } from "widelogger";
56
+
57
+ widelog.set("user.id", userId);
58
+ ```
59
+
52
60
  ### Express
53
61
 
54
- Create a shared logger instance, use middleware to wrap requests in a context, and accumulate fields from anywhere in your codebase.
62
+ Create a logger instance once, use middleware to wrap requests in a context, and accumulate fields from anywhere in your codebase by importing `widelog` directly.
55
63
 
56
64
  ```ts
57
65
  // src/logger.ts
58
66
  import { widelogger } from "widelogger";
59
67
 
60
- export const { widelog, destroy } = widelogger({
68
+ export const { context, destroy } = widelogger({
61
69
  service: "checkout-api",
62
70
  defaultEventName: "http_request",
63
71
  });
@@ -65,10 +73,11 @@ export const { widelog, destroy } = widelogger({
65
73
 
66
74
  ```ts
67
75
  // src/middleware/logging.ts
68
- import { widelog } from "../logger";
76
+ import { widelog } from "widelogger";
77
+ import { context } from "../logger";
69
78
 
70
79
  export const logging = (request, response, next) => {
71
- widelog.context(
80
+ context(
72
81
  () =>
73
82
  new Promise((resolve) => {
74
83
  widelog.set("method", request.method);
@@ -90,9 +99,9 @@ export const logging = (request, response, next) => {
90
99
 
91
100
  ```ts
92
101
  // src/routes/checkout.ts
93
- import { widelog } from "../logger";
102
+ import { widelog } from "widelogger";
94
103
 
95
- export const checkout = (request, response) => {
104
+ export const checkout = async (request, response) => {
96
105
  const { userId } = request.body;
97
106
 
98
107
  widelog.set("user.id", userId);
@@ -109,7 +118,7 @@ export const checkout = (request, response) => {
109
118
  };
110
119
  ```
111
120
 
112
- The handler doesn't need to know about context setup or flushing — it just imports `widelog` and adds fields. `AsyncLocalStorage` ensures concurrent requests never leak into each other.
121
+ The handler doesn't need to know about context setup or flushing — it just imports `widelog` from the package and adds fields. `AsyncLocalStorage` ensures concurrent requests never leak into each other.
113
122
 
114
123
  ### Bun
115
124
 
@@ -119,7 +128,7 @@ The same pattern works with Bun's built-in server.
119
128
  // src/logger.ts
120
129
  import { widelogger } from "widelogger";
121
130
 
122
- export const { widelog, destroy } = widelogger({
131
+ export const { context, destroy } = widelogger({
123
132
  service: "checkout-api",
124
133
  defaultEventName: "http_request",
125
134
  });
@@ -127,7 +136,7 @@ export const { widelog, destroy } = widelogger({
127
136
 
128
137
  ```ts
129
138
  // src/routes/checkout.ts
130
- import { widelog } from "../logger";
139
+ import { widelog } from "widelogger";
131
140
 
132
141
  export const checkout = async (request: Request) => {
133
142
  const { userId } = await request.json();
@@ -149,12 +158,13 @@ export const checkout = async (request: Request) => {
149
158
  ```ts
150
159
  // src/server.ts
151
160
  import { serve } from "bun";
152
- import { widelog } from "./logger";
161
+ import { widelog } from "widelogger";
162
+ import { context } from "./logger";
153
163
  import { checkout } from "./routes/checkout";
154
164
 
155
165
  serve({
156
166
  fetch: (request) =>
157
- widelog.context(async () => {
167
+ context(async () => {
158
168
  const url = new URL(request.url);
159
169
  widelog.set("method", request.method);
160
170
  widelog.set("path", url.pathname);
@@ -200,7 +210,7 @@ Events with `status_code >= 500` or `outcome === "error"` are emitted at `error`
200
210
 
201
211
  ### `widelogger(options)`
202
212
 
203
- Creates a logger instance. Returns `{ widelog, destroy }`.
213
+ Creates a logger instance. Returns `{ context, destroy }`.
204
214
 
205
215
  | Option | Type | Description |
206
216
  |--------|------|-------------|
@@ -212,11 +222,16 @@ Creates a logger instance. Returns `{ widelog, destroy }`.
212
222
  | `environment` | `string` | Environment name (defaults to `NODE_ENV`) |
213
223
  | `level` | `string` | Log level (defaults to `LOG_LEVEL` env or `"info"`) |
214
224
 
225
+ ### `context(fn)`
226
+
227
+ Run a function inside an isolated async context. All `widelog` calls within this function (and any functions it calls) are scoped to this context. Supports both sync and async callbacks.
228
+
215
229
  ### `widelog`
216
230
 
231
+ Imported directly from `"widelogger"`. All methods operate on the current async context established by `context()`.
232
+
217
233
  | Method | Description |
218
234
  |--------|-------------|
219
- | `context(fn)` | Run a function in an isolated async context |
220
235
  | `set(key, value)` | Set a field value (last write wins) |
221
236
  | `count(key, amount?)` | Increment a counter (default +1) |
222
237
  | `append(key, value)` | Append a value to an array |
package/dist/index.d.ts CHANGED
@@ -12,24 +12,24 @@ export interface ErrorFieldsOptions {
12
12
  prefix?: string;
13
13
  includeStack?: boolean;
14
14
  }
15
+ export declare const widelog: {
16
+ set: <K extends string>(key: DottedKey<K>, value: FieldValue) => void;
17
+ count: <K extends string>(key: DottedKey<K>, amount?: number) => void;
18
+ append: <K extends string>(key: DottedKey<K>, value: FieldValue) => void;
19
+ max: <K extends string>(key: DottedKey<K>, value: number) => void;
20
+ min: <K extends string>(key: DottedKey<K>, value: number) => void;
21
+ time: {
22
+ start: <K extends string>(key: DottedKey<K>) => void;
23
+ stop: <K extends string>(key: DottedKey<K>) => void;
24
+ };
25
+ errorFields: (error: unknown, options?: ErrorFieldsOptions) => void;
26
+ flush: () => void;
27
+ };
15
28
  export declare const widelogger: (options: WideloggerOptions) => {
16
- widelog: {
17
- set: <K extends string>(key: DottedKey<K>, value: FieldValue) => void;
18
- count: <K extends string>(key: DottedKey<K>, amount?: number) => void;
19
- append: <K extends string>(key: DottedKey<K>, value: FieldValue) => void;
20
- max: <K extends string>(key: DottedKey<K>, value: number) => void;
21
- min: <K extends string>(key: DottedKey<K>, value: number) => void;
22
- time: {
23
- start: <K extends string>(key: DottedKey<K>) => void;
24
- stop: <K extends string>(key: DottedKey<K>) => void;
25
- };
26
- errorFields: (error: unknown, options?: ErrorFieldsOptions) => void;
27
- flush: () => void;
28
- context: {
29
- <T>(callback: () => Promise<T>): Promise<T>;
30
- <T>(callback: () => T): T;
31
- };
29
+ context: {
30
+ <T>(callback: () => Promise<T>): Promise<T>;
31
+ <T>(callback: () => T): T;
32
32
  };
33
33
  destroy: () => Promise<void>;
34
34
  };
35
- export type Widelog = ReturnType<typeof widelogger>["widelog"];
35
+ export type Widelog = typeof widelog;
package/dist/index.js CHANGED
@@ -134,6 +134,69 @@ function getErrorFields(error, includeStack = true) {
134
134
  error_message: "Unknown error"
135
135
  };
136
136
  }
137
+ var storage = new AsyncLocalStorage;
138
+ var widelog = {
139
+ set: (key, value) => {
140
+ storage.getStore()?.operations.push({ operation: "set", key, value });
141
+ },
142
+ count: (key, amount = 1) => {
143
+ storage.getStore()?.operations.push({ operation: "count", key, amount });
144
+ },
145
+ append: (key, value) => {
146
+ storage.getStore()?.operations.push({ operation: "append", key, value });
147
+ },
148
+ max: (key, value) => {
149
+ storage.getStore()?.operations.push({ operation: "max", key, value });
150
+ },
151
+ min: (key, value) => {
152
+ storage.getStore()?.operations.push({ operation: "min", key, value });
153
+ },
154
+ time: {
155
+ start: (key) => {
156
+ storage.getStore()?.operations.push({
157
+ operation: "time.start",
158
+ key,
159
+ time: performance.now()
160
+ });
161
+ },
162
+ stop: (key) => {
163
+ storage.getStore()?.operations.push({
164
+ operation: "time.stop",
165
+ key,
166
+ time: performance.now()
167
+ });
168
+ }
169
+ },
170
+ errorFields: (error, options = {}) => {
171
+ const context = storage.getStore();
172
+ if (!context) {
173
+ return;
174
+ }
175
+ const prefix = options.prefix ?? "error";
176
+ const fields = getErrorFields(error, options.includeStack ?? true);
177
+ const nameKey = `${prefix}.error_name`;
178
+ const messageKey = `${prefix}.error_message`;
179
+ context.operations.push({ operation: "set", key: nameKey, value: fields.error_name }, { operation: "set", key: messageKey, value: fields.error_message });
180
+ if (fields.error_stack !== undefined) {
181
+ context.operations.push({
182
+ operation: "set",
183
+ key: `${prefix}.error_stack`,
184
+ value: fields.error_stack
185
+ });
186
+ }
187
+ },
188
+ flush: () => {
189
+ const store = storage.getStore();
190
+ if (!store) {
191
+ return;
192
+ }
193
+ const event = flush(store);
194
+ if (Object.keys(event).length === 0) {
195
+ return;
196
+ }
197
+ store.transport(event);
198
+ }
199
+ };
137
200
  var widelogger = (options) => {
138
201
  const environment = options.environment ?? "development" ?? "development";
139
202
  const isDevelopment = environment !== "production";
@@ -157,11 +220,7 @@ var widelogger = (options) => {
157
220
  environment
158
221
  }
159
222
  }, pinoTransport);
160
- const storage = new AsyncLocalStorage;
161
223
  const transport = (event) => {
162
- if (Object.keys(event).length === 0) {
163
- return;
164
- }
165
224
  const statusCode = typeof event.status_code === "number" ? event.status_code : undefined;
166
225
  const isError = statusCode !== undefined ? statusCode >= 500 : event.outcome === "error";
167
226
  const payload = { event_name: options.defaultEventName, ...event };
@@ -172,13 +231,13 @@ var widelogger = (options) => {
172
231
  logger.info(payload);
173
232
  };
174
233
  const clearContext = () => {
175
- const context = storage.getStore();
176
- if (context && context.operations.length > 0) {
177
- context.operations = [];
234
+ const context2 = storage.getStore();
235
+ if (context2 && context2.operations.length > 0) {
236
+ context2.operations = [];
178
237
  }
179
238
  };
180
- function runContext(callback) {
181
- return storage.run({ operations: [] }, () => {
239
+ function context(callback) {
240
+ return storage.run({ operations: [], transport }, () => {
182
241
  let result;
183
242
  try {
184
243
  result = callback();
@@ -193,62 +252,6 @@ var widelogger = (options) => {
193
252
  return result;
194
253
  });
195
254
  }
196
- const widelog = {
197
- set: (key, value) => {
198
- storage.getStore()?.operations.push({ operation: "set", key, value });
199
- },
200
- count: (key, amount = 1) => {
201
- storage.getStore()?.operations.push({ operation: "count", key, amount });
202
- },
203
- append: (key, value) => {
204
- storage.getStore()?.operations.push({ operation: "append", key, value });
205
- },
206
- max: (key, value) => {
207
- storage.getStore()?.operations.push({ operation: "max", key, value });
208
- },
209
- min: (key, value) => {
210
- storage.getStore()?.operations.push({ operation: "min", key, value });
211
- },
212
- time: {
213
- start: (key) => {
214
- storage.getStore()?.operations.push({
215
- operation: "time.start",
216
- key,
217
- time: performance.now()
218
- });
219
- },
220
- stop: (key) => {
221
- storage.getStore()?.operations.push({
222
- operation: "time.stop",
223
- key,
224
- time: performance.now()
225
- });
226
- }
227
- },
228
- errorFields: (error, options2 = {}) => {
229
- const context = storage.getStore();
230
- if (!context) {
231
- return;
232
- }
233
- const prefix = options2.prefix ?? "error";
234
- const fields = getErrorFields(error, options2.includeStack ?? true);
235
- const nameKey = `${prefix}.error_name`;
236
- const messageKey = `${prefix}.error_message`;
237
- context.operations.push({ operation: "set", key: nameKey, value: fields.error_name }, { operation: "set", key: messageKey, value: fields.error_message });
238
- if (fields.error_stack !== undefined) {
239
- context.operations.push({
240
- operation: "set",
241
- key: `${prefix}.error_stack`,
242
- value: fields.error_stack
243
- });
244
- }
245
- },
246
- flush: () => {
247
- const event = flush(storage.getStore());
248
- transport(event);
249
- },
250
- context: runContext
251
- };
252
255
  const destroy = async () => {
253
256
  await new Promise((resolve) => {
254
257
  logger.flush(() => resolve());
@@ -257,8 +260,9 @@ var widelogger = (options) => {
257
260
  pinoTransport.end();
258
261
  }
259
262
  };
260
- return { widelog, destroy };
263
+ return { context, destroy };
261
264
  };
262
265
  export {
263
- widelogger
266
+ widelogger,
267
+ widelog
264
268
  };
package/dist/types.d.ts CHANGED
@@ -36,5 +36,6 @@ export type Operation = {
36
36
  };
37
37
  export interface Context {
38
38
  operations: Operation[];
39
+ transport: (event: Record<string, unknown>) => void;
39
40
  }
40
41
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "widelogger",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -9,7 +9,8 @@
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
13
14
  }
14
15
  },
15
16
  "repository": {