Add basic routing.
parent
b9798f1b13
commit
557e5ec0b4
@ -0,0 +1,61 @@
|
|||||||
|
import { RouteResolver } from './routes';
|
||||||
|
|
||||||
|
const routes = {
|
||||||
|
home: '',
|
||||||
|
post: {
|
||||||
|
_base: 'post',
|
||||||
|
_id: {
|
||||||
|
_base: ':postId',
|
||||||
|
comment: 'comment/:commentId',
|
||||||
|
revision: 'history/:revisionId/:someOtherVar/test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const routeResolver = new RouteResolver(routes);
|
||||||
|
|
||||||
|
it('translating routes', () => {
|
||||||
|
// Working basic resolves
|
||||||
|
expect(routeResolver.getRoute('home')).toBe('/');
|
||||||
|
expect(routeResolver.getRoute('post')).toBe('/post');
|
||||||
|
expect(routeResolver.getRoute('post._id')).toBe('/post/:postId');
|
||||||
|
expect(routeResolver.getRoute('post._id.comment')).toBe('/post/:postId/comment/:commentId');
|
||||||
|
|
||||||
|
// Working translation resolves
|
||||||
|
expect(routeResolver.getRoute('home')).toBe('/');
|
||||||
|
expect(routeResolver.getRoute('post')).toBe('/post');
|
||||||
|
expect(routeResolver.getRoute('post._id', { postId: 3 })).toBe('/post/3');
|
||||||
|
expect(routeResolver.getRoute('post._id.comment',
|
||||||
|
{ postId: 3, commentId: 5 })).toBe('/post/3/comment/5');
|
||||||
|
expect(routeResolver.getRoute('post._id.revision',
|
||||||
|
{ postId: 3, revisionId: 5, someOtherVar: 'a' })).toBe('/post/3/history/5/a/test');
|
||||||
|
|
||||||
|
// Failing basic resolves
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('bad');
|
||||||
|
}).toThrow();
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('home.bad');
|
||||||
|
}).toThrow();
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('post._id.bad');
|
||||||
|
}).toThrow();
|
||||||
|
|
||||||
|
// Failing translations
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('home', { test: 4 });
|
||||||
|
}).toThrow();
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('post._id', { test: 4 });
|
||||||
|
}).toThrow();
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('post._id', { postId: 3, test: 4 });
|
||||||
|
}).toThrow();
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('post._id.comment', { postId: 3, commentId: 5, test: 4 });
|
||||||
|
}).toThrow();
|
||||||
|
expect(() => {
|
||||||
|
routeResolver.getRoute('post._id.comment', { postId: 3 });
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
export type RouteKeysType = { [Identifier: string]: any };
|
||||||
|
|
||||||
|
export class RouteResolver {
|
||||||
|
routes: {};
|
||||||
|
|
||||||
|
constructor(routes: {}) {
|
||||||
|
this.routes = routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRoute(name: string, _keys?: RouteKeysType): string {
|
||||||
|
let dict = this.routes;
|
||||||
|
|
||||||
|
let path: string[] = [];
|
||||||
|
name.split('.').forEach((key) => {
|
||||||
|
const val = (typeof dict[key] === 'string') ? dict[key] : dict[key]._base;
|
||||||
|
path.push(val);
|
||||||
|
|
||||||
|
dict = dict[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (_keys) {
|
||||||
|
let keys = Object.assign({}, _keys);
|
||||||
|
|
||||||
|
path = path.map((pathComponent) => {
|
||||||
|
return pathComponent.split('/').map((val) => {
|
||||||
|
if (val[0] === ':') {
|
||||||
|
const ret = keys[val.slice(1)];
|
||||||
|
if (ret === undefined) {
|
||||||
|
throw new Error('Missing key: ' + val.slice(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete keys[val.slice(1)];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}).join('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(keys).length !== 0) {
|
||||||
|
throw new Error('Too many keys for route.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '/' + path.join('/');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue