@naturalcycles/js-lib 15.89.0 → 15.90.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.
@@ -52,8 +52,14 @@ export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
52
52
  */
53
53
  export declare function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): CommonLogger;
54
54
  export type CommonLogSink = CommonLogger | CommonLogWithLevelFunction;
55
+ /**
56
+ * A plain object is copied once, at creation.
57
+ * A function is called on every log call, for context that changes after the logger is created
58
+ * (e.g a request context whose user is resolved later).
59
+ */
60
+ export type CommonLogContext = AnyObject | (() => AnyObject);
55
61
  export interface CommonLoggerWithContext extends CommonLogger {
56
- child: (context: AnyObject) => CommonLoggerWithContext;
62
+ child: (context: CommonLogContext) => CommonLoggerWithContext;
57
63
  }
58
64
  /**
59
65
  * Creates a CommonLogger from a single function that takes `level` and `args`.
@@ -62,4 +68,4 @@ export interface CommonLoggerWithContext extends CommonLogger {
62
68
  * the rest joined into `msg`.
63
69
  */
64
70
  export declare function commonLoggerCreate(sink: CommonLogSink): CommonLogger;
65
- export declare function commonLoggerCreate(sink: CommonLogSink, context: AnyObject): CommonLoggerWithContext;
71
+ export declare function commonLoggerCreate(sink: CommonLogSink, context: CommonLogContext): CommonLoggerWithContext;
@@ -83,16 +83,26 @@ export function commonLoggerCreate(sink, context) {
83
83
  error: (...args) => fn('error', args),
84
84
  };
85
85
  }
86
- const ctx = { ...context };
86
+ const getContext = contextGetter(context);
87
87
  const logger = {
88
- debug: (...args) => fn('debug', [toLogEntry(ctx, args)]),
89
- log: (...args) => fn('log', [toLogEntry(ctx, args)]),
90
- warn: (...args) => fn('warn', [toLogEntry(ctx, args)]),
91
- error: (...args) => fn('error', [toLogEntry(ctx, args)]),
92
- child: c => commonLoggerCreate(fn, { ...ctx, ...c }),
88
+ debug: (...args) => fn('debug', [toLogEntry(getContext(), args)]),
89
+ log: (...args) => fn('log', [toLogEntry(getContext(), args)]),
90
+ warn: (...args) => fn('warn', [toLogEntry(getContext(), args)]),
91
+ error: (...args) => fn('error', [toLogEntry(getContext(), args)]),
92
+ child: c => {
93
+ const getChild = contextGetter(c);
94
+ return commonLoggerCreate(fn, () => ({ ...getContext(), ...getChild() }));
95
+ },
93
96
  };
94
97
  return logger;
95
98
  }
99
+ function contextGetter(context) {
100
+ // AnyObject also admits functions, so typeof does not narrow the union
101
+ if (typeof context === 'function')
102
+ return context;
103
+ const copy = { ...context };
104
+ return () => copy;
105
+ }
96
106
  function toLogEntry(context, args) {
97
107
  const entry = { ...context };
98
108
  let err;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
3
  "type": "module",
4
- "version": "15.89.0",
4
+ "version": "15.90.0",
5
5
  "dependencies": {
6
6
  "tslib": "^2"
7
7
  },
@@ -128,8 +128,15 @@ export function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): Co
128
128
 
129
129
  export type CommonLogSink = CommonLogger | CommonLogWithLevelFunction
130
130
 
131
+ /**
132
+ * A plain object is copied once, at creation.
133
+ * A function is called on every log call, for context that changes after the logger is created
134
+ * (e.g a request context whose user is resolved later).
135
+ */
136
+ export type CommonLogContext = AnyObject | (() => AnyObject)
137
+
131
138
  export interface CommonLoggerWithContext extends CommonLogger {
132
- child: (context: AnyObject) => CommonLoggerWithContext
139
+ child: (context: CommonLogContext) => CommonLoggerWithContext
133
140
  }
134
141
 
135
142
  /**
@@ -139,8 +146,11 @@ export interface CommonLoggerWithContext extends CommonLogger {
139
146
  * the rest joined into `msg`.
140
147
  */
141
148
  export function commonLoggerCreate(sink: CommonLogSink): CommonLogger
142
- export function commonLoggerCreate(sink: CommonLogSink, context: AnyObject): CommonLoggerWithContext
143
- export function commonLoggerCreate(sink: CommonLogSink, context?: AnyObject): CommonLogger {
149
+ export function commonLoggerCreate(
150
+ sink: CommonLogSink,
151
+ context: CommonLogContext,
152
+ ): CommonLoggerWithContext
153
+ export function commonLoggerCreate(sink: CommonLogSink, context?: CommonLogContext): CommonLogger {
144
154
  const fn: CommonLogWithLevelFunction =
145
155
  typeof sink === 'function' ? sink : (level, args) => sink[level](...args)
146
156
 
@@ -153,18 +163,28 @@ export function commonLoggerCreate(sink: CommonLogSink, context?: AnyObject): Co
153
163
  }
154
164
  }
155
165
 
156
- const ctx: AnyObject = { ...context }
166
+ const getContext = contextGetter(context)
157
167
 
158
168
  const logger: CommonLoggerWithContext = {
159
- debug: (...args) => fn('debug', [toLogEntry(ctx, args)]),
160
- log: (...args) => fn('log', [toLogEntry(ctx, args)]),
161
- warn: (...args) => fn('warn', [toLogEntry(ctx, args)]),
162
- error: (...args) => fn('error', [toLogEntry(ctx, args)]),
163
- child: c => commonLoggerCreate(fn, { ...ctx, ...c }),
169
+ debug: (...args) => fn('debug', [toLogEntry(getContext(), args)]),
170
+ log: (...args) => fn('log', [toLogEntry(getContext(), args)]),
171
+ warn: (...args) => fn('warn', [toLogEntry(getContext(), args)]),
172
+ error: (...args) => fn('error', [toLogEntry(getContext(), args)]),
173
+ child: c => {
174
+ const getChild = contextGetter(c)
175
+ return commonLoggerCreate(fn, () => ({ ...getContext(), ...getChild() }))
176
+ },
164
177
  }
165
178
  return logger
166
179
  }
167
180
 
181
+ function contextGetter(context: CommonLogContext): () => AnyObject {
182
+ // AnyObject also admits functions, so typeof does not narrow the union
183
+ if (typeof context === 'function') return context as () => AnyObject
184
+ const copy = { ...context }
185
+ return () => copy
186
+ }
187
+
168
188
  function toLogEntry(context: AnyObject, args: any[]): AnyObject {
169
189
  const entry: AnyObject = { ...context }
170
190
  let err: Error | undefined