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