atomic-router
Advanced tools
Comparing version 0.5.0-dev.15 to 0.5.0-dev.16
@@ -1,7 +0,123 @@ | ||
export * from './create-route'; | ||
export * from './create-history-router'; | ||
export * from './utils/build-path'; | ||
export * from './utils/is-route'; | ||
export * from './utils/redirect'; | ||
export * from './utils/chain-route'; | ||
export * from './types'; | ||
import * as effector from 'effector'; | ||
import { Store, Event, Effect, Clock } from 'effector'; | ||
import { History } from 'history'; | ||
declare type RouteParams = Record<string, any>; | ||
declare type RouteQuery = Record<string, any>; | ||
declare type RouteParamsAndQuery<Params extends RouteParams> = { | ||
params: Params; | ||
query: RouteQuery; | ||
}; | ||
declare type RouteInstance<Params extends RouteParams> = { | ||
$isOpened: Store<boolean>; | ||
$params: Store<Params>; | ||
$query: Store<RouteQuery>; | ||
opened: Event<RouteParamsAndQuery<Params>>; | ||
updated: Event<RouteParamsAndQuery<Params>>; | ||
closed: Event<void>; | ||
/** @deprecated Will be removed in 0.6.0. Use `route.closed` instead */ | ||
left: Event<void>; | ||
navigate: Effect<RouteParamsAndQuery<Params>, RouteParamsAndQuery<Params>>; | ||
open: Effect<Params, RouteParamsAndQuery<Params>>; | ||
kind: typeof Kind.ROUTE; | ||
}; | ||
declare type PathCreator<Params extends RouteParams> = string; | ||
declare const Kind: { | ||
ROUTE: symbol; | ||
}; | ||
declare type createRouteParams = { | ||
filter?: Store<boolean>; | ||
}; | ||
declare const createRoute: <Params extends RouteParams = {}>(params?: createRouteParams) => RouteInstance<Params>; | ||
declare type RouteObject<Params extends RouteParams> = { | ||
route: RouteInstance<Params>; | ||
path: string; | ||
}; | ||
declare type UnmappedRouteObject<Params extends RouteParams> = { | ||
route: RouteInstance<Params> | RouteInstance<Params>[]; | ||
path: string; | ||
}; | ||
declare type HistoryPushParams = { | ||
history: History; | ||
path: string; | ||
params: RouteParams; | ||
query: RouteQuery; | ||
method: 'replace' | 'push'; | ||
}; | ||
declare const createHistoryRouter: (params: { | ||
routes: UnmappedRouteObject<any>[]; | ||
hydrate?: boolean; | ||
}) => { | ||
$path: effector.Store<string>; | ||
$query: effector.Store<{}>; | ||
$activeRoutes: effector.Store<RouteInstance<any>[]>; | ||
$history: effector.Store<History>; | ||
setHistory: effector.Event<History>; | ||
push: effector.Effect<Omit<HistoryPushParams, "history">, HistoryPushParams, Error>; | ||
routes: RouteObject<any>[]; | ||
initialized: effector.Event<{ | ||
activeRoutes: RouteInstance<any>[]; | ||
path: string; | ||
query: {}; | ||
}>; | ||
routeNotFound: effector.Event<void>; | ||
}; | ||
declare type BuildPathParams<Params extends RouteParams> = { | ||
pathCreator: PathCreator<Params>; | ||
params: Params; | ||
query: RouteQuery; | ||
}; | ||
declare function buildPath<Params extends RouteParams>({ pathCreator, params, query, }: BuildPathParams<Params>): string; | ||
declare type MatchPathParams<Params extends RouteParams> = { | ||
pathCreator: PathCreator<Params>; | ||
actualPath: string; | ||
}; | ||
declare function matchPath<Params extends RouteParams>({ pathCreator, actualPath, }: MatchPathParams<Params>): { | ||
readonly matches: true; | ||
readonly params: object; | ||
} | { | ||
readonly matches: false; | ||
readonly params?: undefined; | ||
}; | ||
/** Detects whether passed value is a `RouteInstance<any>` or not */ | ||
declare const isRoute: (route: RouteInstance<any> | unknown) => route is RouteInstance<any>; | ||
declare type RedirectParams<T, Params> = { | ||
clock?: Clock<T>; | ||
route: RouteInstance<Params>; | ||
params?: ((clock: T) => Params) | Store<Params> | Params; | ||
query?: ((clock: T) => RouteQuery) | Store<RouteQuery> | RouteQuery; | ||
}; | ||
/** Opens passed `route` upon `clock` trigger */ | ||
declare const redirect: <T, Params>(options: RedirectParams<T, Params>) => Event<T>; | ||
declare type ChainRouteParamsWithEffect<Params> = { | ||
route: RouteInstance<Params>; | ||
chainedRoute?: RouteInstance<Params>; | ||
beforeOpen: Effect<RouteParamsAndQuery<Params>, any, any>; | ||
}; | ||
declare type ChainRouteParamsAdvanced<Params> = { | ||
route: RouteInstance<Params>; | ||
chainedRoute?: RouteInstance<Params>; | ||
beforeOpen: Clock<RouteParamsAndQuery<Params>>; | ||
openOn: Clock<any>; | ||
cancelOn?: Clock<any>; | ||
}; | ||
declare type chainRouteParams<Params> = RouteInstance<Params> | ChainRouteParamsWithEffect<Params> | ChainRouteParamsAdvanced<Params>; | ||
/** | ||
* Creates chained route | ||
* @link https://github.com/Kelin2025/atomic-router/issues/10 | ||
* @param {RouteInstance<any>} params.route - Route to listen | ||
* @param {RouteInstance<any>} [params.chainedRoute] - Route to be created | ||
* @param {Clock<any>} params.beforeOpen - Will be triggered when `params.route` open | ||
* @param {Clock<any>} params.enterOn - Will open `chainedRoute` if `params.route` is still opened | ||
* @param {Clock<any>} params.cancelOn - Cancels chain | ||
* @returns {RouteInstance<any>} `chainedRoute` | ||
*/ | ||
declare const chainRoute: <Params>(params: chainRouteParams<Params>) => RouteInstance<Params>; | ||
export { Kind, PathCreator, RouteInstance, RouteParams, RouteParamsAndQuery, RouteQuery, buildPath, chainRoute, createHistoryRouter, createRoute, isRoute, matchPath, redirect }; |
@@ -1,8 +0,1 @@ | ||
'use strict' | ||
if (process.env.NODE_ENV === 'production') { | ||
module.exports = require('./atomic-router.cjs.production.min.js') | ||
} else { | ||
module.exports = require('./atomic-router.cjs.development.js') | ||
} | ||
var A=Object.defineProperty,L=Object.defineProperties,N=Object.getOwnPropertyDescriptor,V=Object.getOwnPropertyDescriptors,W=Object.getOwnPropertyNames,F=Object.getOwnPropertySymbols;var M=Object.prototype.hasOwnProperty,G=Object.prototype.propertyIsEnumerable;var w=(e,t,a)=>t in e?A(e,t,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[t]=a,j=(e,t)=>{for(var a in t||(t={}))M.call(t,a)&&w(e,a,t[a]);if(F)for(var a of F(t))G.call(t,a)&&w(e,a,t[a]);return e},z=(e,t)=>L(e,V(t));var J=(e,t)=>{for(var a in t)A(e,a,{get:t[a],enumerable:!0})},X=(e,t,a,p)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of W(t))!M.call(e,s)&&s!==a&&A(e,s,{get:()=>t[s],enumerable:!(p=N(t,s))||p.enumerable});return e};var Y=e=>X(A({},"__esModule",{value:!0}),e);var ne={};J(ne,{Kind:()=>C,buildPath:()=>T,chainRoute:()=>se,createHistoryRouter:()=>ae,createRoute:()=>q,isRoute:()=>H,matchPath:()=>U,redirect:()=>re});module.exports=Y(ne);var i=require("effector");var C={ROUTE:Symbol()};var q=(e={})=>{let t=(0,i.createEffect)(async({params:n,query:m})=>({params:n||{},query:m||{}})),a=(0,i.attach)({effect:t,mapParams:n=>({params:n||{},query:{}})}),p=(0,i.createStore)(!1),s=(0,i.createStore)({}),d=(0,i.createStore)({}),P=(0,i.createEvent)(),y=(0,i.createEvent)(),R=(0,i.createEvent)(),h=(0,i.createEvent)();if(p.on(P,()=>!0).on(R,()=>!1),s.on(P,(n,{params:m})=>m).on(y,(n,{params:m})=>m),d.on(P,(n,{query:m})=>m).on(y,(n,{query:m})=>m),(0,i.split)({source:t.doneData,match:p.map(n=>n?"updated":"opened"),cases:{opened:P,updated:y}}),(0,i.sample)({clock:h,target:R}),e.filter){let n=e.filter;(0,i.split)({source:(0,i.sample)({clock:n}),match:m=>m?"true":"false",cases:{true:P,false:h}})}return{$isOpened:p,$params:s,$query:d,opened:P,updated:y,closed:h,left:R,navigate:t,open:a,kind:C.ROUTE,settings:{derived:Boolean(e.filter)}}};var I=require("path-to-regexp"),Z=e=>{let t=new URL(`http://_${e}`);return[t.pathname,t.hash].join("")};function T({pathCreator:e,params:t,query:a}){let p=(0,I.compile)(e)(t),s=Object.keys(a).length?`?${new URLSearchParams(a)}`:"";return`${p}${s}`}function U({pathCreator:e,actualPath:t}){let a=(0,I.match)(e)(Z(t));return a?{matches:!0,params:a.params}:{matches:!1}}var r=require("effector");var D=(e,t)=>{if(Object.keys(e).length!==Object.keys(t).length)return!1;for(let a in e)if(`${e[a]}`!=`${t[a]}`)return!1;return!0};var ee=(0,r.createEffect)(e=>{if(!e.history)throw new Error("[Routing] No history provided");return e.history[e.method](e.path,{}),e}),te=e=>{let t=[];for(let s of e)Array.isArray(s.route)?t.push(...s.route.map(d=>z(j({},s),{route:d}))):t.push(s);let a=[],p=[];for(let s of t)s.route.settings.derived?a.push(s):p.push(s);if(a.length)for(let s of a)console.error(`createHistoryRouter: ${s.path} uses derived route. This won't work`);return p},ae=e=>{let t=te(e.routes),a=(0,r.createEvent)(),p=(0,r.createEvent)(),s=(0,r.createStore)({}),d=(0,r.createStore)(""),P=(0,r.createStore)([],{serialize:"ignore"}),y=(0,r.createStore)(!1),R=(0,r.createStore)(null,{serialize:"ignore"});R.on(a,(o,c)=>c);let h=(0,r.attach)({source:{history:R},effect:ee,mapParams:(o,{history:c})=>j({history:c},o)}),E=(0,r.createEffect)(({route:o,params:c,query:f})=>({path:T({pathCreator:o.path,params:c,query:f}),params:c,query:f,method:"push"})),n=(0,r.createEffect)(({path:o,query:c,hash:f})=>{let k=[],b=[];for(let Q of t){let l=Q.path.includes("#")?`${o}${f}`:o,{matches:O,params:$}=U({pathCreator:Q.path,actualPath:l});(O?k:b).push({route:Q,params:$,query:c})}return{opened:k,closed:b}});d.on(n.done,(o,{params:{path:c}})=>c),s.on(n.done,(o,{params:{query:c}})=>c),P.on(n.doneData,(o,{opened:c})=>c.map(f=>f.route.route)),(0,r.sample)({clock:E.doneData,target:h}),(0,r.guard)({clock:n.doneData,filter:({opened:o})=>o.length===0,target:p});let m=n.doneData.map(({opened:o})=>o),v=n.doneData.map(({closed:o})=>o);for(let o of t){let c=(0,r.createStore)(!1),f=o.route.navigate.done;(0,r.sample)({clock:f,fn:({result:{params:l,query:O}})=>({route:o,params:l,query:O}),target:E});let k=l=>{let O=l.find($=>$.route===o);if(!!O)return{params:O.params,query:O.query}},b={opened:(0,r.guard)({clock:m.filterMap(k),filter:o.route.$isOpened.map(l=>!l)}),updated:(0,r.guard)({clock:m.filterMap(k),filter:o.route.$isOpened}),closed:(0,r.guard)({clock:v.filterMap(k),filter:o.route.$isOpened})};c.on(f,()=>!0);let Q=(0,r.guard)({clock:b.updated,filter:c.map(l=>!l)});(0,r.sample)({source:(0,r.restore)(Q,null),clock:(0,r.guard)({clock:Q,source:[o.route.$params,o.route.$query],filter:([l,O],$)=>!D(l,$.params)||!D(O,$.query)}),fn:l=>l,target:o.route.updated}),(0,r.guard)({clock:b.opened,filter:c.map(l=>!l),target:o.route.opened}),(0,r.sample)({clock:b.closed,target:o.route.closed}),c.reset((0,r.sample)({clock:m}))}let S=(0,r.attach)({source:{history:R},effect:async({history:o})=>{let[c,f,k]=[o.location.pathname,Object.fromEntries(new URLSearchParams(o.location.search)),o.location.hash];return{path:c,query:f,hash:k}}});(0,r.sample)({source:S.doneData,target:n});let _=(0,r.attach)({source:{history:R},effect:async({history:o})=>{let c=S;try{c=(0,r.scopeBind)(S)}catch{}return o.listen(()=>{c()}),!0}});e.hydrate||(0,r.sample)({clock:_.doneData,target:S}),(0,r.sample)({clock:R,target:_}),y.on(n.doneData,()=>!0).reset(R);let K=(0,r.sample)({clock:(0,r.guard)({clock:y,filter:Boolean}),source:{activeRoutes:P,path:d,query:s}});return{$path:d,$query:s,$activeRoutes:P,$history:R,setHistory:a,push:h,routes:t,initialized:K,routeNotFound:p}};var H=e=>typeof e=="object"&&e!==null&&"kind"in e&&e.kind===C.ROUTE;var g=require("effector"),re=e=>{let t=e.clock?(0,g.sample)({clock:e.clock}):(0,g.createEvent)(),a=B(e.params||{}),p=B(e.query||{});return(0,g.sample)({clock:t,source:{params:a,query:p},fn:({params:s,query:d},P)=>({params:typeof s=="function"?s(P):s,query:typeof d=="function"?d(P):d}),target:e.route.navigate}),t},B=e=>g.is.store(e)?e:(0,g.createStore)(e);var u=require("effector");var oe=e=>{if(H(e))return{route:e,chainedRoute:q(),beforeOpen:(0,u.createEvent)(),openOn:[e.opened,e.closed],cancelOn:[(0,u.createEvent)()]};let t=e;if(!("enterOn"in t)&&u.is.effect(t.beforeOpen))return{route:t.route,chainedRoute:t.chainedRoute||q(),beforeOpen:t.beforeOpen,openOn:t.beforeOpen.doneData,cancelOn:t.beforeOpen.failData};let a=e;return{route:a.route,chainedRoute:a.chainedRoute||q(),beforeOpen:a.beforeOpen,openOn:(0,u.sample)({clock:a.openOn}),cancelOn:(0,u.sample)({clock:a.cancelOn||(0,u.createEvent)()})}},se=e=>{let{route:t,chainedRoute:a,beforeOpen:p,openOn:s,cancelOn:d}=oe(e),P=(0,u.createStore)({}),y=(0,u.createStore)({}),R=(0,u.combine)((0,u.combine)([t.$params,t.$query]),(0,u.combine)([P,y]),(m,v)=>m[0]===v[0]&&m[1]===v[1]),h=(0,u.sample)({clock:[t.opened,t.updated]});(0,u.sample)({clock:h,target:p}),P.on(h,(m,{params:v})=>v),y.on(h,(m,{query:v})=>v);let E=(0,u.guard)({clock:s,source:{params:P,query:y},filter:R});(0,u.sample)({clock:E,target:a.navigate});let n=(0,u.merge)([t.closed,d]);return P.reset(n),y.reset(n),(0,u.sample)({clock:n,target:a.closed}),a};0&&(module.exports={Kind,buildPath,chainRoute,createHistoryRouter,createRoute,isRoute,matchPath,redirect}); |
{ | ||
"version": "0.5.0-dev.15", | ||
"version": "0.5.0-dev.16", | ||
"license": "MIT", | ||
@@ -14,7 +14,7 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"start": "tsdx watch", | ||
"build": "tsdx build", | ||
"test": "tsdx test", | ||
"lint": "tsdx lint", | ||
"prepare": "tsdx build" | ||
"start": "tsup src/index.ts --watch", | ||
"test": "jest -i", | ||
"test:watch": "jest --watch -i", | ||
"build": "npm run test && tsup src/index.ts --minify --dts", | ||
"prepare": "npm run build" | ||
}, | ||
@@ -26,6 +26,10 @@ "peerDependencies": { | ||
"devDependencies": { | ||
"@types/jest": "^27.5.0", | ||
"effector": "^22", | ||
"history": "^5", | ||
"tsdx": "^0.14.1", | ||
"tslib": "^2.3.1" | ||
"jest": "^28.1.0", | ||
"ts-jest": "^28.0.1", | ||
"tslib": "^2.4.0", | ||
"tsup": "^5.12.7", | ||
"typescript": "^4.6.3" | ||
}, | ||
@@ -32,0 +36,0 @@ "dependencies": { |
@@ -145,2 +145,3 @@ import { buildPath, matchPath } from './utils/build-path'; | ||
query: RouteQuery; | ||
hash: string; | ||
}, | ||
@@ -151,3 +152,3 @@ { | ||
} | ||
>(({ path, query }) => { | ||
>(({ path, query, hash }) => { | ||
const opened = [] as RecheckResult<any>[]; | ||
@@ -157,5 +158,7 @@ const closed = [] as RecheckResult<any>[]; | ||
for (const route of remappedRoutes) { | ||
// NOTE: Use hash string as well if route.path contains # | ||
const actualPath = route.path.includes('#') ? `${path}${hash}` : path; | ||
const { matches, params } = matchPath({ | ||
pathCreator: route.path, | ||
actualPath: path, | ||
actualPath: actualPath, | ||
}); | ||
@@ -220,5 +223,12 @@ (matches ? opened : closed).push({ | ||
const containsCurrentRoute = (recheckResults: RecheckResult<any>[]) => { | ||
return recheckResults.find( | ||
const result = recheckResults.find( | ||
recheckResult => recheckResult.route === routeObj | ||
); | ||
if (!result) { | ||
return; | ||
} | ||
return { | ||
params: result.params, | ||
query: result.query, | ||
}; | ||
}; | ||
@@ -257,3 +267,5 @@ | ||
filter: ([params, query], next) => { | ||
return !paramsEqual(params, next.params) || !paramsEqual(query, next.query); | ||
return ( | ||
!paramsEqual(params, next.params) || !paramsEqual(query, next.query) | ||
); | ||
}, | ||
@@ -289,8 +301,8 @@ }), | ||
effect: async ({ history }) => { | ||
const [path, query] = [ | ||
const [path, query, hash] = [ | ||
history.location.pathname, | ||
Object.fromEntries( | ||
// @ts-expect-error | ||
new URLSearchParams(history.location.search) | ||
) as RouteQuery, | ||
history.location.hash, | ||
]; | ||
@@ -300,2 +312,3 @@ return { | ||
query, | ||
hash, | ||
}; | ||
@@ -302,0 +315,0 @@ }, |
@@ -79,2 +79,3 @@ import { | ||
split({ | ||
// @ts-expect-error | ||
source: sample({ clock: filter }), | ||
@@ -81,0 +82,0 @@ // @ts-expect-error |
@@ -5,3 +5,6 @@ import { match, compile } from 'path-to-regexp'; | ||
const getPathname = (path: string) => new URL(`http://_${path}`).pathname; | ||
const getPathname = (path: string) => { | ||
const url = new URL(`http://_${path}`); | ||
return [url.pathname, url.hash].join(''); | ||
}; | ||
@@ -8,0 +11,0 @@ type BuildPathParams<Params extends RouteParams> = { |
@@ -74,4 +74,6 @@ import { | ||
beforeOpen: advancedParams.beforeOpen, | ||
openOn: sample({ clock: advancedParams.openOn }), | ||
cancelOn: sample({ clock: advancedParams.cancelOn || createEvent() }), | ||
openOn: sample({ clock: advancedParams.openOn as Unit<any> }), | ||
cancelOn: sample({ | ||
clock: (advancedParams.cancelOn as Unit<any>) || createEvent(), | ||
}), | ||
}; | ||
@@ -91,9 +93,4 @@ }; | ||
export const chainRoute = <Params>(params: chainRouteParams<Params>) => { | ||
const { | ||
route, | ||
chainedRoute, | ||
beforeOpen, | ||
openOn, | ||
cancelOn, | ||
} = normalizeChainRouteParams(params); | ||
const { route, chainedRoute, beforeOpen, openOn, cancelOn } = | ||
normalizeChainRouteParams(params); | ||
const $params = createStore({} as StoreValue<typeof route['$params']>); | ||
@@ -100,0 +97,0 @@ const $query = createStore({} as StoreValue<typeof route['$query']>); |
@@ -1,2 +0,10 @@ | ||
import { Clock, createEvent, createStore, is, sample, Store } from 'effector'; | ||
import { | ||
Clock, | ||
createEvent, | ||
createStore, | ||
Event, | ||
is, | ||
sample, | ||
Store, | ||
} from 'effector'; | ||
import { RouteInstance, RouteQuery } from '../types'; | ||
@@ -14,3 +22,3 @@ | ||
const clock = options.clock | ||
? sample({ clock: options.clock }) | ||
? sample({ clock: options.clock as Event<T> }) | ||
: createEvent<T>(); | ||
@@ -17,0 +25,0 @@ let params = toStore(options.params || {}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
0
1
38273
8
14
824