@difizen/mana-observable
Version:
95 lines (92 loc) • 2.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.defineProperty = defineProperty;
exports.observable = observable;
var _config = require("./config");
var _notifiable = require("./notifiable");
var _notifier = require("./notifier");
var _utils = require("./utils");
/* eslint-disable @typescript-eslint/no-explicit-any */
var propertyRelatedNotifier = Symbol('propertyRelatedNotifier');
// redefine observable properties
function defineProperty(target, property, defaultValue) {
var notifier = _notifier.Notifier.getOrCreate(target, property);
/**
* notify notifier when property changed
*/
var onChange = function onChange() {
if (_config.ObservableConfig.paused) {
return;
}
_notifier.Notifier.trigger(target, property);
};
/**
* set observable property value and register onChange listener
* @param value
* @param notifier
*/
var handleValue = function handleValue(value) {
_utils.InstanceValue.set(target, property, value);
if (notifier) {
var last = _utils.Observability.getDisposable(propertyRelatedNotifier, notifier);
if (last) {
last.dispose();
}
}
if (_notifiable.Notifiable.is(value)) {
var valueNotifier = _notifiable.Notifiable.getNotifier(value);
if (notifier && valueNotifier) {
var toDispose = valueNotifier.onChangeSync(onChange);
_utils.Observability.setDisposable(propertyRelatedNotifier, toDispose, notifier);
}
}
};
var initialValue = target[property] === undefined ? defaultValue : target[property];
handleValue(_notifiable.Notifiable.transform(initialValue));
// property getter
var getter = function getter() {
var value = Reflect.getMetadata(property, target);
return value;
};
// property setter
var setter = function setter(value) {
var notifiableValue = _notifiable.Notifiable.transform(value);
var oldValue = _utils.InstanceValue.get(target, property);
if (notifiableValue !== oldValue) {
handleValue(notifiableValue);
onChange();
}
};
// define property
if (Reflect.deleteProperty(target, property)) {
Reflect.defineProperty(target, property, {
configurable: true,
enumerable: true,
get: getter,
set: setter
});
}
// mark observable property
_utils.ObservableProperties.add(target, property);
_utils.Observability.mark(target, property);
}
function observable(target) {
if (!_utils.Observability.canBeObservable(target)) {
return target;
}
var origin = _utils.Observability.getOrigin(target);
var properties = _utils.ObservableProperties.find(origin);
if (!properties) {
var notifiableValue = _notifiable.Notifiable.transform(origin);
if (_notifiable.Notifiable.is(notifiableValue)) {
_utils.Observability.mark(origin);
}
return notifiableValue;
}
properties.forEach(function (property) {
return defineProperty(origin, property);
});
return origin;
}