1- import { combine , createEvent , createStore } from 'effector' ;
2- import { createMemoryHistory , History , State , Update } from 'history' ;
3- import { compile as createCompile , match as createMatch } from 'path-to-regexp' ;
1+ import { createEvent , createStore } from 'effector' ;
2+ import {
3+ BrowserHistory ,
4+ HashHistory ,
5+ MemoryHistory ,
6+ State ,
7+ Update ,
8+ } from 'history' ;
49
510import {
6- CompileConfig ,
711 Delta ,
812 MergedRoute ,
913 Params ,
@@ -14,86 +18,27 @@ import {
1418 RouterConfig ,
1519 ToLocation ,
1620} from './types' ;
17-
18- import { shouldUpdate , normalizeLocation , onImmediate } from './utils' ;
19-
20- const createRoute = < R , P extends Params = Params > (
21- router : R extends Router < infer Q , infer S > ? Router < Q , S > : never ,
22- config : RouteConfig
23- ) : Route < P , R > => {
24- const { path, matchOptions } = config ;
25- const match = createMatch < P > ( path , matchOptions ) ;
26- const navigate = createEvent < P | void > ( ) ;
27- const redirect = createEvent < P | void > ( ) ;
28- const $params = createStore < P | null > ( null ) ;
29- const $visible = $params . map ( Boolean ) ;
30-
31- onImmediate ( $params , router . pathname , ( _ , pathname ) => {
32- const result = match ( pathname ) ;
33- return result ? result . params : null ;
34- } ) . reset ( router . pathname ) ;
35-
36- const compile = ( {
37- params,
38- query,
39- hash,
40- options,
41- } : CompileConfig < P > = { } ) : string => {
42- const queryString = String ( new URLSearchParams ( query ) ) ;
43- const pathname = createCompile < P > ( config . path , options ) ( params ) ;
44- const search = queryString ? `?${ queryString } ` : '' ;
45- const hashSign = ! hash || hash . startsWith ( '#' ) ? '' : `#${ hash } ` ;
46- return `${ pathname } ${ search } ${ hashSign } ${ hash ?? '' } ` ;
47- } ;
48-
49- navigate . watch ( params =>
50- router . navigate ( compile ( { params : params as P | undefined } ) )
51- ) ;
52-
53- redirect . watch ( params =>
54- router . redirect ( compile ( { params : params as P | undefined } ) )
55- ) ;
56-
57- return {
58- visible : $visible ,
59- params : $params ,
60- config,
61- compile,
62- router,
63- navigate,
64- redirect,
65- } ;
66- } ;
67-
68- const createMergedRoute = ( routes : Route [ ] ) : MergedRoute => {
69- const $someVisible = combine (
70- routes . map ( route => route . visible )
71- ) . map ( statuses => statuses . some ( Boolean ) ) ;
72-
73- const $visible = onImmediate (
74- createStore ( false ) ,
75- $someVisible ,
76- ( visible , someVisible ) => visible || someVisible
77- ) . reset ( $someVisible ) ;
78-
79- const configs = routes . map ( route => route . config ) ;
80-
81- return {
82- visible : $visible ,
83- routes,
84- configs,
85- } ;
86- } ;
21+ import {
22+ createHistory ,
23+ getQueryParams ,
24+ historyChanger ,
25+ reduceStore ,
26+ } from './utils' ;
27+ import { createRoute , createMergedRoute } from './route' ;
8728
8829export const createRouter = < Q extends Query = Query , S extends State = State > ( {
8930 history : userHistory ,
31+ root,
9032} : RouterConfig < S > = { } ) : Router < Q , S > => {
91- const history = ( userHistory ?? createMemoryHistory ( ) ) as History < S > ;
33+ let history = userHistory ! ?? createHistory < S > ( root ) ;
34+
9235 const historyUpdated = createEvent < Update < S > > ( ) ;
9336 const $historyUpdate = createStore < Update < S > > ( {
9437 location : history . location ,
9538 action : history . action ,
96- } ) ;
39+ } ) . on ( historyUpdated , ( _ , update ) => update ) ;
40+
41+ let unlisten = history . listen ( historyUpdated ) ;
9742
9843 const navigate = createEvent < ToLocation < S > > ( ) ;
9944 const redirect = createEvent < ToLocation < S > > ( ) ;
@@ -108,45 +53,20 @@ export const createRouter = <Q extends Query = Query, S extends State = State>({
10853 const $hash = $location . map ( location => location . hash ) ;
10954 const $state = $location . map ( location => location . state ) ;
11055 const $key = $location . map ( location => location . key ) ;
111- const $resource = $location . map (
112- ( { pathname, search, hash } ) => `${ pathname } ${ search } ${ hash } `
113- ) ;
114- const $query = $search . map (
115- // @ts -ignore
116- search => Object . fromEntries ( new URLSearchParams ( search ) ) as Q
117- ) ;
56+ const $href = $location . map ( history . createHref ) ;
57+ const $query = $search . map < Q > ( getQueryParams ) ;
11858
11959 const $hasMatches = createStore ( false ) ;
12060 const $noMatches = $hasMatches . map ( hasMatches => ! hasMatches ) ;
12161
122- history . listen ( historyUpdated ) ;
123-
124- $location . on ( historyUpdated , ( _ , update ) => update . location ) ;
125-
126- $location . watch ( navigate , ( location , toLocation ) => {
127- const newLocation = normalizeLocation < S > ( toLocation ) ;
128- if ( shouldUpdate ( location , newLocation ) ) {
129- const { state, ...path } = newLocation ;
130- history . push ( path , state ) ;
131- }
132- } ) ;
133-
134- $location . watch ( redirect , ( location , toLocation ) => {
135- const newLocation = normalizeLocation < S > ( toLocation ) ;
136- if ( shouldUpdate ( location , newLocation ) ) {
137- const { state, ...path } = newLocation ;
138- history . replace ( path , state ) ;
139- }
140- } ) ;
141-
142- shift . watch ( delta => {
143- history . go ( delta ) ;
144- } ) ;
62+ $location . watch ( navigate , historyChanger < S > ( history . push ) ) ;
63+ $location . watch ( redirect , historyChanger < S > ( history . replace ) ) ;
64+ shift . watch ( history . go ) ;
14565
14666 const connectRoute = < P extends Params = Params > (
14767 route : Route < P , unknown > | MergedRoute
14868 ) : void => {
149- onImmediate (
69+ reduceStore (
15070 $hasMatches ,
15171 route . visible ,
15272 ( hasMatches , visible ) => hasMatches || visible
@@ -171,8 +91,9 @@ export const createRouter = <Q extends Query = Query, S extends State = State>({
17191 hash : $hash ,
17292 state : $state ,
17393 key : $key ,
174- resource : $resource ,
94+ href : $href ,
17595 query : $query ,
96+
17697 hasMatches : $hasMatches ,
17798 noMatches : $noMatches ,
17899
@@ -197,6 +118,18 @@ export const createRouter = <Q extends Query = Query, S extends State = State>({
197118 route . visible = route . visible . map ( visible => ! visible ) ;
198119 return route ;
199120 } ,
121+
122+ use : (
123+ givenHistory : BrowserHistory < S > | HashHistory < S > | MemoryHistory < S >
124+ ) => {
125+ const { location, action } = givenHistory ;
126+ const defaultState = { location, action } ;
127+ $historyUpdate . defaultState = defaultState ;
128+ unlisten ( ) ;
129+ unlisten = givenHistory . listen ( historyUpdated ) ;
130+ history = givenHistory ;
131+ historyUpdated ( defaultState ) ;
132+ } ,
200133 } ;
201134
202135 return router ;
0 commit comments