proxy-vir
Version:
An easier Proxy.
71 lines (70 loc) • 2.47 kB
JavaScript
import { check } from '@augment-vir/assert';
import { getObjectTypedKeys } from '@augment-vir/common';
function listToMapInit(options) {
if (options?.initialList) {
return options.initialList.flatMap((initialEntry) => {
return getObjectTypedKeys(initialEntry).map((key) => {
return [
key,
initialEntry[key],
];
});
});
}
return [];
}
/**
* Stores and allows updating of a list of entries from which a single object is created. Properties
* for the single object are chosen from the entries by the entry order in the list.
*/
export function createPrioritizedProperties(options) {
const list = [...(options?.initialList ?? [])];
const combinedProperties = Object.fromEntries(listToMapInit(options));
function updateObject() {
// clear out all the object's current keys
getObjectTypedKeys(combinedProperties).forEach((property) => {
delete combinedProperties[property];
});
list.forEach((entry) => {
getObjectTypedKeys(entry).forEach((property) => {
// only save the property if it hasn't been saved already
if (!check.hasKey(combinedProperties, property)) {
combinedProperties[property] = entry[property];
}
});
});
options?.updateCallback?.(combinedProperties);
}
return {
/**
* An object containing all properties combined from the current priority list of entries.
* This reference never changes, just its contents, so you are safe to grab and use this
* object directly.
*/
combinedProperties,
addOverride(entry) {
list.splice(options?.overrideEntryPoint ?? 0, 0, entry);
updateObject();
},
addFallback(entry) {
list.push(entry);
updateObject();
},
/** Return value indicates if the given entry was removed or not. */
removeEntry(entry) {
const entryIndex = list.indexOf(entry);
if (entryIndex === -1) {
return false;
}
list.splice(entryIndex, 1);
updateObject();
return true;
},
forceUpdate() {
updateObject();
},
getCurrentList() {
return [...list];
},
};
}