Skip to content

Commit

Permalink
Merge 079a9d9 into a067045
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdobry committed Jan 16, 2014
2 parents a067045 + 079a9d9 commit 883261e
Show file tree
Hide file tree
Showing 12 changed files with 478 additions and 216 deletions.
347 changes: 239 additions & 108 deletions dist/angular-data.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/angular-data.min.js

Large diffs are not rendered by default.

65 changes: 33 additions & 32 deletions src/datastore/async_methods/create/index.js
Expand Up @@ -45,47 +45,48 @@ var utils = require('utils'),
* - `{UnhandledError}`
*/
function create(resourceName, attrs) {
var deferred = $q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise;

if (!services.store[resourceName]) {
deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!utils.isObject(attrs)) {
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object!', { attrs: { actual: typeof attrs, expected: 'object' } }));
}

try {
var resource = services.store[resourceName],
_this = this,
url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name);
} else {
try {
var resource = services.store[resourceName],
_this = this;

if (resource.validate) {
resource.validate(attrs, null, function (err) {
if (err) {
deferred.reject(err);
} else {
promise = promise
.then(function (attrs) {
return services.$q.promisify(resource.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.validate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.beforeCreate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.POST(utils.makePath(resource.baseUrl, resource.endpoint), attrs, null);
})
.then(function (data) {
return services.$q.promisify(resource.afterCreate)(resourceName, data);
})
.then(function (data) {
return _this.inject(resource.name, data);
});

_this.POST(url, attrs, null).then(function (data) {
try {
deferred.resolve(_this.inject(resource.name, data));
} catch (err) {
deferred.reject(err);
}
}, deferred.reject);
}
});
} else {
_this.POST(url, attrs, null).then(function (data) {
try {
deferred.resolve(_this.inject(resource.name, data));
} catch (err) {
deferred.reject(err);
}
}, deferred.reject);
deferred.resolve(attrs);
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
}
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
}

return deferred.promise;
return promise;
}

module.exports = create;
2 changes: 1 addition & 1 deletion src/datastore/async_methods/destroy/index.js
Expand Up @@ -45,7 +45,7 @@ var utils = require('utils'),
* - `{UnhandledError}`
*/
function destroy(resourceName, id) {
var deferred = $q.defer();
var deferred = service.$q.defer();
if (!services.store[resourceName]) {
deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!utils.isString(id) && !utils.isNumber(id)) {
Expand Down
2 changes: 1 addition & 1 deletion src/datastore/async_methods/find/index.js
Expand Up @@ -49,7 +49,7 @@ var utils = require('utils'),
* - `{UnhandledError}`
*/
function find(resourceName, id, options) {
var deferred = $q.defer();
var deferred = services.$q.defer();
options = options || {};

if (!services.store[resourceName]) {
Expand Down
34 changes: 20 additions & 14 deletions src/datastore/async_methods/findAll/index.js
Expand Up @@ -26,7 +26,7 @@ function processResults(data, resourceName, queryHash) {
return data;
}

function _findAll(deferred, resourceName, params, options) {
function _findAll(resourceName, params, options) {
var resource = services.store[resourceName],
_this = this;

Expand All @@ -41,18 +41,19 @@ function _findAll(deferred, resourceName, params, options) {

if (!resource.pendingQueries[queryHash]) {

// This particular query has never even been started
var url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name);
resource.pendingQueries[queryHash] = GET(url, { params: params }).then(function (data) {
try {
deferred.resolve(processResults.apply(_this, [data, resourceName, queryHash]));
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
}
}, deferred.reject);
// This particular query has never even been made
resource.pendingQueries[queryHash] = GET(utils.makePath(resource.baseUrl, resource.endpoint), { params: params })
.then(function (data) {
try {
return processResults.apply(_this, [data, resourceName, queryHash]);
} catch (err) {
throw new errors.UnhandledError(err);
}
});
}
return resource.pendingQueries[queryHash];
} else {
deferred.resolve(this.filter(resourceName, params, options));
return this.filter(resourceName, params, options);
}
}

Expand Down Expand Up @@ -124,7 +125,9 @@ function _findAll(deferred, resourceName, params, options) {
* - `{UnhandledError}`
*/
function findAll(resourceName, params, options) {
var deferred = services.$q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise,
_this = this;

options = options || {};

Expand All @@ -136,13 +139,16 @@ function findAll(resourceName, params, options) {
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }));
} else {
try {
_findAll.apply(this, [deferred, resourceName, params, options]);
promise = promise.then(function () {
return _findAll.apply(_this, [resourceName, params, options]);
});
deferred.resolve();
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
}
}

return deferred.promise;
return promise;
}

module.exports = findAll;
66 changes: 32 additions & 34 deletions src/datastore/async_methods/save/index.js
@@ -1,19 +1,8 @@
var utils = require('utils'),
errors = require('errors'),
services = require('services'),
PUT = require('../../http').PUT,
errorPrefix = 'DS.save(resourceName, id[, options]): ';

function _save(deferred, resource, id, options) {
var _this = this;
var url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name, id);
PUT(url, resource.index[id], null).then(function (data) {
var saved = _this.inject(resource.name, data, options);
resource.saved[id] = utils.updateTimestamp(resource.saved[id]);
deferred.resolve(saved);
}, deferred.reject);
}

/**
* @doc method
* @id DS.async_methods:save
Expand Down Expand Up @@ -58,7 +47,8 @@ function _save(deferred, resource, id, options) {
* - `{UnhandledError}`
*/
function save(resourceName, id, options) {
var deferred = $q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise;

options = options || {};

Expand All @@ -68,33 +58,41 @@ function save(resourceName, id, options) {
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }));
} else if (!utils.isObject(options)) {
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'id: Must be an object!', { options: { actual: typeof options, expected: 'object' } }));
} else if (!(id in services.store[resourceName].index)) {
deferred.reject(new errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!'));
} else {
var _this = this;
var resource = services.store[resourceName],
_this = this;

try {
var resource = services.store[resourceName];
promise = promise
.then(function (attrs) {
return services.$q.promisify(resource.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.validate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.PUT(utils.makePath(resource.baseUrl, resource.endpoint, id), attrs, null);
})
.then(function (data) {
return services.$q.promisify(resource.afterUpdate)(resourceName, data);
})
.then(function (data) {
var saved = _this.inject(resource.name, data, options);
resource.saved[id] = utils.updateTimestamp(resource.saved[id]);
return saved;
});

if (resource.schema) {
resource.schema.validate(resource.index[id], function (err) {
if (err) {
deferred.reject(err);
} else {
_save.call(_this, deferred, resource, id, options);
}
});
} else {
_save.call(_this, deferred, resource, id, options);
}
} catch (err) {
if (!(err instanceof errors.UnhandledError)) {
deferred.reject(new errors.UnhandledError(err));
} else {
deferred.reject(err);
}
}
deferred.resolve(resource.index[id]);
}

return deferred.promise;
return promise;
}

module.exports = save;
34 changes: 28 additions & 6 deletions src/datastore/index.js
@@ -1,6 +1,5 @@
var utils = require('utils'),
errors = require('errors'),
IllegalArgumentError = errors.IllegalArgumentError,
services = require('services'),
errorPrefix = 'DSProvider.config(options): ';

Expand All @@ -19,7 +18,8 @@ var utils = require('utils'),
* ## Example:
* ```js
* DSProvider.config({
* baseUrl: 'http://myapp.com/api'
* baseUrl: 'http://myapp.com/api',
* idAttribute: '_id'
* });
* ```
*
Expand All @@ -33,12 +33,34 @@ function config(options) {
options = options || {};

if (!utils.isObject(options)) {
throw new IllegalArgumentError(errorPrefix + 'options: Must be an object!', { actual: typeof options, expected: 'object' });
} else if (!utils.isString(options.baseUrl)) {
throw new IllegalArgumentError(errorPrefix + 'options: Must be an object!', { baseUrl: { actual: typeof options, expected: 'object' } });
throw new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { actual: typeof options, expected: 'object' });
} else if ('baseUrl' in options && !utils.isString(options.baseUrl)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.baseUrl: Must be a string!', { baseUrl: { actual: typeof options.baseUrl, expected: 'string' } });
} else if ('idAttribute' in options && !utils.isString(options.idAttribute)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.idAttribute: Must be a string!', { idAttribute: { actual: typeof options.idAttribute, expected: 'string' } });
} else if ('mergeStrategy' in options && !utils.isString(options.mergeStrategy)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.mergeStrategy: Must be a string!', { mergeStrategy: { actual: typeof options.mergeStrategy, expected: 'string' } });
} else if ('beforeValidate' in options && !utils.isFunction(options.beforeValidate)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.beforeValidate: Must be a function!', { beforeValidate: { actual: typeof options.beforeValidate, expected: 'function' } });
} else if ('validate' in options && !utils.isFunction(options.validate)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.validate: Must be a function!', { validate: { actual: typeof options.validate, expected: 'function' } });
} else if ('afterValidate' in options && !utils.isFunction(options.afterValidate)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.afterValidate: Must be a function!', { afterValidate: { actual: typeof options.afterValidate, expected: 'function' } });
} else if ('beforeCreate' in options && !utils.isFunction(options.beforeCreate)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.beforeCreate: Must be a function!', { beforeCreate: { actual: typeof options.beforeCreate, expected: 'function' } });
} else if ('afterCreate' in options && !utils.isFunction(options.afterCreate)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.afterCreate: Must be a function!', { afterCreate: { actual: typeof options.afterCreate, expected: 'function' } });
} else if ('beforeUpdate' in options && !utils.isFunction(options.beforeUpdate)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.beforeUpdate: Must be a function!', { beforeUpdate: { actual: typeof options.beforeUpdate, expected: 'function' } });
} else if ('afterUpdate' in options && !utils.isFunction(options.afterUpdate)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.afterUpdate: Must be a function!', { afterUpdate: { actual: typeof options.afterUpdate, expected: 'function' } });
} else if ('beforeDestroy' in options && !utils.isFunction(options.beforeDestroy)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.beforeDestroy: Must be a function!', { beforeDestroy: { actual: typeof options.beforeDestroy, expected: 'function' } });
} else if ('afterDestroy' in options && !utils.isFunction(options.afterDestroy)) {
throw new errors.IllegalArgumentError(errorPrefix + 'options.afterDestroy: Must be a function!', { afterDestroy: { actual: typeof options.afterDestroy, expected: 'function' } });
}

utils.deepMixIn(services.config, options);
services.config = new services.BaseConfig(options);
}

/**
Expand Down
67 changes: 65 additions & 2 deletions src/datastore/services/index.js
@@ -1,6 +1,69 @@
module.exports = {
function lifecycleNoop(resourceName, attrs, cb) {
cb(null, attrs);
}

var services = module.exports = {
config: {
idAttribute: 'id'
},
store: {}
store: {},
BaseConfig: function (options) {
if ('idAttribute' in options) {
this.idAttribute = options.idAttribute;
}

if ('baseUrl' in options) {
this.baseUrl = options.baseUrl;
}

if ('beforeValidate' in options) {
this.beforeValidate = options.beforeValidate;
}

if ('validate' in options) {
this.validate = options.validate;
}

if ('afterValidate' in options) {
this.afterValidate = options.afterValidate;
}

if ('beforeCreate' in options) {
this.beforeCreate = options.beforeCreate;
}

if ('afterCreate' in options) {
this.afterCreate = options.afterCreate;
}

if ('beforeUpdate' in options) {
this.beforeUpdate = options.beforeUpdate;
}

if ('afterUpdate' in options) {
this.afterUpdate = options.afterUpdate;
}

if ('beforeDestroy' in options) {
this.beforeDestroy = options.beforeDestroy;
}

if ('afterDestroy' in options) {
this.afterDestroy = options.afterDestroy;
}
}
};


services.BaseConfig.prototype.idAttribute = 'id';
services.BaseConfig.prototype.baseUrl = '';
services.BaseConfig.prototype.endpoint = '';
services.BaseConfig.prototype.beforeValidate = lifecycleNoop;
services.BaseConfig.prototype.validate = lifecycleNoop;
services.BaseConfig.prototype.afterValidate = lifecycleNoop;
services.BaseConfig.prototype.beforeCreate = lifecycleNoop;
services.BaseConfig.prototype.afterCreate = lifecycleNoop;
services.BaseConfig.prototype.beforeUpdate = lifecycleNoop;
services.BaseConfig.prototype.afterUpdate = lifecycleNoop;
services.BaseConfig.prototype.beforeDestroy = lifecycleNoop;
services.BaseConfig.prototype.afterDestroy = lifecycleNoop;

0 comments on commit 883261e

Please sign in to comment.