mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-12 15:22:55 +01:00
Initial commit
Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com> Co-Authored-By: Johan <4934465+joolsus@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
This commit is contained in:
215
packages/noodl-runtime/src/model.js
Normal file
215
packages/noodl-runtime/src/model.js
Normal file
@@ -0,0 +1,215 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// Model
|
||||
// ------------------------------------------------------------------------------
|
||||
function Model(id, data) {
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
const models = (Model._models = {});
|
||||
const proxies = {};
|
||||
|
||||
// Get and set proxy
|
||||
const _modelProxyHandler = {
|
||||
get: function (target, prop, receiver) {
|
||||
if (typeof target[prop] === 'function') return target[prop].bind(target);
|
||||
else if (prop in target) return Reflect.get(target, prop, receiver);
|
||||
else return target.get(prop);
|
||||
},
|
||||
set: function (obj, prop, value) {
|
||||
if (prop === '_class') {
|
||||
obj._class = value;
|
||||
} else if (prop === 'id') {
|
||||
console.log(`Noodl.Object warning: id is readonly (Id is ${obj.id}, trying to set to ${value})`);
|
||||
return true; //if a proxy doesn't return true an exception will be thrown
|
||||
} else {
|
||||
obj.set(prop, value);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
return Reflect.ownKeys(target.data);
|
||||
},
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
return Object.getOwnPropertyDescriptor(target.data, prop);
|
||||
}
|
||||
};
|
||||
|
||||
Model.get = function (id) {
|
||||
if (id === undefined) id = Model.guid();
|
||||
if (!models[id]) {
|
||||
models[id] = new Model(id, {});
|
||||
proxies[id] = new Proxy(models[id], _modelProxyHandler);
|
||||
}
|
||||
return proxies[id];
|
||||
};
|
||||
|
||||
Model.create = function (data) {
|
||||
var modelData = data ? data : {};
|
||||
var m = Model.get(modelData.id);
|
||||
for (var key in modelData) {
|
||||
if (key === 'id') continue;
|
||||
m.set(key, modelData[key]);
|
||||
}
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
Model.exists = function (id) {
|
||||
return models[id] !== undefined;
|
||||
};
|
||||
|
||||
Model.instanceOf = function (collection) {
|
||||
return collection instanceof Model || collection.target instanceof Model;
|
||||
};
|
||||
|
||||
function _randomString(size) {
|
||||
if (size === 0) {
|
||||
throw new Error('Zero-length randomString is useless.');
|
||||
}
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789';
|
||||
let objectId = '';
|
||||
for (let i = 0; i < size; ++i) {
|
||||
objectId += chars[Math.floor((1 + Math.random()) * 0x10000) % chars.length];
|
||||
}
|
||||
return objectId;
|
||||
}
|
||||
|
||||
Model.guid = function guid() {
|
||||
return _randomString(10);
|
||||
};
|
||||
|
||||
Model.prototype.on = function (event, listener) {
|
||||
if (!this.listeners) this.listeners = {};
|
||||
if (!this.listeners[event]) this.listeners[event] = [];
|
||||
this.listeners[event].push(listener);
|
||||
};
|
||||
|
||||
Model.prototype.off = function (event, listener) {
|
||||
if (!this.listeners) return;
|
||||
if (!this.listeners[event]) return;
|
||||
var idx = this.listeners[event].indexOf(listener);
|
||||
if (idx !== -1) this.listeners[event].splice(idx, 1);
|
||||
};
|
||||
|
||||
Model.prototype.notify = function (event, args) {
|
||||
if (!this.listeners) return;
|
||||
if (!this.listeners[event]) return;
|
||||
|
||||
var l = this.listeners[event].slice(); //clone in case listeners array is modified in the callbacks
|
||||
for (var i = 0; i < l.length; i++) {
|
||||
l[i](args);
|
||||
}
|
||||
};
|
||||
|
||||
Model.prototype.setAll = function (obj) {
|
||||
for (var i in obj) {
|
||||
if (i === 'id') continue; // Skip id
|
||||
if (this.data[i] !== obj[i]) {
|
||||
var old = this.data[i];
|
||||
this.data[i] = obj[i];
|
||||
this.notify('change', { name: i, value: obj[i], old: old });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Model.prototype.fill = function (value = null) {
|
||||
for (const key in this.data) {
|
||||
if (key === 'id') continue; // Skip id
|
||||
const temp = this.data[key];
|
||||
this.data[key] = value;
|
||||
this.notify('change', { name: key, value: this.data[key], old: temp });
|
||||
}
|
||||
};
|
||||
|
||||
Model.prototype.set = function (name, value, args) {
|
||||
if (args && args.resolve && name.indexOf('.') !== -1) {
|
||||
// We should resolve path references
|
||||
var path = name.split('.');
|
||||
var model = this;
|
||||
for (var i = 0; i < path.length - 1; i++) {
|
||||
var v = model.get(path[i]);
|
||||
if (Model.instanceOf(v)) model = v;
|
||||
else return; // Path resolve failed
|
||||
}
|
||||
model.set(path[path.length - 1], value);
|
||||
return;
|
||||
}
|
||||
|
||||
const forceChange = args && args.forceChange;
|
||||
|
||||
var oldValue = this.data[name];
|
||||
this.data[name] = value;
|
||||
(forceChange || oldValue !== value) &&
|
||||
(!args || !args.silent) &&
|
||||
this.notify('change', { name: name, value: value, old: oldValue });
|
||||
};
|
||||
|
||||
Model.prototype.getId = function () {
|
||||
return this.id;
|
||||
};
|
||||
|
||||
Model.prototype.get = function (name, args) {
|
||||
if (args && args.resolve && name.indexOf('.') !== -1) {
|
||||
// We should resolve path references
|
||||
var path = name.split('.');
|
||||
var model = this;
|
||||
for (var i = 0; i < path.length - 1; i++) {
|
||||
var v = model.get(path[i]);
|
||||
if (Model.instanceOf(v)) model = v;
|
||||
else return; // Path resolve failed
|
||||
}
|
||||
return model.get(path[path.length - 1]);
|
||||
}
|
||||
|
||||
return this.data[name];
|
||||
};
|
||||
|
||||
Model.prototype.toJSON = function () {
|
||||
return Object.assign({}, this.data, { id: this.id });
|
||||
};
|
||||
|
||||
Model.Scope = function () {
|
||||
this.models = {};
|
||||
this.proxies = {};
|
||||
};
|
||||
|
||||
Model.Scope.prototype.get = function (id) {
|
||||
if (id === undefined) id = Model.guid();
|
||||
if (!this.models[id]) {
|
||||
this.models[id] = new Model(id, {});
|
||||
this.proxies[id] = new Proxy(this.models[id], _modelProxyHandler);
|
||||
}
|
||||
return this.proxies[id];
|
||||
};
|
||||
|
||||
Model.Scope.prototype.create = function (data) {
|
||||
var modelData = data ? data : {};
|
||||
var m = this.get(modelData.id);
|
||||
for (var key in modelData) {
|
||||
if (key === 'id') continue;
|
||||
m.set(key, modelData[key]);
|
||||
}
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
Model.Scope.prototype.exists = function (id) {
|
||||
return this.models[id] !== undefined;
|
||||
};
|
||||
|
||||
Model.Scope.prototype.instanceOf = function (collection) {
|
||||
return collection instanceof Model || collection.target instanceof Model;
|
||||
};
|
||||
|
||||
Model.Scope.prototype.guid = function guid() {
|
||||
return _randomString(10);
|
||||
};
|
||||
|
||||
Model.Scope.prototype.reset = function () {
|
||||
this.models = {};
|
||||
this.proxies = {};
|
||||
delete this._cloudStore;
|
||||
};
|
||||
|
||||
module.exports = Model;
|
||||
Reference in New Issue
Block a user