resource-router-middleware
resource-router-middleware copied to clipboard
As ES6 Class?
That seems like a nice idea. I'll try to find time today.
Hey,
I ended up assembling something myself. I'm using experimental decorators though, so you can merge it as an optional if you want.
my fork: https://github.com/mrapogee/resource-router-middleware
To make a resource
@resource('user')
export default class UserResource {
This exports as an express router.
Also, you can use the route decorator on a class method.
// Custom route
@route.patch('/:user/:foo')
updateFoo({user, params}, res) {
user.foo = params.foo
res.status(204).send()
}
Full example
import {resource, route} from './src/resource-router-middleware'
const users = [{id:'foo', test: 'test'}]
@resource('user')
export default class UserResource {
load(req, id, callback) {
var user = users.find( user => user.id===id ),
err = user ? null : 'Not found'
callback(err, user)
}
list({ params }, res) {
res.json(users)
}
create({ body }, res) {
body.id = users.length.toString(36)
users.push(body)
res.json(body)
}
read({ user }, res) {
res.json(user)
}
update({ user, body }, res) {
for (let key in body) {
if (key!=='id') {
user[key] = body[key]
}
}
res.status(204).send()
}
// Custom route
@route.patch('/:user/:foo')
updateFoo({user, params}, res) {
user.foo = params.foo
res.status(204).send()
}
delete({ user }, res) {
users.splice(users.indexOf(user), 1)
res.status(204).send()
}
}
UserResource // Is an express router
Interesting approach. I like the custom route decorator, but I wonder: why go with @resource('name')
for decorating the class rather than just using inheritance?
import { Resource } from 'resource-router-middleware';
export default class UserResource extends Resource {
name = 'user';
// etc
}
This would also work nicely into the existing syntax:
import { Resource, default as resource } from 'resource-router-middleware';
export default new Resource({ name: 'user' });
// ...which would be the same as:
export default resource({ name: 'user' });
// such that:
(resource() instanceof Resource); // true
(resource() instanceof express.Router); // true
... just my thoughts. Perhaps it's easy to support all of the above and the @resource
decorator?
I moved away from inheritance due to needing a getMiddleware() method, but I didn't think of extending express Router. I wasn't to keen on the class UserResource
then UserResource
returning a completely separate Router instance, but this solves that.
We'd need to rename delete to remove though. And watch out for overrides.
Overrides yes. What's the need to rename delete
? It's a valid method name, and babel's transpiled classes add defined methods using Strings for names (versus literals, which would be reason to avoid). Since these class methods are generally only called by the module's routing logic, I think we should be good?
Router already has the method delete defined. We could just use super.delete to fix this.
Also, just tried this. Express Router doesn't seem to be compatible with ES6 classes
If I use this for Router:
class Router {
param () {
}
}
Calling super.param works inside the constructor of a class extending from Router. But super.param is undefined when using the express Router.
Ah, good catch - Router
doesn't appear to be a class at all.
Score one for the decorator solution...
The other option is having a getMiddleware() function that returns the Router.
That way instanceof Resource
would work, but not instanceof Router
. Also, slightly simpler inheritance as well multiple instances of the same resource without calling the decorator.
Any advantage you see here?