@api3/commons 0.8.0 → 0.9.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/README.md +9 -59
- package/dist/blockchain-utilities/derivation.d.ts +3 -0
- package/dist/blockchain-utilities/derivation.d.ts.map +1 -1
- package/dist/blockchain-utilities/derivation.js +19 -1
- package/dist/blockchain-utilities/derivation.js.map +1 -1
- package/dist/blockchain-utilities/schema.js.map +1 -1
- package/dist/config-hash/index.js.map +1 -1
- package/dist/eslint/jest.js +7 -7
- package/dist/eslint/jest.js.map +1 -1
- package/dist/eslint/next-js.js +1 -1
- package/dist/eslint/next-js.js.map +1 -1
- package/dist/eslint/react.js +10 -10
- package/dist/eslint/react.js.map +1 -1
- package/dist/eslint/universal.js +60 -60
- package/dist/eslint/universal.js.map +1 -1
- package/dist/http/index.d.ts +4 -2
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +10 -5
- package/dist/http/index.js.map +1 -1
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +9 -1
- package/dist/logger/index.js.map +1 -1
- package/dist/processing/processing.js.map +1 -1
- package/dist/processing/unsafe-evaluate.js.map +1 -1
- package/dist/processing/vm-timers.js.map +1 -1
- package/package.json +21 -17
- package/src/blockchain-utilities/derivation.test.ts +153 -81
- package/src/blockchain-utilities/derivation.ts +23 -0
- package/src/http/index.test.ts +4 -6
- package/src/http/index.ts +14 -6
- package/src/logger/index.test.ts +94 -83
- package/src/logger/index.ts +9 -1
package/src/logger/index.test.ts
CHANGED
|
@@ -16,114 +16,125 @@ const createTestLogger = (
|
|
|
16
16
|
return { baseLogger, logger };
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const { baseLogger, logger } = createTestLogger();
|
|
22
|
-
|
|
23
|
-
logger.runWithContext({ requestId: 'parent' }, () => {
|
|
24
|
-
logger.debug('parent start');
|
|
25
|
-
logger.runWithContext({ requestId: 'child' }, () => {
|
|
26
|
-
logger.debug('child');
|
|
27
|
-
});
|
|
19
|
+
test('works with sync functions', () => {
|
|
20
|
+
const { baseLogger, logger } = createTestLogger();
|
|
28
21
|
|
|
29
|
-
|
|
22
|
+
logger.runWithContext({ requestId: 'parent' }, () => {
|
|
23
|
+
logger.debug('parent start');
|
|
24
|
+
logger.runWithContext({ requestId: 'child' }, () => {
|
|
25
|
+
logger.debug('child');
|
|
30
26
|
});
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('child', { ctx: { requestId: 'child' } });
|
|
34
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('parent end', { ctx: { requestId: 'parent' } });
|
|
28
|
+
logger.debug('parent end');
|
|
35
29
|
});
|
|
36
30
|
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('parent start', { ctx: { requestId: 'parent' } });
|
|
32
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('child', { ctx: { requestId: 'child' } });
|
|
33
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('parent end', { ctx: { requestId: 'parent' } });
|
|
34
|
+
});
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
await logger.runWithContext({ requestId: 'child' }, async () => {
|
|
43
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
44
|
-
logger.debug('child');
|
|
45
|
-
});
|
|
36
|
+
test('works with async functions', async () => {
|
|
37
|
+
const { baseLogger, logger } = createTestLogger();
|
|
46
38
|
|
|
47
|
-
|
|
39
|
+
await logger.runWithContext({ requestId: 'parent' }, async () => {
|
|
40
|
+
logger.debug('parent start');
|
|
41
|
+
await logger.runWithContext({ requestId: 'child' }, async () => {
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
43
|
+
logger.debug('child');
|
|
48
44
|
});
|
|
49
45
|
|
|
50
|
-
|
|
51
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('parent start', { ctx: { requestId: 'parent' } });
|
|
52
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('child', { ctx: { requestId: 'child' } });
|
|
53
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('parent end', { ctx: { requestId: 'parent' } });
|
|
46
|
+
logger.debug('parent end');
|
|
54
47
|
});
|
|
55
48
|
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
expect(baseLogger.debug).toHaveBeenCalledTimes(3);
|
|
50
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('parent start', { ctx: { requestId: 'parent' } });
|
|
51
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('child', { ctx: { requestId: 'child' } });
|
|
52
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('parent end', { ctx: { requestId: 'parent' } });
|
|
53
|
+
});
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
test('works with deeply nested functions', async () => {
|
|
56
|
+
const { baseLogger, logger } = createTestLogger();
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
await logger.runWithContext({ parent: true }, async () => {
|
|
59
|
+
logger.debug('parent start');
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
setTimeout(() => logger.debug('D'), 50);
|
|
68
|
-
setTimeout(() => logger.debug('E'), 75);
|
|
61
|
+
await logger.runWithContext({ A: true }, async () => {
|
|
62
|
+
logger.debug('A start');
|
|
69
63
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
await logger.runWithContext({ B: true }, async () => {
|
|
65
|
+
setTimeout(() => logger.debug('C'), 25);
|
|
66
|
+
setTimeout(() => logger.debug('D'), 50);
|
|
67
|
+
setTimeout(() => logger.debug('E'), 75);
|
|
73
68
|
|
|
74
|
-
|
|
69
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
70
|
+
logger.debug('B end');
|
|
75
71
|
});
|
|
76
72
|
|
|
77
|
-
logger.debug('
|
|
73
|
+
logger.debug('A end');
|
|
78
74
|
});
|
|
79
75
|
|
|
80
|
-
|
|
81
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('parent start', { ctx: { parent: true } });
|
|
82
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('A start', { ctx: { parent: true, A: true } });
|
|
83
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('C', { ctx: { parent: true, A: true, B: true } });
|
|
84
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('D', { ctx: { parent: true, A: true, B: true } });
|
|
85
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('E', { ctx: { parent: true, A: true, B: true } });
|
|
86
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('B end', { ctx: { parent: true, A: true, B: true } });
|
|
87
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('A end', { ctx: { parent: true, A: true } });
|
|
88
|
-
expect(baseLogger.debug).toHaveBeenCalledWith('parent end', { ctx: { parent: true } });
|
|
76
|
+
logger.debug('parent end');
|
|
89
77
|
});
|
|
90
78
|
|
|
91
|
-
|
|
92
|
-
|
|
79
|
+
expect(baseLogger.debug).toHaveBeenCalledTimes(8);
|
|
80
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('parent start', { ctx: { parent: true } });
|
|
81
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('A start', { ctx: { parent: true, A: true } });
|
|
82
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('C', { ctx: { parent: true, A: true, B: true } });
|
|
83
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('D', { ctx: { parent: true, A: true, B: true } });
|
|
84
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('E', { ctx: { parent: true, A: true, B: true } });
|
|
85
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('B end', { ctx: { parent: true, A: true, B: true } });
|
|
86
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('A end', { ctx: { parent: true, A: true } });
|
|
87
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('parent end', { ctx: { parent: true } });
|
|
88
|
+
});
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
throw new Error('some-error');
|
|
97
|
-
})
|
|
98
|
-
).toThrow('some-error');
|
|
99
|
-
});
|
|
90
|
+
test('throws if the sync callback function throws', () => {
|
|
91
|
+
const { logger } = createTestLogger();
|
|
100
92
|
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
expect(() =>
|
|
94
|
+
logger.runWithContext({}, () => {
|
|
95
|
+
throw new Error('some-error');
|
|
96
|
+
})
|
|
97
|
+
).toThrow('some-error');
|
|
98
|
+
});
|
|
103
99
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
logger.runWithContext({}, async () => {
|
|
107
|
-
throw new Error('some-error');
|
|
108
|
-
})
|
|
109
|
-
).rejects.toThrow('some-error');
|
|
110
|
-
});
|
|
100
|
+
test('returns rejected promise if the async callback function rejects', async () => {
|
|
101
|
+
const { logger } = createTestLogger();
|
|
111
102
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
103
|
+
await expect(async () =>
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
105
|
+
logger.runWithContext({}, async () => {
|
|
106
|
+
throw new Error('some-error');
|
|
107
|
+
})
|
|
108
|
+
).rejects.toThrow('some-error');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('can log using all variants of logger.error', () => {
|
|
112
|
+
const { baseLogger, logger } = createTestLogger();
|
|
113
|
+
|
|
114
|
+
logger.error('only message');
|
|
115
|
+
logger.error('message and context', { requestId: 'parent' });
|
|
116
|
+
logger.error('message and error', new Error('some-error'));
|
|
117
|
+
logger.error('message, error and context', new Error('some-error'), { requestId: 'parent' });
|
|
118
|
+
|
|
119
|
+
expect(baseLogger.error).toHaveBeenNthCalledWith(1, 'only message', undefined);
|
|
120
|
+
expect(baseLogger.error).toHaveBeenNthCalledWith(2, 'message and context', { ctx: { requestId: 'parent' } });
|
|
121
|
+
expect(baseLogger.error).toHaveBeenNthCalledWith(3, 'message and error', new Error('some-error'), undefined);
|
|
122
|
+
expect(baseLogger.error).toHaveBeenNthCalledWith(4, 'message, error and context', new Error('some-error'), {
|
|
123
|
+
ctx: {
|
|
124
|
+
requestId: 'parent',
|
|
125
|
+
},
|
|
128
126
|
});
|
|
129
127
|
});
|
|
128
|
+
|
|
129
|
+
test('logs an error when passed as context to non error level', () => {
|
|
130
|
+
const { baseLogger, logger } = createTestLogger();
|
|
131
|
+
const e = new Error('some-error');
|
|
132
|
+
|
|
133
|
+
logger.debug('debug message', e);
|
|
134
|
+
logger.info('info message', e);
|
|
135
|
+
logger.warn('warn message', e);
|
|
136
|
+
|
|
137
|
+
expect(baseLogger.debug).toHaveBeenCalledWith('debug message', { ctx: { error: 'some-error', name: 'Error' } });
|
|
138
|
+
expect(baseLogger.info).toHaveBeenCalledWith('info message', { ctx: { error: 'some-error', name: 'Error' } });
|
|
139
|
+
expect(baseLogger.warn).toHaveBeenCalledWith('warn message', { ctx: { error: 'some-error', name: 'Error' } });
|
|
140
|
+
});
|
package/src/logger/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import isError from 'lodash/isError';
|
|
1
2
|
import winston from 'winston';
|
|
2
3
|
import { consoleFormat } from 'winston-console-format';
|
|
3
4
|
|
|
@@ -87,10 +88,17 @@ export interface Logger {
|
|
|
87
88
|
child: (options: { name: string }) => Logger;
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
const parseLocalContext = (localContext: LogContext | undefined) => {
|
|
92
|
+
// Sometimes an error passed as a context, but when JS error has no own enumerable properties, so when it is spread
|
|
93
|
+
// (using ...) we get an empty object and lose all the context.
|
|
94
|
+
if (isError(localContext)) return { error: localContext.message, name: localContext.name };
|
|
95
|
+
return localContext;
|
|
96
|
+
};
|
|
97
|
+
|
|
90
98
|
const createFullContext = (localContext: LogContext | undefined) => {
|
|
91
99
|
const globalContext = getAsyncLocalStorage().getStore();
|
|
92
100
|
if (!globalContext && !localContext) return;
|
|
93
|
-
const fullContext = { ...globalContext, ...localContext };
|
|
101
|
+
const fullContext = { ...globalContext, ...parseLocalContext(localContext) };
|
|
94
102
|
|
|
95
103
|
// If the context contains a `name` or `message` field, it will override the `name` and `message` fields of the log
|
|
96
104
|
// entry. To avoid this, we return the context as a separate field.
|