Skip to content
This repository has been archived by the owner on Dec 28, 2018. It is now read-only.

WIP: Introduce router modules #901

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
],
"license": "MIT",
"dependencies": {
"@types/crossroads": "^0.0.29",
"@types/js-cookie": "^2.0.28",
"@types/mocha": "^2.2.41",
"@types/node": "^7.0.22",
Expand All @@ -70,6 +71,7 @@
"compression": "^1.6.2",
"cpx": "^1.5.0",
"cross-env": "^5.0.0",
"crossroads": "^0.12.2",
"del": "^2.2.2",
"del-cli": "^1.0.0",
"eslint": "^3.19.0",
Expand Down
127 changes: 127 additions & 0 deletions src/lib/Router/Router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import crossroads from './crossroads';

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Subscription, } from 'rxjs/Subscription';

import { ViewContext } from '../ViewContext';

export type PathString = string;

type OnRouteFn = (id?: string) => ViewContext;
export type Route = [PathString, OnRouteFn];
export type RouteConfig = Array<Route>;

export const enum RoutingActionType {
Push = 0,
Replace = 1,
StaticReload = 2,
}

export interface RoutingAction {
type: RoutingActionType;
path: PathString;
}

export class Router {

private _router: typeof crossroads;
private _intent: Observable<RoutingAction>;
private _nextContext: Subject<ViewContext>;
private _changedLocaton: Subject<PathString>;
private _disposer: Subscription;

private constructor(channel: Observable<RoutingAction>, config: RouteConfig) {
this._router = crossroads.create();
this._intent = channel;
this._nextContext = new Subject<ViewContext>();
this._changedLocaton = new Subject<PathString>();
this._disposer = new Subscription();

this._setupRouting(config);
}

static create(channel: Observable<RoutingAction>, routeConfig: RouteConfig): Router {
const r = new Router(channel, routeConfig);
return r;
}

private _setupRouting(list: RouteConfig): void {
for (const [path, fn] of list) {
this._router.addRoute(path, (id: string) => {
const ctx: ViewContext = fn(id);
this._nextContext.next(ctx);
this._changedLocaton.next(path);
});
}

this._router.bypassed.add((aReq: PathString) => {
const e = new ReferenceError(`tried to route to the non-registered one: ${aReq}`);
this._nextContext.error(e);
console.error(e);
});
}

activate(): void {
const disposer = this._disposer;

const intent = this._intent;
const nextPath = intent.subscribe((action) => {
this._router.parse(action.path);
});
disposer.add(nextPath);
}

destroy(): void {
this._disposer.unsubscribe();

this._changedLocaton.complete();
this._changedLocaton.unsubscribe();

this._nextContext.complete();
this._nextContext.unsubscribe();

// XXX: for destruction
// tslint:disable:no-any
this._disposer = null as any;
this._changedLocaton = null as any;
this._nextContext = null as any;
// tslint:enable
}
/**
* @returns
* This represents the actual path by
* The component class which displays a url subscribes this to observe
* a url which it should display.
*/
changedLocation(): Observable<RoutingAction> {
return this._changedLocaton.zip(this._intent, (_, action) => {
return action;
});
}

nextContext(): Observable<ViewContext> {
return this._nextContext;
}
}

export function toPathPushAction(path: PathString): RoutingAction {
return {
type: RoutingActionType.Push,
path,
};
}

export function toPathReplaceAction(path: PathString): RoutingAction {
return {
type: RoutingActionType.Replace,
path,
};
}

export function toStaticReloadAction(path: PathString): RoutingAction {
return {
type: RoutingActionType.StaticReload,
path,
};
}
7 changes: 7 additions & 0 deletions src/lib/Router/crossroads.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// XXX: hack TypeScript module resolution to load d.ts which has legacy default export
// To avoid it, we can also use `allowSyntheticDefaultImports` compiler option,
// But we would not like to use at this moment. So we do this hack.
// See also `./crossroads.d.ts` in the same directory.
import CrossroadsJs = require('crossroads'); // tslint:disable-line:no-require-imports
declare const crossroads: typeof CrossroadsJs;
export default crossroads; // tslint:disable-line:no-default-export
6 changes: 6 additions & 0 deletions src/lib/Router/crossroads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// XXX: hack TypeScript module resolution to load d.ts which has legacy default export
// To avoid it, we can also use `allowSyntheticDefaultImports` compiler option,
// But we would not like to use at this moment. So we do this hack.
// See also `./crossroads.js` in the same directory.
import crossroads from 'crossroads';
export default crossroads;
1 change: 1 addition & 0 deletions src/lib/Router/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Router';
20 changes: 20 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
# yarn lockfile v1


"@types/crossroads@^0.0.29":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/crossroads/-/crossroads-0.0.29.tgz#f2308c106c68c4a84a0b23affa20989abbd38cb1"
dependencies:
"@types/signals" "*"

"@types/js-cookie@^2.0.28":
version "2.0.28"
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.0.28.tgz#d6a9136d699257970fc74d899cd7b12a608d14da"
Expand All @@ -28,6 +34,10 @@
version "15.0.24"
resolved "https://registry.yarnpkg.com/@types/react/-/react-15.0.24.tgz#8a75299dc37906df327c18ca918bf97a55e7123b"

"@types/signals@*":
version "0.0.17"
resolved "https://registry.yarnpkg.com/@types/signals/-/signals-0.0.17.tgz#93911b0f09518f314a21805420143aab0c2f7ee4"

"@types/socket.io-client@^1.4.29":
version "1.4.29"
resolved "https://registry.yarnpkg.com/@types/socket.io-client/-/socket.io-client-1.4.29.tgz#f8743070cee93175e36e0b6a77a8af73e58ccb32"
Expand Down Expand Up @@ -1258,6 +1268,12 @@ cross-spawn@^5.1.0:
shebang-command "^1.2.0"
which "^1.2.9"

crossroads@^0.12.2:
version "0.12.2"
resolved "https://registry.yarnpkg.com/crossroads/-/crossroads-0.12.2.tgz#b1d5f9c1d98af3bdd61f1bda6a86dd1aee4ff8f2"
dependencies:
signals "<2.0"

[email protected]:
version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
Expand Down Expand Up @@ -4665,6 +4681,10 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"

signals@<2.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/signals/-/signals-1.0.0.tgz#65f0c1599352b35372ecaae5a250e6107376ed69"

slash@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
Expand Down