-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathRouterSource.ts
108 lines (96 loc) · 3.36 KB
/
RouterSource.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { Location, Pathname } from '@cycle/history';
import { LocationDescriptorObject } from 'history';
import {
RouteDefinitionsMap,
RouteDefinitionsArray,
RouteMatcher
} from './interfaces';
import * as util from './util';
import { adapt } from '@cycle/run/lib/adapt';
function isStrictlyInScope(namespace: Pathname[], path: Pathname): boolean {
const pathParts = util.splitPath(path);
return namespace.every((v, i) => {
return pathParts[i] === v;
});
}
function getFilteredPath(namespace: Pathname[], path: Pathname): Pathname {
const pathParts = util.splitPath(path);
return '/' + util.filterPath(pathParts, namespace);
}
export class RouterSource {
constructor(
private _history$: any,
private _namespace: Pathname[],
private _createHref: (path: LocationDescriptorObject) => Pathname,
private _routeMatcher: RouteMatcher,
private _name: string
) {}
history$ = adapt(this._history$);
path(pathname: Pathname): RouterSource {
const scopedNamespace = this._namespace.concat(
util.splitPath(pathname)
);
const scopedHistory$ = this._history$
.filter(({ pathname: _path }: Location) =>
isStrictlyInScope(scopedNamespace, _path)
)
.remember();
const createHref = this._createHref;
return new RouterSource(
scopedHistory$,
scopedNamespace,
createHref,
this._routeMatcher,
this._name
);
}
private _define(
routes: RouteDefinitionsMap | RouteDefinitionsArray,
routeMatcher?: RouteMatcher
): any {
const namespace = this._namespace;
const _createHref = this._createHref;
const createHref = util.makeCreateHref(namespace, _createHref);
return this._history$
.map((location: Location) => {
const matcher = routeMatcher || this._routeMatcher;
const filteredPath = getFilteredPath(
namespace,
location.pathname
);
const { path, value } = matcher(filteredPath, routes);
return { path, value, location, createHref };
})
.filter(({ path }: any) => path !== undefined && path !== null)
.remember();
}
define(
routes: RouteDefinitionsMap | RouteDefinitionsArray,
routeMatcher?: RouteMatcher
): any {
const _createHref = this._createHref;
const createHref = util.makeCreateHref(this._namespace, _createHref);
const out$ = adapt(this._define(routes, routeMatcher));
out$.createHref = createHref;
return out$;
}
routedComponent(
routes: RouteDefinitionsMap | RouteDefinitionsArray,
routeMatcher?: RouteMatcher
): (sources: any) => any {
const name = this._name;
return sources => {
const match$ = this._define(routes, routeMatcher);
const page$ = match$.map(({ path, value }: any) => {
return value({
...sources,
[name]: sources[name].path(path)
});
});
return adapt(page$);
};
}
createHref(path: Pathname): Pathname {
return util.makeCreateHref(this._namespace, this._createHref)(path);
}
}