@naturalcycles/js-lib 15.88.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.
- package/dist/is.util.d.ts +5 -1
- package/dist/is.util.js +9 -0
- package/dist/log/commonLogger.d.ts +16 -2
- package/dist/log/commonLogger.js +51 -9
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
- package/src/is.util.ts +10 -1
- package/src/log/commonLogger.ts +76 -7
- package/src/types.ts +5 -0
package/dist/is.util.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyObject, FalsyValue, NullishValue, Primitive } from './types.js';
|
|
1
|
+
import type { AnyObject, FalsyValue, NullishValue, PlainObject, Primitive } from './types.js';
|
|
2
2
|
type Nullish<T> = T extends NullishValue ? T : never;
|
|
3
3
|
type Truthy<T> = T extends FalsyValue ? never : T;
|
|
4
4
|
type Falsy<T> = T extends FalsyValue ? T : never;
|
|
@@ -25,6 +25,10 @@ export declare const _isFalsy: <T>(v: T) => v is Falsy<T>;
|
|
|
25
25
|
* Currently treats RegEx as Object too, e.g _isObject(/some/) === true
|
|
26
26
|
*/
|
|
27
27
|
export declare function _isObject(obj: any): obj is AnyObject;
|
|
28
|
+
/**
|
|
29
|
+
* Returns true if item is an object literal: not an Array, Error, RegExp or class instance.
|
|
30
|
+
*/
|
|
31
|
+
export declare function _isPlainObject(v: any): v is PlainObject;
|
|
28
32
|
export declare function _isPrimitive(v: any): v is Primitive;
|
|
29
33
|
export declare function _isEmptyObject(obj: AnyObject): boolean;
|
|
30
34
|
export declare function _isNotEmptyObject(obj: AnyObject): boolean;
|
package/dist/is.util.js
CHANGED
|
@@ -23,6 +23,15 @@ export const _isFalsy = (v) => !v;
|
|
|
23
23
|
export function _isObject(obj) {
|
|
24
24
|
return (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) || false;
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns true if item is an object literal: not an Array, Error, RegExp or class instance.
|
|
28
|
+
*/
|
|
29
|
+
export function _isPlainObject(v) {
|
|
30
|
+
if (typeof v !== 'object' || v === null)
|
|
31
|
+
return false;
|
|
32
|
+
const proto = Object.getPrototypeOf(v);
|
|
33
|
+
return proto === Object.prototype || proto === null;
|
|
34
|
+
}
|
|
26
35
|
export function _isPrimitive(v) {
|
|
27
36
|
return (v === null ||
|
|
28
37
|
v === undefined ||
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MutateOptions } from '../types.js';
|
|
1
|
+
import type { AnyObject, MutateOptions } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* These levels follow console.* naming,
|
|
4
4
|
* so you can use console[level] safely.
|
|
@@ -51,7 +51,21 @@ export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
|
|
|
51
51
|
* Creates a "child" CommonLogger with prefix (one or multiple).
|
|
52
52
|
*/
|
|
53
53
|
export declare function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): CommonLogger;
|
|
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);
|
|
61
|
+
export interface CommonLoggerWithContext extends CommonLogger {
|
|
62
|
+
child: (context: CommonLogContext) => CommonLoggerWithContext;
|
|
63
|
+
}
|
|
54
64
|
/**
|
|
55
65
|
* Creates a CommonLogger from a single function that takes `level` and `args`.
|
|
66
|
+
*
|
|
67
|
+
* With a context, every call emits one object: plain-object args merged in, first Error as `err`,
|
|
68
|
+
* the rest joined into `msg`.
|
|
56
69
|
*/
|
|
57
|
-
export declare function commonLoggerCreate(
|
|
70
|
+
export declare function commonLoggerCreate(sink: CommonLogSink): CommonLogger;
|
|
71
|
+
export declare function commonLoggerCreate(sink: CommonLogSink, context: CommonLogContext): CommonLoggerWithContext;
|
package/dist/log/commonLogger.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _isPlainObject } from '../is.util.js';
|
|
1
2
|
// copy-pasted to avoid weird circular dependency
|
|
2
3
|
const _noop = (..._args) => undefined;
|
|
3
4
|
export const commonLogLevelNumber = {
|
|
@@ -72,14 +73,55 @@ export function commonLoggerPrefix(logger, ...prefixes) {
|
|
|
72
73
|
error: (...args) => logger.error(...prefixes, ...args),
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
export function commonLoggerCreate(sink, context) {
|
|
77
|
+
const fn = typeof sink === 'function' ? sink : (level, args) => sink[level](...args);
|
|
78
|
+
if (!context) {
|
|
79
|
+
return {
|
|
80
|
+
debug: (...args) => fn('debug', args),
|
|
81
|
+
log: (...args) => fn('log', args),
|
|
82
|
+
warn: (...args) => fn('warn', args),
|
|
83
|
+
error: (...args) => fn('error', args),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const getContext = contextGetter(context);
|
|
87
|
+
const logger = {
|
|
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
|
+
},
|
|
84
96
|
};
|
|
97
|
+
return logger;
|
|
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
|
+
}
|
|
106
|
+
function toLogEntry(context, args) {
|
|
107
|
+
const entry = { ...context };
|
|
108
|
+
let err;
|
|
109
|
+
let msg;
|
|
110
|
+
for (const arg of args) {
|
|
111
|
+
if (_isPlainObject(arg)) {
|
|
112
|
+
Object.assign(entry, arg);
|
|
113
|
+
}
|
|
114
|
+
else if (!err && arg instanceof Error) {
|
|
115
|
+
err = arg;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const s = String(arg);
|
|
119
|
+
msg = msg === undefined ? s : `${msg} ${s}`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (err)
|
|
123
|
+
entry['err'] = err;
|
|
124
|
+
if (msg !== undefined)
|
|
125
|
+
entry['msg'] = msg;
|
|
126
|
+
return entry;
|
|
85
127
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -25,6 +25,10 @@ export interface StringMap<T = string> {
|
|
|
25
25
|
* Because `object` type is not safe/recommended to be used (e.g discouraged by eslint-typescript due to: https://github.com/microsoft/TypeScript/issues/21732)
|
|
26
26
|
*/
|
|
27
27
|
export type AnyObject = Record<string, any>;
|
|
28
|
+
/**
|
|
29
|
+
* Object literal, with a prototype of `Object.prototype` or `null`. What `_isPlainObject` narrows to.
|
|
30
|
+
*/
|
|
31
|
+
export type PlainObject = Branded<AnyObject, 'PlainObject'>;
|
|
28
32
|
export type AnyEnum = NumberEnum;
|
|
29
33
|
export type NumberEnum = Record<string, number | string>;
|
|
30
34
|
export type StringEnum = Record<string, string>;
|
package/package.json
CHANGED
package/src/is.util.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyObject, FalsyValue, NullishValue, Primitive } from './types.js'
|
|
1
|
+
import type { AnyObject, FalsyValue, NullishValue, PlainObject, Primitive } from './types.js'
|
|
2
2
|
|
|
3
3
|
type Nullish<T> = T extends NullishValue ? T : never
|
|
4
4
|
type Truthy<T> = T extends FalsyValue ? never : T
|
|
@@ -32,6 +32,15 @@ export function _isObject(obj: any): obj is AnyObject {
|
|
|
32
32
|
return (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) || false
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Returns true if item is an object literal: not an Array, Error, RegExp or class instance.
|
|
37
|
+
*/
|
|
38
|
+
export function _isPlainObject(v: any): v is PlainObject {
|
|
39
|
+
if (typeof v !== 'object' || v === null) return false
|
|
40
|
+
const proto = Object.getPrototypeOf(v)
|
|
41
|
+
return proto === Object.prototype || proto === null
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
export function _isPrimitive(v: any): v is Primitive {
|
|
36
45
|
return (
|
|
37
46
|
v === null ||
|
package/src/log/commonLogger.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { _isPlainObject } from '../is.util.js'
|
|
2
|
+
import type { AnyObject, MutateOptions } from '../types.js'
|
|
2
3
|
|
|
3
4
|
// copy-pasted to avoid weird circular dependency
|
|
4
5
|
const _noop = (..._args: any[]): undefined => undefined
|
|
@@ -125,14 +126,82 @@ export function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): Co
|
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
|
|
129
|
+
export type CommonLogSink = CommonLogger | CommonLogWithLevelFunction
|
|
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
|
+
|
|
138
|
+
export interface CommonLoggerWithContext extends CommonLogger {
|
|
139
|
+
child: (context: CommonLogContext) => CommonLoggerWithContext
|
|
140
|
+
}
|
|
141
|
+
|
|
128
142
|
/**
|
|
129
143
|
* Creates a CommonLogger from a single function that takes `level` and `args`.
|
|
144
|
+
*
|
|
145
|
+
* With a context, every call emits one object: plain-object args merged in, first Error as `err`,
|
|
146
|
+
* the rest joined into `msg`.
|
|
130
147
|
*/
|
|
131
|
-
export function commonLoggerCreate(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
148
|
+
export function commonLoggerCreate(sink: CommonLogSink): CommonLogger
|
|
149
|
+
export function commonLoggerCreate(
|
|
150
|
+
sink: CommonLogSink,
|
|
151
|
+
context: CommonLogContext,
|
|
152
|
+
): CommonLoggerWithContext
|
|
153
|
+
export function commonLoggerCreate(sink: CommonLogSink, context?: CommonLogContext): CommonLogger {
|
|
154
|
+
const fn: CommonLogWithLevelFunction =
|
|
155
|
+
typeof sink === 'function' ? sink : (level, args) => sink[level](...args)
|
|
156
|
+
|
|
157
|
+
if (!context) {
|
|
158
|
+
return {
|
|
159
|
+
debug: (...args) => fn('debug', args),
|
|
160
|
+
log: (...args) => fn('log', args),
|
|
161
|
+
warn: (...args) => fn('warn', args),
|
|
162
|
+
error: (...args) => fn('error', args),
|
|
163
|
+
}
|
|
137
164
|
}
|
|
165
|
+
|
|
166
|
+
const getContext = contextGetter(context)
|
|
167
|
+
|
|
168
|
+
const logger: CommonLoggerWithContext = {
|
|
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
|
+
},
|
|
177
|
+
}
|
|
178
|
+
return logger
|
|
179
|
+
}
|
|
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
|
+
|
|
188
|
+
function toLogEntry(context: AnyObject, args: any[]): AnyObject {
|
|
189
|
+
const entry: AnyObject = { ...context }
|
|
190
|
+
let err: Error | undefined
|
|
191
|
+
let msg: string | undefined
|
|
192
|
+
|
|
193
|
+
for (const arg of args) {
|
|
194
|
+
if (_isPlainObject(arg)) {
|
|
195
|
+
Object.assign(entry, arg)
|
|
196
|
+
} else if (!err && arg instanceof Error) {
|
|
197
|
+
err = arg
|
|
198
|
+
} else {
|
|
199
|
+
const s = String(arg)
|
|
200
|
+
msg = msg === undefined ? s : `${msg} ${s}`
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (err) entry['err'] = err
|
|
205
|
+
if (msg !== undefined) entry['msg'] = msg
|
|
206
|
+
return entry
|
|
138
207
|
}
|
package/src/types.ts
CHANGED
|
@@ -30,6 +30,11 @@ export interface StringMap<T = string> {
|
|
|
30
30
|
*/
|
|
31
31
|
export type AnyObject = Record<string, any>
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Object literal, with a prototype of `Object.prototype` or `null`. What `_isPlainObject` narrows to.
|
|
35
|
+
*/
|
|
36
|
+
export type PlainObject = Branded<AnyObject, 'PlainObject'>
|
|
37
|
+
|
|
33
38
|
export type AnyEnum = NumberEnum
|
|
34
39
|
export type NumberEnum = Record<string, number | string>
|
|
35
40
|
export type StringEnum = Record<string, string>
|