Socket
Socket
Sign inDemoInstall

alamid

Package Overview
Dependencies
152
Maintainers
2
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.0 to 0.8.0

.idea/.name

231

lib/shared/EventEmitter.class.js

@@ -0,1 +1,5 @@

"use strict";
var Class = require("nodeclass").Class;
// Copyright Joyent, Inc. and other Node contributors.

@@ -23,5 +27,3 @@ // Translated to class module by Johannes Ewald.

var isArray = Array.isArray?
Array.isArray:
function isArray(obj) {return Object.prototype.toString.call(obj) === '[object Array]';};
var isArray = Array.isArray ? Array.isArray: function isArray(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; };

@@ -32,24 +34,36 @@ // By default EventEmitters will print a warning if more than

//
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
var defaultMaxListeners = 10;
var Class = {
"__events": {},
"setMaxListeners": function setMaxListeners(n) {
if (!this.__events) {
this.__events = {};
var EventEmitter = new Class("EventEmitter", {
/**
* Use this function to increase the number of max listener. Default is 10.
* If you pass 0 this means unlimited number of listeners is possible.
*
* @param {number} n
*/
"setMaxListeners": function (n) {
if (!this._events) {
this._events = {};
}
this.__events.maxListeners = n;
this._maxListeners = n;
},
"emit": function emit(type) {
/**
* @param {string} type
* @param {Error} err
* @return {boolean}
*/
"emit": function (type, err) {
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this.__events || !this.__events.error ||
(isArray(this.__events.error) && !this.__events.error.length)) {
if (arguments[1] instanceof Error) {
throw arguments[1]; // Unhandled 'error' event
//Check if there is at least one handler for event-type error defined
if (!this._events || !this._events.error || (isArray(this._events.error) && !this._events.error.length)) {
if (err instanceof Error) {
throw err; // Unhandled 'error' event
} else {
throw new Error("Uncaught, unspecified 'error' event.");
}
return false;

@@ -59,6 +73,9 @@ }

if (!this.__events) {
if (!this._events) {
return false;
}
var handler = this.__events[type];
var handler = this._events[type];
//Return false if no handler is defined for given event-type.
if (!handler) {

@@ -68,3 +85,8 @@ return false;

var args,
listeners;
//If there is one defined event-handler executed it with given arguments.
if (typeof handler === 'function') {
switch (arguments.length) {

@@ -83,23 +105,39 @@ // fast cases

default:
var args = Array.prototype.slice.call(arguments, 1);
//Use Array's prototype slice method because arguments is not a real array. So it has no slice method.
//@see https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments
args = Array.prototype.slice.call(arguments, 1);
handler.apply(this, args);
}
return true;
//Check if there are many handlers and execute them.
} else if (isArray(handler)) {
var args = Array.prototype.slice.call(arguments, 1);
var listeners = handler.slice();
args = Array.prototype.slice.call(arguments, 1);
listeners = handler.slice();
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i].apply(this, args);
}
return true;
} else {
return false;
}
},
/**
* @param {string} type
* @param {function} listener
* @return {EventEmitter}
*/
"addListener": function addListener(type, listener) {
if ('function' !== typeof listener) {
throw new Error('addListener only takes instances of Function');
}
if (!this.__events) {
this.__events = {};
if (!this._events) {
this._events = {};
}

@@ -109,38 +147,65 @@

// adding it to the listeners, first emit "newListeners".
this.emit('newListener', type, listener);
this.emit('newListener', type, typeof listener.listener === 'function' ? listener.listener : listener);
if (!this.__events[type]) {
if (!this._events[type]) {
// Optimize the case of one listener. Don't need the extra array object.
this.__events[type] = listener;
} else if (isArray(this.__events[type])) {
this._events[type] = listener;
} else if (isArray(this._events[type])) {
// If we've already got an array, just append.
this.__events[type].push(listener);
this._events[type].push(listener);
// Check for listener leak
if (!this.__events[type].warned) {
var m;
if (this.__events.maxListeners !== undefined) {
m = this.__events.maxListeners;
} else {
m = defaultMaxListeners;
}
if (m && m > 0 && this.__events[type].length > m && console.error && console.trace) {
this.__events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this.__events[type].length);
console.trace();
}
}
} else {
// Adding the second element, need to change to array.
this.__events[type] = [this.__events[type], listener];
this._events[type] = [this._events[type], listener];
}
// Check for listener leak
if (isArray(this._events[type]) && !this._events[type].warned) {
var m;
if (this._maxListeners !== undefined) {
m = this._maxListeners;
} else {
m = defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
var errorMessage =
'(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.'
this._events[type].warned = true;
console && console.error && console.error(errorMessage, this._events[type].length);
console.trace();
}
}
return this;
},
/**
* @see {EventEmitter.addListener}
*
* @param {string} type
* @param {function} listener
* @return {EventEmitter}
*/
"on": function (type, listener) {
return this.addListener(type, listener);
},
/**
* @param {string} type
* @param {function} listener
* @return {EventEmitter}
*/
"once": function(type, listener) {
if ('function' !== typeof listener) {

@@ -151,2 +216,3 @@ throw new Error('.once only takes instances of Function');

var self = this;
function g() {

@@ -162,3 +228,10 @@ self.removeListener(type, g);

},
"removeListener": function removeListener(type, listener) {
/**
* @param {string} type
* @param {function }listener
* @return {EventEmitter}
*/
"removeListener": function (type, listener) {
if ('function' !== typeof listener) {

@@ -169,13 +242,21 @@ throw new Error('removeListener only takes instances of Function');

// does not use listeners(), so no side effect of creating __events[type]
if (!this.__events || !this.__events[type]) {
if (!this._events || !this._events[type]) {
return this;
}
var list = this.__events[type];
// does not use listeners(), so no side effect of creating _events[type]
if (!this._events || !this._events[type]) {
return this;
}
var list = this._events[type];
if (isArray(list)) {
var position = -1;
for (var i = 0, length = list.length; i < length; i++) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
(list[i].listener && list[i].listener === listener))
{
position = i;

@@ -185,2 +266,3 @@ break;

}
if (position < 0) {

@@ -190,8 +272,5 @@ return this;

list.splice(position, 1);
if (list.length == 0) {
delete this.__events[type];
}
} else if (list === listener ||
(list.listener && list.listener === listener)) {
delete this.__events[type];
} else if (list === listener || (list.listener && list.listener === listener)) {
delete this._events[type];
}

@@ -201,5 +280,11 @@

},
/**
* @param {string} type
* @return {EventEmitter}
*/
"removeAllListeners": function removeAllListeners(type) {
if (arguments.length === 0) {
this.__events = {};
this._events = {};
return this;

@@ -209,4 +294,4 @@ }

// does not use listeners(), so no side effect of creating __events[type]
if (type && this.__events && this.__events[type]) {
this.__events[type] = null;
if (type && this._events && this._events[type]) {
this._events[type] = null;
}

@@ -216,17 +301,25 @@

},
/**
* @param {string} type
* @return {Array.<function>}
*/
"listeners": function listeners(type) {
if (!this.__events) {
this.__events = {};
if (!this._events) {
this._events = {};
}
if (!this.__events[type]) {
this.__events[type] = [];
if (!this._events[type]) {
this._events[type] = [];
}
if (!isArray(this.__events[type])) {
this.__events[type] = [this.__events[type]];
if (!isArray(this._events[type])) {
this._events[type] = [this._events[type]];
}
return this.__events[type];
return this._events[type];
}
};
});
Class.on = Class.addListener;
module.exports = EventEmitter;

@@ -1,30 +0,151 @@

var typeOf = require('./typeOf.js'),
servicesAdapter = require('misc/servicesAdapter.js');
"use strict";
var acceptedFunctions = [Number, String, Boolean, Date, Array, Object],
acceptedFunctionsLiteral = ['Number', 'String', 'Boolean', 'Date', 'Array', 'Object'];
var nodeclass = require("nodeclass"),
is = nodeclass.is,
Class = nodeclass.Class,
NodeClass = nodeclass.Class,
EventEmitter = require('./EventEmitter.class.js'),
modelStatics = require("./modelStatics.js");
var typeOf = require("./helpers/typeOf.js"),
log = require("./logger.js").get("shared"),
schemaHelpers = require("./helpers/schemaHelpers.js"),
validate = require("./validator.js").validate,
schemas = require("./registries/schemaRegistry.js"),
services = require("./registries/serviceRegistry.js"),
ModelCollection = require("./ModelCollection.class.js"),
modelCache = require("./modelCache.js"),
config = require("./config.js"),
environment = require("./environment.js"),
RemoteService = require("../client/RemoteService.js");
function noop() {}
function getFunctionName(func) {
var name;
/**
* @class Model
* @type {Class}
* @extends EventEmitter
*/
var Model = new Class("Model", {
if (func.name === undefined) {
name = func.toString();
name = name.substr('function '.length + 1);
name = name.match(/^[^\(]*/)[0];
} else {
name = func.name;
}
Extends: EventEmitter,
return name;
}
/**
* @event
* @name Model#change
*/
var Extends = require('./EventEmitter.class.js');
var Class = {
"init": function init(id) {
this._id = id || null;
this.Super();
/**
* @event
* @name Model#save
*/
/**
* @event
* @name Model#delete
*/
/**
* @event
* @name Model#save
*/
/**
* @private
* @type {Object}
*/
__parentIds: {},
/**
* @private
* @type {String}
*/
__url : null,
/**
* @private
* @type {Array}
*/
__keys: null,
/**
* @private
* @type {Function}
*/
__defaults: null,
/**
* @private
* @type {Function}
*/
__attributes: null,
/**
* @private
* @type {Function}
*/
__changed: null,
/**
* @private
* @type {Object}
*/
__schema: null,
/**
* @private
* @type {Object}
*/
__sharedSchema : null,
/**
* @protected
* @type {Boolean}
*/
_casting: true,
/**
* @protected
* @type {Object}
*/
_service: null,
/**
* @protected
* @type {String|Number}
*/
_id: null,
/**
* @protected
* @type {Boolean}
*/
muted: false,
/**
* Create a new Model-Instance
* @construct
* @param {String|Number} id
*/
init: function init(id) {
this.__url = this.Instance.constructor.url || null;
if(id !== undefined && id !== null){
this.__setId(id);
}
var url = this.__url,
schema = schemas.getSchema(url),
sharedSchema = schemas.getSchema(url, "shared"),
service;
//load schemas
if(schema !== null) {
this.setSchema(schema);
}
if(sharedSchema !== null) {
this.setSchema(sharedSchema, "shared");
}
if(config.useCasting === undefined || config.useCasting === false) {
this._casting = true;
}
//load service
service = services.getService(url);
if(service !== null) {
this.setService(service);
}
},
"__init": function __init() { // used by the init function and removeAll since they act similarly
__reset: function() { // used by the init function and removeAll since they act similarly
function Attributes() {}

@@ -37,87 +158,260 @@ function Changed() {}

},
"__keys": null,
"__defaults": null,
"__attributes": null,
"__changed": null,
"_casting": false,
"_service": null,
"_validators": null,
"_id": null,
"muted": false,
"getId": function () {
__setId : function(id) {
if(this.__parentIds[this.__url] === undefined) {
this.__parentIds[this.__url] = id;
}
return this._id = id;
},
/**
* get ID of active model
* @return {String}
*/
getId: function () {
return this._id;
},
"__processResponse": function (response) {
var err,
/**
* set ids of parent models
* @param {!Object} parentIds
*/
setParentIds : function(parentIds) {
//always append actual id
parentIds[this.__url] = this._id;
this.__parentIds = parentIds;
},
/**
* set a single parent id
* @param {!String} parentName
* @param {!String|!Number} parentId
*/
setParentId : function(parentName, parentId) {
this.__parentIds[parentName] = parentId;
},
/**
* get ids of parent models
* @return {Object}
*/
getParentIds : function() {
return this.__parentIds;
},
getParentId : function(parentName) {
return this.__parentIds[parentName];
},
setUrl : function(url) {
this.__url = url;
},
getUrl : function() {
return this.__url;
},
/**
* processes service-response according to jSend-spec
* { status : "success/fail/error", data : {}, message : "error message?" }
* @param {!Object} response
* @return {Error} err
* @private
*/
__processResponse: function (response) {
var err = null,
id,
ids,
model;
err = response.error || null;
id = response.id;
model = response.model;
if(typeof response !== "object" || response === null) {
return new Error("(alamid) Invalid Response: Object expected.");
}
if(response.status === "error") {
err = new Error(response.message || "An error occurred");
}
if(response.data !== undefined && response.status === "success") {
model = response.data;
//fetch special attributes
id = model.id;
ids = model.ids;
//delete special attributes to make set work
delete model.id;
delete model.ids;
}
if (!err) {
//set parent ids
if(ids !== undefined) {
this.__setParentIds(ids);
}
//set id
if (id !== undefined) {
this._id = id;
this.__setId(id);
}
//set model data
if (model) {
try {
this.set(model);
} catch (e) {
err = e;
}
this.set(model); // this may throw an exception
//append special attributes again to keep original response
model.id = id;
model.ids = ids;
}
}
return err;
},
"_setDefaults": function (defaults) {
var key;
/**
* set Schema to be used with model
* if no schema is passed, the schema will be auto-loaded
* @param {!Object} schema
* @param {String} schemaType (optional) shared
*/
setSchema: function (schema, schemaType) {
var key,
fieldDefinition,
type;
if(schemaType === "shared") {
this.__sharedSchema = schema;
}
else {
this.__schema = schema;
}
this.__keys = [];
for (key in defaults) {
if (typeof key === 'object'
|| (typeof key === 'function'
&& acceptedFunctions.indexOf(key) === -1)
) {
throw new TypeError('A model can only contain native types.'
+ '\nIf you want to save a reference, you should store the ID');
this.__defaults = {};
this.__types = {};
for (key in schema) {
if(schema.hasOwnProperty(key)){
this.__keys.push(key);
fieldDefinition = schema[key];
//determine supported types
type = schemaHelpers.determineType(fieldDefinition);
if(fieldDefinition.default === undefined) {
fieldDefinition.default = null;
}
this.__types[key] = type;
//defaults can be functions
if(typeof fieldDefinition.default === "function") {
this.__defaults[key] = fieldDefinition.default();
}
else {
this.__defaults[key] = fieldDefinition.default;
}
}
this.__keys.push(key);
}
this.__defaults = defaults;
this.__init();
this.__reset();
},
"set": function set(key, value) {
/**
* set the service the model should use
* @param {!Object|Function} service
*/
setService : function(service) {
this._service = service;
},
/**
* Cast value from actualType to expectedType
*
* @param value
* @param actualType
* @param expectedType
* @return {*}
* @private
*/
__doCast : function(value, actualType, expectedType) {
var caster = {
String : {
Date : function(value) {
var resDate = new Date(value);
if(resDate.toString() !== "Invalid Date") {
return resDate;
}
return null;
},
Number : function(value) {
var num = parseFloat(value);
if(Number.isNaN(num)){
return false;
}
return num;
}
},
Number : {
Date : function(value) {
//detected float!
if(value % 1 !== 0) {
return null;
}
var resDate = new Date();
resDate.setTime(value);
return resDate;
},
String : function(value) {
return String(value);
}
},
Date : {
String : function(value) {
return String(value);
},
Number : function(value) {
return value.getTime();
}
}
};
if(caster[actualType] !== undefined && caster[actualType][expectedType] !== undefined) {
return caster[actualType][expectedType](value);
}
return null;
},
/**
* Set a single or multiple values
*
* use like .set("name", "octo");
* or
* .set({ name : "octo", age : 3 });
*
* @param {String|Object} key
* @param {*} value
*/
set: function set(key, value) {
var map,
mapKey,
self = this;
function doSet(key, value) {
var castingFunc,
defaultValue,
expectedType,
var expectedType,
actualType;
if (self.__keys.indexOf(key) === -1) {
throw new Error('Unknown property ' + key);
if(key === "id") {
throw new Error("(alamid) Setting ids via 'set' is not allowed. Use construct!");
}
//we always want null instead of undefined
if (value === null || value === undefined) {
value = null;
} else {
defaultValue = self.__defaults[key];
if (defaultValue !== undefined && defaultValue !== null) {
expectedType = typeOf(defaultValue);
}
if (Object.keys(self.__types).indexOf(key) === -1) {
throw new Error('(alamid) Unknown property ' + key);
}
else {
expectedType = self.__types[key];
if (expectedType !== undefined && expectedType !== null) {
actualType = typeOf(value);
if (expectedType === 'Function') {
expectedType = getFunctionName(defaultValue);
}
//type-checking
if (actualType !== expectedType) {
//do cast!
if (self._casting) {
castingFunc = acceptedFunctionsLiteral.indexOf(expectedType);
castingFunc = acceptedFunctions[castingFunc];
if (castingFunc === Date) {
value = new Date(value);
} else {
value = castingFunc(value);
}
} else {
value = self.__doCast(value, actualType, expectedType);
}
else {
throw new TypeError("Cannot set '" + key + "' to " +

@@ -132,38 +426,53 @@ value + ". '" + key + "' must be type of " + expectedType + ".");

//setting multiple at once
if (arguments.length === 1 && typeof key === 'object') {
map = key;
for (key in map) { if(map.hasOwnProperty(key)) {
doSet(key, map[key]);
}}
for (mapKey in map) {
if(map.hasOwnProperty(mapKey)) {
doSet(mapKey, map[mapKey]);
}
}
} else {
doSet(key, value);
}
this.emit('change');
},
/**
* simple emit proxy taking care of muting
* @param {!String} event
*/
emit : function(event) {
if (!this.muted) {
this.Super.emit('change');
this.Super.emit(event);
}
},
"get": function get(key) {
/**
* return a specific key of the model or all keys at once
* use like
* .get("name") to retrieve just the name.
* or
* .get() to retrieve all model-attributes as object
*
* @param {String} key
* @return {*}
*/
get: function get(key) {
var result,
i, l;
i, l, keysToLoad;
function checkSingleResult(result) {
if (typeof result === 'function') { // IF TRUE: Its a constructor function, thus a default value
result = null;
}
return result;
}
//we want to retrieve all
if (arguments.length === 0) {
arguments = this.__keys;
keysToLoad = this.__keys;
}
else {
keysToLoad = arguments;
}
if (arguments.length === 1) {
result = this.__changed[key];
result = checkSingleResult(result);
} else {
}
else {
result = {};
for (i = 0, l = arguments.length; i < l; i++) {
key = arguments[i];
result[key] = checkSingleResult(this.__changed[key]);
for (i = 0, l = keysToLoad.length; i < l; i++) {
key = keysToLoad[i];
result[key] =this.__changed[key];
}

@@ -174,5 +483,12 @@ }

},
"escape": function escape(key) {
/**
* Escape a given attribute or all attributes at once
* Function returns the given attributes
* @param {!String} key
* @return {*}
*/
escape: function escape(key) {
var result,
i, l;
i, l,
keysToEscape;

@@ -201,10 +517,13 @@ function doEscape(value) {

if (arguments.length === 0) {
arguments = this.__keys;
keysToEscape = this.__keys;
}
if (arguments.length === 1) {
else {
keysToEscape = arguments;
}
if (keysToEscape.length === 1) {
result = doEscape(this.__changed[key]);
} else {
result = {};
for (i = 0, l = arguments.length; i < l; i++) {
key = arguments[i];
for (i = 0, l = keysToEscape.length; i < l; i++) {
key = keysToEscape[i];
result[key] = doEscape(this.__changed[key]);

@@ -216,3 +535,13 @@ }

},
"remove": function remove(key) {
/**
* Resets the attribute with the given key to the defaults
* You can pass many keys as arguments
*
* .remove("name");
* or
* .remove("name","age");
*
* @param {!String} key
*/
remove: function remove(key) {
var i, l;

@@ -225,13 +554,17 @@

}
if (!this.muted) {
this.Super.emit('change');
}
this.emit('change');
},
"removeAll": function removeAll() {
this.__init();
if (!this.muted) {
this.Super.emit('change');
}
/**
* Remove all attribute and reset the class to the init-state
*/
removeAll: function removeAll() {
this.__reset();
this.emit('change');
},
"unset": function unset(key) {
/**
* Unset the given key and revert it to the last accepted state
* You can pass many keys at once to unset multiple keys
* @param {!String} key
*/
unset: function unset(key) {
var i, l;

@@ -243,18 +576,28 @@

}
if (!this.muted) {
this.Super.emit('change');
}
this.emit('change');
},
"unsetAll": function unsetAll() {
/**
* Unset all attributes at once
* Reverts all attributes to the last accepted state
*/
unsetAll: function unsetAll() {
var key,
changed = this.__changed;
for (key in changed) { if (changed.hasOwnProperty(key)) {
delete changed[key];
}}
if (!this.muted) {
this.Super.emit('change');
for (key in changed) {
if (changed.hasOwnProperty(key)) {
delete changed[key];
}
}
this.emit('change');
},
"hasChanged": function hasChanged(key) {
/**
* Check if a attribute has changed
* You can check multiple attributes by passing many keys as arguments
*
* @param {!String} key
* @return {Boolean}
*/
hasChanged: function hasChanged(key) {
var result = false,

@@ -279,6 +622,9 @@ strict = false,

arr = this.__keys;
} else if(argsLength === 1 && typeof key === 'boolean') {
}
else if(argsLength === 1 && typeof key === 'boolean') {
strict = true;
arr = this.__keys;
} else {
}
else {
arr = arguments;
if (typeof arguments[argsLength - 1] === 'boolean') {

@@ -288,9 +634,10 @@ strict = arguments[argsLength - 1];

}
arr = arguments;
}
if (strict) {
checkFunc = doStrictCheck;
} else {
}
else {
checkFunc = doNormalCheck;
}
for (i = 0, l = arr.length; i < l; i++) {

@@ -306,3 +653,12 @@ key = arr[i];

},
"isDefault": function isDefault(key) {
/**
* Check if value equals the default value
* pass true as last argument to enable strict mode
* strict mode checks if the value is the default value and is initial (has never been changed)
*
* @param {!String} key
* @params {Boolean} strict
* @return {Boolean}
*/
isDefault: function isDefault(key) {
var result = false,

@@ -323,4 +679,3 @@ strict = false,

function doStrictCheck() {
return !changed.hasOwnProperty(key)
&& !attributes.hasOwnProperty(key);
return !changed.hasOwnProperty(key) && !attributes.hasOwnProperty(key);
}

@@ -330,6 +685,9 @@

arr = this.__keys;
} else if(argsLength === 1 && typeof key === 'boolean') {
}
else if(argsLength === 1 && typeof key === 'boolean') {
strict = true;
arr = this.__keys;
} else {
}
else {
arr = arguments;
if (typeof arguments[argsLength - 1] === 'boolean') {

@@ -339,3 +697,2 @@ strict = arguments[argsLength - 1];

}
arr = arguments;
}

@@ -357,105 +714,137 @@ if (strict) {

},
"getDefaults": function getDefaults() {
/**
* returns the default-values
* @return {Object}
*/
getDefaults: function () {
return this.__defaults;
},
"toJSON": function toJSON() {
var keys = this.__keys,
key,
result = {},
i, l;
/**
* Get the object-re-presentation of the model
*
* @return {*}
*/
toObject : function() {
var obj = this.get(),
key;
function doEscape(value) {
if (value === undefined || value === null) {
return null;
} else if (typeof value === 'function') { // IF TRUE: Its a constructor function, thus a default value
return null;
} else if (value instanceof Date) {
return value.getTime();
} else {
return value;
for (key in obj) {
if(obj.hasOwnProperty(key)){
if(obj[key] === null) {
delete obj[key];
}
}
}
for (i = 0, l = keys.length; i < l; i++) {
key = keys[i];
result[key] = doEscape(this.__changed[key]);
}
return result;
return obj;
},
"validate": function validate(clientOnly, callback) {
var validators = this._validators,
type,
i = 0,
self = this,
finalResult = {
"result": false
};
/**
* Get the object-serialized as JSON
*
* @return {*}
*/
toJSON: function () {
return JSON.stringify(this.get());
},
/**
* Validate the Model on client- and serverside
*
* @param {!Boolean} remote Pass false if you want to disable remote-validation
* @param {Function} callback
*/
validate: function (remote, callback) {
function finish() {
if (finalResult.client) {
finalResult.result = finalResult.client.result === true;
}
if (finalResult.server) {
finalResult.result = finalResult.server.result === true;
}
if (!self.muted) {
self.Super.emit('validate', finalResult);
}
callback(finalResult);
if(arguments.length === 1) {
callback = arguments[0] || noop;
remote = true;
}
function onValidationResult(result) {
finalResult[type] = result;
if (result.result === true) {
doValidation();
} else {
finish();
}
var schema = this.__schema,
sharedSchema = this.__sharedSchema;
if(schema !== null && sharedSchema !== null) {
validate(sharedSchema, schema, this.__url, this.get(), remote, callback);
}
else{
throw new Error("(alamid) No schema defined for model");
}
},
/**
* Call the passed service function with the given params
* This functions takes care of sync and async service-definition
*
* @param {Function} serviceFunction
* @param {Boolean} remote
* @param {Object} model
* @param {Object} ids
* @param {Object} data
* @param {Function} callback
* @private
*/
__callService : function(serviceFunction, remote, model, ids, data, callback) {
function doValidation() {
if (i === 0) {
type = 'client';
} else if (i === 1 && !clientOnly) {
type = 'server';
} else {
finish();
var args = Array.prototype.slice.call(arguments, 0),
method = args[1];
//the last param is callback dude!
callback = args[args.length-1];
return;
//remove the first two elements, because it's the function itself and the method name
args.splice(0, 2);
//we don't have remote on server-services!
if(environment.isServer()) {
args.splice(0, 1);
}
else {
if(remote) {
//load remote-service-adapter for given method
args[0] = new RemoteService(this.__url)[method];
}
i++;
if (typeof validators[type] === "object") {
validators[type].validate(self._id, self.toJSON(), onValidationResult);
} else {
doValidation();
}
}
if (!validators || (clientOnly && !validators.client) ||
(!validators.client && !validators.server)) {
throw new Error('Cannot validate: There is no validator available.');
if (serviceFunction.length === args.length) {
serviceFunction.apply(this, args);
}
if (typeof clientOnly === 'function') {
callback = clientOnly;
clientOnly = undefined;
else if(serviceFunction.length === args.length - 1) {
//remove the final callback
args.splice(args.length-1, 1);
callback(serviceFunction.apply(this, args));
}
if (clientOnly === undefined) {
clientOnly = false;
else {
throw new Error("(alamid) Function '" +
String(serviceFunction).substr(0,String(serviceFunction).indexOf(")") + 1) + "' accepts unexpected number of arguments");
}
if (callback === undefined) {
callback = noop;
}
doValidation();
},
"fetch": function fetch(callback) {
/**
* Fetch the data for the model from the defined service (client and/or server)
* Fetch only works for models with existing IDs
*
* @param {Boolean} remote contact remoteService, defaults to true
* @param {function(err)} callback
*/
fetch: function fetch(remote, callback) {
var service = this._service,
id = this._id,
ids = this.getParentIds(),
self = this;
function onServiceResult(code, response) {
if(arguments.length === 1) {
callback = arguments[0] || noop;
remote = true;
}
function onServiceResponse(response) {
var err;
response = servicesAdapter.GET(code, response);
err = self.__processResponse(response);
try {
err = self.__processResponse(response);
} catch (err) {
err.message = "(alamid) Error while fetching the model: " + err.message;
callback(err, response);
return;
}
if (!err) {
self.emit("fetch");
}
callback(err);

@@ -465,56 +854,110 @@ }

if (!service) {
console.error('Cannot fetch model: There is no service available.');
callback(new Error("(alamid) Cannot fetch model: There is no service available."));
return;
}
if (!id && typeof console !== 'undefined') {
console.error('Cannot fetch model: You havent specified an id.');
if (id === undefined) {
callback(new Error("(alamid) Cannot fetch model: You have to set an ID"));
return;
}
callback = callback || noop;
service.GET(id, onServiceResult);
this.__callService(service.read, "read", remote, ids, onServiceResponse);
},
"save": function save(callback) {
/**
* Save or Update Model depending on an ID being set or not
*
* @param {Boolean} remote should a remote service be contacted (defaults to true)
* @param {function(err)} callback
*/
save: function save(remote, callback) {
var service = this._service,
id = this._id,
ids = this.getParentIds(),
self = this,
id = this._id,
method,
model = this.toJSON();
method = "update";
function onServiceResult(code, response) {
var err;
if(arguments.length === 1) {
callback = arguments[0] || noop;
remote = true;
}
response = servicesAdapter[method](code, response);
err = self.__processResponse(response);
if (!err) {
self.Super.emit("save");
}
callback(err);
if (id === null || typeof id === "undefined") {
method = "create";
}
if (!service) {
console.error('Cannot save model: There is no service available.');
if (!service || !service[method]) {
callback(new Error("(alamid) Cannot save model: There is no service available for '" + method + "'"));
return;
}
callback = callback || noop;
if (id === null || typeof id === "undefined") {
method = 'POST';
service.POST(model, onServiceResult);
} else {
method = 'PUT';
service.PUT(id, model, onServiceResult);
function onServiceResponse(response) {
var err,
event = {};
try {
err = self.__processResponse(response);
} catch (err) {
err.message = "(alamid) Error while updating the model: " + err.message;
callback(err, response);
return;
}
if (!err) {
//instance has not been part of the registry before -> store new instance
//cache only for newly CREATED / update instances should already be cached
if(method === "create" && modelCache.get(self.__url, id) !== undefined) {
modelCache.add(self.Instance);
}
self.emit("save");
//model is always attached for create and update
event.model = self.Instance;
if(method === "update") {
event.parentIds = response.id; //should be IDs later
event.data = response.data;
}
self.Instance.constructor.emit(method, event);
}
callback(err, response);
}
this.__callService(service[method], method, remote, ids, this.Instance, onServiceResponse);
},
"destroy": function destroy(callback) {
/**
* Calls the "delete" service, returning the status of the request (err)
* @param {Boolean} remote
* @param {!Function} callback
*/
delete: function (remote, callback) {
var service = this._service,
id = this._id,
ids = this.getParentIds(),
self = this;
function finish(err) {
if(arguments.length === 1) {
callback = arguments[0] || noop;
remote = true;
}
function onServiceResponse(response) {
var err,
event = {};
try {
err = self.__processResponse(response);
} catch (err) {
err.message = "(alamid) Error while deleting the model: " + err.message;
callback(err, response);
return;
}
if (!err) {
self.Super.emit("destroy");
self.emit("delete");
event.model = self.Instance;
self.Instance.constructor.emit("delete", event);
}

@@ -524,18 +967,19 @@ callback(err);

function onServiceResult(code, response) {
var err;
response = servicesAdapter.DELETE(code, response);
err = self.__processResponse(response);
finish(err);
if (!service) {
callback(new Error("(alamid) Cannot delete model: There is no service available."));
return;
}
callback = callback || noop;
if (service && id !== null) {
service.DELETE(id, onServiceResult);
} else {
finish(null);
if (!id) {
callback(new Error("(alamid) Cannot delete model: You have to set an ID."));
return;
}
this.__callService(service.delete, "delete", remote, ids, onServiceResponse);
},
"acceptCurrentState": function _acceptCurrentState() {
/**
* Accept the current state of the attributes
* If you have accepted a state, unset will never go beyond this state
*
* @private
*/
acceptCurrentState: function _acceptCurrentState() {
var key,

@@ -546,8 +990,77 @@ value,

for (key in changed) { if(changed.hasOwnProperty(key)) {
value = changed[key];
attributes[key] = value;
delete changed[key];
}}
for (key in changed) {
if (changed.hasOwnProperty(key)) {
value = changed[key];
attributes[key] = value;
delete changed[key];
}
}
},
/**
* Dispose Model
* Removes all event listeners
*/
dispose : function() {
this.Super.emit("dispose");
this.Super.removeAllListeners();
},
/**
* check if a given descriptor is a child class of "Model"
*
* @param descriptor
* @return {Boolean}
*/
$extendsModel : function(descriptor) {
while(descriptor !== undefined) {
if(descriptor.Extends === Model) {
return true;
}
descriptor = descriptor.Extends;
}
return false;
},
/** Create a new Model based on the Model-Class
*
* Model.define("Octocat", {
* - your model definition goes here -
* });
*
*
* @static
* @param descriptor
* @return {*}
*/
$define : function(name, descriptor) {
var eventEmitter = new EventEmitter(),
attribute;
for(attribute in eventEmitter) {
if(eventEmitter.hasOwnProperty(attribute)) {
descriptor["$"+attribute] = eventEmitter[attribute];
}
}
if(descriptor.Extends === undefined) {
descriptor.Extends = Model;
}
else {
if(!Model.extendsModel(descriptor)) {
throw new Error("(alamid) '" + name + "' doesn't extend Model.");
}
}
descriptor.$find = modelStatics.find;
descriptor.$findById = modelStatics.findById;
descriptor.$url = descriptor.$url.toLowerCase();
return new NodeClass(name, descriptor);
}
};
});
module.exports = Model;

@@ -1,21 +0,221 @@

var Extends = require('./EventEmitter.class.js');
"use strict";
var Class = {
"init": function init(modelClass) {
if (!modelClass) {
throw new Error('You havent passed a model class.A model collection needs a class that describes the '
+ 'the contained models')
var Class = require("nodeclass").Class,
Nodeclass = Class,
Collection = require("./Collection.class.js"),
_ = require("underscore");
var ModelCollection = new Class("ModelCollection", {
Extends: Collection,
/**
* @type Array
* @private
*/
__changeListeners: [],
/**
* @type Array
* @private
*/
__changeListenersModels: [],
/**
* @param {String} className
* @param {Object} descriptor
* @return {Function}
*/
$define: function (className, descriptor) {
descriptor.Extends = ModelCollection;
return new Nodeclass(className, descriptor);
},
/**
* @param {Class} ModelClass
* @param {array|Models} models
*
* @constructor
*/
init: function (ModelClass, models) {
this.Super(ModelClass);
if (models !== undefined) {
this.push(models);
}
},
"__modelClass": null,
"getModelClass": function getModelClass() {
/**
* @param {number} index
* @param {Model} model
* @return {ModelCollection}
*/
set: function (index, model) {
var models = this.Super._getElements();
if (models[index]) {
models[index].removeListener("change", this.__findChangeListener(models[index]));
}
model.on("change", this.__createChangeListener(model));
this.Super.set(index, model);
return this.Instance;
},
"_elements": [],
"muted": false,
"pop": function pop() {
if (!this.muted) {
this.Super.emit('change');
/**
* @return {Model}
*/
pop: function () {
var poppedModel = this.Super.pop(),
changeListener;
changeListener = this.__findChangeListener(poppedModel);
poppedModel.removeListener("change", changeListener);
return poppedModel;
},
/**
* @return {Model}
*/
shift: function () {
var shiftedModel = this.Super.shift(),
changeListener;
changeListener = this.__findChangeListener(shiftedModel);
shiftedModel.removeListener("change", changeListener);
return shiftedModel;
},
/**
* @param {Model} models
* @return {ModelCollection}
*/
push: function (models) {
var self = this;
if (_(models).isArray() === false) {
models = [models];
}
_(models).each(function addChangeListener(model, index) {
model.on("change", self.__createChangeListener(model));
});
this.Super.push(models);
return this.Instance;
},
/**
* @param {Model} models
* @return {ModelCollection}
*/
unshift: function (models) {
var self = this;
if (_(models).isArray() === false) {
models = [models];
}
_(models).each(function addChangeListener(model, index) {
model.on("change", self.__createChangeListener(model));
});
this.Super.unshift(models);
return this.Instance;
},
/**
* @param {string} modelAttribute
* @param {boolean} descending (optional)
* @return {ModelCollection}
*/
sortBy: function (modelAttribute, descending) {
var elements = this.Super._getElements(),
elementsLength = elements.length;
if (elements[0].get(modelAttribute) === undefined) {
throw new Error(
"(alamid) Unable to sort by " + modelAttribute + "." +
"Models do not have an attribute called " + modelAttribute + "."
);
}
elements = _(elements).sortBy(function sortModelBy(model, index) {
return model.get(modelAttribute);
});
if (descending === true) {
elements.reverse();
}
this.Super._setElements(elements);
this.Super.emit("sort");
return this.Instance;
},
/**
* Prepares all Collection-Models for Garbage-Collector
*/
dispose: function () {
var self = this;
this.Super.each(function disposeEachModel(model, index) {
model.removeListener("change", self.__findChangeListener(model));
});
this.Super._setElements([]);
},
/**
* @param {Model} model
* @return {function}
* @private
*/
__createChangeListener: function (model) {
var self = this;
function changeListener() {
self.Super.emit("change", model);
}
this.__changeListenersModels.push(model);
this.__changeListeners.push(changeListener);
return changeListener;
},
/**
* @param {Model} changeListenerModel
* @return {function}
* @private
*/
__findChangeListener: function (changeListenerModel) {
var changeListenerIndex;
_(this.__changeListenersModels).find(function findEventListenerIndex(model, index) {
if(changeListenerModel === model) {
changeListenerIndex = index;
return true;
}
});
return this.__changeListeners[changeListenerIndex];
}
};
});
module.exports = ModelCollection;
{
"name": "alamid",
"description": "Framework for RESTful JavaScript web applications that run both on the server- and clientside.",
"version": "0.1.0",
"repository": "git://github.com/pandaa/alamid.git",
"author": "pandaa",
"main": "./lib/core/index.js",
"keywords": ["client", "server", "framework", "rest", "web application"],
"engines": {
"node": "0.6.x"
},
"dependencies": {
"underscore": "1.1.x",
"async": "0.1.x",
"connect": "1.x",
"fshelpers": "git://github.com/pandaa/fshelpers.git",
"node2browser": "git://github.com/pandaa/node2browser.git",
"toSrc": "0.1.x",
"nodeclass": "git://github.com/pandaa/nodeclass.git"
},
"devDependencies": {
"expect.js": "0.1.x",
"mocha": "0.12.x"
}
"name": "alamid",
"description": "Framework for realtime JavaScript web applications that run both on the server- and clientside.",
"version": "0.8.0",
"repository": "git://github.com/peerigon/alamid",
"author": "peerigon <developers@peerigon.com>",
"main": "./lib/index.js",
"keywords": ["client", "server", "framework", "rest", "web application", "websockets", "realtime"],
"engines": {
"node": "< 0.9"
},
"dependencies": {
"underscore": "1.x",
"async": "0.x",
"connect": "2.x",
"winston": "0.x",
"fshelpers": "https://github.com/peerigon/fshelpers/tarball/v0.2.1",
"toSrc": "0.x",
"nodeclass": "https://github.com/peerigon/nodeclass/tarball/v0.2.4",
"nconf" : "0.5.1",
"socket.io" : "0.x",
"cookie" : "0.x",
"webpack": "0.6.x",
"raw-loader": "0.x",
"page": "1.3.x"
},
"devDependencies": {
"expect.js": "0.x",
"mocha": "1.x",
"xunit-file" : "*",
"rewire": "1.x",
"zombie" : "1.x",
"supertest" : "0.x",
"grunt-simple-mocha" : "0.x"
},
"scripts" : {
"test" : "grunt test-all"
}
}

@@ -1,6 +0,10 @@

alamid
========
![alamid-logo](http://alamidjs.com/img/alamid.0.jpg)
Framework for RESTful JavaScript web applications that run both on the server- and clientside.
Further documentation comming soon...
__node.js framework for JavaScript real-time applications.__
alamid is an exciting new framework for JavaScript real-time applications that run both on the client and on the server. It manages all the bundling and communication so you can focus on your stuff: your application.
The framework has been designed to ease offline-ability and component re-use. It leverages modern web technologies like WebSockets and provides a reasonable class-system that enables you to use inheritance and scopes in an intuitive way.
Inspired by great frameworks like backbone.js, mongoose and express and motivated by the sedulous node.js-community we've been working hard to create a framework that really fits your needs. It is totally free and open source. Try it out - we're curious about your feedback!

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc