Skip to content

Commit b882115

Browse files
authored
Merge pull request #4 from fabrix-app/v1.1
[feat] Route Refine
2 parents 32c674d + 3cf4d53 commit b882115

File tree

5 files changed

+121
-12
lines changed

5 files changed

+121
-12
lines changed

README.md

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,42 @@ that takes the following form:
6464
{
6565
// ...
6666
'/example/test': {
67-
'GET': 'ExampleController.test',
68-
config: {
69-
pre: [ 'ExamplePolicy.test' ]
67+
'GET': {
68+
handler: 'ExampleController.test',
69+
config: {
70+
pre: [ ]
71+
}
72+
}
73+
}
74+
// ...
75+
}
76+
```
77+
78+
You can also refine this by explicitly defining the handler and config:
79+
80+
```js
81+
{
82+
// ...
83+
'/example/test': {
84+
'GET': {
85+
handler: 'ExampleController.get',
86+
config: {
87+
pre: [ 'ExamplePolicy.get' ]
88+
}
89+
},
90+
'POST': {
91+
handler: 'ExampleController.post',
92+
config: {
93+
pre: [ 'ExamplePolicy.post' ]
94+
}
7095
}
7196
}
7297
// ...
7398
}
7499
```
100+
Which is useful for refining controller over different http methods on a route.
75101

102+
##### Prefixes
76103
```js
77104
{
78105
// ...

lib/utils.ts

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,65 @@ export const Utils = {
2828
Utils.getHandlerFromString(app, route)
2929

3030
route.config.pre = route.config.pre
31-
.map(pre => this.getHandlerFromPrerequisite(app, pre))
31+
.map(pre => Utils.getHandlerFromPrerequisite(app, pre))
3232
.filter(handler => !!handler)
3333

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

36-
if (!routeHandlers.some(v => Utils.methods.indexOf(v) >= 0)) {
36+
if (!routeHandlers.some(v => Utils.methods.indexOf(v) >= 0 || !!route[v])) {
3737
app.log.error('spool-router: route ', path, ' handler [', routeHandlers.join(', '), ']',
3838
'does not correspond to any defined Controller handler')
3939
return {}
4040
}
41+
42+
routeHandlers.forEach(method => {
43+
if (route[method]) {
44+
route[method].config = route[method].config || route.config
45+
route[method].config.pre = route[method].config.pre || route.config.pre
46+
route[method].config.pre = route[method].config.pre
47+
.map(pre => Utils.getHandlerFromPrerequisite(app, pre))
48+
.filter(handler => !!handler)
49+
}
50+
})
51+
4152
return { path, route }
4253
},
4354

55+
/**
56+
* Expands the search for the prefix to the route or config.* level
57+
*/
58+
getRouteLevelPrefix(app: FabrixApp, route) {
59+
const configuredPrefix = app.config.get(route.config.prefix)
60+
const routePrefix = route.config.prefix
61+
if (typeof configuredPrefix !== 'undefined') {
62+
if (configuredPrefix) {
63+
return (configuredPrefix).replace(/$\//, '')
64+
}
65+
else {
66+
return
67+
}
68+
}
69+
else {
70+
return (routePrefix || '').replace(/$\//, '')
71+
}
72+
},
73+
74+
/**
75+
* Get's the prefix for a path
76+
*/
4477
getPrefix (app: FabrixApp, route): string {
4578
if (!route || !(route instanceof Object)) {
4679
throw new RangeError('Expected a route object')
4780
}
4881

4982
const hasPrefix = route.config && route.config.hasOwnProperty('prefix') && route.config.prefix !== false
5083
const ignorePrefix = route.config && route.config.hasOwnProperty('prefix') && route.config.prefix === false
51-
const routeLevelPrefix = hasPrefix ? app.config.get(route.config.prefix) || route.config.prefix.replace('$/', '') : null
84+
const routeLevelPrefix = hasPrefix ? Utils.getRouteLevelPrefix(app, route) : null
5285
const prefix = (app.config.get('router.prefix') || '').replace(/$\//, '')
5386

5487
return `${ ignorePrefix ? '' : routeLevelPrefix || prefix}`
5588
},
89+
5690
/**
5791
* Build the Path from the Route config
5892
*/
@@ -67,16 +101,23 @@ export const Utils = {
67101
return `${ prefix }/${ path }`
68102
},
69103

104+
getPolicyFromString(app: FabrixApp, handler) {
105+
return get(app.policies, handler)
106+
},
107+
70108
/**
71109
* Get handler method from a "hapi/hapi-like" prerequisite object/string
72110
*/
73111
getHandlerFromPrerequisite (app: FabrixApp, pre) {
74112
let handler
75113
if (pre && typeof pre === 'string') {
76-
handler = get(app.policies, pre)
114+
handler = Utils.getPolicyFromString(app, pre)
77115
}
78116
else if (pre && typeof pre.method === 'string') {
79-
handler = get(app.policies, pre.method)
117+
handler = Utils.getPolicyFromString(app, pre.method)
118+
}
119+
else if (pre && typeof pre === 'function') {
120+
handler = pre
80121
}
81122

82123
if (!handler) {
@@ -88,6 +129,10 @@ export const Utils = {
88129
return handler
89130
},
90131

132+
getControllerFromString(app: FabrixApp, handler) {
133+
return get(app.controllers, handler)
134+
},
135+
91136
/**
92137
* Get handler method from a controller.method string path
93138
*/
@@ -103,7 +148,15 @@ export const Utils = {
103148
Utils.methods.forEach(method => {
104149
if (route[method]) {
105150
if (typeof route[method] === 'string') {
106-
return route[method] = get(app.controllers, route[method])
151+
return route[method] = { handler: Utils.getControllerFromString(app, route[method]) }
152+
}
153+
else if (route[method] instanceof Object && route[method].hasOwnProperty('handler')) {
154+
if (typeof route[method].handler === 'string') {
155+
return route[method].handler = Utils.getControllerFromString(app, route[method].handler)
156+
}
157+
else {
158+
return route[method].handler
159+
}
107160
}
108161
else {
109162
return route[method]
@@ -112,6 +165,9 @@ export const Utils = {
112165
})
113166
},
114167

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

179+
/**
180+
* Sort a route collection by object key
181+
*/
123182
sortRoutes(routes, order) {
124183
const toReturn = {}
125184
const sorted = Object.keys(routes).sort(Utils.createSpecificityComparator({ order: order }))

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@fabrix/spool-router",
3-
"version": "1.1.0",
3+
"version": "1.1.1",
44
"description": "Spool - Router for Fabrix",
55
"scripts": {
66
"build": "tsc -p ./lib/tsconfig.release.json",

test/integration/lib/util.test.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ describe('lib.Util', () => {
1616
'*': 'FooController.bar'
1717
})
1818

19-
assert.equal(route.GET, global.app.controllers.FooController.bar)
19+
assert.equal(route.GET.handler, global.app.controllers.FooController.bar)
20+
})
21+
it('should resolve the route handler to the correct controller method', () => {
22+
const {path, route} = lib.Utils.buildRoute(global.app, '/foo/bar', {
23+
'*': {
24+
handler: 'FooController.bar'
25+
}
26+
})
27+
assert.equal(route.GET.handler, global.app.controllers.FooController.bar)
2028
})
2129
it('should resolve the prerequisite handler (string) to the correct policy method', () => {
2230
const {path, route} = lib.Utils.buildRoute(global.app, '/foo/bar', {
@@ -43,6 +51,21 @@ describe('lib.Util', () => {
4351
})
4452

4553
assert.equal(route.config.pre[0], global.app.policies.FooPolicy.bar)
54+
assert.equal(route.GET.config.pre[0], global.app.policies.FooPolicy.bar)
55+
})
56+
it('should resolve the prerequisite handler (string) to the correct policy method', () => {
57+
const {path, route} = lib.Utils.buildRoute(global.app, '/foo/bar', {
58+
'GET': {
59+
method: 'FooController.bar',
60+
config: {
61+
pre: [
62+
'FooPolicy.bar'
63+
]
64+
}
65+
}
66+
})
67+
68+
assert.equal(route.GET.config.pre[0], global.app.policies.FooPolicy.bar)
4669
})
4770
})
4871

0 commit comments

Comments
 (0)