@pilotlab/data
Version:
A luxurious user experience framework, developed by your friends at Pilot.
204 lines • 9.61 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const is_1 = require("@pilotlab/is");
const nodes_1 = require("@pilotlab/nodes");
const debug_1 = require("@pilotlab/debug");
const result_1 = require("@pilotlab/result");
const signals_1 = require("@pilotlab/signals");
const attributeEnums_1 = require("./attributes/attributeEnums");
const attributeBase_1 = require("./attributes/attributeBase");
const attributeRoot_1 = require("./attributes/attributeRoot");
const attributeChangeOptions_1 = require("./attributes/attributeChangeOptions");
const attributeCreateOptions_1 = require("./attributes/attributeCreateOptions");
const ids_1 = require("@pilotlab/ids");
const dataEnums_1 = require("./dataEnums");
const sha1_1 = require("@pilotlab/sha1");
const commands_1 = require("@pilotlab/commands");
debug_1.Debug.setCategoryMode('data_save', false);
class Data extends attributeBase_1.default {
constructor(data, isStoreKey = true, dataStore, isSaveDataTypes = false, isAutoSave = false, key, label, progressTracker, isInitialize = true) {
super(attributeRoot_1.default.create, data, attributeEnums_1.DataType.COLLECTION, label, key, nodes_1.NodeType.ROOT, false);
this.isStoreKey = true;
this.p_keyAutoGenerationType = dataEnums_1.KeyAutoGenerationType.SESSION_UNIQUE;
this.p_isAutoHash = false;
this._isAutoSave = false;
/**
* This will be set to true if autoSave() was called while isAutoSave was false.
* This triggers a save of the data immediately after isAutoSave is set to true.
*/
this._isAutoSaveQueued = false;
/*====================================================================*
START: Signals
*====================================================================*/
this.storeSet = new signals_1.Signal(true);
/**
* Dispatched after a response is received back from the data store when data has been saved.
* Completes with the response from the data store.
*/
this.saved = new signals_1.Signal(false);
/*====================================================================*
START: Signals
*====================================================================*/
this.saveTriggered = new signals_1.Signal(false);
//===== Save
this._saveDebounceDelayInMilliseconds = 125;
this.isStoreKey = isStoreKey;
if (isInitialize)
this.initialize(data, dataStore, isSaveDataTypes, isAutoSave, progressTracker);
}
initialize(data, dataStore, isSaveDataTypes = false, isAutoSave = false, progressTracker) {
return super.p_initialize([data, dataStore, isSaveDataTypes, isAutoSave, progressTracker]);
}
p_onInitializeStarted(result, args) {
const data = args[0];
const dataStore = args[1];
const isSaveDataTypes = args[2];
const isAutoSave = args[3];
const progressTracker = args[4];
super.p_onInitializeStarted(new result_1.Result(), [data, attributeEnums_1.DataType.COLLECTION, nodes_1.NodeType.ROOT]).then(() => {
this.p_value.changed.listen((args) => { this.p_onChanged(args); });
if (is_1.default.notEmpty(dataStore))
this.store = dataStore;
if (!this.isStoreKey) {
if (this.p_keyAutoGenerationType === dataEnums_1.KeyAutoGenerationType.SESSION_UNIQUE) {
this.p_key = ids_1.Identifier.getSessionUniqueInteger().toString();
}
else
this.p_key = ids_1.Identifier.generate();
}
else {
this.p_key = ids_1.Identifier.generate();
}
this._isSaveDataTypes = isSaveDataTypes;
this._isAutoSave = isAutoSave;
this._saveCommand = new commands_1.ThrottlingCommand(() => {
let result = new result_1.Result();
let data = this.toObject(this.isSaveDataTypes);
if (is_1.default.empty(data) || is_1.default.empty(this.key) || typeof this.key !== 'string')
return result.resolve(false);
//----- Reset _isAutoSaveQueued
this._isAutoSaveQueued = false;
if (!this.hash.omitFromDataStore && this.p_isAutoHash) {
sha1_1.SHA1.hash(JSON.stringify(data)).then((hash) => {
data['hash'] = hash;
debug_1.Debug.log('saving to database', 'Data._saveCommand', 'data_save');
debug_1.Debug.log(data, 'Data._saveCommand', 'data_save');
this._dataStore.save(data, this.key).then((response) => {
if (is_1.default.notEmpty(response) && typeof response === 'string')
this._revision = response;
result.resolve(response);
this.saved.dispatch(response);
});
});
}
else {
debug_1.Debug.log('saving to database', 'Data._saveCommand', 'data_save');
debug_1.Debug.log(data, 'Data._saveCommand', 'data_save');
this._dataStore.save(data, this.key).then((response) => {
if (is_1.default.notEmpty(response) && typeof response === 'string')
this._revision = response;
result.resolve(response);
this.saved.dispatch(response);
});
}
return result;
}, null, this, this._saveDebounceDelayInMilliseconds);
this.p_value.update(data, attributeChangeOptions_1.default.signal.durationZero, progressTracker).then(() => result.resolve(data));
});
return result;
}
/*====================================================================*
START: Properties
*====================================================================*/
/**
* If the key is stored, this will be a globally unique ID, used to identify the data
* object associated with this entity in the data store.
*/
set key(value) {
this.p_key = value;
if (this.isStoreKey)
this.save();
}
/**
* The revision ID, which may be managed by the database and can be used to determine
* if the data associated with this entity is up-to-date.
*/
get revision() { return this._revision; }
/**
* An SHA-1 hash representing the precise contents of the associated blob or text.
* Can be used to check the uniqueness of a data object to avoid storing duplicates.
*/
get hash() {
return this.p_value.get('hash', new attributeCreateOptions_1.default('', attributeEnums_1.DataType.STRING, null, null, null, attributeChangeOptions_1.default.zero));
}
get isAutoHash() { return this.p_isAutoHash; }
set isAutoHash(value) { this.p_isAutoHash = value; }
//===== DataStore
/**
* The data store where the data associated with this entity will be stored.
*/
get store() { return this._dataStore; }
set store(value) {
this._dataStore = value;
this.storeSet.dispatch(value);
}
//===== Save
/**
* Determines whether a dataType property is saved with the data objects,
* which can be used to verify the data's type when the object is deserialized.
*/
get isSaveDataTypes() { return this._isSaveDataTypes; }
set isSaveDataTypes(value) { this._isSaveDataTypes = value; }
/**
* Toggles auto-save functionality.
* Can be used to pause auto-saving while changes to the data are batched.
*/
get isAutoSave() { return this._isAutoSave; }
set isAutoSave(value) {
if (this._isAutoSave === value)
return;
this._isAutoSave = value;
if (value && this._isAutoSaveQueued)
this.save();
}
p_onChanged(args) {
if (is_1.default.empty(args))
return;
if (args.changeOptions.isSave && is_1.default.notEmpty(this.key)) {
this.autoSave();
this.saveTriggered.dispatch(args);
}
}
/*====================================================================*
START: Public Methods
*====================================================================*/
update(data, changeOptions = attributeChangeOptions_1.default.default, progressTracker) {
return this.p_value.update(data, changeOptions, progressTracker);
}
save() {
if (is_1.default.empty(this._dataStore)) {
//----- Save immediately after the data store has been set.
this.storeSet.listenOnce(() => this.save());
return result_1.Result.resolve(null);
}
return this._saveCommand.debounce();
}
autoSave() {
if (!this.isAutoSave)
this._isAutoSaveQueued = true;
else if (is_1.default.notEmpty(this.key))
this.save();
}
delete() {
if (is_1.default.empty(this.key) || typeof this.key !== 'string')
return result_1.Result.resolve(false);
let result = new result_1.Result();
this._dataStore.delete(this.key).then((isSuccess) => {
result.resolve(isSuccess);
}, (e) => { result.reject(e); });
return result;
}
} // End of class
exports.Data = Data;
exports.default = Data;
//# sourceMappingURL=data.js.map