superdata
Version:
A lightweight data layer module motivated by extjs' data layer. It can be used with any client-side framework.
176 lines (146 loc) • 4.1 kB
JavaScript
/*jslint node: true */
;
var createModelObject = require("./modelObject");
module.exports = function createModel(options) {
if (!options) {
options = {};
}
if (!options.idField) {
throw new Error("options.idField is mandatory!");
}
if (!options.fields) {
throw new Error("options.fields is mandatory!");
}
if (!options.proxy) {
throw new Error("options.proxy is mandatory!");
}
if(options.belongsTo && !Array.isArray(options.belongsTo)) {
throw new Error("options.belongsTo has to be an array!");
}
if(Array.isArray(options.belongsTo)) {
for(var i=0; i<options.belongsTo.length; i += 1) {
if(!options.fields[options.belongsTo[i]]) {
throw new Error("options.belongsTo has to contain field names!");
}
}
}
var idField = options.idField;
var fields = options.fields;
var proxy = options.proxy;
var belongsTo = options.belongsTo || [];
//options.fields should be an array of objects
//the objects should describe the fields:
// - name
// - type
// - validators
// - mapping
// - defaultValue
// - beforeChange
// - afterChange
function checkReferences(belongsToValues) {
for(var i = 0; i < belongsTo.length; i += 1) {
if(!belongsToValues[belongsTo[i]]) {
return false;
}
}
return true;
}
function checkReferenceTypes(belongsToValues) {
for(var i = 0; i < belongsTo.length; i += 1) {
if(typeof belongsToValues[belongsTo[i]] !== fields[belongsTo[i]].type) {
return false;
}
}
return true;
}
function list(options, belongsToValues, callback) {
if(!callback) {
callback = belongsToValues;
belongsToValues = undefined;
}
if(!checkReferences(belongsToValues)) {
return callback("belongsToValues has to have properties for references given in belongsTo");
}
if(!checkReferenceTypes(belongsToValues)) {
return callback("Each property of belongsToValues has to match type with corresponding property of options.fields");
}
var filters = {};
for(var i=0; i<belongsTo.length; i += 1) {
filters[belongsTo[i]] = belongsToValues[belongsTo[i]];
}
proxy.read(options, filters, function(err, result) {
if (err) {
return callback(err);
}
var data = [];
result.items.forEach(function(item) {
data.push(createModelObject({
model: model,
data: item
}));
});
var resultObj = {
items: data,
count: result.count
};
callback(null, resultObj);
});
}
function load(id, belongsToValues, callback) {
if(!callback) {
callback = belongsToValues;
belongsToValues = undefined;
}
if(!checkReferences(belongsToValues)) {
return callback("belongsToValues has to have properties for references given in belongsTo");
}
if(!checkReferenceTypes(belongsToValues)) {
return callback("Each property of belongsToValues has to match type with corresponding property of options.fields");
}
var filters = {};
for(var i=0; i<belongsTo.length; i += 1) {
filters[belongsTo[i]] = belongsToValues[belongsTo[i]];
}
proxy.readOneById(id, filters, function(err, result) {
if (err) {
return callback(err);
}
var modelObject = createModelObject({
model: model,
data: result
});
callback(null, modelObject);
});
}
function create(modelValues, callback) {
if(!checkReferences(modelValues)) {
return callback("modelValues has to have properties for references given in belongsTo");
}
if(!checkReferenceTypes(modelValues)) {
return callback("Each property of modelValues contained by belongsTo has to match type with corresponding property of options.fields");
}
var filters = {};
for(var i = 0; i < belongsTo.length; i += 1) {
filters[belongsTo[i]] = modelValues[belongsTo[i]];
}
proxy.createOne(modelValues, filters, function(err, result) {
if (err) {
return callback(err);
}
callback(null, createModelObject({
model: model,
data: result
}));
});
}
var model = Object.freeze({
fields: fields,
proxy: proxy,
idField: idField,
belongsTo: belongsTo,
list: list,
load: load,
create: create
});
return model;
};