diff --git a/README.md b/README.md index fbae224e..f3266bef 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Services: Global: - [`Helpers`](#Helpers) Global Routers helpers -- [`Routers object`](#Routers) Global Routers object contains all routers properties (history, instances...) +- [`Routers object`](#Routers) Global Routers object contains all Routers properties (history, instances...) ## Installation @@ -202,8 +202,8 @@ const routesList = [ ## Sub-router -cher-ami router supports nested routes from sub routers instance 🙏🏽. -It is possible to nest as many routers as you want. +cher-ami router supports nested routes from sub Routers instance 🙏🏽. +It is possible to nest as many Routers as you want. 1. Define children routes in initial routes list with `children` property; @@ -883,7 +883,7 @@ Push new route in current history. Stack(s) component(s) will return the appriop ## Routers -Routers is a global object who contains all routers informations. Because @cher-ami/router is possibly multi-stack, we need a global object to store shared informations between router instances. +Routers is a global object who contains all Routers informations. Because @cher-ami/router is possibly multi-stack, we need a global object to store shared informations between router instances. #### Routers.routes diff --git a/src/components/Router.tsx b/src/components/Router.tsx index a86c659b..2caa49d0 100644 --- a/src/components/Router.tsx +++ b/src/components/Router.tsx @@ -12,7 +12,7 @@ import React, { } from "react" import { formatRoutes, TParams, TQueryParams } from "../core/core" import { getNotFoundRoute, getRouteFromUrl } from "../core/core" -import { ROUTERS } from "../core/ROUTERS" +import { Routers } from "../core/Routers" import LangService, { TLanguage } from "../core/LangService" import { staticPropsCache } from "../core/staticPropsCache" import { isSSR, removeLastCharFromString } from "../core/helpers" @@ -115,7 +115,7 @@ function Router(props: { }): JSX.Element { /** * Check if is the first router or a sub-router - * If is the first router, reset ROUTERS store + * If is the first router, reset Routers store */ const IS_CLIENT_OR_SERVER_ROOT_ROUTER = useMemo(() => { // base on supposition that: @@ -124,17 +124,17 @@ function Router(props: { const isRootRouter = !!props.staticLocation || !!props.history log(props.id, "IS_CLIENT_OR_SERVER_ROOT_ROUTER", isRootRouter) - // reset ROUTERS store + // reset Routers store if (IS_SERVER && isRootRouter) { - ROUTERS.base = undefined - ROUTERS.routes = undefined - ROUTERS.history = undefined - ROUTERS.staticLocation = undefined - ROUTERS.routeCounter = 1 - ROUTERS.isFirstRoute = true - ROUTERS.currentRoute = undefined - ROUTERS.langService = undefined - ROUTERS.staticPropsCache = {} + Routers.base = undefined + Routers.routes = undefined + Routers.history = undefined + Routers.staticLocation = undefined + Routers.routeCounter = 1 + Routers.isFirstRoute = true + Routers.currentRoute = undefined + Routers.langService = undefined + Routers.staticPropsCache = {} } return isRootRouter }, [props.id, props.staticLocation, props.history]) @@ -142,19 +142,19 @@ function Router(props: { /** * 0. LangService * Check if langService props exist. - * If props exist, store langService instance in ROUTERS store. + * If props exist, store langService instance in Routers store. */ const langService = useMemo(() => { if (IS_CLIENT_OR_SERVER_ROOT_ROUTER) { - ROUTERS.langService = props.langService + Routers.langService = props.langService } - return ROUTERS.langService + return Routers.langService }, [props.langService]) /** * 1. routes * Format and return routes list - * If is the first Router instance, register routes in 'ROUTERS' store. + * If is the first Router instance, register routes in 'Routers' store. * In other case, return current props.routes * * const { routes } = useRouter(); @@ -169,8 +169,8 @@ function Router(props: { ) // register is Store if... - if (!ROUTERS.routes && props.routes) { - ROUTERS.routes = routesList + if (!Routers.routes && props.routes) { + Routers.routes = routesList } // return current instance routes list @@ -180,38 +180,38 @@ function Router(props: { /** * 2. base * Format and return base URL - * Register base in 'ROUTERS' obj if is the first Router instance + * Register base in 'Routers' obj if is the first Router instance * In all case, return current props.base */ - if (!ROUTERS.base) { - ROUTERS.base = props.base + if (!Routers.base) { + Routers.base = props.base } - const base = ROUTERS.base + const base = Routers.base /** * 3. history - * If is the first Router instance, register history in 'ROUTERS' store + * If is the first Router instance, register history in 'Routers' store * 'history' object need to be the same between each Router instance */ - if (!ROUTERS.history && props.history) { - ROUTERS.history = props.history + if (!Routers.history && props.history) { + Routers.history = props.history } - const history = ROUTERS.history + const history = Routers.history /** * 4 static location * Is useful in SSR context */ if (props.staticLocation) { - ROUTERS.staticLocation = props.staticLocation + Routers.staticLocation = props.staticLocation } - const staticLocation: string | undefined = ROUTERS.staticLocation + const staticLocation: string | undefined = Routers.staticLocation /** * 5. reset is fist route visited */ if (IS_SERVER) { - ROUTERS.isFirstRoute = true + Routers.isFirstRoute = true } // -------------------------------------------------------------------------------- ROUTE CHANGE @@ -334,7 +334,7 @@ function Router(props: { // CLIENT else { // CLIENT > FIRST ROUTE - if (ROUTERS.isFirstRoute) { + if (Routers.isFirstRoute) { if (props.initialStaticProps) { log(props.id, "firstRoute > isClient > assign initialStaticProps to newRoute props & set cache"); Object.assign(newRoute.props, props.initialStaticProps?.props ?? {}); @@ -363,10 +363,10 @@ function Router(props: { // Final process: update context currentRoute from dispatch method \o/ ! dispatch({ type: "update-current-route", value: newRoute }) - // & register this new route as currentRoute in local and in ROUTERS store + // & register this new route as currentRoute in local and in Routers store currentRouteRef.current = newRoute - ROUTERS.currentRoute = newRoute - ROUTERS.isFirstRoute = false + Routers.currentRoute = newRoute + Routers.isFirstRoute = false } /** diff --git a/src/core/LangService.ts b/src/core/LangService.ts index a31bb5b6..c57638fc 100644 --- a/src/core/LangService.ts +++ b/src/core/LangService.ts @@ -1,4 +1,4 @@ -import { ROUTERS } from "./ROUTERS" +import { Routers } from "./Routers" import { compileUrl, createUrl } from "./core" import { isSSR, joinPaths, removeLastCharFromString } from "./helpers" import { TRoute } from "../components/Router" @@ -97,7 +97,7 @@ class LangService { public setLang( toLang: TLanguage, forcePageReload = true, - currentRoute: TRoute = ROUTERS.currentRoute, + currentRoute: TRoute = Routers.currentRoute, ): void { if (toLang.key === this.currentLang.key) { log("setLang: This is the same language, exit.") @@ -142,7 +142,6 @@ class LangService { } // 3. if current lang is default lang, add /currentLang.key after base - // else if (this.needToContainLangInUrl(toLang.key)) { else if (!this.showDefaultLangInUrl && this.isDefaultLangKey(this.currentLang.key)) { const newUrlWithoutBase = preparedNewUrl.substring( this.base.length, @@ -415,7 +414,7 @@ class LangService { */ protected reloadOrRefresh(newUrl: string, forcePageReload = true): void { if (isSSR()) return - forcePageReload ? window?.open(newUrl, "_self") : ROUTERS.history.push(newUrl) + forcePageReload ? window?.open(newUrl, "_self") : Routers.history.push(newUrl) } } diff --git a/src/core/routers.ts b/src/core/Routers.ts similarity index 91% rename from src/core/routers.ts rename to src/core/Routers.ts index 4515950d..1eaf0d67 100644 --- a/src/core/routers.ts +++ b/src/core/Routers.ts @@ -45,10 +45,10 @@ export type TRouters = { } /** - * ROUTERS object allows to keep safe globales values between ROUTERS instances + * ROUTERS object allows to keep safe globales values between Routers instances * This object values do not depend of one single router */ -export const ROUTERS: TRouters = { +export const Routers: TRouters = { base: undefined, routes: undefined, history: undefined, diff --git a/src/core/core.ts b/src/core/core.ts index cfa657d4..49267b20 100644 --- a/src/core/core.ts +++ b/src/core/core.ts @@ -1,4 +1,4 @@ -import { ROUTERS } from "./ROUTERS" +import { Routers } from "./Routers" import debug from "@cher-ami/debug" import { compile, match } from "path-to-regexp" import { TRoute } from "../components/Router" @@ -31,21 +31,21 @@ export type TOpenRouteParams = { */ export function createUrl( args: string | TOpenRouteParams, - base: string = ROUTERS.base, - allRoutes: TRoute[] = ROUTERS.routes, - langService = ROUTERS.langService, + base: string = Routers.base, + allRoutes: TRoute[] = Routers.routes, + langService = Routers.langService, ): string { if (!allRoutes) return - let finalURL: string + let urlToPush: string // STRING param if (typeof args === "string") { - finalURL = args as string + urlToPush = args as string if (!!langService) { - finalURL = addLangToUrl(finalURL) + urlToPush = addLangToUrl(urlToPush) } - finalURL = joinPaths([base === "/" ? "" : base, finalURL]) - return finalURL + urlToPush = joinPaths([base === "/" ? "" : base, urlToPush]) + return urlToPush } // OBJECT param, add lang to params if no exist @@ -73,7 +73,7 @@ export function createUrl( return getUrlByRouteName(allRoutes, args, base) + queryParams + hash - // in other case return + // in other case return. } else { console.warn("createUrl param isn't valid. to use createUrl return.", args) return @@ -96,7 +96,7 @@ export function getSubRouterBase( ): string { // case langService is init, and we don't want to show default lang in URL, and we are on default lang. // /:lang is return as path, but we want to get no lang in returned base string - const addLang = ROUTERS.langService?.showLangInUrl() && addLangToUrl ? "/:lang" : "" + const addLang = Routers.langService?.showLangInUrl() && addLangToUrl ? "/:lang" : "" const pathAfterLang = path === "/:lang" ? getLangPath("/") : getLangPath(path) return joinPaths([base, addLang, pathAfterLang]) } @@ -114,7 +114,7 @@ export function getSubRouterRoutes( // case langService is init, and we don't want to show default lang in URL, and we are on default lang. // /:lang is return as path, but we want to search path with "/" instead const formattedPath = - !ROUTERS.langService?.showLangInUrl() && path === "/:lang" ? "/" : path + !Routers.langService?.showLangInUrl() && path === "/:lang" ? "/" : path return routes.find((route) => { return getLangPath(route.path) === getLangPath(formattedPath) @@ -137,7 +137,7 @@ export function getPathByRouteName( if (route.name === name || route?.component?.displayName === name) { // specific case, we want to retrieve path of route with "/" route and langService is used, // we need to patch it with lang param - if (route.path === "/" && ROUTERS.langService) { + if (route.path === "/" && Routers.langService) { return "/:lang" } else { return route.path @@ -159,7 +159,7 @@ export function getPathByRouteName( * @param args can be string or TOpenRouteParams object * @param history */ -export function openRoute(args: string | TOpenRouteParams, history = ROUTERS?.history) { +export function openRoute(args: string | TOpenRouteParams, history = Routers?.history) { const url = typeof args === "string" ? args : createUrl(args) history?.push(url) } @@ -404,7 +404,7 @@ export const extractQueryParamsAndHash = ( * ] * @param routes */ -export function patchMissingRootRoute(routes: TRoute[] = ROUTERS.routes): TRoute[] { +export function patchMissingRootRoute(routes: TRoute[] = Routers.routes): TRoute[] { if (!routes) { log("routes doesnt exist, return", routes) return @@ -448,7 +448,7 @@ export function applyMiddlewaresToRoutes( /** * Format and return routes list - * If is the first Router instance, register routes in 'ROUTERS' store. + * If is the first Router instance, register routes in 'Routers' store. * In other case, return current props.routes */ export function formatRoutes( @@ -498,7 +498,7 @@ export function getFullPathByPath( routes: TRoute[], path: string | { [x: string]: string }, routeName: string, - lang: string = ROUTERS.langService?.currentLang.key || undefined, + lang: string = Routers.langService?.currentLang.key || undefined, basePath: string = null, ): string { let localPath: string[] = [basePath] @@ -550,7 +550,7 @@ export function getFullPathByPath( export function getUrlByRouteName( pRoutes: TRoute[], pParams: TOpenRouteParams, - base: string, + base?: string, ): string { // need to wrap the function to be able to access the preserved "pRoutes" param // in local scope after recursion @@ -603,7 +603,7 @@ export function getUrlByRouteName( */ export function getLangPath( langPath: string | { [p: string]: string }, - lang: string = ROUTERS.langService?.currentLang.key, + lang: string = Routers.langService?.currentLang.key, ) { let path if (typeof langPath === "string") { @@ -639,8 +639,8 @@ export function getLangPath( */ export function addLangToUrl( url: string, - lang: string = ROUTERS.langService?.currentLang.key, - enable = ROUTERS.langService?.showLangInUrl(), + lang: string = Routers.langService?.currentLang.key, + enable = Routers.langService?.showLangInUrl(), ): string { if (!enable) return url url = joinPaths([`/${lang}`, url === "/" ? "" : url]) diff --git a/src/core/staticPropsCache.ts b/src/core/staticPropsCache.ts index 77f750e8..94d644e5 100644 --- a/src/core/staticPropsCache.ts +++ b/src/core/staticPropsCache.ts @@ -1,4 +1,4 @@ -import { ROUTERS } from "./ROUTERS" +import { Routers } from "./Routers" import debug from "@cher-ami/debug" const componentName: string = "cache" const log = debug(`router:${componentName}`) @@ -7,7 +7,7 @@ const log = debug(`router:${componentName}`) * Cache used to store getStaticProps result * @param cache */ -export function staticPropsCache(cache = ROUTERS.staticPropsCache) { +export function staticPropsCache(cache = Routers.staticPropsCache) { /** * Get data in static props cache */ diff --git a/src/hooks/useLang.ts b/src/hooks/useLang.ts index d310bfef..4d74ff82 100644 --- a/src/hooks/useLang.ts +++ b/src/hooks/useLang.ts @@ -1,7 +1,7 @@ import LangService, { TLanguage } from "../core/LangService" import debug from "@cher-ami/debug" import React from "react" -import { ROUTERS } from "../core/ROUTERS" +import { Routers } from "../core/Routers" import { useHistory } from "../hooks/useHistory" const log = debug("router:useLang") @@ -9,7 +9,7 @@ const log = debug("router:useLang") * useLang */ export const useLang = ( - langService: LangService = ROUTERS.langService, + langService: LangService = Routers.langService, ): [lang: TLanguage, setLang: (lang: TLanguage | string, force: boolean) => void] => { const [lang, setLang] = React.useState(langService?.currentLang) diff --git a/src/hooks/useRouteCounter.ts b/src/hooks/useRouteCounter.ts index f6090fed..a6ab808c 100644 --- a/src/hooks/useRouteCounter.ts +++ b/src/hooks/useRouteCounter.ts @@ -1,6 +1,6 @@ import { useHistory } from "../hooks/useHistory" import { useState } from "react" -import { ROUTERS } from "../core/ROUTERS" +import { Routers } from "../core/Routers" /** * use Route Counter @@ -11,15 +11,15 @@ export const useRouteCounter = (): { resetCounter: () => void } => { // get current route count - const [routeCounter, setRouteCounter] = useState(ROUTERS.routeCounter) + const [routeCounter, setRouteCounter] = useState(Routers.routeCounter) // check if is first route - const [isFirstRoute, setIsFirstRoute] = useState(ROUTERS.isFirstRoute) + const [isFirstRoute, setIsFirstRoute] = useState(Routers.isFirstRoute) // handle history useHistory(() => { - ROUTERS.routeCounter = routeCounter + 1 + Routers.routeCounter = routeCounter + 1 setRouteCounter(routeCounter + 1) - ROUTERS.isFirstRoute = false + Routers.isFirstRoute = false setIsFirstRoute(false) }, [routeCounter, isFirstRoute]) diff --git a/src/index.ts b/src/index.ts index 2a3c7045..40498842 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -export { ROUTERS } from "./core/ROUTERS" +export { Routers } from "./core/Routers" export { Router } from "./components/Router" export type { TRoute } from "./components/Router" export { Link } from "./components/Link" diff --git a/src/tests/Link.test.tsx b/src/tests/Link.test.tsx index 9f023b77..79ed96a1 100644 --- a/src/tests/Link.test.tsx +++ b/src/tests/Link.test.tsx @@ -5,7 +5,7 @@ import { vi, it, expect, describe } from "vitest" import React from "react" import { render, fireEvent } from "@testing-library/react" -import { ROUTERS } from "../core/ROUTERS" +import { Routers } from "../core/Routers" import LangService from "../core/LangService" import { TOpenRouteParams } from "../core/core" import { Link } from ".." @@ -52,7 +52,7 @@ describe("Link", () => { expect(link.textContent).toBe("Foo") }) - // Can't test base URL added on link because the base /master is store in "ROUTERS" object + // Can't test base URL added on link because the base /master is store in "Routers" object // and this one is used by Link > createUrl() it("sould add formatted URL to href attr if custom base is set", () => { // const { container } = render(); @@ -83,7 +83,7 @@ describe("Link", () => { it("should return the right href URL", () => { const { container } = render() fireEvent.click(container.firstChild) - expect(ROUTERS.history.location.pathname).toBe("/foo") + expect(Routers.history.location.pathname).toBe("/foo") }) it("should return the right href URL with param", () => { @@ -91,13 +91,13 @@ describe("Link", () => { , ) fireEvent.click(container.firstChild) - expect(ROUTERS.history.location.pathname).toBe("/bar/test") + expect(Routers.history.location.pathname).toBe("/bar/test") }) it("should push in history on click", () => { const { container } = render() fireEvent.click(container.firstChild) - expect(ROUTERS.history.location.pathname).toBe("/bar") - expect(ROUTERS.history.action).toBe("PUSH") + expect(Routers.history.location.pathname).toBe("/bar") + expect(Routers.history.action).toBe("PUSH") }) }) diff --git a/src/tests/core.test.ts b/src/tests/core.test.ts index 0eda3f4a..23f84d9a 100644 --- a/src/tests/core.test.ts +++ b/src/tests/core.test.ts @@ -21,7 +21,7 @@ import { } from "../core/core" import { preventSlashes } from "../core/helpers" import { routeList } from "./_fixtures/routeList" -import { ROUTERS, LangService } from ".." +import { Routers, LangService } from ".." /** * Public @@ -92,17 +92,17 @@ describe("public", () => { "/custom/base/hello/foo", ) - ROUTERS.langService = new LangService({ + Routers.langService = new LangService({ languages: [{ key: "en" }, { key: "fr" }], }) const langPathTest = { en: "/foo-en", fr: "/foo-fr" } expect(getSubRouterBase(langPathTest, "/base/", true)).toBe("/base/:lang/foo-en") expect(getSubRouterBase(langPathTest, "/base/", false)).toBe("/base/foo-en") - ROUTERS.langService = undefined + Routers.langService = undefined }) it("should return subRouter base URL with 'showDefaultLangInUrl: false' option", () => { - ROUTERS.langService = new LangService({ + Routers.langService = new LangService({ languages: [{ key: "en" }, { key: "fr" }], showDefaultLangInUrl: false, }) @@ -110,7 +110,7 @@ describe("public", () => { expect(getSubRouterBase(e, "/base/", true)).toBe(`/base${e}`) expect(getSubRouterBase(e, "/base/", false)).toBe(`/base${e}`) }) - ROUTERS.langService = undefined + Routers.langService = undefined }) })