{"_id":"apiman","_rev":"29-687fb64dc965718c30f5acc7ad3c8743","name":"apiman","description":"Generic API methods manager","dist-tags":{"latest":"1.0.1"},"versions":{"0.0.1":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.0.1","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.9"},"devDependencies":{"vows":"0.7.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type')\n    .param(2, 'command', function(req, res, next, value){\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index, [, callback])` Resource method \nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output: `function(err, result)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user');\n\nuser.method('load', function(req, res){/*...*/});\nuser.method('save', function(req, res){/*...*/});\nuser.method('del', function(req, res){/*...*/});\nuser.method('block', function(req, res){/*...*/});\nuser.method('list', function(req, res){/*...*/});\n\nuser.map('express', function(path, verb){\n    // Trick the incoming (path,verb)\n    switch (path){\n        case '': // endpoint\n            return [\n                path, \n                // Change the verb\n                {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n            ];\n        case '/list': // fake path\n            return ['', 'list']; // route to the method\n        case '/block':\n            return ['', 'block'];\n    }\n    return undefined; // unchanged\n});\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb)` pair, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.0.1","dist":{"shasum":"c320e7ba33dbd14be9482b6277442c1e89652e5c","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.0.1.tgz","integrity":"sha512-YPwk6PVJ2UdqugDMeB86IvPCQC2X1/8350IxVdJEOohNWQ95EMvSr9PfSxa/2adlZD3KKMWaXagO5p8QDMd0jw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDhVMlINpI2N5QCz8h/FmMrwl5yuAF5XlHYCTOJLIb5gAIhAMjF0jvMpok15xl/T7ZBN7SCQhZcRJt1OUM/5zCGySlZ"}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.0.2":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.0.2","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.9"},"devDependencies":{"vows":"0.7.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, 'command', function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    Alternatively, you can just provide a name and the handler will just copy it.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output: `function(err, result)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user');\n\nuser.method('load', function(req, res){/*...*/});\nuser.method('save', function(req, res){/*...*/});\nuser.method('del', function(req, res){/*...*/});\nuser.method('block', function(req, res){/*...*/});\nuser.method('list', function(req, res){/*...*/});\n\nuser.map('express', function(path, verb){\n    // Trick the incoming (path,verb)\n    switch (path){\n        case '': // endpoint\n            return [\n                path, \n                // Change the verb\n                {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n            ];\n        case '/list': // fake path\n            return ['', 'list']; // route to the method\n        case '/block':\n            return ['', 'block'];\n    }\n    return undefined; // unchanged\n});\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb)` pair, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.0.2","dist":{"shasum":"10ebf072b6cb40bffcef1430ff9899972a4e7d76","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.0.2.tgz","integrity":"sha512-Ee2KGQmIl7wSjPsTTWv1aHPk9sS1WwHqAvQhcyiEyuuvfijM+0nvGVZzWbDsp4AkwPwIKQ1Fr6uXN9Jatsa3Ag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICtjQuUhChbNVcJ+DIIify3oWs3ROQ+7JWXs84wq3TPQAiEAj3UJmgLASdgaJ55R9Hk7FiJTjawhTpCybnyOfGb8Ehs="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.0.3":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.0.3","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.9"},"devDependencies":{"vows":"0.7.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    Alternatively, you can just provide a name and the handler will just copy it.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output: `function(err, result)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(path, verb, prev){\n    // Trick the incoming (path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.0.3","dist":{"shasum":"1a021a0021d63e90e74f93f336a3455c084cd4e7","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.0.3.tgz","integrity":"sha512-LoHykDYpZhtUcMv5osBQGaOjhq3HnMlIrXPDfhD0+C9ntMw/lD+7nrU7z2mIu4n4njhW3ChOkcWgwm1qO4ncOw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGtP0FRnJEE2QVjvI9TQYyJeoAEs8/lCU5vWpUSk2v7gAiEAjw+HT45sgI4R13NDRHXhBC+DHGd+aLA1AgVmdSlmZCg="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.0.4":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.0.4","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.9"},"devDependencies":{"vows":"0.7.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `EventEmitter#method (method: Method)`: called before a method under this resource is executed\n* `EventEmitter#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    Alternatively, you can just provide a name and the handler will just copy it.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output: `function(err, result)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(path, verb, prev){\n    // Trick the incoming (path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.0.4","dist":{"shasum":"89bfa168d1c721e0031a076493ee79d8a99bed81","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.0.4.tgz","integrity":"sha512-TrSv+7049GRjjH7v26trcA7lQ6LNlkcBnVuqukF+DT3WS2S0+YXANyS2uok+ZscYg2C34kAtLriz700r+AKU9A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBlzFjajqW2ppYBWlPhcHszj4Dpr8u5ODMWgQo5mkAITAiADsuEhtGeBiNdQOfXaEyqugW/EwzI4wvniihD+MYFfEg=="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.0.5":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.0.5","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.9"},"devDependencies":{"vows":"0.7.x","connect":"2.11.x","uid2":"0.0.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `Request#method (method: Method)`: called before a method under this resource is executed\n* `Request#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    Alternatively, you can just provide a name and the handler will just copy it.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output and the `Request` object: `function(err, result, req)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(path, verb, prev){\n    // Trick the incoming (path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n\n\n\n\n\n\nBundled Middleware\n==================\n\nAll bundled middleware comes in `require('apiman').middleware` module.\n\napiman.middleware.session\n-------------------------\n\nA compatible port of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto use the same `Session` object API and the session Store backends\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n    :::javascript\n    var root = new apiman.Root;\n    root.use(apiman.middleware.session({\n        // Session store backend, Connect-compatible.\n        // When unspecified, uses MemoryStore\n        store: new connect.session.MemoryStore(),\n        // Maximum session lifetime in milliseconds.\n        // `null` produces a single-connection session.\n        maxAge: 60*60*24 *1000, // 1 day\n        // Session id is signed with this secret to prevent tampering\n        // NOTE: not implemented!\n        secret: 'cockatoo parrot'\n    });\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.0.5","dist":{"shasum":"3b8eb91b1b3bfdc9c20889835bae81c279a1031e","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.0.5.tgz","integrity":"sha512-hpbOwfGe5qxcQBS9uZtOe1ZoWWsGQxxeJ20tX+EbX9HrYSJG1Q2ALxG+Hjz5GKDaeAq4MUVbn7oYiTtzOzjlvg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC3U7wC8WEx3ddGxNXDbnz8rvg6t1LeJC0Y5i0Gwx88XAIgCF9ZGsqLWnMospLhb0fvAvsLf9ySvB5cgNtFi4/sC1k="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.0.6":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.0.6","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.9"},"devDependencies":{"vows":"0.7.x","connect":"2.11.x","uid2":"0.0.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `Request#method (method: Method)`: called before a method under this resource is executed\n* `Request#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    Alternatively, you can just provide a name and the handler will just copy it.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output and the `Request` object: `function(err, result, req)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(path, verb, prev){\n    // Trick the incoming (path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n\n\n\n\n\n\nBundled Middleware\n==================\n\nAll bundled middleware comes in `require('apiman').middleware` module.\n\napiman.middleware.session\n-------------------------\n\nA compatible port of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto use the same `Session` object API and the session Store backends\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a single-connection session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.0.6","dist":{"shasum":"a1d0afbf308e7a3b7088fca91551b3012cf07229","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.0.6.tgz","integrity":"sha512-9kS0j27kwGM5TJisC0ebKmLMoJTATQ4ua1pjCeYXdUfhsHsl6DTjcN993+wR9IKicTVQlDkRfzBMQW+jzy8PNQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCJ3OIJcvniB/IraFCjiD9TbCheUUvoaAPNaSuVe9BDvwIhAK1LtpRQZOTCjbuneBcdy5FjS5MM3PsM0FR7otogJPeM"}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.0.7":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.0.7","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.x"},"devDependencies":{"vows":"0.7.x","connect":"2.11.x","uid2":"0.0.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `Request#method (method: Method)`: called before a method under this resource is executed\n* `Request#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    Alternatively, you can just provide a name and the handler will just copy it.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n### Express-style parameters\nApiMan provides a convenience wrapper which allows you to use Express-style parameters:\n\n`Resource.xresource(path, opts)`\n\n- `path` is the Express-style path with `:named` parameters:\n\n    Use `:name` for required parameters.\n    Use `:name?` for optional parameters.\n\n- `opts` is an optional object to tune the parameter behavior.\n    Maps parameter names to `{{ regex: RegExp?, proc: funtion(req:Request, value:*):* }}`\n\n    `regex` is an alternative RegExp. The default is `[^/]+`.\n\n    `proc` is a preprocessor function with two arguments: the request, and the captured value.\n\nExample:\n\n```js\nroot.xresource('/user-:login/profile/:type/:id?/:option?', {\n    id: { regex: '\\\\d+' },\n    type: { proc: function(req, value){\n        if (value !== 'personal')\n            throw new Error('Invalid profile type: ' + value);\n        return value.toUpperCase();\n    } }\n}).method('get', function(req, res){\n    res.ok({\n        login: req.params.login,\n        type: req.params.type,\n        id: req.params.id || undefined,\n        option: req.params.option || ''\n    });\n});\n```\n\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output and the `Request` object: `function(err, result, req)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(path, verb, prev){\n    // Trick the incoming (path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n\n\n\n\n\n\nBundled Middleware\n==================\n\nAll bundled middleware comes in `require('apiman').middleware` module.\n\napiman.middleware.session\n-------------------------\n\nA compatible port of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto use the same `Session` object API and the session Store backends\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a single-connection session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.0.7","dist":{"shasum":"76dedce2a6eb02a138278e6ef77ecbfcc71948a9","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.0.7.tgz","integrity":"sha512-Rb8lIuVjINoiZTBr/wz4cFtIqGrFHEh1tWf/CX/Wv8WkDMGVAZV5RtdFpyWjNMpnNLtCd7ue4QsZ5/pQx8f7KQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBq5WShb4nYZpQWOeuj0z0YdPe/IFVGZiwnMRcrAD5M2AiEAxaH/JW1vJoqlbub8c4WAC8jkbsztgZkdQnUlDTbJJAg="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.1.0":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.1.0","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.x"},"devDependencies":{"vows":"0.7.x","connect":"2.11.x","uid2":"0.0.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `Request#method (method: Method)`: called before a method under this resource is executed\n* `Request#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    Alternatively, you can just provide a name and the handler will just copy it.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n### Express-style parameters\nApiMan provides a convenience wrapper which allows you to use Express-style parameters:\n\n`Resource.xresource(path, opts)`\n\n- `path` is the Express-style path with `:named` parameters:\n\n    Use `:name` for required parameters.\n    Use `:name?` for optional parameters.\n\n- `opts` is an optional object to tune the parameter behavior.\n    Maps parameter names to `{{ regex: RegExp?, proc: funtion(req:Request, value:*):* }}`\n\n    `regex` is an alternative RegExp. The default is `[^/]+`.\n\n    `proc` is a preprocessor function with two arguments: the request, and the captured value.\n\nExample:\n\n```js\nroot.xresource('/user-:login/profile/:type/:id?/:option?', {\n    id: { regex: '\\\\d+' },\n    type: { proc: function(req, value){\n        if (value !== 'personal')\n            throw new Error('Invalid profile type: ' + value);\n        return value.toUpperCase();\n    } }\n}).method('get', function(req, res){\n    res.ok({\n        login: req.params.login,\n        type: req.params.type,\n        id: req.params.id || undefined,\n        option: req.params.option || ''\n    });\n});\n```\n\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output and the `Request` object: `function(err, result, req)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(path, verb, prev){\n    // Trick the incoming (req,path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n\n\n\n\n\n\nBundled Middleware\n==================\n\nAll bundled middleware comes in `require('apiman').middleware` module.\n\napiman.middleware.session\n-------------------------\n\nA compatible port of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto use the same `Session` object API and the session Store backends\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a single-connection session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.1.0","dist":{"shasum":"f1f7af25b4fa8f2ef7ad76acc3d277661f5079b6","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.1.0.tgz","integrity":"sha512-DFxec1dqfIT6JX85Dacj2NfCW5NFPIEMMlYkUxyTpJi7MNB3HAKMtg6//nDaHjLJi5/tNrTn2UydYuSLknU+9A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICRX8F9/NoYXwmQE4yCmFfXRpKmyXHuDrUnuEvJlUYtPAiEAoeWVGTJEj3ETaIohk+0UUG+AdrH2OuL3jed0cqMP4ls="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.1.1":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.1.1","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.x"},"devDependencies":{"vows":"0.7.x","connect":"2.11.x","uid2":"0.0.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `Request#method (method: Method)`: called before a method under this resource is executed\n* `Request#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`. The function is a middleware.\n\n    Alternatively, you can just provide a name and the handler will just copy it.\n\n    Finally, by providing a function with the arity of 2, `function(req, value)`, you\n    can bind non-middleware parameters at the request phase: useful to have parameters accessible from mappers.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n### Express-style parameters\nApiMan provides a convenience wrapper which allows you to use Express-style parameters:\n\n`Resource.xresource(path, opts)`\n\n- `path` is the Express-style path with `:named` parameters:\n\n    Use `:name` for required parameters.\n    Use `:name?` for optional parameters.\n\n- `opts` is an optional object to tune the parameter behavior.\n    Maps parameter names to `{{ regex: RegExp?, proc: funtion(req:Request, value:*):* }}`\n\n    `regex` is an alternative RegExp. The default is `[^/]+`.\n\n    `proc` is a preprocessor function with two arguments: the request, and the captured value.\n        Like normal params, it also can be a middleware: `function(req, res, next, value)`.\n\nExample:\n\n```js\nroot.xresource('/user-:login/profile/:type/:id?/:option?', {\n    id: { regex: '\\\\d+' },\n    type: { proc: function(req, value){\n        if (value !== 'personal')\n            throw new Error('Invalid profile type: ' + value);\n        return value.toUpperCase();\n    } }\n}).method('get', function(req, res){\n    res.ok({\n        login: req.params.login,\n        type: req.params.type,\n        id: req.params.id || undefined,\n        option: req.params.option || ''\n    });\n});\n```\n\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output and the `Request` object: `function(err, result, req)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(req, path, verb, prev){\n        // Trick the incoming (req,path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n\n\n\n\n\n\nBundled Middleware\n==================\n\nAll bundled middleware comes in `require('apiman').middleware` module.\n\napiman.middleware.session\n-------------------------\n\nA compatible port of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto use the same `Session` object API and the session Store backends\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a single-connection session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.1.1","dist":{"shasum":"d9eb0390fea354b8eef0b9c7137eacd0720bc488","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.1.1.tgz","integrity":"sha512-t11j0X45Eoo/ojZQ1Vlpg7d4XDFV3EjG24DLRS2ENwP5z37GgTjKmIZ7jc+7AS1uLEszcLuYayP3cDoH74jbyA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD5cqydlEGamiExlGdtIk3/pSyisLk7oukbQ5GyjVbb1gIhANhEnD5xGXkYIQI5yFGuZHQyEJXSuMtw2WOKpQIuQNuU"}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.1.2":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.1.2","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"underscore":"1.5.x","async":"0.2.x"},"devDependencies":{"vows":"0.7.x","connect":"2.11.x","uid2":"0.0.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `Request#method (method: Method)`: called before a method under this resource is executed\n* `Request#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`. The function is a middleware.\n\n    Alternatively, you can just provide a name and the handler will just copy it.\n\n    Finally, by providing a function with the arity of 2, `function(req, value)`, you\n    can bind non-middleware parameters at the request phase: useful to have parameters accessible from mappers.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n### Express-style parameters\nApiMan provides a convenience wrapper which allows you to use Express-style parameters:\n\n`Resource.xresource(path, opts)`\n\n- `path` is the Express-style path with `:named` parameters:\n\n    Use `:name` for required parameters.\n    Use `:name?` for optional parameters.\n\n- `opts` is an optional object to tune the parameter behavior.\n    Maps parameter names to `{{ regex: RegExp?, proc: funtion(req:Request, value:*):* }}`\n\n    `regex` is an alternative RegExp. The default is `[^/]+`.\n\n    `proc` is a preprocessor function with two arguments: the request, and the captured value.\n        Like normal params, it also can be a middleware: `function(req, res, next, value)`.\n\nExample:\n\n```js\nroot.xresource('/user-:login/profile/:type/:id?/:option?', {\n    id: { regex: '\\\\d+' },\n    type: { proc: function(req, value){\n        if (value !== 'personal')\n            throw new Error('Invalid profile type: ' + value);\n        return value.toUpperCase();\n    } }\n}).method('get', function(req, res){\n    res.ok({\n        login: req.params.login,\n        type: req.params.type,\n        id: req.params.id || undefined,\n        option: req.params.option || ''\n    });\n});\n```\n\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nAccessing Resources by Name\n---------------------------\nLike in the examples above, you mostly define methods using a variable with the created resource.\n\nFor highest modularity, you may want to assign names to your resources so other modules can add more methods to them:\n\n```js\nvar root = new apiman.Root();\n\nroot.xresource('/user/:uid').setName('user')\n        .xresource('/device/:id').setName('device')\n            .xresource('/command/:name').setName('command');\n\n// Other module:\nroot.getResource(['user', 'device', 'command'])\n    .method('exec', function(req, res){ ... });\n```\n\nThe following methods are there for you:\n\n`Resource.setName(name: String):Resource`: Specify a name for the resource. Returns the same resource\n\n`Resource.getFullName(): String?`: Get the full name of the current resource as an array\n\n`Resource.getResource(names: Array.<String>): Resource?`: Get a resource by hierarchical name\n\n`Reource.getResourcesMap()`: Generate a purely informational map of named resources under this one.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output and the `Request` object: `function(err, result, req)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(req, path, verb, prev){\n        // Trick the incoming (req,path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n\n\n\n\n\n\nBundled Middleware\n==================\n\nAll bundled middleware comes in `require('apiman').middleware` module.\n\napiman.middleware.session\n-------------------------\n\nA compatible port of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto use the same `Session` object API and the session Store backends\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a single-connection session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"_id":"apiman@0.1.2","dist":{"shasum":"5c3bc37135d2d6d186ed5fc10ab661f0298fabc7","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.1.2.tgz","integrity":"sha512-ahFfz6dDHIzW/Z1HMUsMGt7LwE9X+jeFQAOilHsC6fR/OPWtn0M5t67vXpOrOSDUUi9hJQZkF9CYk/AF/D996w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBC4L6Ff3mgGHtEkkPI2PSGNgfVTISXRVnXnoCne7IB2AiBCPzzwrlXUZ6DRR38EnUCFHE6n1iAlvQ8yDBUr7Zpr0w=="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"0.1.3":{"name":"apiman","description":"Protocol-agnostic API methods manager","version":"0.1.3","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","rest","express"],"dependencies":{"lodash":"2.4.x","async":"0.2.x"},"devDependencies":{"vows":"0.7.x","connect":"2.11.x","uid2":"0.0.x"},"engines":{"node":">= 0.9.0"},"scripts":{"test":"vows tests/*-test.js tests/**/*-test.js --spec"},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\n```\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\nRequest extends the `events.EventEmitter` with the following events:\n\n* `Request#method (method: Method)`: called before a method under this resource is executed\n* `Request#done (err: Object?, result: *)`: called after a method has finished\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('^/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type') // Named param\n    .param(2, function(req, res, next, value){ // Middleware param\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n        req.params.device_type;\n        req.params.command;\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index[, callback])` Resource method\nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`. The function is a middleware.\n\n    Alternatively, you can just provide a name and the handler will just copy it.\n\n    Finally, by providing a function with the arity of 2, `function(req, value)`, you\n    can bind non-middleware parameters at the request phase: useful to have parameters accessible from mappers.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n### Express-style parameters\nApiMan provides a convenience wrapper which allows you to use Express-style parameters:\n\n`Resource.xresource(path, opts)`\n\n- `path` is the Express-style path with `:named` parameters:\n\n    Use `:name` for required parameters.\n    Use `:name?` for optional parameters.\n\n- `opts` is an optional object to tune the parameter behavior.\n    Maps parameter names to `{{ regex: RegExp?, proc: funtion(req:Request, value:*):* }}`\n\n    `regex` is an alternative RegExp. The default is `[^/]+`.\n\n    `proc` is a preprocessor function with two arguments: the request, and the captured value.\n        Like normal params, it also can be a middleware: `function(req, res, next, value)`.\n\nExample:\n\n```js\nroot.xresource('/user-:login/profile/:type/:id?/:option?', {\n    id: { regex: '\\\\d+' },\n    type: { proc: function(req, value){\n        if (value !== 'personal')\n            throw new Error('Invalid profile type: ' + value);\n        return value.toUpperCase();\n    } }\n}).method('get', function(req, res){\n    res.ok({\n        login: req.params.login,\n        type: req.params.type,\n        id: req.params.id || undefined,\n        option: req.params.option || ''\n    });\n});\n```\n\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n    .method('set', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nAccessing Resources by Name\n---------------------------\nLike in the examples above, you mostly define methods using a variable with the created resource.\n\nFor highest modularity, you may want to assign names to your resources so other modules can add more methods to them:\n\n```js\nvar root = new apiman.Root();\n\nroot.xresource('/user/:uid').setName('user')\n        .xresource('/device/:id').setName('device')\n            .xresource('/command/:name').setName('command');\n\n// Other module:\nroot.getResource(['user', 'device', 'command'])\n    .method('exec', function(req, res){ ... });\n```\n\nThe following methods are there for you:\n\n`Resource.setName(name: String):Resource`: Specify a name for the resource. Returns the same resource\n\n`Resource.getFullName(): String?`: Get the full name of the current resource as an array\n\n`Resource.getResource(names: Array.<String>): Resource?`: Get a resource by hierarchical name\n\n`Reource.getResourcesMap()`: Generate a purely informational map of named resources under this one.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output and the `Request` object: `function(err, result, req)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user')\n    .method('load', function(req, res){/*...*/});\n    .method('save', function(req, res){/*...*/});\n    .method('del', function(req, res){/*...*/});\n    .method('block', function(req, res){/*...*/});\n    .method('list', function(req, res){/*...*/});\n\n    .map('express', function(req, path, verb, prev){\n        // Trick the incoming (req,path,verb,prev)\n        switch (path){\n            case '': // endpoint\n                return [\n                    path,\n                    // Change the verb\n                    {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n                ];\n            case '/list': // fake path\n                return ['', 'list']; // route to the method\n            case '/block':\n                return ['', 'block'];\n        }\n        return undefined; // unchanged\n    });\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb,prev)` triple, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed. `match` is the current matching part.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n\n\n\n\n\n\nBundled Middleware\n==================\n\nAll bundled middleware comes in `require('apiman').middleware` module.\n\napiman.middleware.session\n-------------------------\n\nA compatible port of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto use the same `Session` object API and the session Store backends\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a single-connection session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"homepage":"https://github.com/kolypto/nodejs-apiman","_id":"apiman@0.1.3","dist":{"shasum":"9d4202328f4fad09205c5ff91f13e09d1aa111a1","tarball":"https://registry.npmjs.org/apiman/-/apiman-0.1.3.tgz","integrity":"sha512-kuP/m/AFFXl15FHDqP4FlOBZL1pzMhz6e3CSTngIyBb9Duk5FdaAPRLiSbniPUvGQHgF0VJ3UppqZKJ5eZWzDQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKVK+nV5YMX4eUKSa0K3NAdhdql6Pe9k1F7hk/MOBYPgIhAOMKgz8hyEwRfIlMuFXr7wvWuT1ylGwP4kQiYRQhRHoQ"}]},"_from":".","_npmVersion":"1.3.14","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"1.0.0":{"name":"apiman","description":"Generic API methods manager","version":"1.0.0","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","express"],"dependencies":{"lodash":"2.4.x","q":"0.9.x"},"devDependencies":{"nodeunit":"0.8.x","connect":"2.12.x","uid2":"0.0.x"},"engines":{"node":">= 0.10.0"},"scripts":{"test":"./node_modules/.bin/nodeunit tests/*-test.js"},"readme":"[![Version](https://badge.fury.io/js/apiman.png)](https://npmjs.org/package/apiman)\n[![Dependency Status](https://gemnasium.com/kolypto/nodejs-apiman.png)](https://gemnasium.com/kolypto/nodejs-apiman)\n[![Build Status](https://travis-ci.org/kolypto/nodejs-apiman.png?branch=master)](https://travis-ci.org/kolypto/nodejs-apiman)\n\nApiMan\n======\n\nGeneric API methods manager that is exportable to arbitrary protocols, including HTTP and websockets.\n\nKey features:\n\n* Hierarchical API methods stored on Resources\n* Middleware support\n* Promise-based: using the [q](https://npmjs.org/package/q) package\n* Full unit-tests\n\nThe Motivation\n--------------\n\nFor a REST API, Express is a great choice, but imagine you\nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to\nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication?\nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\n\n\n\nTable of Contents\n=================\n\n* <a href=\"#core-components\">Core Components</a> \n    * <a href=\"#resource-root\">Resource, Root</a> \n        * <a href=\"#resourceresourcepathresource\">Resource.resource(path):Resource</a> \n    * <a href=\"#method\">Method</a> \n        * <a href=\"#resourcemethodverbs-middleware---methodresource\">Resource.method(verbs[, middleware, ..., ], method):Resource</a> \n    * <a href=\"#request\">Request</a> \n    * <a href=\"#response\">Response</a> \n        * <a href=\"#responsesenderr-result\">Response.send(err, result)</a> \n        * <a href=\"#responseokresult\">Response.ok(result)</a> \n        * <a href=\"#responseerrorerr\">Response.error(err)</a> \n        * <a href=\"#responseispendingboolean\">Response.isPending():Boolean</a> \n* <a href=\"#middleware\">Middleware</a> \n    * <a href=\"#method-middleware\">Method Middleware</a> \n    * <a href=\"#resource-middleware\">Resource Middleware</a> \n        * <a href=\"#resourceusemiddleware-resource\">Resource.use(middleware[, ...]):Resource</a> \n* <a href=\"#executing-methods\">Executing Methods</a> \n    * <a href=\"#public-api\">Public API</a> \n        * <a href=\"#resourceexecpath-verb-args-reqq\">Resource.exec(path, verb, args, req):Q</a> \n    * <a href=\"#internal-methods\">Internal Methods</a> \n        * <a href=\"#resourcewhichpath-verb-requestmethod\">Resource.which(path, verb[, request]):Method?</a> \n        * <a href=\"#resourcerequestrequestresponse\">Resource.request(request):Response</a> \n    * <a href=\"#handling-results\">Handling Results</a> \n    * <a href=\"#prefix-matching\">Prefix Matching</a> \n* <a href=\"#special-features\">Special Features</a> \n    * <a href=\"#endpoint-resources\">Endpoint Resources</a> \n        * <a href=\"#resourceendpointmethodmiddleware--methodresource\">Resource.endpointMethod([middleware, ...], method):Resource</a> \n    * <a href=\"#controller-methods\">Controller Methods</a> \n        * <a href=\"#resourcecontrollermethodsctrlresource\">Resource.controllerMethods(ctrl):Resource</a> \n* <a href=\"#bundled-middleware\">Bundled Middleware</a> \n    * <a href=\"#session-middleware\">Session Middleware</a> \n\n\n\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA Resource is a collection of sub-resources, middleware and methods that is identified by path.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of\na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nYou create a Root resource first, then continue defining the resources on it.\nThe Root is actually a resource with an empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any\nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\nuser.path; // Parent resource\n```\n\n### Resource.resource(path):Resource\nAdd a new child Resource and assign a `path` to it.\n\nReturns: the new `Resource` object.\n\n\n\nMethod\n------\n\nAfter you have set up the resources hierarchy, you can define methods on them, including the Root.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of  a `Resource`:\n\n```js\nuser_profile.method('save', function(req, res){\n    return save_to_db(req.args.user)\n        .then(function(){\n            res.ok({saved: true, id: id});\n        });\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects. Use them to access the request data and\nsend responses.\n\nThe method should return a promise which is resolved when the method sends a result with [`Response.send()`](#responsesenderr-result).\n\n### Resource.method(verbs[, middleware, ..., ], method):Resource\nAdd a Method to the Resource.\n\nArguments:\n\n* `verbs: String|Array.<String>`: Method name, or an array of names.\n    Later, the method will be available under this name.\n* `middleware: function(req: Request, res: Response):Q`:\n    Optionally provide an array of middleware methods that will be called before the method itself.\n    See: [Middleware](#middleware).\n* `method: function(req: Request, res: Response):Q`:\n    The method function.\n\n\n\nRequest\n-------\n\nThe `Request` object is created for each request and contains the info about the request: resource path, method name,\nmethod arguments, fields added by the middleware, etc.\n\nThe `Request` object has the following properties:\n\n* `req.path`: The requested resource:\n    `'/user/profile'`\n* `req.verb`: The requested method:\n    `'save'`\n* `req.args`: Method arguments object:\n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_arr`: An array of path components split on matched resources:\n    `['/user', '/profile']`\n* `req.path_tail`: The remaining path suffix that's left after matching the resources.\n\n\n\nResponse\n--------\n\nThe `Response` object is created coupled with the corresponding `Request` to handle the results of a method call:\na method reports errors and sends results through it.\n\nResponse has two *channels* to send the results with:\n\n* *System channel*:\n    A promise which is automatically resolved when the middleware and the method has finished successfully.\n    If there was an unhandled exception, the promise is rejected with a *runtime error*.\n    This logic is handled by the `Response.system` promise.\n* *Result channel*:\n    A promise which is manually resolved by the middleware or the method using `Response.send()`.\n    This returns a result, or an expected erorr.\n    This logic is handled by the `Response.result` promise.\n\nThis separation allows to differentiate unexpected erorrs and expected error responses:\nthe *System channel* reports unexpected runtime errors, while the\n*Result channel* handles the expected results, including errors, which are usually send to the client as is.\n\n### Response.send(err, result)\nSend a result to the client: either an error or a successful result.\n\nNote: when a promise, returned by a method, is resolved without sending any response, ApiMan creates a \"No response sent\"\nerror:\n\n```js\nroot.method('empty', function(req, res){\n    save_to_db(req.user, function(err){\n        res.send(err, { ok: true }); // send an error, or an \"ok\" response\n    });\n\n    // the method returns nothing, so the response is resolved before callback function is called.\n    // This results in a \"No response sent\" error.\n});\n```\n\nThis logic actually ensures that you'll never have your requests hanging indefinitely if a method does not send anything,\nfor instance, in case of a runtime error.\n\nTo make the above code error-prone, just return a promise which resolves once all operations are finished.\n\n### Response.ok(result)\nConvenience method that wraps `Response.send(undefined, result)`\n### Response.error(err)\nConvenience method that wraps `Response.send(err, undefined)`\n\n### Response.isPending():Boolean\nCheck whether the response is in *pending* state: did not explicitly send any result.\n\nWhen any middleware or method uses `Response.send()`, the Response is resolved and no subsequent middleware/method\nis executed. In other words, if a middleware function sends a response, the method is not executed.\n\n\n\n\n\n\nMiddleware\n==========\nA middleware function is no different from the Method function: it accepts the `Request`, `Response` objects as arguments\nand can send responses.\n\nThe difference is that the middleware is called before the Method function, and the middleware can be assigned to both\nResources and Methods.\n\n\n\nMethod Middleware\n-----------------\nLike in Express, each method can use an arbitrary list of middleware functions which are specified before the method\nfunction. See: [Resource.method()](#resourcemethodverbs-middleware---methodresource).\n\n```js\n// Middleware function\nvar adminOnly = function(req, res){\n    // Middleware\n    if (!req.user.isAdmin)\n        res.error('This action is forbidden for non-admin users');\n};\n\nuser.method('delete',\n    adminOnly, // middleware\n    function(req, res){ // method function\n        return db_delete(req.user_id); // remove the user\n    }\n);\n```\n\nNote that if any middleware sends a response, no subsequent middleware are executed, nor the method itself.\n\n\n\nResource Middleware\n-------------------\nMoreover, a middleware can be attached to a `Resource`: it will be executed for all methods of the resource itself\nas well as for the methods of sub-resources:\n\n```js\nadmin = root.resource('/admin');\nadmin.use(adminOnly); // all methods & sub-resources are not admin-only\n```\n\n### Resource.use(middleware[, ...]):Resource\nUse the given middleware functions for the Resource.\n\n\n\n\n\n\nExecuting Methods\n=================\nAfter the Resource hierarchy and the methods are set up, you can call the methods by resource path and method name.\n\nPublic API\n----------\n\n### Resource.exec(path, verb, args, req):Q\nLocate a method by `path` and `verb`, then execute it with `args`. Is usually called on the Root resource.\n\nArguments:\n\n* `path: String`: Path to some resource.\n* `verb: String`: Name of the method to execute.\n* `args: Object?`: Method arguments object.\n* `req: Object?`: Additional fields for the `Request` object. Useful to pre-populate the user session.\n  The provided object also receives all the fields set by ApiMan: see [Request](#request).\n\nReturns: A promise for a result, or an error. For runtime errors (reported through the [*System channel*](#response)), ApiMan sets\nthe Error object's `system` property to `true`: `err.system = true`.\n\nThis method does the following:\n\n1. Create the `Request` and `Response` objects\n2. Traverse the resources tree and find the matching resource with prefix matching.\n   For instance, `'/user/profile'` first matches the `'/user'` resource, then its `'/profile'` child resource.\n3. Find the method by name\n4. Executes all resource middleware down the matching resources chain\n5. Executed the method middleware and the method\n6. If any middleware has sent a response, no subsequent middleware is executed, nor the method is.\n7. If no response was sent, a \"No response sent\" error is reported\n8. A promise for a result is returned\n\nInternal Methods\n----------------\nWhile the `Resource.exec()` is usually enough, you might need these also.\n\n### Resource.which(path, verb[, request]):Method?\nFind a matching method by path and verb.\n\nArguments:\n\n* `path: String`: Path to the wanted resource\n* `verb: String`: Method name to look for\n* `request: Request?`: Optional `Request` object. Is used to populate its fields.\n\nReturns: The `Method` object, or `undefined` if not found.\n\n### Resource.request(request):Response\nProcess the provided Request and return a Response.\n\nThis method allows you to use a custom `Request` object and process the `Response` in an arbitrary fashion.\n\nHandling Results\n----------------\n\n```js\nroot.exec(\n    '/user', // path\n    'save', // method\n    { login: 'kolypto' }, // method arguments\n    {} // additional request fields\n)\n.then(function(result){\n    // success: we have the result\n})\n.catch(function(err){\n    // An error has occurred\n    if (err.system){\n        // runtime error: unhandled exception\n    } else {\n        // method error: reported with Response.send()\n    }\n});\n```\n\nPrefix Matching\n---------------\n\nGiven a path, ApiMan performs a case-sensitive precise prefix matching.\nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by\nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic\nby design and, potentially, all special characters might have a meaning.\nFor instance, you can use `'user.device.commands'` for resource names.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse multiple slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nSpecial Features\n================\n\nEndpoint Resources\n------------------\n\nYou can create Resources that consume all requests that go into it: such resources have a single function that\nhandles all requests.\n\n### Resource.endpointMethod([middleware, ...], method):Resource\nAdd an endpoint method on the Resource: the method that handles all requests that fall into the resource.\n\nThe `Request` object will have the `path_tail` property set to the remaining path suffix.\n\nArguments:\n\n* `middleware: function(req: Request, res: Response):Q`:\n    Optional middleware functions to use. See: [Method Middleware](#method-middleware)\n* `method: function(req: Request, res: Response):Q`:\n    The endpoint method to use.\n\nExample:\n\n```\nvar root = new apiman.Root(),\n    upload = root.resource('/upload')\n    ;\n\nupload.endpointMethod(function(req, res){\n    req.path_tail; // path suffix\n    req.verb; // arbitrary method name\n});\n\nroot.exec('/upload/file.txt', 'save', { file: ... })\n    .then(function(){\n        // upload saved\n    });\n```\n\n\n\nController Methods\n------------------\nAdding all the methods manually is not the only way to define them: you can feed a Resource with an arbitrary object,\nand ApiMan will import its methods. The MVC world knows this approach as *Controllers*.\n\n### Resource.controllerMethods(ctrl):Resource\nAdd methods from a controller object.\n\nApiMan imports a property only if:\n\n* It is a function (non-functional properties are ignored)\n* Its name does not start with an underscore `_` (protected members are ignored).\n\nArguments:\n\n* `ctrl: Object`: The controller to import the methods from.\n\nNotes:\n\n* All methods maintain the `this` binding: you can freely use controller fields and protected methods!\n* In order to set middleware functions for a method, put them in the `middleware` proeprty of the method function.\n\nExample:\n\n```js\n// Controller\nvar UserCtrl = function(something){ // constructor\n    this.something = something;\n};\n\nUserCtrl.prototype.get = function(req, res){ // method\n    res.ok({\n        something: this.something,\n        mw_worked: req.mw_worked,\n        login: 'kolypto'\n    });\n};\nUserCtrl.prototype.get.middleware = [ // middleware for the method\n    function(req, res){\n        req.mw_worked = 'yesss!';\n    }\n];\n\nUserCtrl.prototype.set = function(req, res){ // another method\n    res.ok({ ok: true });\n};\n\nUserCtrl.prototype._private = function(){};\n\n// Import an instantiated controller\nvar root = new apiman.Root(),\n    user = root.resource('/user')\n    ;\nuser.controllerMethods(new UserCtrl('anything'));\n```\n\nThis will make the '/user:get' and '/user:set' methods available.\n\n\n\n\n\n\nBundled Middleware\n==================\nAll bundled middleware comes in `require('apiman').middleware` module.\n\nSession Middleware\n------------------\n\nInitializer: `apiman.middleware.session()`\n\nPort of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto reuse the session Store backends,\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a one-shot session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n\nWhen a session middleware is in effect, the `Request` object gets the following extra fields:\n\n* `req.sessionID: String`: The session identifier string\n* `req.session: Object`: The persistent session object\n* `req.sessionStore: connect.Store`: The session store backend\n\nExample on how to make 2 requests using a single session:\n\n```js\nvar sessionID; // remember the session ID\n\n// First request: sign in, get the session\nvar req = {}; // sessionID will be stored here\n\nroot.exec('/login', 'login', { user: 'kolypto', pass: '1234' }, req)\n    .then(function(result){\n        // Successful login\n        // req.sessionID is populated\n        sessionID = req.sessionID; // keep it\n    })\n// Second request: use the same session id\n    .then(function(){\n        // use sessionID got from the previous request\n        return root.exec('/cart', 'show', {}, { sessionID: sessionID })\n            .then(function(result){\n                // fine\n            });\n    })\n    .done()\n    ;\n```\n\n\n\n\n\n\nExporting the APIs\n==================\n\nExpress\n-------\nAssuming you already have your APIs set up under the `root` Resource, let's export these to HTTP with\n[Express](https://npmjs.org/package/express).\n\nFirst, you need to decide on the conventions to use for:\n\n1. Method call convention.\n\n    Example: Using URI for Resource paths, method is provided after a colon `:`. the arguments are sent either through\n    the query params or in the request body as a JSON object.\n\n2. Successful responses\n\n    Example: encode the output as JSON, with HTTP code 200.\n\n3. Error responses:\n\n   Example: `{ error: { code: Number, message: String } }`, as JSON.\n   If the Error object has the `httpcode` property, send it as a code.\n\n3. Error responses and HTTP codes\n\n    Example: use HTTP code 400 by default.\n\n4. System Error responses and HTTP codes\n\n    Example: use HTTP code 500 by default.\n\nHere's a full solution that supports files, sessions, and handles errors correctly:\n\n```js\nvar express = require('express'),\n    _ = require('lodash')\n    ;\n\nvar root = new apiman.Root(); // assuming the resources and methods are defined\n\nvar app = express();\n\napp.use('/api', function(req, res){\n    // Input\n    var _pathmethod = req.path.split(':'),\n        path = _pathmethod[0], // resource path\n        verb = _pathmethod[1], // method name\n        args = _(req.body).extend(req.query), // combine query & body\n        apireq = { // additional fields for Request\n            files: req.files, // pass files\n            sessionID: req.cookies['sessionID'] // pass session cookie\n        }\n        ;\n\n    // Ensure a leading slash, no trailing slash, and collapse multiple slashes\n    path = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n\n    // Execute the method\n    root.exec(path, verb, args, apireq)\n        // Always\n        .finally(function(){\n            // Session cookie\n            if (apireq.session){\n                res.cookie(\n                    'sessionID',\n                    apireq.sessionID,\n                    { path: '/api', maxAge: 60*60*24*31 }\n                );\n            }\n        })\n        // Handle success\n        .then(function(result){\n            res.type('json').send(result);\n        })\n        // Handle error\n        .catch(function(err){\n            // Wrap the error object\n            var errResp = {\n                error: _.isObject(err)\n                    ? _.pick(err, 'code', 'message')\n                    : { message: err }\n            };\n\n            // System errors\n            if (err.system)\n                res.type('json').send(err.httpcode || 500, errResp);\n            else\n                res.type('json').send(err.httpcode || 400, errResp);\n        })\n        ;\n});\n```\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a\nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the\npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, result: Object, error: null }}`\n* Error:    `{{ id: Number, error: { code: Number, message: String } }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.exec(data.path, data.verb, data.args)\n            .then(function(result){\n                socket.emit('api.result', {\n                    id: data.id, // send the same id back\n                    result: result,\n                    error: null\n                });\n            })\n            .catch(function(err){\n                socket.emit('api.result', {\n                    id: data.id, // send the same id back\n                    result: null,\n                    error: err\n                });\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\napicall = function(path, verb, args, callback){\n    var request = {\n        id: apicall._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args || {}\n    };\n    apicall._wait[request.id] = callback;\n    socket.emit('api', request);\n};\napicall._id=0;\napicall._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    apicall._wait[data.id].apply(null, data.ret);\n});\n\n// Usage\napicall('/news', 'list', {}, function(err, news){\n    if (err){\n        // error :(\n    } else {\n        // yeehaw!\n    }\n});\n```\n\nWeak points:\n\n1. On reconnect, the response can't be received transparently\n2. The exposed error objects can potentially contain sensitive data like stack traces\n3. Callback-based interface: use promises instead\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"homepage":"https://github.com/kolypto/nodejs-apiman","_id":"apiman@1.0.0","dist":{"shasum":"6f03b8c145afa0f0ed6643b828d407cfe1b6cd33","tarball":"https://registry.npmjs.org/apiman/-/apiman-1.0.0.tgz","integrity":"sha512-Fc1+0ccO1j4ClF2g7bbOIPxlrhuwhoZIWq2TMaIP8BnQBMWag4MRvAYKoHO9YwmfD7rJw7fqYZ3XA1teQ/dEeQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDQPKJIxytOJ5C2Sf0XX04IfgcLs3pFhnW0P+6nhWSJKAiASHJX3zpjhozHYewqvfSnjGFbsS08gS8QubIDunD9uBw=="}]},"_from":".","_npmVersion":"1.3.17","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}},"1.0.1":{"name":"apiman","description":"Generic API methods manager","version":"1.0.1","author":{"name":"kolypto","email":"kolypto@gmail.com"},"license":"MIT","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"},"main":"./lib/index","keywords":["api","express"],"dependencies":{"lodash":"2.4.x","q":"0.9.x"},"devDependencies":{"nodeunit":"0.8.x","connect":"2.12.x","uid2":"0.0.x","express":"3.4.x","request":"2.30.x"},"engines":{"node":">= 0.10.0"},"scripts":{"test":"./node_modules/.bin/nodeunit tests/*-test.js"},"readme":"[![Version](https://badge.fury.io/js/apiman.png)](https://npmjs.org/package/apiman)\n[![Dependency Status](https://gemnasium.com/kolypto/nodejs-apiman.png)](https://gemnasium.com/kolypto/nodejs-apiman)\n[![Build Status](https://travis-ci.org/kolypto/nodejs-apiman.png?branch=master)](https://travis-ci.org/kolypto/nodejs-apiman)\n\nApiMan\n======\n\nGeneric API methods manager that is exportable to arbitrary protocols, including HTTP and websockets.\n\nKey features:\n\n* Hierarchical API methods stored on Resources\n* Middleware support\n* Promise-based: using the [q](https://npmjs.org/package/q) package\n* Full unit-tests\n\nThe Motivation\n--------------\n\nFor a REST API, Express is a great choice, but imagine you\nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to\nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication?\nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\n\n\n\nTable of Contents\n=================\n\n* <a href=\"#core-components\">Core Components</a> \n    * <a href=\"#resource-root\">Resource, Root</a> \n        * <a href=\"#resourceresourcepathresource\">Resource.resource(path):Resource</a> \n    * <a href=\"#method\">Method</a> \n        * <a href=\"#resourcemethodverbs-middleware---methodresource\">Resource.method(verbs[, middleware, ..., ], method):Resource</a> \n    * <a href=\"#request\">Request</a> \n    * <a href=\"#response\">Response</a> \n        * <a href=\"#responsesenderr-result\">Response.send(err, result)</a> \n        * <a href=\"#responseokresult\">Response.ok(result)</a> \n        * <a href=\"#responseerrorerr\">Response.error(err)</a> \n        * <a href=\"#responseispendingboolean\">Response.isPending():Boolean</a> \n* <a href=\"#middleware\">Middleware</a> \n    * <a href=\"#method-middleware\">Method Middleware</a> \n    * <a href=\"#resource-middleware\">Resource Middleware</a> \n        * <a href=\"#resourceusemiddleware-resource\">Resource.use(middleware[, ...]):Resource</a> \n* <a href=\"#executing-methods\">Executing Methods</a> \n    * <a href=\"#public-api\">Public API</a> \n        * <a href=\"#resourceexecpath-verb-args-reqq\">Resource.exec(path, verb, args, req):Q</a> \n    * <a href=\"#internal-methods\">Internal Methods</a> \n        * <a href=\"#resourcewhichpath-verb-requestmethod\">Resource.which(path, verb[, request]):Method?</a> \n        * <a href=\"#resourcerequestrequestresponse\">Resource.request(request):Response</a> \n    * <a href=\"#handling-results\">Handling Results</a> \n    * <a href=\"#prefix-matching\">Prefix Matching</a> \n* <a href=\"#special-features\">Special Features</a> \n    * <a href=\"#endpoint-resources\">Endpoint Resources</a> \n        * <a href=\"#resourceendpointmethodmiddleware--methodresource\">Resource.endpointMethod([middleware, ...], method):Resource</a> \n    * <a href=\"#controller-methods\">Controller Methods</a> \n        * <a href=\"#resourcecontrollermethodsctrlresource\">Resource.controllerMethods(ctrl):Resource</a> \n* <a href=\"#bundled-middleware\">Bundled Middleware</a> \n    * <a href=\"#session-middleware\">Session Middleware</a> \n\n\n\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA Resource is a collection of sub-resources, middleware and methods that is identified by path.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of\na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nYou create a Root resource first, then continue defining the resources on it.\nThe Root is actually a resource with an empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any\nconvention you're comfortable with.\n\nThe following properties may be useful:\n\n```js\nuser.root; // Reference to the root Resource\nuser.parent; // Parent resource\nuser.path; // Parent resource\n```\n\n### Resource.resource(path):Resource\nAdd a new child Resource and assign a `path` to it.\n\nReturns: the new `Resource` object.\n\n\n\nMethod\n------\n\nAfter you have set up the resources hierarchy, you can define methods on them, including the Root.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of  a `Resource`:\n\n```js\nuser_profile.method('save', function(req, res){\n    return save_to_db(req.args.user)\n        .then(function(){\n            res.ok({saved: true, id: id});\n        });\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects. Use them to access the request data and\nsend responses.\n\nThe method should return a promise which is resolved when the method sends a result with [`Response.send()`](#responsesenderr-result).\n\n### Resource.method(verbs[, middleware, ..., ], method):Resource\nAdd a Method to the Resource.\n\nArguments:\n\n* `verbs: String|Array.<String>`: Method name, or an array of names.\n    Later, the method will be available under this name.\n* `middleware: function(req: Request, res: Response):Q`:\n    Optionally provide an array of middleware methods that will be called before the method itself.\n    See: [Middleware](#middleware).\n* `method: function(req: Request, res: Response):Q`:\n    The method function.\n\n\n\nRequest\n-------\n\nThe `Request` object is created for each request and contains the info about the request: resource path, method name,\nmethod arguments, fields added by the middleware, etc.\n\nThe `Request` object has the following properties:\n\n* `req.path`: The requested resource:\n    `'/user/profile'`\n* `req.verb`: The requested method:\n    `'save'`\n* `req.args`: Method arguments object:\n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_arr`: An array of path components split on matched resources:\n    `['/user', '/profile']`\n* `req.path_tail`: The remaining path suffix that's left after matching the resources.\n\n\n\nResponse\n--------\n\nThe `Response` object is created coupled with the corresponding `Request` to handle the results of a method call:\na method reports errors and sends results through it.\n\nResponse has two *channels* to send the results with:\n\n* *System channel*:\n    A promise which is automatically resolved when the middleware and the method has finished successfully.\n    If there was an unhandled exception, the promise is rejected with a *runtime error*.\n    This logic is handled by the `Response.system` promise.\n* *Result channel*:\n    A promise which is manually resolved by the middleware or the method using `Response.send()`.\n    This returns a result, or an expected erorr.\n    This logic is handled by the `Response.result` promise.\n\nThis separation allows to differentiate unexpected erorrs and expected error responses:\nthe *System channel* reports unexpected runtime errors, while the\n*Result channel* handles the expected results, including errors, which are usually send to the client as is.\n\n### Response.send(err, result)\nSend a result to the client: either an error or a successful result.\n\nNote: when a promise, returned by a method, is resolved without sending any response, ApiMan creates a \"No response sent\"\nerror:\n\n```js\nroot.method('empty', function(req, res){\n    save_to_db(req.user, function(err){\n        res.send(err, { ok: true }); // send an error, or an \"ok\" response\n    });\n\n    // the method returns nothing, so the response is resolved before callback function is called.\n    // This results in a \"No response sent\" error.\n});\n```\n\nThis logic actually ensures that you'll never have your requests hanging indefinitely if a method does not send anything,\nfor instance, in case of a runtime error.\n\nTo make the above code error-prone, just return a promise which resolves once all operations are finished.\n\n### Response.ok(result)\nConvenience method that wraps `Response.send(undefined, result)`\n### Response.error(err)\nConvenience method that wraps `Response.send(err, undefined)`\n\n### Response.isPending():Boolean\nCheck whether the response is in *pending* state: did not explicitly send any result.\n\nWhen any middleware or method uses `Response.send()`, the Response is resolved and no subsequent middleware/method\nis executed. In other words, if a middleware function sends a response, the method is not executed.\n\n\n\n\n\n\nMiddleware\n==========\nA middleware function is no different from the Method function: it accepts the `Request`, `Response` objects as arguments\nand can send responses.\n\nThe difference is that the middleware is called before the Method function, and the middleware can be assigned to both\nResources and Methods.\n\n\n\nMethod Middleware\n-----------------\nLike in Express, each method can use an arbitrary list of middleware functions which are specified before the method\nfunction. See: [Resource.method()](#resourcemethodverbs-middleware---methodresource).\n\n```js\n// Middleware function\nvar adminOnly = function(req, res){\n    // Middleware\n    if (!req.user.isAdmin)\n        res.error('This action is forbidden for non-admin users');\n};\n\nuser.method('delete',\n    adminOnly, // middleware\n    function(req, res){ // method function\n        return db_delete(req.user_id); // remove the user\n    }\n);\n```\n\nNote that if any middleware sends a response, no subsequent middleware are executed, nor the method itself.\n\n\n\nResource Middleware\n-------------------\nMoreover, a middleware can be attached to a `Resource`: it will be executed for all methods of the resource itself\nas well as for the methods of sub-resources:\n\n```js\nadmin = root.resource('/admin');\nadmin.use(adminOnly); // all methods & sub-resources are not admin-only\n```\n\n### Resource.use(middleware[, ...]):Resource\nUse the given middleware functions for the Resource.\n\n\n\n\n\n\nExecuting Methods\n=================\nAfter the Resource hierarchy and the methods are set up, you can call the methods by resource path and method name.\n\nPublic API\n----------\n\n### Resource.exec(path, verb, args, req):Q\nLocate a method by `path` and `verb`, then execute it with `args`. Is usually called on the Root resource.\n\nArguments:\n\n* `path: String`: Path to some resource.\n* `verb: String`: Name of the method to execute.\n* `args: Object?`: Method arguments object.\n* `req: Object?`: Additional fields for the `Request` object. Useful to pre-populate the user session.\n  The provided object also receives all the fields set by ApiMan: see [Request](#request).\n\nReturns: A promise for a result, or an error. For runtime errors (reported through the [*System channel*](#response)), ApiMan sets\nthe Error object's `system` property to `true`: `err.system = true`.\n\nThis method does the following:\n\n1. Create the `Request` and `Response` objects\n2. Traverse the resources tree and find the matching resource with prefix matching.\n   For instance, `'/user/profile'` first matches the `'/user'` resource, then its `'/profile'` child resource.\n3. Find the method by name\n4. Executes all resource middleware down the matching resources chain\n5. Executed the method middleware and the method\n6. If any middleware has sent a response, no subsequent middleware is executed, nor the method is.\n7. If no response was sent, a \"No response sent\" error is reported\n8. A promise for a result is returned\n\nInternal Methods\n----------------\nWhile the `Resource.exec()` is usually enough, you might need these also.\n\n### Resource.which(path, verb[, request]):Method?\nFind a matching method by path and verb.\n\nArguments:\n\n* `path: String`: Path to the wanted resource\n* `verb: String`: Method name to look for\n* `request: Request?`: Optional `Request` object. Is used to populate its fields.\n\nReturns: The `Method` object, or `undefined` if not found.\n\n### Resource.request(request):Response\nProcess the provided Request and return a Response.\n\nThis method allows you to use a custom `Request` object and process the `Response` in an arbitrary fashion.\n\nHandling Results\n----------------\n\n```js\nroot.exec(\n    '/user', // path\n    'save', // method\n    { login: 'kolypto' }, // method arguments\n    {} // additional request fields\n)\n.then(function(result){\n    // success: we have the result\n})\n.catch(function(err){\n    // An error has occurred\n    if (err.system){\n        // runtime error: unhandled exception\n    } else {\n        // method error: reported with Response.send()\n    }\n});\n```\n\nPrefix Matching\n---------------\n\nGiven a path, ApiMan performs a case-sensitive precise prefix matching.\nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by\nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic\nby design and, potentially, all special characters might have a meaning.\nFor instance, you can use `'user.device.commands'` for resource names.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse multiple slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nSpecial Features\n================\n\nEndpoint Resources\n------------------\n\nYou can create Resources that consume all requests that go into it: such resources have a single function that\nhandles all requests.\n\n### Resource.endpointMethod([middleware, ...], method):Resource\nAdd an endpoint method on the Resource: the method that handles all requests that fall into the resource.\n\nThe `Request` object will have the `path_tail` property set to the remaining path suffix.\n\nArguments:\n\n* `middleware: function(req: Request, res: Response):Q`:\n    Optional middleware functions to use. See: [Method Middleware](#method-middleware)\n* `method: function(req: Request, res: Response):Q`:\n    The endpoint method to use.\n\nExample:\n\n```\nvar root = new apiman.Root(),\n    upload = root.resource('/upload')\n    ;\n\nupload.endpointMethod(function(req, res){\n    req.path_tail; // path suffix\n    req.verb; // arbitrary method name\n});\n\nroot.exec('/upload/file.txt', 'save', { file: ... })\n    .then(function(){\n        // upload saved\n    });\n```\n\n\n\nController Methods\n------------------\nAdding all the methods manually is not the only way to define them: you can feed a Resource with an arbitrary object,\nand ApiMan will import its methods. The MVC world knows this approach as *Controllers*.\n\n### Resource.controllerMethods(ctrl):Resource\nAdd methods from a controller object.\n\nApiMan imports a property only if:\n\n* It is a function (non-functional properties are ignored)\n* Its name does not start with an underscore `_` (protected members are ignored).\n\nArguments:\n\n* `ctrl: Object`: The controller to import the methods from.\n\nNotes:\n\n* All methods maintain the `this` binding: you can freely use controller fields and protected methods!\n* In order to set middleware functions for a method, put them in the `middleware` proeprty of the method function.\n\nExample:\n\n```js\n// Controller\nvar UserCtrl = function(something){ // constructor\n    this.something = something;\n};\n\nUserCtrl.prototype.get = function(req, res){ // method\n    res.ok({\n        something: this.something,\n        mw_worked: req.mw_worked,\n        login: 'kolypto'\n    });\n};\nUserCtrl.prototype.get.middleware = [ // middleware for the method\n    function(req, res){\n        req.mw_worked = 'yesss!';\n    }\n];\n\nUserCtrl.prototype.set = function(req, res){ // another method\n    res.ok({ ok: true });\n};\n\nUserCtrl.prototype._private = function(){};\n\n// Import an instantiated controller\nvar root = new apiman.Root(),\n    user = root.resource('/user')\n    ;\nuser.controllerMethods(new UserCtrl('anything'));\n```\n\nThis will make the '/user:get' and '/user:set' methods available.\n\n\n\n\n\n\nBundled Middleware\n==================\nAll bundled middleware come in the `require('apiman').middleware` module.\n\nSession Middleware\n------------------\n\nInitializer: `apiman.middleware.session(options)`\n\nPort of the [connect.session](http://www.senchalabs.org/connect/session.html) middleware which allows you\nto reuse the session Store backends,\nlike the [connect-redis](https://npmjs.org/package/connect-redis) package.\n\n```js\nvar root = new apiman.Root;\nroot.use(apiman.middleware.session({\n    // Session store backend, Connect-compatible.\n    // When unspecified, uses MemoryStore\n    store: new connect.session.MemoryStore(),\n    // Maximum session lifetime in milliseconds.\n    // `null` produces a one-shot session.\n    maxAge: 60*60*24 *1000, // 1 day\n    // Session id is signed with this secret to prevent tampering\n    // NOTE: not implemented!\n    secret: 'cockatoo parrot'\n});\n```\n\nWhen a session middleware is in effect, the `Request` object gets the following extra fields:\n\n* `req.sessionID: String`: The session identifier string\n* `req.session: Object`: The persistent session object\n* `req.sessionStore: connect.Store`: The session store backend\n\nThe session is only saved if the middleware & the method has had no runtime errors (thrown exceptions)!\n\nExample on how to make 2 requests using a single session:\n\n```js\nvar sessionID; // remember the session ID\n\n// First request: sign in, get the session\nvar req = {}; // sessionID will be stored here\n\nroot.exec('/login', 'login', { user: 'kolypto', pass: '1234' }, req)\n    .then(function(result){\n        // Successful login\n        // req.sessionID is populated\n        sessionID = req.sessionID; // keep it\n    })\n// Second request: use the same session id\n    .then(function(){\n        // use sessionID got from the previous request\n        return root.exec('/cart', 'show', {}, { sessionID: sessionID })\n            .then(function(result){\n                // fine\n            });\n    })\n    .done()\n    ;\n```\n\n\n\n\n\n\nExporting the APIs\n==================\n\nIn order to expose your APIs to some protocol, you need to implement the ApiMan method caller as a singular endpoint:\nin other words, create a handler which transforms the input into an ApiMan `Resource.exec()` call and formats the output.\n\nYou can either [Export The APIs Manually](#exporting-the-apis-manually) or use one of the [Bundled Adapters](#bundled-adapters).\n\nBundled Adapters\n----------------\n\nBundled adapters implement the most wanted protocol adapters in a reusable manner.\n\nAll bundled middleware come in the `require('apiman').adapters` module.\n\n### Express Adapter\nExpress adapter is a middleware maker that catches all incoming requests under a path and handles them with ApiMan methods.\n\nInitializer: `apiman.adapters.express(root, options)`\n\nArguments:\n\n* `root: Resource|Root`: The resource to serve\n* `options: Object`: Middleware options\n\n    * `prepareRequest: function(req: Object):Request?`: An optional custom function that converts the incoming\n      [Express `req` request](http://expressjs.com/api.html#req.path) into an ApiMan request.\n\n      It should return an object with the additional Request fields. It's also required to return: `path`, `verb`, `args`.\n\n      Default: split the request URI in 2 on ':' and get the `path` & `verb` ; combine request query & body into `args` ;\n      pass the `req.files` as is.\n\n      As a result, you call methods with '/path/to/resource:methodName', the arguments are provided as query params or sent\n      in the request body as JSON.\n\n    * `sessionCookie: { name: String, maxAge: Number }?`: When the [Session Middleware](#session-middleware) is used,\n      you probably want to pass the sessionID through a cookie. To do that, specify the cookie settings here.\n\n      Default: disabled.\n\n      Fields: `name` is the name of the cookie (default: 'sessionID'), `maxAge` is the session expire time in seconds.\n\n      See [express.cookie()](http://expressjs.com/api.html#res.cookie) and (connect.session)[http://www.senchalabs.org/connect/session.html] for more details.\n\n    * `fixSlashes: Boolean?`: Whether to forgive extra slashes in the path. See [Prefix Matching](#prefix-matching).\n\n      Default: true.\n\n    * `sendResult: function(req: Object, res: Object, result: *)?`: An optional custom function that sends the result\n      with [Express `res` response](http://expressjs.com/api.html#res.send).\n\n      Default: sends the result as JSON with HTTP code 200.\n\n      Arguments:\n\n    * `sendError: function(req: Object, res: Object, error: Object, e:*)`: An optional custom function that sends the\n      error with [Express `res` response](http://expressjs.com/api.html#res.send).\n\n      Default: sends the result as JSON `{ error: error }`, with HTTP status code 500 for system errors, 400 for method errors.\n      If the `e` error specifies the `httpcode` field, it overrides the chosen HTTP code.\n\n      Arguments: `req`, `res` are Express request and response ; `e` is the original error; `error` is the prepared\n      error object which is guaranteed to be an object.\n\n      Note: as methods in general can return errors of any type, this adapter casts them to a guaranteed object\n      `{ message: String, system: Boolean }` format.\n\nExample:\n\n```js\nvar apiman = require('apiman'),\n    express = require('express')\n    ;\n\n// Resources\nvar root = new apiman.Root();\nroot.use(apiman.middleware.session()); // ApiMan sessions\n\n// Prepare Express\nvar app = express();\napp.use(express.cookieParser()); // enable cookies\napp.use(express.bodyParser()); // enable JSON\n\n// Expose the APIs\napp.use('/api', apiman.adapters.express(root));\n```\n\nFor a mature example, see [/tests/adapters-express-test.js](tests/adapters-express-test.js).\n\n\nExporting The APIs Manually\n---------------------------\n\nThis section describes how to export the APIs manually. There are [Bundled Adapters](#bundled-adapters) that\nsimplify this part with convenient helpers.\n\n### Express\nAssuming you already have your APIs set up under the `root` Resource, let's export these to HTTP with\n[Express](https://npmjs.org/package/express).\n\nFirst, you need to decide on the conventions to use for:\n\n1. Method call convention.\n\n    Example: Using URI for Resource paths, method is provided after a colon `:`. the arguments are sent either through\n    the query params or in the request body as a JSON object.\n\n2. Successful responses\n\n    Example: encode the output as JSON, with HTTP code 200.\n\n3. Error responses:\n\n   Example: `{ error: { code: Number, message: String } }`, as JSON.\n   If the Error object has the `httpcode` property, send it as a code.\n\n3. Error responses and HTTP codes\n\n    Example: use HTTP code 400 by default.\n\n4. System Error responses and HTTP codes\n\n    Example: use HTTP code 500 by default.\n\nHere's a simple solution:\n\n```js\nvar express = require('express'),\n    _ = require('lodash')\n    ;\n\nvar root = new apiman.Root(); // assuming the resources and methods are defined\n\nvar app = express();\n\napp.use('/api', function(req, res){\n    // Input\n    var _pathverb = req.path.split(':'),\n        path = _pathverb[0], // resource path\n        verb = _pathverb[1], // method name\n        args = _(req.body).extend(req.query), // combine query & body\n        apireq = {} // additional request fields\n        ;\n    // Execute the method\n    root.exec(pathmethod, verb, args, apireq)\n        // Handle success\n        .then(function(result){\n            res.type('json').send(result); // send the result\n        })\n        // Handle error\n        .catch(function(err){\n            res.type('json').send(err.system? 500 : 400, err); // send the error object\n        })\n        ;\n});\n```\n\nFor a full solution which supports files, sessions, and handles errors correctly, see [Express Adapter](#express-adapter).\n\n### socket.io\n\nPiece of cake: as socket.io can exchange json objects, you just need a\nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the\npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, result: Object, error: null }}`\n* Error:    `{{ id: Number, error: { code: Number, message: String } }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.exec(data.path, data.verb, data.args)\n            .then(function(result){\n                socket.emit('api.result', {\n                    id: data.id, // send the same id back\n                    result: result,\n                    error: null\n                });\n            })\n            .catch(function(err){\n                socket.emit('api.result', {\n                    id: data.id, // send the same id back\n                    result: null,\n                    error: err\n                });\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\napicall = function(path, verb, args, callback){\n    var request = {\n        id: apicall._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args || {}\n    };\n    apicall._wait[request.id] = callback;\n    socket.emit('api', request);\n};\napicall._id=0;\napicall._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    apicall._wait[data.id].apply(null, data.ret);\n});\n\n// Usage\napicall('/news', 'list', {}, function(err, news){\n    if (err){\n        // error :(\n    } else {\n        // yeehaw!\n    }\n});\n```\n\nWeak points:\n\n1. On reconnect, the response can't be received transparently\n2. The exposed error objects can potentially contain sensitive data like stack traces\n3. Callback-based interface: use promises instead\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kolypto/nodejs-apiman/issues"},"homepage":"https://github.com/kolypto/nodejs-apiman","_id":"apiman@1.0.1","dist":{"shasum":"bf6495f6aeb9b1aa7fb96d6346c8929c07939e0e","tarball":"https://registry.npmjs.org/apiman/-/apiman-1.0.1.tgz","integrity":"sha512-T9UuipylO+zNmjk+GLNZ/ZBvmLZIueAq6Xk03SX8FkWlgbvTGd7g8XP3nRxcgsWEMpgEKX8akDw2THH62NCRbA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEGUj9b8LW9gG26v+jslYRWCMfqZEXCeDstvYcc3MRauAiEA9QdOqu+zJdgngNRAzdkGhGoYUc7nA39uMqZxpKEqTTQ="}]},"_from":".","_npmVersion":"1.3.17","_npmUser":{"name":"kolypto","email":"kolypto@gmail.com"}}},"readme":"ApiMan\n======\n\nApiMan is the API methods manager that is exportable to multiple protocols, \nincluding REST via Express.\n\nThe Motivation\n--------------\n\nWhen your app needs a REST API - Express is a great choice, but imagine you \nneed to support multiple protocols at the same time and want to have the code\norganized. Faking requests for Express is a tricky thing that is not guaranteed\nto function as it progresses...\n\nApiMan steps in: you define a tree of resources with named methods bound to \nthem, and now just bind it to Express as a middleware. Wait, some methods should\nalso be available through socket.io? No problem.\n\nNow, we want some middleware for data preparation and authentication? \nYes, we support that.\n\nEnjoy it, guys :)\n\n\n\nCore Components\n===============\n\nResource, Root\n--------------\n\nA resource is a collection of methods and sub-resources identified by path.\nIt also keeps the related information: parameters info, middleware etc.\n\nYou create a sub-resource by calling the `Resource.resource(path)` method of \na parent `Resource` or the `Root` container:\n\n```js\nvar root = new apiman.Root();\n\nvar user = root.resource('/user');\nvar user_profile = user.resource('/profile');\n```\n\nThe `Root` is actually a resource with empty path.\n\nAlthough we follow the HTTP-style slash-separated paths, you're free to use any \nconvention you're comfortable with.\n\n\n\nMethod\n------\n\nAfter you have a hierarchy of resources, you can define methods on each, \nincluding the root container.\n\nA `Method` is defined with the `Resource.method(verbs, ...callbacks)` method of \na `Resource`. \n`verbs` is the name of the method, or, optionally, an array of them.\nAfter the `verb`, you specify a callback to be executed when the method matches\nthe request:\n\n```js\nuser_profile.method('set', function(req, res){\n    save_to_db(\n        req.args['user'], \n        function(err, id){\n            if (err)\n                res.error(err);\n            else\n                res.ok({saved: true, id: id});\n        }\n    );\n});\n```\n\nThe method callback accepts two arguments: the `Request` and `Response` objects.\n\n### Request\n\nThe `Request` object has the following useful properties:\n\n* `req.path` is the full path to the current resource: \n    `'/user/profile'`\n* `req.verb` is the current verb than made the method match: \n    `'set'`\n* `req.args` is an object of method arguments: \n    `{ user: {login: 'kolypto', ...} }`\n* `req.path_array` is an array of path components split on a resource match: \n    `['/user', '/profile']`\n* `req.params` is an object of parameters from RegExps on path (see below).\n    `{ uid: 10 }`\n\nAnd also some internal informational fields:\n\n* `req.middleware` is an array of middleware assigned to this very request.\n* `req.response` is the `Response` object shortcut used internally\n\n### Response\n\nThe `Response` object is a naive wrapper for a NodeJS-style \n`function(err,result)` callback and has the following methods:\n\n* `Response.send(err, result)` is the generic callback with both options\n* `Response.error(err)` is the callback for errors that \n    wraps `Response.send(err)`\n* `Response.ok(result)` is the callback for results that \n    wraps `Response.send(undefined, result)`\n\n    \n    \nMiddleware\n----------\n\n### Method middleware\n\nLike in Express, each method can use an arbitrary list of middleware callbacks\nbefore the method function:\n\n```js\n// middleware to check the permissions\nvar accessCheck = function(req, res, next){\n    if (req.args['uid'] != 10) // stupid access check\n        next(new Error('Access denied')); // error\n    else \n        next(); // proceed\n};\n\nuser_profile.method('get', accessCheck, function(req, res){\n    load_from_db(function(err, user){\n        res.send(err, user); // delegate both arguments to the response handler\n    });\n});\n```\n\nNow, the method function is only executed once all preceding middleware \ncallbacks have called `next()` with no arguments, which indicates success.\n\n### Resource middleware\n\nAdditionally, a middleware can be attached to a `Resource`: it will be executed\nfor all requests to its methods or methods of the sub-resources:\n\n```js\nuser_profile.use(function(req, res, next){\n    if (req.args['uid'] === undefined)\n        next(new Error('Missing required argument: uid'));\n    else\n        next();\n});\n```\n\n\n\nParameters\n----------\n\nResource paths can be specified as regular expressions, just don't forget to \nanchor them to the start of the string. As RegExps can capture parts of the \ninput, I could't resist to not add the parameters support:\n\n```js\nvar device_commands = root.resource(new RegExp('/device/(\\w+)/command/(\\w+)'))\n    .param(1, 'device_type')\n    .param(2, 'command', function(req, res, next, value){\n        if (['start', 'stop'].indexOf(value) == -1)\n            next(new Error('Unsupported command'));\n        else {\n            req.params['command'] = value;\n            next();\n        }\n    })\n    .method('invoke', function(req, res){\n    });\n```\n\nParameters are defined as simple capture groups in a RegExp. To have named \nparams, you use the `Resource.param(index, [, callback])` Resource method \nwhich maps a group to a middleware invocation:\n\n* `index` is the positional index of the capture group\n* `callback` is the middleware that alters the `Request` object using the \n    parameter value: `function(req, res, next, value)`.\n    \nTo have named parameters, you typically place them in the `Request.params` \nobject designed for that.\n\n\n\nMerging Resources\n-----------------\n\nFor modularity, you might want to distribute your resources across different \nfiles and then merge with with the `Resource.merge(resource, ...)` method:\n\n1. Adds all methods from the resources to the current one\n1. Adds all middleware from the resources\n2. Adds all sub-resources to the current one\n3. If a resource would have been overwritten, it's merged.\n\n```js\n// Module\nvar module = new apiman.Root();\nmodule.resource('/user')\n    .method('get', function(req, res){ /* ... */})\n\n// Extension\nvar extension = new apiman.Root();\nmodule.resource('/user')\n    .method('command', function(req, res){ /* ... */})\n\n// Index file\nvar api = new apiman.Root();\napi.merge(module, extension);\n```\n\nThe example above results in a tree with a single `/user` Resource which has\ntwo methods defined: `get` and `command`.\n\n\n\nExecuting methods\n-----------------\n\nTo execute a method of your API root, use the \n`Resource.request(path, verb, args[, req], callback)` method:\n\n* `path` is the path to some resource within the tree\n* `verb` is the name of the method to execute\n* `args` is the arguments object for the method. Optional.\n* `req` is an object with extended request fields. Optional.\n    Useful to populate additional `Request` fields at the invocation time: say,\n    user session.\n* `callback` accepts the method output: `function(err, result)`.\n\n`Resource.request()` does the following:\n\n1. Creates the `Request` and `Response` object\n2. Traverses the tree using a prefix match technique and gets down \n    to the matching Resource\n3. All middleware added to resources down the path are scheduled for the request\n4. Any parameter callbacks down the path are also scheduled\n5. Picks a method by `verb`\n6. Executes all collected middleware\n7. Executes the method middleware\n8. Executes the method\n9. Fires the callback\n\nIf a resource or method is not found, the function returns `false`.\n\n### Matching\n\nIn the examples above we follow the REST naming conventions for clarity, but \nagain, that is not required.\n\nGiven a path, ApiMan performs a case-sensitive exact prefix matching. \nFor instance, given the following resources chain:\n\n```js\nvar root = new apiman.Root();\nroot.resource('/user')\n    .resource('/device/commands')\n        .resource('/private');\n```\n\npath `'/user/device/commands/private'` recursively matches each resource by \nprefix: `'/user'`, `'/device/commands'`, `'/private'`.\n\nDon't expect ApiMan to forgive extra or missing slashes: it's protocol-agnostic \nby design and, potentially, all special characters might have a meaning.\n\nAnyway, nothing prevents you from making a preprocessor which tunes the input\nto your taste:\n\n```js\n// Ensure a leading slash, no trailing slash, and collapse duplicate slashes\npath = ('/' + path).replace(/\\/+/g, '/').replace(/\\/$/, '');\n```\n\n\n\n\n\n\nExporting the API\n=================\n\nsocket.io\n---------\n\nPiece of cake: as socket.io can exchange json objects, you just need a \nhandy convention for sending requests and getting responses.\n\nThe only difficulty is that socket.io does not support the request-response\nprotocol out of the box, but we can easily overcome that by numbering the \npackets.\n\nGiven the above, let's use the following data exchange protocol:\n\n* Request:  `{{ id: Number, path: String, verb: String, args: Object }}`\n* Response: `{{ id: Number, data: [ undefined, Object ] }}`\n* Error:    `{{ id: Number, data: [ String|Error, undefined ] }}`\n\nOn the server:\n\n```js\nio.sockets.on('connection', function (socket) {\n    socket.on('api', function (data) {\n        root.request(data.path, data.verb, data.args, function(err, result){\n            // Emit the result using the same method id\n            socket.emit('api.result', { \n                id: data.id, \n                ret: [err, result]\n            });\n        }) ||\n            socket.emit('api.result', {\n                id: data.id, \n                ret: ['unknown method', undefined]\n            });\n    });\n});\n```\n\nAnd on the client:\n\n```js\nio_method = function(path, verb, args, callback){\n    var request = {\n        id: io_method._id++, // packet id\n        path: path,\n        verb: verb,\n        args: args\n    };\n    io_method._wait[request.id] = callback;\n    socket.emit('api', request);\n};\nio_method._id=0;\nio_method._wait = {};\n\n// Listen for responses\nsocket.on('api.result', function(data){\n    io_method._wait[data.id].apply(null, data.ret);\n});\n```\n\nThis approach, however, has 2 weak points:\n\n* On reconnect, the response can't be received transparently\n* The exposed error objects can potentially contain sensitive data \n    like stack traces\n\n\n\nExpress\n-------\n\nAssume you already have your API defined under the `root` variable, and now it's \ntime to export it to Express. There are a couple of things to take care of:\n\n1. Map your resources and methods to paths\n2. Format the output for responses\n3. Decide on the HTTP status code for errors\n\nIf your resources & methods (expecially their verbs) are directly exportable\nto Express and compatible with REST, you're lucky:\n\n```js\napp.use('/api', function(req, res){\n    var path = req.path,\n        args = _(req.body).extend(req.query), // combine\n        verb = req.method,\n        apireq = {} // additional fields for Request\n        ;\n    \n    // Pass the request to ApiMan\n    var found = root.request(path, verb, args, apireq, function(err, result){\n        // Format the output\n        if (err)\n            res.type('json').send(err.httpCode || 500, { error: err.message });\n        else\n            res.type('json').send(result);\n    });\n    \n    // Method not found\n    if (!found)\n        res.type('json').send(404, { error: 'Unknown API method' });\n});\n```\n\nThe only issue that remains is that all error codes are `400`: we don't \ndifferentiate server errors, client errors and stuff. To overcome that, you'd \nneed a convention:\n\n* Always return an error object with a custom HTTP status code set.\n    Default to 500 for other cases (all other errors)\n* Create a hierarchy of custom `Error` objects with an http status code\n    defined on each, and return them.\n\n### Complex mappings\n\nApiMan supports a richer methods collection interface which's not limited to\nHTTP methods: as an example, imagine a `/user` resource with methods \n`load`, `save`, `del`, `block`, `list`. While for CRUD methods you can just \nmap the HTTP verbs (`GET` -> `load`), the `block` and `list` method would have \nrequired sub-resources and/or query strings.\n\nThat's what you need the mappers for.\n\nFirst, change your Express middleware a little to enable mappers for 'express' \non the request:\n\n```js\n// Tell ApiMan we're from Express\nroot.requestFrom('express', path, verb, args, req, function(err, result){ \n    /* ...*/ \n});\n```\n\nIn order for the magic to work for us, we need to declare mappers on \nnon-exportable resources which routes the REST requests to ApiMan methods.\n\nObserve the example:\n\n```js\nvar user = root.resource('/user');\n\nuser.method('load', function(req, res){/*...*/});\nuser.method('save', function(req, res){/*...*/});\nuser.method('del', function(req, res){/*...*/});\nuser.method('block', function(req, res){/*...*/});\nuser.method('list', function(req, res){/*...*/});\n\nuser.map('express', function(path, verb){\n    // Trick the incoming (path,verb)\n    switch (path){\n        case '': // endpoint\n            return [\n                path, \n                // Change the verb\n                {GET: 'load', POST: 'save', DELETE: 'del'}[verb]\n            ];\n        case '/list': // fake path\n            return ['', 'list']; // route to the method\n        case '/block':\n            return ['', 'block'];\n    }\n    return undefined; // unchanged\n});\n```\n\nThe mapper function can be defined on any resource and is invoked when the \nresource tree is traversed. It accepts the `(path,verb)` pair, where `path` is\nthe current path remainder with all matched prefixes already truncated. It's\nexpected to return an altered `[path,verb]` pair sufficient for the subsequent\nresource/method lookup to succeed.\n\nAs usually simple path/verb mapping is enough, you can save a callback and give\na mapping instead:\n\n```js\nuser.map('express', {\n    '': ['', {GET: 'load', POST: 'save', DELETE: 'del'}]\n    '/list': ['', 'list'],\n    '/block': ['', 'block'],\n});\n```\n\nThe mapper will search for the path remainder in the object keys. If the value\nis an array - it's taken as a `[path,verb]` pair, where the verb can be \nspecified as a mapping.\n","maintainers":[{"name":"kolypto","email":"kolypto@gmail.com"}],"time":{"modified":"2022-06-13T03:13:54.985Z","created":"2013-07-10T13:46:14.445Z","0.0.1":"2013-07-10T13:46:18.376Z","0.0.2":"2013-10-27T00:39:43.303Z","0.0.3":"2013-10-27T21:51:20.057Z","0.0.4":"2013-11-01T17:11:51.247Z","0.0.5":"2013-11-02T03:19:54.683Z","0.0.6":"2013-11-05T21:16:46.248Z","0.0.7":"2013-11-06T21:23:57.225Z","0.1.0":"2013-11-06T21:32:58.367Z","0.1.1":"2013-11-06T22:47:31.215Z","0.1.2":"2013-11-16T01:54:38.988Z","0.1.3":"2013-12-12T00:33:56.715Z","1.0.0":"2013-12-16T01:18:38.680Z","1.0.1":"2013-12-16T10:33:17.435Z"},"author":{"name":"kolypto","email":"kolypto@gmail.com"},"repository":{"type":"git","url":"git@github.com:kolypto/nodejs-apiman.git"}}