alamid-schema
Version:
Extendable mongoose-like schemas for node.js and the browser
178 lines (148 loc) • 4.02 kB
JavaScript
;
var processDefinition = require("./processDefinition.js");
var merge = require("./merge.js");
var slice = Array.prototype.slice;
function Schema() {
Schema.prototype.constructor.apply(this, arguments);
}
/**
* Creates a new Schema.
*
* @param {string} [name=Anonymous]
* @param {string|Object} definition
*/
Schema.prototype.constructor = function (name, definition) {
var schema;
if (arguments.length === 1) {
name = "Anonymous";
definition = arguments[0];
}
this.name = name;
this.definition = definition;
schema = processDefinition(definition);
this.fields = schema.fields;
this.types = schema.types;
};
/**
* Returns a subset of the current schema with the given fields. You may pass an array with fields
* or just the keys as arguments.
*
* @param {string|Array} key1
* @param {string} key2
* @param {string} key3
* @returns {Schema}
*/
Schema.prototype.only = function (key1, key2, key3) {
var subset = Object.create(this);
var fields;
if (arguments.length === 1 && Array.isArray(key1)) {
fields = key1;
} else {
fields = slice.call(arguments);
}
subset.fields = fields;
return subset;
};
/**
* Returns a subset of the current schema without the given keys. You may pass an array with fields
* or just the keys as arguments.
*
* @param {string|Array} key1
* @param {string} key2
* @param {string} key3
* @returns {Schema}
*/
Schema.prototype.except = function (key1, key2, key3) {
var subset = Object.create(this);
var fields;
if (arguments.length === 1 && Array.isArray(key1)) {
fields = key1;
} else {
fields = slice.call(arguments);
}
subset.fields = this.fields.filter(function (value) {
return fields.indexOf(value) === -1;
});
return subset;
};
/**
* Returns all writable fields as array.
*
* @returns {Array}
*/
Schema.prototype.writableFields = function () {
var self = this;
return this.fields.filter(function (key) {
return self.definition[key].writable === true;
});
};
/**
* Returns a schema with only writable fields.
*
* @returns {Schema}
*/
Schema.prototype.writable = function () {
return this.only(this.writableFields());
};
/**
* Returns all writable Fields as array.
*
* @returns {Array}
*/
Schema.prototype.readableFields = function () {
var self = this;
return this.fields.filter(function (key) {
return self.definition[key].readable === true;
});
};
/**
* Returns a Schema with only readable fields.
*
* @returns {Schema}
*/
Schema.prototype.readable = function () {
return this.only(this.readableFields());
};
/**
* Creates a new schema that inherits from the current schema. Field definitions are merged
* where appropriate. If a definition conflicts with the parent definition, the child's definition supersedes.
*
* @param {string} [name=Anonymous]
* @param {Object} definition
* @returns {Schema}
*/
Schema.prototype.extend = function (name, definition) {
if (arguments.length === 1) {
name = "Anonymous";
definition = arguments[0];
}
return new Schema(name, merge(this.definition, definition));
};
/**
* Removes all properties that are not defined in this.fields.
* Will not remove properties that are inherited from the prototype.
*
* @param {Object} model
*/
Schema.prototype.strip = function (model) {
var fields = this.fields;
Object.keys(model)
.forEach(function (key) {
if (fields.indexOf(key) === -1) {
delete model[key];
}
});
};
/**
* Calls the given function with the Schema as first argument and the given config (optionally). Plugins can be used
* to hook into class methods by overriding them.
*
* @param {Function} plugin
* @param {Object=} config
* @returns {Function}
*/
Schema.use = function (plugin, config) {
plugin(this, config);
return this;
};
module.exports = Schema;