@x5e/gink
Version:
an eventually consistent database
192 lines • 8.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Container = void 0;
const Bundler_1 = require("./Bundler");
const utils_1 = require("./utils");
const Deletion_1 = require("./Deletion");
const Inclusion_1 = require("./Inclusion");
const builders_1 = require("./builders");
const builders_2 = require("./builders");
const Addressable_1 = require("./Addressable");
const store_utils_1 = require("./store_utils");
class Container extends Addressable_1.Addressable {
constructor(database, address, behavior) {
super(address);
this.database = database;
this.behavior = behavior;
}
toString() {
const address = this.address;
return `Container(${address.timestamp},${address.medallion},${address.offset})`;
}
async toJson(indent = false, asOf, seen) {
return Promise.resolve(`"${this.toString()}"`);
}
async setName(name, bundlerOrComment) {
return await this.database
.getGlobalProperty()
.set(this, name, bundlerOrComment);
}
async getName(asOf) {
return await this.database.getGlobalProperty().get(this, asOf);
}
async clear(purge, bundlerOrComment) {
if (!(purge === undefined || purge === true || purge === false)) {
throw new Error("first parameter to clear must be boolean (true => purge)");
}
let immediate = false;
let bundler;
if (bundlerOrComment instanceof Bundler_1.Bundler) {
bundler = bundlerOrComment;
}
else {
immediate = true;
bundler = new Bundler_1.Bundler(bundlerOrComment);
}
const clearanceBuilder = new builders_1.ClearanceBuilder();
clearanceBuilder.setPurge(purge || false);
clearanceBuilder.setContainer((0, utils_1.muidToBuilder)(this.address, bundler.medallion));
const changeBuilder = new builders_1.ChangeBuilder();
changeBuilder.setClearance(clearanceBuilder);
const address = bundler.addChange(changeBuilder);
if (immediate) {
await this.database.addBundler(bundler);
}
return address;
}
/**
* Reset this Container to a previous time. If no time is specified, the container will
* be cleared.
* @param args Optional arguments, including:
* @argument toTime Optional time to reset to. If absent, the container will be cleared.
* @argument bundlerOrComment Bundler to add this change to, string to add a comment to a
* new bundle, or empty to apply immediately.
* @argument skipProperties If true, do not reset properties of this container. By default,
* all properties associated with this container will be reset to the time specified in toTime.
* @argument recurse Recursively reset all child containers held by this container at reset time?
* @argument seen A Set of seen container muids (in string form) to prevent infinite recursion.
* Primarily for internal use, but could be used to prevent specific containers from being reset.
*/
async reset(args) {
throw new Error("Child class should have implemented this method.");
}
async size() {
throw new Error("Child class should have implemented this method.");
}
/**
*
* @param key If absent, create a boxed entry, if KeyType, set a key in entry, if true, create a list entry
* @param value What the container ought to contain (an immediate Value, a reference, or a deletion)
* @param bundlerOrComment Bundler to add this change to, or empty to apply immediately.
* @returns a promise the resolves to the muid of the change
*/
addEntry(key, value, bundlerOrComment) {
let immediate = false;
let bundler;
if (bundlerOrComment instanceof Bundler_1.Bundler) {
bundler = bundlerOrComment;
}
else {
immediate = true;
bundler = new Bundler_1.Bundler(bundlerOrComment);
}
const entryBuilder = new builders_1.EntryBuilder();
if (this.address) {
entryBuilder.setContainer((0, utils_1.muidToBuilder)(this.address, bundler.medallion));
}
entryBuilder.setBehavior(this.behavior);
if (typeof key === "number" ||
typeof key === "string" ||
key instanceof Uint8Array) {
entryBuilder.setKey((0, utils_1.wrapKey)(key));
}
else if (Array.isArray(key)) {
const pair = new builders_2.PairBuilder();
let key1 = key[0];
let key2 = key[1];
if ("address" in key[0] && "address" in key[1]) {
key1 = key[0].address;
key2 = key[1].address;
}
pair.setLeft((0, utils_1.muidToBuilder)(key1));
pair.setRite((0, utils_1.muidToBuilder)(key2));
entryBuilder.setPair(pair);
}
else if (key instanceof Addressable_1.Addressable) {
entryBuilder.setDescribing((0, utils_1.muidToBuilder)(key.address));
}
else if (key && "timestamp" in key) {
entryBuilder.setDescribing((0, utils_1.muidToBuilder)(key));
}
// TODO: check that the destination/value is compatible with Container
if (value !== undefined) {
if (value instanceof Addressable_1.Addressable) {
entryBuilder.setPointee((0, utils_1.muidToBuilder)(value.address, bundler.medallion));
}
else if (value instanceof Deletion_1.Deletion) {
entryBuilder.setDeletion(true);
}
else if (value instanceof Inclusion_1.Inclusion) {
}
else {
entryBuilder.setValue((0, utils_1.wrapValue)(value));
}
}
const changeBuilder = new builders_1.ChangeBuilder();
changeBuilder.setEntry(entryBuilder);
const address = bundler.addChange(changeBuilder);
if (immediate) {
return this.database.addBundler(bundler).then((_) => address);
}
return Promise.resolve(address);
}
/**
* Reset the properties associated with this container to a previous time.
* @param toTime optional timestamp to reset to. If not provided, the properties will be deleted.
* @param bundlerOrComment optional bundler to add this change to, or a string to add a comment to a new bundle.
*/
async resetProperties(toTime, bundlerOrComment) {
let immediate = false;
let bundler;
if (bundlerOrComment instanceof Bundler_1.Bundler) {
bundler = bundlerOrComment;
}
else {
immediate = true;
bundler = new Bundler_1.Bundler(bundlerOrComment);
}
const propertiesNow = await this.database.store.getContainerProperties(this);
if (!toTime) {
for (const [key, _] of propertiesNow.entries()) {
const propertyMuid = (0, utils_1.strToMuid)(key);
// Omitting value parameter creates a deleting entry
(0, store_utils_1.bundlePropertyEntry)(bundler, propertyMuid, this.address);
}
}
else {
const propertiesThen = await this.database.store.getContainerProperties(this, toTime);
for (const [key, value] of propertiesThen.entries()) {
if (value !== propertiesNow.get(key)) {
const propertyMuid = (0, utils_1.strToMuid)(key);
(0, store_utils_1.bundlePropertyEntry)(bundler, propertyMuid, this.address, value);
}
// Remove from propertiesNow so we can delete the rest
// after this iteration
propertiesNow.delete(key);
}
// Now loop through the remaining propertiesNow and delete them
for (const [key, _] of propertiesNow.entries()) {
const propertyMuid = (0, utils_1.strToMuid)(key);
// Omitting value parameter creates a deleting entry
(0, store_utils_1.bundlePropertyEntry)(bundler, propertyMuid, this.address);
}
}
if (immediate) {
await this.database.addBundler(bundler);
}
}
}
exports.Container = Container;
Container.DELETION = new Deletion_1.Deletion();
Container.INCLUSION = new Inclusion_1.Inclusion();
//# sourceMappingURL=Container.js.map