3 const { common
} = require('@squeep/api-dingus');
4 const { randomBytes
} = require('node:crypto');
5 const { promisify
} = require('node:util');
7 const randomBytesAsync
= promisify(randomBytes
);
10 * Recursively freeze an object.
11 * @param {object} o object to freeze
12 * @returns {object} frozen object
14 const freezeDeep
= (o
) => {
16 Object
.getOwnPropertyNames(o
).forEach((prop
) => {
17 if (Object
.hasOwn(o
, prop
)
18 && ['object', 'function'].includes(typeof o
[prop
]) // eslint-disable-line security/detect-object-injection
19 && !Object
.isFrozen(o
[prop
])) { // eslint-disable-line security/detect-object-injection
20 return freezeDeep(o
[prop
]); // eslint-disable-line security/detect-object-injection
27 * Return a new object duplicating `o`, without the properties specified.
28 * @param {object} o source object
29 * @param {string[]} props list of property names to omit
30 * @returns {object} pruned object
32 const omit
= (o
, props
) => {
33 return Object
.fromEntries(Object
.entries(o
).filter(([k
]) => !props
.includes(k
)));
37 * Helper to log mystery-box statistics.
38 * @param {object} logger logger
39 * @param {Function} logger.debug log debug
40 * @param {string} scope scope
41 * @returns {Function} stats log decorator
43 const mysteryBoxLogger
= (logger
, scope
) => {
45 logger
.debug(scope
, `${s.packageName}@${s.packageVersion}:${s.method}`, omit(s
, [
54 * Hide sensitive part of an Authorization header.
55 * @param {string} authHeader header value
56 * @returns {string} scrubbed header value
58 const obscureAuthorizationHeader
= (authHeader
) => {
62 const space
= authHeader
.indexOf(' ');
63 // This blurs entire string if no space found, because -1.
64 return authHeader
.slice(0, space
+ 1) + '*'.repeat(authHeader
.length
- (space
+ 1));
67 module
.exports
= Object
.assign(Object
.create(common
), {
70 obscureAuthorizationHeader
,