avocado/packages/traits/src/trait.js
2022-03-30 04:09:16 -05:00

177 lines
3.8 KiB
JavaScript

import {JsonResource} from '@avocado/resource';
export default class Trait extends JsonResource {
$$markedAsDirty = true;
$$memoizedListeners = undefined;
$$previousState = {};
constructor() {
super();
const {constructor} = this;
this.params = constructor.defaultParams();
this.state = constructor.defaultState();
this.$$previousState = JSON.parse(JSON.stringify(this.state));
if (this.tick) {
this.tick = this.tick.bind(this);
}
if (this.renderTick) {
this.renderTick = this.renderTick.bind(this);
}
}
// eslint-disable-next-line class-methods-use-this, no-unused-vars
acceptPacket(packet) {}
cleanPackets() {
if (!this.$$markedAsDirty) {
return;
}
this.markAsClean();
}
static defaultJSON() {
return {
params: this.defaultParams(),
state: this.defaultState(),
};
}
static defaultParams() {
return {};
}
static defaultParamsWith(defaults) {
return {...this.defaultParams(), ...defaults};
}
static defaultState() {
return {};
}
static defaultStateWith(defaults) {
return {...this.defaultState(), ...defaults};
}
static dependencies() {
return [];
}
destroy() {
this.$$memoizedListeners = undefined;
}
// eslint-disable-next-line class-methods-use-this
hooks() {
return {};
}
// eslint-disable-next-line class-methods-use-this
listeners() {
return {};
}
load({entity, params = {}, state = {}} = {}) {
this.entity = entity;
const {constructor} = this;
this.params = constructor.defaultParamsWith(params);
this.state = constructor.defaultStateWith(state);
this.$$previousState = JSON.parse(JSON.stringify(this.state));
}
markAsClean() {
const state = Object.entries(this.state);
for (let i = 0; i < state.length; i++) {
const [key, value] = state[i];
this.$$previousState[key] = value;
}
this.$$markedAsDirty = false;
}
markAsDirty() {
this.$$markedAsDirty = true;
this.entity.markAsDirty();
}
memoizedListeners() {
if (!this.$$memoizedListeners) {
this.$$memoizedListeners = this.listeners();
}
return this.$$memoizedListeners;
}
// eslint-disable-next-line class-methods-use-this
methods() {
return {};
}
// eslint-disable-next-line class-methods-use-this
packetsFor() {
return [];
}
static get resourceId() {
return this.id;
}
// eslint-disable-next-line class-methods-use-this
get s13nId() {
return 0;
}
stateDifferences() {
const differences = {};
const state = Object.entries(this.state);
for (let i = 0; i < state.length; i++) {
const [key, value] = state[i];
if (value !== this.$$previousState[key]) {
differences[key] = {
old: this.$$previousState[key],
value,
};
}
}
return differences;
}
toNetwork() {
return this.toJSON();
}
toJSON() {
return {
params: this.params,
state: this.state,
};
}
static withDefaults(json = {}) {
return {
params: this.defaultParamsWith(json.params || {}),
state: this.defaultStateWith(json.state || {}),
};
}
static withoutDefaults(json) {
const without = {};
const defaultParams = this.defaultParams();
Object.entries(json.params || {}).forEach(([key, value]) => {
if (JSON.stringify(value) !== JSON.stringify(defaultParams[key])) {
without.params = without.params || {};
without.params[key] = value;
}
});
const defaultState = this.defaultState();
Object.entries(json.state || {}).forEach(([key, value]) => {
if (JSON.stringify(value) !== JSON.stringify(defaultState[key])) {
without.state = without.state || {};
without.state[key] = value;
}
});
return without;
}
}