domain-objects
Version:
A simple, convenient way to represent domain objects, leverage domain knowledge, and add runtime validation in your code base.
69 lines • 3.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.dedupe = void 0;
const helpful_errors_1 = require("helpful-errors");
const isOfDomainEntity_1 = require("../../instantiation/inherit/isOfDomainEntity");
const isOfDomainObject_1 = require("../../instantiation/inherit/isOfDomainObject");
const getUniqueIdentifier_1 = require("../../manipulation/getUniqueIdentifier");
const omitMetadata_1 = require("../../manipulation/omitMetadata");
const serialize_1 = require("../../manipulation/serde/serialize");
// define how to get the dedupe identity key for any object
const toDedupeIdentity = (obj) => (0, serialize_1.serialize)((0, isOfDomainObject_1.isOfDomainObject)(obj) ? (0, getUniqueIdentifier_1.getUniqueIdentifier)(obj) : obj);
const toVersionIdentity = (obj) => (0, isOfDomainEntity_1.isOfDomainEntity)(obj)
? (0, serialize_1.serialize)((0, omitMetadata_1.omitMetadata)(obj))
: undefined; // if not an entity, there is no version identity
/**
* a method which deduplicates objects by their identity from within an array
*
* note
* - when it operates on dobj instances, it extracts their identity via getUniqueIdentifier
* - when it operates on anything else, it simply serializes the object
*/
const dedupe = (objs, options) => {
// track the objects we have seen
const objsSeenMetadata = {};
// track the ordered, deduped objs array, which we will build
const objsDedupedList = [];
// define how to check whether an obj has been seen already
const getObjSeenMetadata = (obj) => objsSeenMetadata[toDedupeIdentity(obj)] ?? null;
// define how to add a new distinct item
const addNewDistinctObj = (obj) => {
// add to the objs seen lookup table
objsSeenMetadata[toDedupeIdentity(obj)] = {
seen: true,
version: toVersionIdentity(obj),
};
// add to the objs deduped list
objsDedupedList.push(obj);
};
// iterate through each object and add it to the deduped list as needed
objs.forEach((thisObj) => {
// determine if its been seen before
const prevSeenMetadata = getObjSeenMetadata(thisObj);
const hasBeenPrevSeen = prevSeenMetadata !== null;
// if it has been seen, is an entity, and the caller didn't ask to CHOOSE_FIRST_OCCURRENCE, then check whether we should fail fast
if (hasBeenPrevSeen &&
(0, isOfDomainEntity_1.isOfDomainEntity)(thisObj) &&
options?.onMultipleEntityVersions !== 'CHOOSE_FIRST_OCCURRENCE') {
const versionPrevSeen = prevSeenMetadata.version;
if (!versionPrevSeen)
throw new helpful_errors_1.UnexpectedCodePathError('should have had prev seen metadata declared for a domain entity', { thisObj });
const versionCurrSeen = toVersionIdentity(thisObj);
if (versionCurrSeen !== versionPrevSeen)
throw new helpful_errors_1.BadRequestError(`Two different versions of the same entity were asked to be deduped. Options.onMultipleEntityVersions !== 'CHOOSE_FIRST_OCCURRENCE', so we're failing fast here, since we don't know which version should be kept.`, {
thisObj,
versionCurrSeen,
versionPrevSeen,
});
}
// if it's been previously seen otherwise, then we can exit here as its a dupe
if (hasBeenPrevSeen)
return;
// otherwise, since its not been previously seen, add it as a new distinct obj
addNewDistinctObj(thisObj);
});
// return all the distinct objs
return objsDedupedList;
};
exports.dedupe = dedupe;
//# sourceMappingURL=dedupe.js.map