2022-07-22 22:39:48 +02:00
|
|
|
/**
|
2023-08-30 01:17:58 +02:00
|
|
|
* This symbol matches all object properties when used in a mask
|
|
|
|
*/
|
|
|
|
export const AllProperties = Symbol('*');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a "masked" copy of the given object. The returned object includes
|
|
|
|
* only the properties present in the mask.
|
2022-07-22 22:39:48 +02:00
|
|
|
*
|
2023-08-30 01:17:58 +02:00
|
|
|
* The mask is an object that mirrors the structure of the given object, except
|
|
|
|
* the only values are `true`, `false, a sub-mask, or the 'AllProperties"
|
|
|
|
* symbol. `true` implies the property should be included, and `false` will
|
|
|
|
* exclude it. A sub-mask implies the property should be further masked
|
|
|
|
* according to that sub-mask. The "AllProperties" symbol is used for objects
|
|
|
|
* with dynamic keys, and applies a rule (either `true`, `false`, or a
|
|
|
|
* sub-mask`) to every property in that object.
|
2022-07-22 22:39:48 +02:00
|
|
|
*
|
2023-08-30 01:17:58 +02:00
|
|
|
* If a property is excluded, its type is included instead.
|
2023-08-17 01:41:17 +02:00
|
|
|
*
|
2022-07-27 15:28:05 +02:00
|
|
|
* @param {object} object - The object to mask
|
2022-07-26 20:10:51 +02:00
|
|
|
* @param {Object<object | boolean>} mask - The mask to apply to the object
|
2022-07-22 22:39:48 +02:00
|
|
|
*/
|
|
|
|
export function maskObject(object, mask) {
|
2023-08-30 01:17:58 +02:00
|
|
|
let maskAllProperties = false;
|
|
|
|
if (Object.keys(mask).includes(AllProperties)) {
|
|
|
|
if (Object.keys(mask).length > 1) {
|
|
|
|
throw new Error('AllProperties mask key does not support sibling keys');
|
|
|
|
}
|
|
|
|
maskAllProperties = true;
|
|
|
|
}
|
2022-07-22 22:39:48 +02:00
|
|
|
return Object.keys(object).reduce((state, key) => {
|
2023-08-30 01:17:58 +02:00
|
|
|
const maskKey = maskAllProperties ? mask[AllProperties] : mask[key];
|
|
|
|
if (maskKey === true) {
|
2022-07-22 22:39:48 +02:00
|
|
|
state[key] = object[key];
|
2023-08-30 01:17:58 +02:00
|
|
|
} else if (maskKey && typeof maskKey === 'object') {
|
|
|
|
state[key] = maskObject(object[key], maskKey);
|
|
|
|
} else if (maskKey === undefined || maskKey === false) {
|
2023-08-17 01:41:17 +02:00
|
|
|
state[key] = typeof object[key];
|
2023-08-30 01:17:58 +02:00
|
|
|
} else {
|
|
|
|
throw new Error(`Unsupported mask entry: ${maskKey}`);
|
2022-07-22 22:39:48 +02:00
|
|
|
}
|
|
|
|
return state;
|
|
|
|
}, {});
|
|
|
|
}
|