Skip to content

Commit

Permalink
Merge pull request #4 from fabrix-app/v1.1
Browse files Browse the repository at this point in the history
[feat] Route Refine
  • Loading branch information
scott-wyatt authored Jul 18, 2018
2 parents 32c674d + 3cf4d53 commit b882115
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 12 deletions.
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,42 @@ that takes the following form:
{
// ...
'/example/test': {
'GET': 'ExampleController.test',
config: {
pre: [ 'ExamplePolicy.test' ]
'GET': {
handler: 'ExampleController.test',
config: {
pre: [ ]
}
}
}
// ...
}
```

You can also refine this by explicitly defining the handler and config:

```js
{
// ...
'/example/test': {
'GET': {
handler: 'ExampleController.get',
config: {
pre: [ 'ExamplePolicy.get' ]
}
},
'POST': {
handler: 'ExampleController.post',
config: {
pre: [ 'ExamplePolicy.post' ]
}
}
}
// ...
}
```
Which is useful for refining controller over different http methods on a route.

##### Prefixes
```js
{
// ...
Expand Down
71 changes: 65 additions & 6 deletions lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,65 @@ export const Utils = {
Utils.getHandlerFromString(app, route)

route.config.pre = route.config.pre
.map(pre => this.getHandlerFromPrerequisite(app, pre))
.map(pre => Utils.getHandlerFromPrerequisite(app, pre))
.filter(handler => !!handler)

const routeHandlers = Object.keys(route).filter(value => -1 !== Utils.methods.indexOf(value))

if (!routeHandlers.some(v => Utils.methods.indexOf(v) >= 0)) {
if (!routeHandlers.some(v => Utils.methods.indexOf(v) >= 0 || !!route[v])) {
app.log.error('spool-router: route ', path, ' handler [', routeHandlers.join(', '), ']',
'does not correspond to any defined Controller handler')
return {}
}

routeHandlers.forEach(method => {
if (route[method]) {
route[method].config = route[method].config || route.config
route[method].config.pre = route[method].config.pre || route.config.pre
route[method].config.pre = route[method].config.pre
.map(pre => Utils.getHandlerFromPrerequisite(app, pre))
.filter(handler => !!handler)
}
})

return { path, route }
},

/**
* Expands the search for the prefix to the route or config.* level
*/
getRouteLevelPrefix(app: FabrixApp, route) {
const configuredPrefix = app.config.get(route.config.prefix)
const routePrefix = route.config.prefix
if (typeof configuredPrefix !== 'undefined') {
if (configuredPrefix) {
return (configuredPrefix).replace(/$\//, '')
}
else {
return
}
}
else {
return (routePrefix || '').replace(/$\//, '')
}
},

/**
* Get's the prefix for a path
*/
getPrefix (app: FabrixApp, route): string {
if (!route || !(route instanceof Object)) {
throw new RangeError('Expected a route object')
}

const hasPrefix = route.config && route.config.hasOwnProperty('prefix') && route.config.prefix !== false
const ignorePrefix = route.config && route.config.hasOwnProperty('prefix') && route.config.prefix === false
const routeLevelPrefix = hasPrefix ? app.config.get(route.config.prefix) || route.config.prefix.replace('$/', '') : null
const routeLevelPrefix = hasPrefix ? Utils.getRouteLevelPrefix(app, route) : null
const prefix = (app.config.get('router.prefix') || '').replace(/$\//, '')

return `${ ignorePrefix ? '' : routeLevelPrefix || prefix}`
},

/**
* Build the Path from the Route config
*/
Expand All @@ -67,16 +101,23 @@ export const Utils = {
return `${ prefix }/${ path }`
},

getPolicyFromString(app: FabrixApp, handler) {
return get(app.policies, handler)
},

/**
* Get handler method from a "hapi/hapi-like" prerequisite object/string
*/
getHandlerFromPrerequisite (app: FabrixApp, pre) {
let handler
if (pre && typeof pre === 'string') {
handler = get(app.policies, pre)
handler = Utils.getPolicyFromString(app, pre)
}
else if (pre && typeof pre.method === 'string') {
handler = get(app.policies, pre.method)
handler = Utils.getPolicyFromString(app, pre.method)
}
else if (pre && typeof pre === 'function') {
handler = pre
}

if (!handler) {
Expand All @@ -88,6 +129,10 @@ export const Utils = {
return handler
},

getControllerFromString(app: FabrixApp, handler) {
return get(app.controllers, handler)
},

/**
* Get handler method from a controller.method string path
*/
Expand All @@ -103,7 +148,15 @@ export const Utils = {
Utils.methods.forEach(method => {
if (route[method]) {
if (typeof route[method] === 'string') {
return route[method] = get(app.controllers, route[method])
return route[method] = { handler: Utils.getControllerFromString(app, route[method]) }
}
else if (route[method] instanceof Object && route[method].hasOwnProperty('handler')) {
if (typeof route[method].handler === 'string') {
return route[method].handler = Utils.getControllerFromString(app, route[method].handler)
}
else {
return route[method].handler
}
}
else {
return route[method]
Expand All @@ -112,6 +165,9 @@ export const Utils = {
})
},

/**
* Build a route collection
*/
buildRoutes(app: FabrixApp, routes, toReturn = {}) {
Object.keys(routes).forEach(r => {
const { path, route } = Utils.buildRoute(app, r, routes[r])
Expand All @@ -120,6 +176,9 @@ export const Utils = {
return Utils.sortRoutes(toReturn, app.config.get('router.sortOrder'))
},

/**
* Sort a route collection by object key
*/
sortRoutes(routes, order) {
const toReturn = {}
const sorted = Object.keys(routes).sort(Utils.createSpecificityComparator({ order: order }))
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fabrix/spool-router",
"version": "1.1.0",
"version": "1.1.1",
"description": "Spool - Router for Fabrix",
"scripts": {
"build": "tsc -p ./lib/tsconfig.release.json",
Expand Down
25 changes: 24 additions & 1 deletion test/integration/lib/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ describe('lib.Util', () => {
'*': 'FooController.bar'
})

assert.equal(route.GET, global.app.controllers.FooController.bar)
assert.equal(route.GET.handler, global.app.controllers.FooController.bar)
})
it('should resolve the route handler to the correct controller method', () => {
const {path, route} = lib.Utils.buildRoute(global.app, '/foo/bar', {
'*': {
handler: 'FooController.bar'
}
})
assert.equal(route.GET.handler, global.app.controllers.FooController.bar)
})
it('should resolve the prerequisite handler (string) to the correct policy method', () => {
const {path, route} = lib.Utils.buildRoute(global.app, '/foo/bar', {
Expand All @@ -43,6 +51,21 @@ describe('lib.Util', () => {
})

assert.equal(route.config.pre[0], global.app.policies.FooPolicy.bar)
assert.equal(route.GET.config.pre[0], global.app.policies.FooPolicy.bar)
})
it('should resolve the prerequisite handler (string) to the correct policy method', () => {
const {path, route} = lib.Utils.buildRoute(global.app, '/foo/bar', {
'GET': {
method: 'FooController.bar',
config: {
pre: [
'FooPolicy.bar'
]
}
}
})

assert.equal(route.GET.config.pre[0], global.app.policies.FooPolicy.bar)
})
})

Expand Down

0 comments on commit b882115

Please sign in to comment.