{"action":"created","issue":{"url":"https://api.github.com/repos/travist/resourcejs/issues/13","labels_url":"https://api.github.com/repos/travist/resourcejs/issues/13/labels{/name}","comments_url":"https://api.github.com/repos/travist/resourcejs/issues/13/comments","events_url":"https://api.github.com/repos/travist/resourcejs/issues/13/events","html_url":"https://github.com/travist/resourcejs/pull/13","id":90658329,"number":13,"title":"virtual method for aggregate resources","user":{"login":"biofractal","id":329603,"avatar_url":"https://avatars.githubusercontent.com/u/329603?v=3","gravatar_id":"","url":"https://api.github.com/users/biofractal","html_url":"https://github.com/biofractal","followers_url":"https://api.github.com/users/biofractal/followers","following_url":"https://api.github.com/users/biofractal/following{/other_user}","gists_url":"https://api.github.com/users/biofractal/gists{/gist_id}","starred_url":"https://api.github.com/users/biofractal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/biofractal/subscriptions","organizations_url":"https://api.github.com/users/biofractal/orgs","repos_url":"https://api.github.com/users/biofractal/repos","events_url":"https://api.github.com/users/biofractal/events{/privacy}","received_events_url":"https://api.github.com/users/biofractal/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":8,"created_at":"2015-06-24T12:13:46Z","updated_at":"2015-07-02T20:54:49Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/travist/resourcejs/pulls/13","html_url":"https://github.com/travist/resourcejs/pull/13","diff_url":"https://github.com/travist/resourcejs/pull/13.diff","patch_url":"https://github.com/travist/resourcejs/pull/13.patch"},"body":""},"comment":{"url":"https://api.github.com/repos/travist/resourcejs/issues/comments/118165592","html_url":"https://github.com/travist/resourcejs/pull/13#issuecomment-118165592","issue_url":"https://api.github.com/repos/travist/resourcejs/issues/13","id":118165592,"user":{"login":"zackurben","id":2689122,"avatar_url":"https://avatars.githubusercontent.com/u/2689122?v=3","gravatar_id":"","url":"https://api.github.com/users/zackurben","html_url":"https://github.com/zackurben","followers_url":"https://api.github.com/users/zackurben/followers","following_url":"https://api.github.com/users/zackurben/following{/other_user}","gists_url":"https://api.github.com/users/zackurben/gists{/gist_id}","starred_url":"https://api.github.com/users/zackurben/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zackurben/subscriptions","organizations_url":"https://api.github.com/users/zackurben/orgs","repos_url":"https://api.github.com/users/zackurben/repos","events_url":"https://api.github.com/users/zackurben/events{/privacy}","received_events_url":"https://api.github.com/users/zackurben/received_events","type":"User","site_admin":false},"created_at":"2015-07-02T20:54:49Z","updated_at":"2015-07-02T20:54:49Z","body":"Hey @biofractal,\r\n\r\nas it stands, I believe my addition of composable middleware will work for you, however I'm not sure it will be the most elegant solution, when compared to your proposed `virtual` solution.\r\n\r\nWith the ability to manually invoke an endpoint, you can do the following with the user/register scenario I described previously:\r\n\r\n```js\r\n// other boilerplate code..\r\n\r\n/**\r\n * Create our resourcejs endpoints for /user\r\n *\r\n * [POST] /user\r\n * [GET] /user\r\n * [GET] /user/:userId\r\n * [PUT] /user/:userId\r\n * [DELETE] /user/:userId\r\n */\r\nvar resourcejs = Resource(app, '', 'user', ResourceModel).rest();\r\n\r\napp.post('/register', function(req, res, next) {\r\n  // Do some user registration specific logic here!\r\n\r\n  // Manually invoke resourcejs endpoint for POST /user!\r\n  resourcejs['/user/:userId'].post.call(this, req, res, next);\r\n});\r\n```\r\n\r\nWith the previous code, any request to `[POST] /register` will execute its specific logic, and internally invoke the `[POST] /user` endpoint to get a response.\r\n\r\nThat is a pretty simple example of what you can do with access to the resourcejs middleware. Additionally for your mocking scenario, you can either set `res.skipResource = true;` and chain an external endpoint to an internal endpoint, where data wont be manipulated or persisted, or just outright mock an endpoint; for example:\r\n\r\n```js\r\n// other boilerplate code..\r\n\r\n/**\r\n * Create our resourcejs endpoints for /user\r\n *\r\n * [POST] /domain/user\r\n * [GET] /domain/user\r\n * [GET] /domain/user/:userId\r\n * [PUT] /domain/user/:userId\r\n * [DELETE] /domain/user/:userId\r\n */\r\nvar resourcejs = Resource(app, '/domain', 'user', ResourceModel).rest({\r\n  beforePost: function(req, res, next) {\r\n    // Some before db storage logic!\r\n\r\n    if (req.skipResource) {\r\n      // if data persistence was cancelled by /mock2/user, \r\n      // return what would have been persisted to the db.\r\n      res.status(201).send(someObject);\r\n    } else {\r\n       // Allow resourcejs to continue normal execution.\r\n       next();\r\n    }\r\n  }\r\n});\r\n\r\n// An example of mocking with the middleware..\r\n// Any request will return a dummy response, where any logic could be added.\r\napp.post('/mock1/user', function(req, res, next) {\r\n  res.status(201).send({_id: null, username: req.body.username});\r\n});\r\n\r\n// An additional way to mock with req.skipResource\r\napp.post('/mock2/user', function(req, res, next) {\r\n  // this will allow the request to perform any logic upto the point of db manipulation.\r\n  req.skipResource = true;\r\n\r\n  resourcejs['/domain/user/:userId'].post.call(this, req, res, next);\r\n});\r\n\r\n// Link the public /gateway/authenticate endpoint to the internal /domain/user endpoint.\r\napp.post('/gateway/authenticate', function(req, res, next) {\r\n  // Do some user authentication specific logic here!\r\n\r\n  // Manually invoke resourcejs endpoint for GET /domain/user/:userId!\r\n  // Here the response is dependent on the result from the manual request\r\n  // with the given request data.\r\n  resourcejs['/domain/user/:userId'].get.call(this, req, res, next);\r\n});\r\n```\r\n\r\nHopefully this has helped you find a solution for your problem, because I think what you want it already in Resource.js! Let me know if you have any additional questions or thoughts!"}}