Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bamboo

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bamboo - npm Package Compare versions

Comparing version 0.0.1-pre2 to 0.0.2

.travis.yml

275

model.js
var Emitter = require('emitter');
var ajax = require('superagent');
var xtend = require('xtend');
var ArrayModel = require('./array_model');
var Model = function(opt) {
var properties = Object.keys(opt);
var Model = function(schema, opt) {
opt = opt || {};
schema = schema || {};
var properties = Object.keys(schema);
// sync function for CRUD
var sync = opt.sync;
var Construct = function(initial) {

@@ -17,6 +23,35 @@ if (!(this instanceof Construct)) {

var self = this;
self.is_new = true;
// default state is saved
self._saved = true;
// basepath for the url
self.url_root = Construct.url_root;
if (initial) {
self.id = initial.id;
}
// url property can be used to overrride the model's url
var _url = undefined;
Object.defineProperty(self, 'url', {
get: function() {
// if user explicitly set, return their value
if (_url) {
return _url;
}
if (self.is_new()) {
return self.url_root;
}
return self.url_root + '/' + self.id;
},
set: function(val) {
_url = val;
}
});
properties.forEach(function(prop) {
var config = opt[prop];
var config = schema[prop];

@@ -28,4 +63,7 @@ var prop_val = (initial) ? initial[prop] : undefined;

// shit... so in this case, we don't need a submodel
// the issue is we have created a Model for each item
// but, our model does not get the proper url rool
if (typeof item === 'object') {
prop_val = ArrayModel(Model(item), prop_val, self);
prop_val = ArrayModel(Model(item, opt), prop_val, self);
}

@@ -37,22 +75,91 @@ else {

if (prop_val && config instanceof Function && !(prop_val instanceof config)) {
var is_constructor = (config instanceof Function);
if (prop_val && is_constructor && !(prop_val instanceof config)) {
prop_val = config(prop_val);
}
if (config.type === 'property') {
// create an object wrapper, this lets us emit events
// when internal properties are set
function inner_obj(key_path, props, initial) {
var properties = {};
initial = initial || {};
Object.keys(props).forEach(function(key) {
var path = key_path + '.' + key;
var value_holder = initial[key];
properties[key] = {
enumerable: true,
get: function() {
return value_holder;
},
set: function(val) {
var old = value_holder;
value_holder = val;
self.emit('change ' + path, val, old);
}
}
});
var proto = null;
return Object.create(proto, properties);
}
if (config instanceof Function) {
// see if it has keys
Object.defineProperty(self, prop, {
enumerable: false,
get: config.get
enumerable: true,
get: function() {
return prop_val;
},
set: function(val) {
var old = prop_val;
// this handles the case of setting via same object
// we don't need to call constructor
if (val instanceof config) {
prop_val = val
}
else {
prop_val = config(val);
}
self._saved = false;
self.emit('change ' + prop, prop_val, old);
}
});
function change_event() {
self.emit('change ' + prop);
return;
}
// user specified an inner object
// but don't do this for arrays
var keys = Object.keys(config);
if ( !(config instanceof Array) && keys.length > 0) {
// no value set by default
if (prop_val) {
prop_val = inner_obj(prop, config, prop_val);
}
config.depends.forEach(function(parent_prop) {
self.on('change ' + parent_prop, change_event);
// if the nothing above captured and config is a regular object
// see if it has keys
Object.defineProperty(self, prop, {
enumerable: true,
get: function() {
return prop_val;
},
set: function(val) {
var old = prop_val;
prop_val = inner_obj(prop, config, val);
self._saved = false;
self.emit('change ' + prop, prop_val, old);
}
});
return;
}
// if the nothing above captured and config is a single valueish
Object.defineProperty(self, prop, {

@@ -66,3 +173,4 @@ enumerable: true,

prop_val = val;
self.emit('change ' + prop, val, old);
self._saved = false;
self.emit('change ' + prop, prop_val, old);
}

@@ -75,2 +183,4 @@ });

Construct.url_root = opt.url_root;
Construct.prototype.toJSON = function() {

@@ -91,31 +201,41 @@ var self = this;

// if the model has an ID property, then it is not considered new
Construct.prototype.is_new = function() {
var self = this;
return !self.id;
};
// return true if the model state has been persistent to the server
// false for 'is_new()' or if a property has changed since last sync
Construct.prototype.is_saved = function() {
var self = this;
return !self.is_new() && self._saved;
};
Construct.prototype.save = function(cb) {
var self = this;
if (self.parent) {
return self.parent.save();
}
cb = cb || function() {};
if (self.is_new) {
return ajax.post(self.url).send(self).end(function(err, res) {
if (err) {
return cb(err);
}
var sync_opt = {
url: self.url,
method: 'PUT',
body: self
};
if (res.status !== 200) {
return cb(new Error(res.body.error || 'failed to save'));
}
var is_new = self.is_new();
sync_opt.method = is_new ? 'POST' : 'PUT';
self.is_new = false;
// id of the model should be the response
self.id = res.body.id;
self.url += '/' + self.id;
sync(sync_opt, function(err, result) {
if (err) {
return cb(err);
}
return cb(null);
});
}
// only expect id back if new
// for updating existing we don't do this?
if (is_new) {
self.id = result.id;
}
ajax.put(self.url).send(self).end(function(err, res) {
return cb(err);
return cb(null);
});

@@ -126,3 +246,14 @@ };

var self = this;
ajax.get(self.url).end(function(err, res) {
// nothing to fetch if we don't have an id
if (!self.id) {
return;
}
var sync_opt = {
url: self.url_root + '/' + self.id,
method: 'GET'
};
sync(sync_opt, function(err, result) {
if (err) {

@@ -132,11 +263,8 @@ return cb(err);

if (res.status !== 200) {
return cb(new Error('failed to fetch'));
// set our properties
for (var key in result) {
self[key] = result[key];
}
var val = Construct(res.body);
val.is_new = false;
val.url = self.url;
cb(null, val);
return cb(null);
});

@@ -148,7 +276,12 @@ };

// model was never saved to server
if (self.is_new) {
if (self.is_new()) {
return;
}
ajax.del(self.url).end(function(err, res) {
var sync_opt = {
url: self.url,
method: 'DELETE'
};
sync(sync_opt, function(err) {
if (err) {

@@ -163,2 +296,54 @@ return cb(err);

/// Class functions
// get a single Model instance by id
Construct.get = function(id, cb) {
var self = this;
var sync_opt = {
url: self.url_root + '/' + id,
method: 'GET'
};
sync(sync_opt, function(err, result) {
if (err) {
return cb(err);
}
return cb(null, Construct(result));
});
};
// query for a list of Models
// @param [Object] query optional query object
Construct.find = function(query, cb) {
var self = this;
if (typeof query === 'function') {
cb = query;
query = {}
}
var sync_opt = {
url: self.url_root,
query: query,
method: 'GET'
};
sync(sync_opt, function(err, result) {
if (err) {
return cb(err);
}
return cb(null, result.map(Construct));
});
};
// copy this model and optionally mixin some new shit
Construct.extend = function(more_schema, more_opt) {
more_schema = more_schema || {};
more_opt = more_opt || {};
return Model(xtend(schema, more_schema), xtend(opt, more_opt));
};
return Construct;

@@ -165,0 +350,0 @@ };

{
"name": "bamboo",
"version": "0.0.1-pre2",
"version": "0.0.2",
"author": "Roman Shtylman <shtylman@gmail.com>",
"dependencies": {
"emitter-component": "1.0.1",
"superagent": "shtylman/superagent#0.15.4-dz0"
"emitter-component": "1.1.0",
"superagent": "0.15.7",
"xtend": "2.1.1"
},
"scripts": {
"test": "zuul test/index.js",
"test-local": "zuul --local 8080 -- test/index.js"
},
"repository": {
"type": "git",
"url": "https://github.com/defunctzombie/bamboo.git"
},
"main": "./index.js",
"devDependencies": {
"zuul": "1.0.4",
"mocha": "1.14.0",
"express": "3.4.5",
"after": "0.8.1",
"uuid": "1.4.1"
},
"browser": {

@@ -10,0 +27,0 @@ "emitter": "emitter-component"

collection.js
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc