mio
Advanced tools
Comparing version 1.0.8 to 1.1.0
385
dist/mio.js
@@ -51,3 +51,3 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.mio=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
context: this, | ||
handler: 'get', | ||
handler: this.get, | ||
state: options && options.query.toJSON() | ||
@@ -57,7 +57,7 @@ }); | ||
/** | ||
* @property resources | ||
* @memberof module:mio.Resource.Collection | ||
* @type {Array.<Resource>} | ||
*/ | ||
this.resources = (resources || []).map(function (resource) { | ||
return Resource.create(resource); | ||
}); | ||
this.reset(resources); | ||
@@ -133,14 +133,12 @@ /** | ||
* @param {module:mio.Query} query | ||
* @param {module:mio.Resource.get.get} callback | ||
* @param {module:mio.Collection.get.get} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:get | ||
* @fires module:mio.Resource.hook.collection:get | ||
* @fires module:mio.Resource.on.collection:get | ||
*/ | ||
Collection.get = function (query, callback) { | ||
var Collection = this; | ||
if (arguments.length === 0) { | ||
return new Query({ | ||
handler: this.get, | ||
context: this | ||
context: this, | ||
handler: this.get | ||
}); | ||
@@ -158,3 +156,3 @@ } | ||
* @event collection:get | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -179,11 +177,14 @@ * @param {module:mio.Resource.trigger.next} next | ||
'collection:get', | ||
new Query({ state: query }), | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
function (err, collection) { | ||
if (err) return callback.call(this, err); | ||
if (err) return callback.call(this.Collection, err); | ||
if (!collection) { | ||
collection = new Collection([]); | ||
collection = new this.Collection([]); | ||
} | ||
callback.call(this, err, collection); | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -199,5 +200,5 @@ | ||
* @param {Object} representation | ||
* @param {module:mio.Resource.put.put} callback | ||
* @param {module:mio.Collection.put.put} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:put | ||
* @fires module:mio.Resource.hook.collection:put | ||
* @fires module:mio.Resource.on.collection:put | ||
@@ -210,6 +211,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.put(query, resources, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -222,3 +223,3 @@ } | ||
* @event collection:put | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -245,6 +246,10 @@ * @param {Array.<Object|module:mio.Resource>} resources | ||
'collection:put', | ||
new Query({ state: query }), | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
resources, | ||
callback | ||
); | ||
function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -259,5 +264,5 @@ return this; | ||
* @param {Object|Array.<Object>} changes | ||
* @param {module:mio.Resource.patch.patch} callback | ||
* @param {module:mio.Collection.patch.patch} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:patch | ||
* @fires module:mio.Resource.hook.collection:patch | ||
* @fires module:mio.Resource.on.collection:patch | ||
@@ -270,6 +275,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.patch(query, changes, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -282,3 +287,3 @@ } | ||
* @event collection:patch | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -305,6 +310,10 @@ * @param {Object|Array.<Object>} patch | ||
'collection:patch', | ||
new Query({ state: query }), | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
changes, | ||
callback | ||
); | ||
function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -318,5 +327,5 @@ return this; | ||
* @param {Array.<Object>} representations | ||
* @param {module:mio.Resource.post.post} callback | ||
* @param {module:mio.Collection.post.post} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:post | ||
* @fires module:mio.Resource.hook.collection:post | ||
* @fires module:mio.Resource.on.collection:post | ||
@@ -330,3 +339,3 @@ */ | ||
* @event collection:post | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -351,3 +360,6 @@ * @param {Array.<Object>|Array.<module:mio.Resource>} resources | ||
*/ | ||
this.Resource.trigger('collection:post', representations, callback); | ||
this.Resource.trigger('collection:post', representations, function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
return this; | ||
@@ -360,5 +372,5 @@ }; | ||
* @param {module:mio.Query} query | ||
* @param {module:mio.Resource.delete.delete} callback | ||
* @param {module:mio.Collection.delete.delete} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:delete | ||
* @fires module:mio.Resource.hook.collection:delete | ||
* @fires module:mio.Resource.on.collection:delete | ||
@@ -369,4 +381,4 @@ */ | ||
return new Query({ | ||
handler: this.get, | ||
context: this | ||
context: this, | ||
handler: this.get | ||
}); | ||
@@ -384,3 +396,3 @@ } | ||
* @event collection:delete | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -405,5 +417,9 @@ * @param {module:mio.Resource.trigger.next} next | ||
'collection:delete', | ||
new Query({ state: query }), | ||
callback | ||
); | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -445,2 +461,159 @@ return this; | ||
/** | ||
* Refresh the collection instance with the most recent resource | ||
* representations passed to the last hook's `next()`. | ||
* | ||
* @param {module:mio.Collection.get.get} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:get | ||
* @fires module:mio.Resource.on.collection:get | ||
*/ | ||
Collection.prototype.get = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback get | ||
* @memberof module:mio.Collection.get | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:get', this.query, function (err, collection) { | ||
if (err) return callback.call(collection, err); | ||
if (collection) { | ||
collection.reset(collection); | ||
} | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Replace the collection resources using the instance representation. | ||
* | ||
* @param {module:mio.Collection.put.put} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:put | ||
* @fires module:mio.Resource.on.collection:put | ||
*/ | ||
Collection.prototype.put = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback put | ||
* @memberof module:mio.Collection.put | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:put', this.query, this, function () { | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Patch the collection resources using the instance representation. | ||
* | ||
* @param {module:mio.Collection.patch.patch} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:patch | ||
* @fires module:mio.Resource.on.collection:patch | ||
*/ | ||
Collection.prototype.patch = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback patch | ||
* @memberof module:mio.Collection.patch | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:patch', this.query, this, function () { | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Create resources using the instance representation. | ||
* | ||
* @param {module:mio.Collection.post.post} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:post | ||
* @fires module:mio.Resource.on.collection:post | ||
*/ | ||
Collection.prototype.post = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback post | ||
* @memberof module:mio.Collection.post | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:post', this, function () { | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Delete resources in collection. | ||
* | ||
* @param {module:mio.Collection.post.post} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:post | ||
* @fires module:mio.Resource.on.collection:post | ||
*/ | ||
Collection.prototype.delete = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback delete | ||
* @memberof module:mio.Collection.delete | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:delete', this.query, function (err) { | ||
if (err) return callback.call(collection, err); | ||
collection.reset([]); | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Reset collection with given `resources`. | ||
* | ||
* @param {Array.<Resource|Object>} resources | ||
* @returns {module:mio.Collection} | ||
*/ | ||
Collection.prototype.reset = function (resources) { | ||
var Resource = this.Resource; | ||
this.resources = (resources || []).map(function (resource) { | ||
return Resource.create(resource); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Returns map of HTTP methods to collection URLs. If `method` is specified, the | ||
@@ -562,3 +735,4 @@ * URL for that `method` is returned. | ||
/** | ||
* Compose queries functionally. | ||
* Queries are created by actions such as `Resource.get()` and provide a | ||
* consistent query interface across plugins and other related modules. | ||
* | ||
@@ -594,3 +768,2 @@ * @example | ||
* @memberof module:mio | ||
* @alias Query | ||
* @constructor | ||
@@ -605,6 +778,14 @@ */ | ||
if (this.Resource && this.Resource.maxSize) { | ||
this.maxSize = this.Resource.maxSize; | ||
} else { | ||
this.maxSize = 25; | ||
if (this.Resource) { | ||
if (this.Resource.maxPageSize) { | ||
this.maxSize = this.Resource.maxPageSize; | ||
} else { | ||
this.maxSize = 100; | ||
} | ||
if (this.Resource.defaultPageSize) { | ||
this.defaultSize = this.Resource.defaultPageSize; | ||
} else { | ||
this.defaultSize = 20; | ||
} | ||
} | ||
@@ -632,3 +813,3 @@ | ||
if (!this.query.size) { | ||
this.query.size = this.maxSize; | ||
this.query.size = this.defaultSize; | ||
} | ||
@@ -1069,4 +1250,4 @@ | ||
var pluckedStatics = util.pluck(statics, [ | ||
'on', | ||
'before', | ||
'events', | ||
'hooks', | ||
'server', | ||
@@ -1132,4 +1313,4 @@ 'browser', | ||
// register hooks | ||
for (var events in pluckedStatics.before) { | ||
child.before(event, pluckedStatics.before[event]); | ||
for (var events in pluckedStatics.hooks) { | ||
child.hook(event, pluckedStatics.hooks[event]); | ||
} | ||
@@ -1315,3 +1496,3 @@ | ||
* @returns {module:mio.Resource|module:mio.Query} | ||
* @fires module:mio.Resource.before.get | ||
* @fires module:mio.Resource.hook.get | ||
* @fires module:mio.Resource.on.get | ||
@@ -1326,4 +1507,4 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: this.get, | ||
context: this, | ||
state: query | ||
@@ -1337,3 +1518,3 @@ }); | ||
* @event get | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -1361,5 +1542,8 @@ * @param {module:mio.Resource.trigger.next} next | ||
* @param {Error} err | ||
* @param {module:mio.Resource=} resource | ||
* @param {module:mio.Resource} resource | ||
*/ | ||
return this.trigger('get', new Query({ state: query }), callback); | ||
return this.trigger('get', new Query({ | ||
context: this, | ||
state: query | ||
}), callback); | ||
}; | ||
@@ -1374,3 +1558,3 @@ | ||
* @returns {module:mio.Resource|module:mio.Query} | ||
* @fires module:mio.Resource.before.put | ||
* @fires module:mio.Resource.hook.put | ||
* @fires module:mio.Resource.on.put | ||
@@ -1383,6 +1567,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.put(query, representation, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -1395,3 +1579,3 @@ } | ||
* @event put | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -1424,2 +1608,3 @@ * @param {Object|module:mio.Resource} representationresentation | ||
return this.trigger('put', new Query({ | ||
context: this, | ||
state: query | ||
@@ -1446,3 +1631,3 @@ }), representation, callback); | ||
* @returns {module:mio.Resource|module:mio.Query} | ||
* @fires module:mio.Resource.before.patch | ||
* @fires module:mio.Resource.hook.patch | ||
* @fires module:mio.Resource.on.patch | ||
@@ -1455,6 +1640,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.patch(query, changes, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -1467,3 +1652,3 @@ } | ||
* @event patch | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -1496,2 +1681,3 @@ * @param {Object|Array.<Object>} patch | ||
return this.trigger('patch', new Query({ | ||
context: this, | ||
state: query | ||
@@ -1509,3 +1695,3 @@ }), changes, callback); | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.post | ||
* @fires module:mio.Resource.hook.post | ||
* @fires module:mio.Resource.on.post | ||
@@ -1519,3 +1705,3 @@ */ | ||
* @event post | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -1558,3 +1744,3 @@ * @param {Object|module:mio.Resource} representation | ||
* @returns {module:mio.Resource|query} | ||
* @fires module:mio.Resource.before.delete | ||
* @fires module:mio.Resource.hook.delete | ||
* @fires module:mio.Resource.on.delete | ||
@@ -1570,4 +1756,4 @@ */ | ||
return new Query({ | ||
handler: this.delete, | ||
context: this | ||
context: this, | ||
handler: this.delete | ||
}); | ||
@@ -1580,3 +1766,3 @@ } | ||
* @event delete | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -1606,2 +1792,3 @@ * @param {module:mio.Resource.trigger.next} next | ||
return this.trigger('delete', new Query({ | ||
context: this, | ||
state: query | ||
@@ -1858,9 +2045,5 @@ }), callback); | ||
* ```javascript | ||
* User.before('get', function (query, next) { | ||
* User.hook('get', function (query, next) { | ||
* // do something before save such as validation and then call next() | ||
* }); | ||
* | ||
* User.on('patch', function (query, changed) { | ||
* // do something after update | ||
* }); | ||
* ``` | ||
@@ -1871,6 +2054,6 @@ * | ||
*/ | ||
Resource.before = function(event, hook) { | ||
Resource.hook = Resource.before = function(event, hook) { | ||
if (hook instanceof Array) { | ||
for (var i = 0, l = hook.length; i < l; i++) { | ||
this.before(event, hook[i]); | ||
this.hook(event, hook[i]); | ||
} | ||
@@ -1890,2 +2073,3 @@ } else { | ||
Resource.prototype.before = Resource.before; | ||
Resource.prototype.hook = Resource.hook; | ||
@@ -1995,3 +2179,3 @@ /** | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.get | ||
* @fires module:mio.Resource.hook.get | ||
* @fires module:mio.Resource.on.get | ||
@@ -2018,3 +2202,3 @@ */ | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.put | ||
* @fires module:mio.Resource.hook.put | ||
* @fires module:mio.Resource.on.put | ||
@@ -2032,3 +2216,3 @@ */ | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.patch | ||
* @fires module:mio.Resource.hook.patch | ||
* @fires module:mio.Resource.on.patch | ||
@@ -2046,3 +2230,3 @@ */ | ||
* @returns {resource} | ||
* @fires module:mio.Resource.before.post | ||
* @fires module:mio.Resource.hook.post | ||
* @fires module:mio.Resource.on.post | ||
@@ -2061,3 +2245,3 @@ */ | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.delete | ||
* @fires module:mio.Resource.hook.delete | ||
* @fires module:mio.Resource.on.delete | ||
@@ -2147,2 +2331,4 @@ */ | ||
* | ||
* Alternatively, set a key-value pair. | ||
* | ||
* @param {Object} attributes | ||
@@ -2153,15 +2339,22 @@ * @returns {module:mio.Resource} | ||
Resource.prototype.set = function (attributes) { | ||
if (arguments.length === 2) { | ||
var key = arguments[0]; | ||
var value = arguments[1]; | ||
attributes = {}; | ||
attributes[key] = value; | ||
} else { | ||
/** | ||
* @event set | ||
* @memberof module:mio.Resource.on | ||
* @param {Resource} resource | ||
* @param {Object} attributes | ||
*/ | ||
this.constructor.emit('set', this, attributes); | ||
this.emit('set', attributes); | ||
/** | ||
* @event set | ||
* @memberof module:mio.Resource.on | ||
* @param {Resource} resource | ||
* @param {Object} attributes | ||
*/ | ||
this.constructor.emit('set', this, attributes); | ||
this.emit('set', attributes); | ||
for (var attr in attributes) { | ||
if (this.constructor.attributes[attr]) { | ||
this[attr] = attributes[attr]; | ||
for (var attr in attributes) { | ||
if (this.constructor.attributes[attr]) { | ||
this[attr] = attributes[attr]; | ||
} | ||
} | ||
@@ -2168,0 +2361,0 @@ } |
@@ -42,3 +42,3 @@ var Query = require('./query'); | ||
context: this, | ||
handler: 'get', | ||
handler: this.get, | ||
state: options && options.query.toJSON() | ||
@@ -48,7 +48,7 @@ }); | ||
/** | ||
* @property resources | ||
* @memberof module:mio.Resource.Collection | ||
* @type {Array.<Resource>} | ||
*/ | ||
this.resources = (resources || []).map(function (resource) { | ||
return Resource.create(resource); | ||
}); | ||
this.reset(resources); | ||
@@ -124,14 +124,12 @@ /** | ||
* @param {module:mio.Query} query | ||
* @param {module:mio.Resource.get.get} callback | ||
* @param {module:mio.Collection.get.get} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:get | ||
* @fires module:mio.Resource.hook.collection:get | ||
* @fires module:mio.Resource.on.collection:get | ||
*/ | ||
Collection.get = function (query, callback) { | ||
var Collection = this; | ||
if (arguments.length === 0) { | ||
return new Query({ | ||
handler: this.get, | ||
context: this | ||
context: this, | ||
handler: this.get | ||
}); | ||
@@ -149,3 +147,3 @@ } | ||
* @event collection:get | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -170,11 +168,14 @@ * @param {module:mio.Resource.trigger.next} next | ||
'collection:get', | ||
new Query({ state: query }), | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
function (err, collection) { | ||
if (err) return callback.call(this, err); | ||
if (err) return callback.call(this.Collection, err); | ||
if (!collection) { | ||
collection = new Collection([]); | ||
collection = new this.Collection([]); | ||
} | ||
callback.call(this, err, collection); | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -190,5 +191,5 @@ | ||
* @param {Object} representation | ||
* @param {module:mio.Resource.put.put} callback | ||
* @param {module:mio.Collection.put.put} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:put | ||
* @fires module:mio.Resource.hook.collection:put | ||
* @fires module:mio.Resource.on.collection:put | ||
@@ -201,6 +202,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.put(query, resources, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -213,3 +214,3 @@ } | ||
* @event collection:put | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -236,6 +237,10 @@ * @param {Array.<Object|module:mio.Resource>} resources | ||
'collection:put', | ||
new Query({ state: query }), | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
resources, | ||
callback | ||
); | ||
function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -250,5 +255,5 @@ return this; | ||
* @param {Object|Array.<Object>} changes | ||
* @param {module:mio.Resource.patch.patch} callback | ||
* @param {module:mio.Collection.patch.patch} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:patch | ||
* @fires module:mio.Resource.hook.collection:patch | ||
* @fires module:mio.Resource.on.collection:patch | ||
@@ -261,6 +266,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.patch(query, changes, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -273,3 +278,3 @@ } | ||
* @event collection:patch | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -296,6 +301,10 @@ * @param {Object|Array.<Object>} patch | ||
'collection:patch', | ||
new Query({ state: query }), | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
changes, | ||
callback | ||
); | ||
function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -309,5 +318,5 @@ return this; | ||
* @param {Array.<Object>} representations | ||
* @param {module:mio.Resource.post.post} callback | ||
* @param {module:mio.Collection.post.post} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:post | ||
* @fires module:mio.Resource.hook.collection:post | ||
* @fires module:mio.Resource.on.collection:post | ||
@@ -321,3 +330,3 @@ */ | ||
* @event collection:post | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -342,3 +351,6 @@ * @param {Array.<Object>|Array.<module:mio.Resource>} resources | ||
*/ | ||
this.Resource.trigger('collection:post', representations, callback); | ||
this.Resource.trigger('collection:post', representations, function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
return this; | ||
@@ -351,5 +363,5 @@ }; | ||
* @param {module:mio.Query} query | ||
* @param {module:mio.Resource.delete.delete} callback | ||
* @param {module:mio.Collection.delete.delete} callback | ||
* @returns {module:mio.Resource.Collection} | ||
* @fires module:mio.Resource.before.collection:delete | ||
* @fires module:mio.Resource.hook.collection:delete | ||
* @fires module:mio.Resource.on.collection:delete | ||
@@ -360,4 +372,4 @@ */ | ||
return new Query({ | ||
handler: this.get, | ||
context: this | ||
context: this, | ||
handler: this.get | ||
}); | ||
@@ -375,3 +387,3 @@ } | ||
* @event collection:delete | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -396,5 +408,9 @@ * @param {module:mio.Resource.trigger.next} next | ||
'collection:delete', | ||
new Query({ state: query }), | ||
callback | ||
); | ||
new Query({ | ||
context: this, | ||
state: query | ||
}), | ||
function () { | ||
callback.apply(this.Collection, arguments); | ||
}); | ||
@@ -436,2 +452,159 @@ return this; | ||
/** | ||
* Refresh the collection instance with the most recent resource | ||
* representations passed to the last hook's `next()`. | ||
* | ||
* @param {module:mio.Collection.get.get} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:get | ||
* @fires module:mio.Resource.on.collection:get | ||
*/ | ||
Collection.prototype.get = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback get | ||
* @memberof module:mio.Collection.get | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:get', this.query, function (err, collection) { | ||
if (err) return callback.call(collection, err); | ||
if (collection) { | ||
collection.reset(collection); | ||
} | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Replace the collection resources using the instance representation. | ||
* | ||
* @param {module:mio.Collection.put.put} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:put | ||
* @fires module:mio.Resource.on.collection:put | ||
*/ | ||
Collection.prototype.put = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback put | ||
* @memberof module:mio.Collection.put | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:put', this.query, this, function () { | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Patch the collection resources using the instance representation. | ||
* | ||
* @param {module:mio.Collection.patch.patch} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:patch | ||
* @fires module:mio.Resource.on.collection:patch | ||
*/ | ||
Collection.prototype.patch = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback patch | ||
* @memberof module:mio.Collection.patch | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:patch', this.query, this, function () { | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Create resources using the instance representation. | ||
* | ||
* @param {module:mio.Collection.post.post} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:post | ||
* @fires module:mio.Resource.on.collection:post | ||
*/ | ||
Collection.prototype.post = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback post | ||
* @memberof module:mio.Collection.post | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:post', this, function () { | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Delete resources in collection. | ||
* | ||
* @param {module:mio.Collection.post.post} callback | ||
* @returns {module:mio.Collection} | ||
* @fires module:mio.Resource.hook.collection:post | ||
* @fires module:mio.Resource.on.collection:post | ||
*/ | ||
Collection.prototype.delete = function (callback) { | ||
var collection = this; | ||
/** | ||
* Receives arguments passed from the last hook's `next`. | ||
* | ||
* @callback delete | ||
* @memberof module:mio.Collection.delete | ||
* @param {Error} err | ||
* @param {module:mio.Collection} collection | ||
*/ | ||
this.Resource.trigger('collection:delete', this.query, function (err) { | ||
if (err) return callback.call(collection, err); | ||
collection.reset([]); | ||
callback.apply(collection, arguments); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Reset collection with given `resources`. | ||
* | ||
* @param {Array.<Resource|Object>} resources | ||
* @returns {module:mio.Collection} | ||
*/ | ||
Collection.prototype.reset = function (resources) { | ||
var Resource = this.Resource; | ||
this.resources = (resources || []).map(function (resource) { | ||
return Resource.create(resource); | ||
}); | ||
return this; | ||
}; | ||
/** | ||
* Returns map of HTTP methods to collection URLs. If `method` is specified, the | ||
@@ -438,0 +611,0 @@ * URL for that `method` is returned. |
module.exports = Query; | ||
/** | ||
* Compose queries functionally. | ||
* Queries are created by actions such as `Resource.get()` and provide a | ||
* consistent query interface across plugins and other related modules. | ||
* | ||
@@ -35,3 +36,2 @@ * @example | ||
* @memberof module:mio | ||
* @alias Query | ||
* @constructor | ||
@@ -46,6 +46,14 @@ */ | ||
if (this.Resource && this.Resource.maxSize) { | ||
this.maxSize = this.Resource.maxSize; | ||
} else { | ||
this.maxSize = 25; | ||
if (this.Resource) { | ||
if (this.Resource.maxPageSize) { | ||
this.maxSize = this.Resource.maxPageSize; | ||
} else { | ||
this.maxSize = 100; | ||
} | ||
if (this.Resource.defaultPageSize) { | ||
this.defaultSize = this.Resource.defaultPageSize; | ||
} else { | ||
this.defaultSize = 20; | ||
} | ||
} | ||
@@ -73,3 +81,3 @@ | ||
if (!this.query.size) { | ||
this.query.size = this.maxSize; | ||
this.query.size = this.defaultSize; | ||
} | ||
@@ -76,0 +84,0 @@ |
@@ -201,4 +201,4 @@ var Collection = require('./collection'); | ||
var pluckedStatics = util.pluck(statics, [ | ||
'on', | ||
'before', | ||
'events', | ||
'hooks', | ||
'server', | ||
@@ -264,4 +264,4 @@ 'browser', | ||
// register hooks | ||
for (var events in pluckedStatics.before) { | ||
child.before(event, pluckedStatics.before[event]); | ||
for (var events in pluckedStatics.hooks) { | ||
child.hook(event, pluckedStatics.hooks[event]); | ||
} | ||
@@ -447,3 +447,3 @@ | ||
* @returns {module:mio.Resource|module:mio.Query} | ||
* @fires module:mio.Resource.before.get | ||
* @fires module:mio.Resource.hook.get | ||
* @fires module:mio.Resource.on.get | ||
@@ -458,4 +458,4 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: this.get, | ||
context: this, | ||
state: query | ||
@@ -469,3 +469,3 @@ }); | ||
* @event get | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -493,5 +493,8 @@ * @param {module:mio.Resource.trigger.next} next | ||
* @param {Error} err | ||
* @param {module:mio.Resource=} resource | ||
* @param {module:mio.Resource} resource | ||
*/ | ||
return this.trigger('get', new Query({ state: query }), callback); | ||
return this.trigger('get', new Query({ | ||
context: this, | ||
state: query | ||
}), callback); | ||
}; | ||
@@ -506,3 +509,3 @@ | ||
* @returns {module:mio.Resource|module:mio.Query} | ||
* @fires module:mio.Resource.before.put | ||
* @fires module:mio.Resource.hook.put | ||
* @fires module:mio.Resource.on.put | ||
@@ -515,6 +518,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.put(query, representation, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -527,3 +530,3 @@ } | ||
* @event put | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -556,2 +559,3 @@ * @param {Object|module:mio.Resource} representationresentation | ||
return this.trigger('put', new Query({ | ||
context: this, | ||
state: query | ||
@@ -578,3 +582,3 @@ }), representation, callback); | ||
* @returns {module:mio.Resource|module:mio.Query} | ||
* @fires module:mio.Resource.before.patch | ||
* @fires module:mio.Resource.hook.patch | ||
* @fires module:mio.Resource.on.patch | ||
@@ -587,6 +591,6 @@ */ | ||
return new Query({ | ||
context: this, | ||
handler: function (query, callback) { | ||
this.patch(query, changes, callback); | ||
}, | ||
context: this | ||
} | ||
}); | ||
@@ -599,3 +603,3 @@ } | ||
* @event patch | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -628,2 +632,3 @@ * @param {Object|Array.<Object>} patch | ||
return this.trigger('patch', new Query({ | ||
context: this, | ||
state: query | ||
@@ -641,3 +646,3 @@ }), changes, callback); | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.post | ||
* @fires module:mio.Resource.hook.post | ||
* @fires module:mio.Resource.on.post | ||
@@ -651,3 +656,3 @@ */ | ||
* @event post | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -690,3 +695,3 @@ * @param {Object|module:mio.Resource} representation | ||
* @returns {module:mio.Resource|query} | ||
* @fires module:mio.Resource.before.delete | ||
* @fires module:mio.Resource.hook.delete | ||
* @fires module:mio.Resource.on.delete | ||
@@ -702,4 +707,4 @@ */ | ||
return new Query({ | ||
handler: this.delete, | ||
context: this | ||
context: this, | ||
handler: this.delete | ||
}); | ||
@@ -712,3 +717,3 @@ } | ||
* @event delete | ||
* @memberof module:mio.Resource.before | ||
* @memberof module:mio.Resource.hook | ||
* @param {module:mio.Query} query | ||
@@ -738,2 +743,3 @@ * @param {module:mio.Resource.trigger.next} next | ||
return this.trigger('delete', new Query({ | ||
context: this, | ||
state: query | ||
@@ -990,9 +996,5 @@ }), callback); | ||
* ```javascript | ||
* User.before('get', function (query, next) { | ||
* User.hook('get', function (query, next) { | ||
* // do something before save such as validation and then call next() | ||
* }); | ||
* | ||
* User.on('patch', function (query, changed) { | ||
* // do something after update | ||
* }); | ||
* ``` | ||
@@ -1003,6 +1005,6 @@ * | ||
*/ | ||
Resource.before = function(event, hook) { | ||
Resource.hook = Resource.before = function(event, hook) { | ||
if (hook instanceof Array) { | ||
for (var i = 0, l = hook.length; i < l; i++) { | ||
this.before(event, hook[i]); | ||
this.hook(event, hook[i]); | ||
} | ||
@@ -1022,2 +1024,3 @@ } else { | ||
Resource.prototype.before = Resource.before; | ||
Resource.prototype.hook = Resource.hook; | ||
@@ -1127,3 +1130,3 @@ /** | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.get | ||
* @fires module:mio.Resource.hook.get | ||
* @fires module:mio.Resource.on.get | ||
@@ -1150,3 +1153,3 @@ */ | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.put | ||
* @fires module:mio.Resource.hook.put | ||
* @fires module:mio.Resource.on.put | ||
@@ -1164,3 +1167,3 @@ */ | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.patch | ||
* @fires module:mio.Resource.hook.patch | ||
* @fires module:mio.Resource.on.patch | ||
@@ -1178,3 +1181,3 @@ */ | ||
* @returns {resource} | ||
* @fires module:mio.Resource.before.post | ||
* @fires module:mio.Resource.hook.post | ||
* @fires module:mio.Resource.on.post | ||
@@ -1193,3 +1196,3 @@ */ | ||
* @returns {module:mio.Resource} | ||
* @fires module:mio.Resource.before.delete | ||
* @fires module:mio.Resource.hook.delete | ||
* @fires module:mio.Resource.on.delete | ||
@@ -1279,2 +1282,4 @@ */ | ||
* | ||
* Alternatively, set a key-value pair. | ||
* | ||
* @param {Object} attributes | ||
@@ -1285,15 +1290,22 @@ * @returns {module:mio.Resource} | ||
Resource.prototype.set = function (attributes) { | ||
if (arguments.length === 2) { | ||
var key = arguments[0]; | ||
var value = arguments[1]; | ||
attributes = {}; | ||
attributes[key] = value; | ||
} else { | ||
/** | ||
* @event set | ||
* @memberof module:mio.Resource.on | ||
* @param {Resource} resource | ||
* @param {Object} attributes | ||
*/ | ||
this.constructor.emit('set', this, attributes); | ||
this.emit('set', attributes); | ||
/** | ||
* @event set | ||
* @memberof module:mio.Resource.on | ||
* @param {Resource} resource | ||
* @param {Object} attributes | ||
*/ | ||
this.constructor.emit('set', this, attributes); | ||
this.emit('set', attributes); | ||
for (var attr in attributes) { | ||
if (this.constructor.attributes[attr]) { | ||
this[attr] = attributes[attr]; | ||
for (var attr in attributes) { | ||
if (this.constructor.attributes[attr]) { | ||
this[attr] = attributes[attr]; | ||
} | ||
} | ||
@@ -1300,0 +1312,0 @@ } |
{ | ||
"name": "mio", | ||
"description": "A common model layer between client and server for building REST APIs and web applications.", | ||
"version": "1.0.8", | ||
"version": "1.1.0", | ||
"homepage": "https://github.com/mio/mio", | ||
@@ -6,0 +6,0 @@ "repository": { |
270
README.md
@@ -8,14 +8,13 @@ # mio [![Build Status](https://img.shields.io/travis/mio/mio.svg?style=flat)](http://travis-ci.org/mio/mio) [![Coverage Status](https://img.shields.io/coveralls/mio/mio.svg?style=flat)](https://coveralls.io/r/mio/mio?branch=master) [![Bower version](https://img.shields.io/bower/v/mio.svg?style=flat)](http://badge.fury.io/bo/mio) [![NPM version](https://img.shields.io/npm/v/mio.svg?style=flat)](http://badge.fury.io/js/mio) [![Dependency Status](https://img.shields.io/david/mio/mio.svg?style=flat)](http://david-dm.org/mio/mio) | ||
Mio provides a consistent API across client and server for querying, | ||
manipulating, and persisting data. Create a REST API server from your mio | ||
resources and interact with them from the browser using the same interface. No | ||
need for any route handling or AJAX boilerplate. | ||
Create a REST API server from your mio resources and interact with them from the | ||
browser using the same interface. *No need for any route handling or AJAX | ||
boilerplate.* | ||
Mio models are designed to be RESTful and avoid leaky abstractions for mapping | ||
to HTTP methods. For example, providing `Resource.get()` instead of `findOne()` | ||
and `Resource.post()` where most libraries would provide `create()`. | ||
to HTTP methods. For example, providing `get()` instead of `findOne()` | ||
and `patch()` where most libraries would provide `save()`. | ||
* Small readable core (only ~300 SLOC) | ||
* RESTful models and collections | ||
* Simple enumerable objects | ||
* Hooks and events before and after CRUD operations and object lifecycle | ||
* Hooks and events for object lifecycle | ||
* Backbone-style API for extending resources | ||
@@ -25,4 +24,19 @@ * Modular. Plugins provide storage, validation, etc. | ||
## Installation | ||
### [API Documentation](docs/API.md) | ||
### [Plugins](https://github.com/mio/mio/wiki/Plugins/) | ||
### Guide | ||
- [Installation](#installation) | ||
- [Resources](#resources) | ||
- [Collections](#collections) | ||
- [Actions and Queries](#actions-and-queries) | ||
- [Hooks and Events](#hooks-and-events) | ||
- [Relations](#relations) | ||
- [Plugins](#plugins) | ||
- [REST API](#rest-api) | ||
### Installation | ||
Using [npm](https://npmjs.org/): | ||
@@ -47,55 +61,104 @@ | ||
## API | ||
It is recommended to use [browserify](https://github.com/substack/node-browserify) | ||
when using mio in the browser and on the server. Platform-specific code can be | ||
wrapped in [`Resource.server()`](docs/API.md#module_mio.Resource.server) or | ||
[`Resource.browser()`](docs/API.md#module_mio.Resource.browser) and server code | ||
excluded in the client build. | ||
See the full [API documentation](docs/API.md). | ||
### Resources | ||
## Community | ||
New resources are defined by extending the base resource class using | ||
[`mio.Resource.extend()`](docs/API.md#module_mio.Resource.extend). | ||
* [Plugins](https://github.com/mio/mio/wiki/Plugins/) | ||
* [Wiki](https://github.com/mio/mio/wiki/) | ||
* `##mio` on irc.freenode.net | ||
```javascript | ||
var User = mio.Resource.extend(); | ||
``` | ||
## Examples | ||
Attributes can be defined by extending the prototype: | ||
* [Resources](#resources) | ||
* [Queries](#queries) | ||
* [Plugins](#plugins) | ||
* [Hooks](#hooks) | ||
* [Relations](#relations) | ||
* [REST API](#rest-api) | ||
```javascript | ||
var User = mio.Resource.extend({ | ||
attributes: { | ||
id: { | ||
primary: true | ||
} | ||
} | ||
}); | ||
``` | ||
### Resources | ||
Attributes can also be defined using the chainable | ||
[`attr()`](docs/API.md#module_mio.Resource.attr) method: | ||
Define new resources by extending the base `Resource` class. You can pass | ||
attribute definitions to [`.extend()`](docs/API.md#module_mio.Resource.extend) | ||
or use the chainable [`.attr()`](docs/API.md#module_mio.Resource.attr): | ||
```javasciprt | ||
var User = mio.Resource.extend(); | ||
User | ||
.attr('id', { | ||
primary: true | ||
}) | ||
.attr('name') | ||
.attr('email'); | ||
``` | ||
Resources can be extended with prototype or static properties and methods: | ||
```javascript | ||
var User = mio.Resource.extend({ | ||
attributes: { | ||
id: { primary: true }, | ||
name: { required: true }, | ||
active: { default: false }, | ||
created: { | ||
default: function() { | ||
return new Date(); | ||
} | ||
} | ||
}, | ||
sayHello: function() { | ||
return "Hello I'm " + this.name; | ||
sayHello: function () { | ||
return 'hello'; | ||
} | ||
}, { | ||
type: 'User' | ||
}); | ||
var user = new User({ name: 'Mio' }); | ||
console.log(User.type); // => "User" | ||
user.sayHello(); // => "Hello I'm Mio" | ||
var user = new User(); | ||
user.sayHello(); // => "hello" | ||
``` | ||
### Queries | ||
### Collections | ||
Query methods provide a consistent interface for fetching resources. | ||
Storage plugins use the asynchronous events provided for each method to fetch or | ||
persist resources to a database. | ||
Each Resource has an associated collection. Actions that return multiple | ||
resources return instances of | ||
[`Resource.Collection`](docs/API.md#module_mio.Collection). Collections have | ||
REST actions just as resources do. | ||
For example, to fetch a collection of user resources: | ||
```javascript | ||
User.Collection.get().exec(function (err, users) {...}); | ||
``` | ||
Array.prototype methods are available for collections, *but a collection | ||
is not an array*. The array of resources is kept at `Collection#resources`. | ||
Methods such as `map()` return arrays instead of the collection. | ||
```javascript | ||
var resource1 = new Resource(); | ||
var collection = new Resource.Collection([resource]); | ||
collection.push(new Resource()); | ||
collection.splice(1, 1, new Resource()); | ||
collection.at(0) === resource; // => true | ||
collection.length === 2; // => true | ||
collection.indexOf(resource); // => 0 | ||
``` | ||
### Actions and Queries | ||
Mio resource and collection methods map directly to REST actions and HTTP | ||
verbs. Instead of `find()` you use `get()`. Instead of `save()` you use `put()`, | ||
`post()`, or `patch()`. | ||
The actions `get`, `put`, `patch`, `post`, and `delete` exist for the resource | ||
class and instances. Collections also support a subset of these methods. | ||
Storage plugins use event [hooks](#hooks-and-events) provided for | ||
each method to fetch or persist resources to a database. | ||
#### Fetching | ||
Find one user: | ||
@@ -129,5 +192,49 @@ | ||
See the [API documentation](docs/API.md) for a complete list of query methods | ||
and event information. | ||
#### Pagination | ||
All queries are paginated using a common interface provided by the Query and | ||
Collection classes. Both queries and collections maintain `from` and `size` | ||
properties. The default and maximum page size are set by | ||
`Resource.defaultPageSize` and `Resource.maxPageSize` properties. | ||
See the [query](docs/API.md#module_mio.Query) documentation for more | ||
information. | ||
#### Creating and updating | ||
Creating or updating resources is accomplished with `put`, `patch`, and `post`: | ||
```javascript | ||
var user = User.create({ name: 'Bob' }); | ||
user.post(function (err) { | ||
// ... | ||
}); | ||
``` | ||
`User.create()` is just functional sugar for `new User()`. | ||
All instance actions are available as class actions: | ||
```javascript | ||
User.post({ name: 'Bob' }, function (err, user) { | ||
// ... | ||
}); | ||
``` | ||
Update a resource: | ||
```javascript | ||
var user = User.create(); | ||
user | ||
.set({ | ||
name: 'alex' | ||
}).patch(function(err) { | ||
// ... | ||
}); | ||
``` | ||
See the [API documentation](docs/API.md) for a complete list of actions. | ||
### Plugins | ||
@@ -156,19 +263,69 @@ | ||
### Hooks | ||
### Hooks and Events | ||
Before and after hooks are provided for CRUD operations and resource lifecycle | ||
events. Hooks are asynchronous and execute in series. | ||
Asynchronous hooks are provided for CRUD operations and lifecycle events. | ||
They run in series before `get`, `put`, `patch`, `post`, and `delete` methods. | ||
Hooks are used to implement validation, persistence, and other business logic. | ||
Hooks receive a `next` function as the last argument, which must be called | ||
to continue firing subsequent listeners. Subsequent hooks will not be run | ||
if `next` receives any arguments. Arguments received by `next` are passed to | ||
the callback of the method that fired the event. | ||
```javascript | ||
User.before('get', function (query, next) { | ||
// do something before save such as validation and then call next() | ||
User.hook('get', function (query, next) { | ||
// retrieve user from storage using query | ||
db.getUser(query, next); | ||
}); | ||
``` | ||
User.on('patch', function (query, changed) { | ||
// do something after update | ||
Collection hooks are prefixed with `collection:`: | ||
```javascript | ||
User.hook('collection:get', function (query, next) { | ||
// ... | ||
}); | ||
``` | ||
See the full [documentation for events](docs/API.md#module_mio.Resource.before). | ||
See the full [documentation for hooks](docs/API.md#module_mio.Resource.hook). | ||
In addition to hooks, synchronous events are fired after resource actions and | ||
other resource events like attribute changes. | ||
```javascript | ||
User | ||
.on('patch', function (query, changed) { | ||
// do something after update | ||
}) | ||
.on('change:name', function (user, value, prev) { | ||
// ... | ||
}); | ||
``` | ||
See the full [documentation for events](docs/API.md#module_mio.Resource.on). | ||
Hooks and events can also be registered when extending a resource: | ||
```javascript | ||
var User = mio.Resource.extend({ | ||
attributes: { | ||
id: { | ||
primary: true | ||
} | ||
} | ||
}, { | ||
hooks: { | ||
'post': [function (representation, next) { | ||
// ... | ||
}] | ||
}, | ||
events: { | ||
'initialize': [function (resource, attributes) { | ||
// ... | ||
}] | ||
} | ||
}); | ||
``` | ||
### Relations | ||
@@ -194,2 +351,7 @@ | ||
}); | ||
// fetch book by related author | ||
Boook.get().where({ | ||
'author.name': 'alex' | ||
}).exec(function(function (err, book) {...}); | ||
``` | ||
@@ -196,0 +358,0 @@ |
Sorry, the diff of this file is too big to display
421448
13913
426