@salesforce/core
Version:
Core libraries to interact with SFDX projects, orgs, and APIs.
89 lines • 3.9 kB
JavaScript
/*
* Copyright (c) 2023, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.LWWMap = exports.stateFromContents = exports.SYMBOL_FOR_DELETED = void 0;
const ts_types_1 = require("@salesforce/ts-types");
const time_1 = require("../util/time");
const lwwRegister_1 = require("./lwwRegister");
exports.SYMBOL_FOR_DELETED = 'UNIQUE_IDENTIFIER_FOR_DELETED';
/**
* @param contents object aligning with ConfigContents
* @param timestamp a bigInt that sets the timestamp. Defaults to the current time
* construct a LWWState from an object
* @param keysToCheckForDeletion if a key is in this array, AND not in the contents, it will be marked as deleted
* */
const stateFromContents = (contents, timestamp) => Object.fromEntries((0, ts_types_1.entriesOf)(contents).map(([key, value]) => [
key,
new lwwRegister_1.LWWRegister({ timestamp: timestamp ?? (0, time_1.nowBigInt)(), value }),
])
// I'd love to get rid of this ASsertion but don't know how.
);
exports.stateFromContents = stateFromContents;
class LWWMap {
/** map of key to LWWRegister. Used for managing conflicts */
#data = new Map();
constructor(state) {
// create a new register for each key in the initial state
for (const [key, register] of (0, ts_types_1.entriesOf)(state ?? {})) {
this.#data.set(key, new lwwRegister_1.LWWRegister(register));
}
}
get value() {
return Object.fromEntries(Array.from(this.#data.entries())
.filter(([, register]) => register.value !== exports.SYMBOL_FOR_DELETED)
.map(([key, register]) => [key, register.value]));
}
get state() {
return Object.fromEntries(Array.from(this.#data.entries()).map(([key, register]) => [key, register.state]));
}
// Merge top-level properties of the incoming state with the current state.
// The value with the latest timestamp wins.
merge(state) {
// properties that are in the incoming state but not the current state might have been deleted.
// recursively merge each key's register with the incoming state for that key
for (const [key, remote] of (0, ts_types_1.entriesOf)(state)) {
const local = this.#data.get(key);
// if the register already exists, merge it with the incoming state
if (local)
local.merge(remote);
// otherwise, instantiate a new `LWWRegister` with the incoming state
else
this.#data.set(key, new lwwRegister_1.LWWRegister(remote));
}
return this.state;
}
set(key, value) {
// get the register at the given key
const register = this.#data.get(key);
// if the register already exists, set the value
if (register)
register.set(value);
// otherwise, instantiate a new `LWWRegister` with the value
else
this.#data.set(key, new lwwRegister_1.LWWRegister({ timestamp: (0, time_1.nowBigInt)(), value }));
}
get(key) {
// map loses the typing
const value = this.#data.get(key)?.value;
if (value === exports.SYMBOL_FOR_DELETED)
return undefined;
return value;
}
delete(key) {
this.#data.set(key, new lwwRegister_1.LWWRegister({
timestamp: (0, time_1.nowBigInt)(),
value: exports.SYMBOL_FOR_DELETED,
}));
}
has(key) {
// if a register doesn't exist or its value is null, the map doesn't contain the key
return this.#data.has(key) && this.#data.get(key)?.value !== exports.SYMBOL_FOR_DELETED;
}
}
exports.LWWMap = LWWMap;
//# sourceMappingURL=lwwMap.js.map
;