@martinmilo/verve
Version:
TypeScript domain modeling library with field-level authorization, business rule validation, and context-aware access control
217 lines • 8.5 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _Model_proxy, _Model_initializer, _Model_fields, _Model_state, _Model_initialState, _Model_changeLog;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Model = void 0;
const ModelInitializer_1 = require("../initializers/ModelInitializer");
const utils_1 = require("./utils");
const errors_1 = require("../../errors");
const IdField_1 = require("../../field/fields/IdField");
const constants_1 = require("../../constants");
class Model {
constructor() {
_Model_proxy.set(this, this);
_Model_initializer.set(this, 'make');
_Model_fields.set(this, {});
_Model_state.set(this, {});
_Model_initialState.set(this, {});
_Model_changeLog.set(this, []);
}
[(_Model_proxy = new WeakMap(), _Model_initializer = new WeakMap(), _Model_fields = new WeakMap(), _Model_state = new WeakMap(), _Model_initialState = new WeakMap(), _Model_changeLog = new WeakMap(), constants_1.MODEL_INITIALIZER)](initializer) {
__classPrivateFieldSet(this, _Model_initializer, initializer, "f");
}
[constants_1.MODEL_INITIAL_STATE](state) {
__classPrivateFieldSet(this, _Model_initialState, (0, utils_1.deepClone)(state), "f");
}
[constants_1.MODEL_CHANGE_LOG](change) {
if (change.currentValue === undefined) {
__classPrivateFieldSet(this, _Model_changeLog, __classPrivateFieldGet(this, _Model_changeLog, "f").filter(log => log.field !== change.field), "f");
return;
}
__classPrivateFieldGet(this, _Model_changeLog, "f").push(change);
}
[constants_1.MODEL_PROXY](proxyRef) {
if (proxyRef) {
__classPrivateFieldSet(this, _Model_proxy, proxyRef, "f");
}
return __classPrivateFieldGet(this, _Model_proxy, "f");
}
[constants_1.MODEL_STATE]() {
return __classPrivateFieldGet(this, _Model_state, "f");
}
[constants_1.MODEL_FIELDS]() {
return __classPrivateFieldGet(this, _Model_fields, "f");
}
isNew() {
return __classPrivateFieldGet(this, _Model_initializer, "f") === 'make';
}
isExisting() {
return __classPrivateFieldGet(this, _Model_initializer, "f") === 'from';
}
getChanges() {
const changes = {};
const changedFields = [];
for (const log of this.getChangeLog()) {
if (changedFields.includes(log.field)) {
continue;
}
if (__classPrivateFieldGet(this, _Model_initialState, "f")[log.field] === log.currentValue) {
changedFields.push(log.field);
continue;
}
changes[log.field] = log.currentValue;
changedFields.push(log.field);
}
return changes;
}
getChangeLog() {
return [...__classPrivateFieldGet(this, _Model_changeLog, "f")].reverse();
}
validate(keys) {
const keysArray = keys ? (Array.isArray(keys) ? keys : [keys]) : undefined;
const errors = errors_1.VerveErrorList.new();
for (const field of Object.values(this[constants_1.MODEL_FIELDS]())) {
if (keysArray && !keysArray.includes(field.metadata.name)) {
continue;
}
const fieldErrors = field.validate();
errors.merge(fieldErrors);
}
return errors;
}
generate(keys) {
const keysArray = keys ? (Array.isArray(keys) ? keys : [keys]) : undefined;
const fields = this[constants_1.MODEL_FIELDS]();
for (const field of Object.values(fields)) {
if (keysArray && !keysArray.includes(field.metadata.name)) {
continue;
}
// If the field has a generator and is not initialized, generate the value
if (field.options.generator && field.unsafeGet() === undefined) {
field.generate();
}
}
return this;
}
unsafeGet(key) {
const fields = this[constants_1.MODEL_FIELDS]();
const field = fields[key];
return field.unsafeGet();
}
set(data) {
const fields = this[constants_1.MODEL_FIELDS]();
for (const [key, value] of Object.entries(data)) {
// We do not allow setting undefined values
if (value === undefined) {
continue;
}
fields[key].set(value);
}
return this;
}
unset(keys) {
const keysArray = Array.isArray(keys) ? keys : [keys];
const fields = this[constants_1.MODEL_FIELDS]();
for (const key of keysArray) {
fields[key].unset();
}
return this;
}
only(keys) {
const keysArray = Array.isArray(keys) ? keys : [keys];
const fields = this[constants_1.MODEL_FIELDS]();
for (const [fieldName, field] of Object.entries(fields)) {
if (keysArray.includes(fieldName)) {
continue;
}
if (field instanceof IdField_1.IdField) {
continue;
}
field.unset();
}
return this;
}
except(keys) {
const keysArray = Array.isArray(keys) ? keys : [keys];
const fields = this[constants_1.MODEL_FIELDS]();
for (const [fieldName, field] of Object.entries(fields)) {
if (!keysArray.includes(fieldName)) {
continue;
}
if (field instanceof IdField_1.IdField) {
throw new errors_1.VerveError(errors_1.ErrorCode.ID_FIELD_CANNOT_BE_EXCLUDED);
}
field.unset();
}
return this;
}
isValid() {
const keys = Object.keys(this);
return this.hasValid(keys);
}
hasValid(keys) {
const keysArray = Array.isArray(keys) ? keys : [keys];
const fields = this[constants_1.MODEL_FIELDS]();
for (const field of Object.values(fields)) {
if (!keysArray.includes(field.metadata.name)) {
continue;
}
if (!field.isValid()) {
return false;
}
}
return true;
}
isEmpty() {
const keys = Object.keys(this);
return this.hasEmpty(keys);
}
hasEmpty(keys) {
const keysArray = Array.isArray(keys) ? keys : [keys];
const fields = this[constants_1.MODEL_FIELDS]();
for (const field of Object.values(fields)) {
if (!keysArray.includes(field.metadata.name)) {
continue;
}
if (!field.isEmpty()) {
return false;
}
}
return true;
}
isPresent() {
const keys = Object.keys(this);
return this.hasPresent(keys);
}
hasPresent(keys) {
const keysArray = Array.isArray(keys) ? keys : [keys];
const fields = this[constants_1.MODEL_FIELDS]();
for (const field of Object.values(fields)) {
if (!keysArray.includes(field.metadata.name)) {
continue;
}
if (!field.isPresent()) {
return false;
}
}
return true;
}
static Untyped() {
return (0, ModelInitializer_1.createModelClass)();
}
static Typed() {
return (0, ModelInitializer_1.createModelClass)();
}
}
exports.Model = Model;
//# sourceMappingURL=Model.js.map