1
0
mirror of https://github.com/devcode-it/openstamanager.git synced 2025-02-25 07:47:55 +01:00

136 lines
3.8 KiB
JavaScript
Raw Normal View History

import {collect} from 'collect.js';
2021-10-11 19:57:42 +02:00
import {
type PluralResponse,
Model as BaseModel
2021-10-11 19:57:42 +02:00
} from 'coloquent';
import {
capitalize,
snakeCase
} from 'lodash-es';
// noinspection JSPotentiallyInvalidConstructorUsage
/**
* The base model for all models.
*
* @property {number} id
* @abstract
*/
export default class Model extends BaseModel {
jsonApiType: string;
/**
* Specifies the list of relationships, with their model(s) and getters/setters
*
* @type {{[p: string]: {model: typeof Model, get, set}}}
*/
relationValues: {[string]: {
model: typeof Model | (typeof Model)[],
get: {[string]: (models: Model | Model[]) => any},
set: {[string]: (models: Model | Model[]) => void},
}} = {}
/**
* Specifies the list of attributes that should be obtained from the model
* @type {{[p: string]: string}}
* @private
*/
#relationAttributesGet: {[string]: string} = {};
/**
* Specifies the list of attributes that should be set in the model
* @type {{[p: string]: string}}
* @private
*/
#relationAttributesSet: {[string]: string} = {};
constructor() {
super();
const collection = collect(this.relationValues);
this.#relationAttributesGet = collection.pluck('get').keys().all();
this.#relationAttributesSet = collection.pluck('set').keys().all();
// Return a proxy of this object to allow dynamic attributes getters and setters
2021-12-27 16:46:28 +01:00
// eslint-disable-next-line no-constructor-return
return new Proxy(this, {
get(target: this, property, receiver) {
if (property in target.#relationAttributesGet) {
return target.relationValue(property);
}
const snakeCasedProperty = snakeCase(property);
if (snakeCasedProperty in target.getAttributes()) {
return target.getAttribute(snakeCasedProperty);
}
return Reflect.get(target, property, receiver);
},
set(target: this, property, value, receiver) {
if (property in target.#relationAttributesSet) {
return target.relationValue(property, 'set', value);
}
const snakeCasedProperty = snakeCase(property);
if (snakeCasedProperty in target.getAttributes()) {
target.setAttribute(snakeCasedProperty, value);
return true;
}
return Reflect.set(target, property, value, receiver);
}
});
}
/**
* Just an alias to the get() method.
*
* Returns all the instances of the model.
*/
static all(): Promise<PluralResponse<InstanceType<Model>>> {
return this.get();
}
2021-10-08 16:49:17 +02:00
setAttributes(attributes: { [string]: any }): void {
for (const [attribute, value] of Object.entries(attributes)) {
2021-10-11 19:57:42 +02:00
this[attribute] = value;
2021-10-08 16:49:17 +02:00
}
}
getAttribute(attributeName: string): any {
return super.getAttribute(attributeName);
}
setAttribute(attributeName: string, value: any) {
super.setAttribute(attributeName, value);
}
getAttributes(): { [p: string]: any } {
return super.getAttributes();
}
getJsonApiBaseUrl(): string {
return '/api';
2021-09-29 20:29:08 +02:00
}
getJsonApiType(): string {
return (super.getJsonApiType() ?? snakeCase(this.constructor.name));
}
/**
* Returns the attribute of the specified relationship.
*/
// eslint-disable-next-line default-param-last
relationValue(attribute: string, action: 'get' | 'set' = 'get', value: any): void | any {
const relation = this[`relationAttributes${capitalize(action)}`][attribute];
const callback = this.relationValues[relation][action][attribute];
let istanza = this.getRelation(relation);
const model = this.relationValues[relation].model
if (!istanza && !Array.isArray(model)) {
// eslint-disable-next-line new-cap
istanza = new model();
this.setRelation(relation, istanza);
}
2021-12-31 00:45:15 +01:00
2022-01-03 13:09:27 +01:00
return callback(istanza, value);
}
}