@webiny/app 6.0.0 → 6.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/App.d.ts +1 -1
- package/App.js.map +1 -1
- package/core/Plugins.d.ts +1 -1
- package/core/Plugins.js.map +1 -1
- package/exports/admin/env-config.d.ts +1 -0
- package/exports/admin/env-config.js +1 -0
- package/exports/admin/env-config.js.map +1 -1
- package/features/envConfig/EnvConfig.d.ts +1 -0
- package/features/envConfig/EnvConfig.js +3 -0
- package/features/envConfig/EnvConfig.js.map +1 -1
- package/features/envConfig/abstractions.d.ts +1 -0
- package/features/envConfig/abstractions.js.map +1 -1
- package/features/router/Route.js +5 -5
- package/features/router/Route.js.map +1 -1
- package/features/router/RouterPresenter.d.ts +6 -2
- package/features/router/RouterPresenter.js +14 -2
- package/features/router/RouterPresenter.js.map +1 -1
- package/features/router/RouterRepository.d.ts +11 -2
- package/features/router/RouterRepository.js +74 -4
- package/features/router/RouterRepository.js.map +1 -1
- package/features/router/RouterRepository.test.js +42 -27
- package/features/router/RouterRepository.test.js.map +1 -1
- package/features/router/abstractions.d.ts +18 -2
- package/features/router/abstractions.js +2 -0
- package/features/router/abstractions.js.map +1 -1
- package/features/router/index.d.ts +1 -0
- package/features/router/index.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/package.json +16 -16
- package/presentation/envConfig/useEnvConfig.d.ts +6 -0
- package/presentation/envConfig/useEnvConfig.js +13 -0
- package/presentation/envConfig/useEnvConfig.js.map +1 -0
- package/presentation/router/components/RouteContent.js +7 -1
- package/presentation/router/components/RouteContent.js.map +1 -1
- package/presentation/router/hooks/useRouter.d.ts +5 -1
- package/presentation/router/hooks/useRouter.js +5 -1
- package/presentation/router/hooks/useRouter.js.map +1 -1
- package/presentation/router/types.d.ts +1 -1
- package/presentation/router/types.js.map +1 -1
- package/renderApp.d.ts +1 -1
- package/renderApp.js.map +1 -1
package/App.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Decorator, DecoratorsCollection, GenericComponent } from "@webiny/react-composition";
|
|
3
3
|
interface State {
|
|
4
|
-
plugins: JSX.Element[];
|
|
4
|
+
plugins: React.JSX.Element[];
|
|
5
5
|
providers: Decorator<GenericComponent<ProviderProps>>[];
|
|
6
6
|
}
|
|
7
7
|
interface AppContext extends State {
|
package/App.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","createContext","Fragment","useCallback","useContext","useEffect","useMemo","useState","compose","CompositionProvider","PluginsProvider","RouterWithConfig","useRouterConfig","AppContainer","RouteContent","useRouter","AppContext","undefined","displayName","useApp","appContext","Error","AppBase","memo","routes","plugins","providers","children","state","setState","addProvider","component","findIndex","m","addPlugin","element","AppRouter","router","routerConfig","routesFromConfig","combinedRoutes","setRoutes","length","Providers","createElement","Provider","value","map","plugin","index","key","App","decorators","props","Object","assign"],"sources":["App.tsx"],"sourcesContent":["import React, {\n createContext,\n Fragment,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState\n} from \"react\";\nimport {\n compose,\n CompositionProvider,\n Decorator,\n DecoratorsCollection,\n GenericComponent\n} from \"@webiny/react-composition\";\nimport { PluginsProvider } from \"./core/Plugins.js\";\nimport { RouterWithConfig, useRouterConfig } from \"./config/RouterConfig.js\";\nimport { AppContainer } from \"./AppContainer.js\";\nimport { RouteContent } from \"~/presentation/router/components/RouteContent.js\";\nimport { useRouter } from \"~/router.js\";\n\ninterface State {\n plugins: JSX.Element[];\n providers: Decorator<GenericComponent<ProviderProps>>[];\n}\n\ninterface AppContext extends State {\n addProvider(hoc: Decorator<GenericComponent<ProviderProps>>): void;\n addPlugin(plugin: React.ReactNode): void;\n}\n\nconst AppContext = createContext<AppContext | undefined>(undefined);\n\nAppContext.displayName = \"AppContext\";\n\nexport const useApp = () => {\n const appContext = useContext(AppContext);\n if (!appContext) {\n throw Error(\n `AppContext provider was not found. Are you using the \"useApp()\" hook in the right place?`\n );\n }\n return appContext;\n};\n\nexport interface AppProps {\n routes?: Array<any>;\n plugins?: any[];\n providers?: Array<Decorator<GenericComponent<ProviderProps>>>;\n decorators?: DecoratorsCollection;\n children?: React.ReactNode | React.ReactNode[];\n}\n\ninterface ProviderProps {\n children: React.ReactNode;\n}\n\ntype ComponentWithChildren = React.ComponentType<{ children?: React.ReactNode }>;\n\nexport const AppBase = React.memo(\n ({ routes = [], plugins = [], providers = [], children }: AppProps) => {\n const [state, setState] = useState<State>({\n plugins,\n providers\n });\n\n const addProvider = useCallback((component: Decorator<any>) => {\n setState(state => {\n if (state.providers.findIndex(m => m === component) > -1) {\n return state;\n }\n\n return {\n ...state,\n providers: [...state.providers, component]\n };\n });\n }, []);\n\n const addPlugin = useCallback((element: JSX.Element) => {\n setState(state => {\n return {\n ...state,\n plugins: [...state.plugins, element]\n };\n });\n }, []);\n\n const appContext = useMemo(\n () => ({\n ...state,\n addProvider,\n addPlugin\n }),\n [state]\n );\n\n const AppRouter = useMemo(() => {\n return function AppRouter() {\n const router = useRouter();\n const routerConfig = useRouterConfig();\n const routesFromConfig = routerConfig.routes;\n const combinedRoutes = [...routes, ...routesFromConfig];\n\n useEffect(() => {\n router.setRoutes(combinedRoutes);\n }, [combinedRoutes.length]);\n\n return null;\n };\n }, []);\n\n const Providers = useMemo(() => {\n return React.memo(\n compose(...(state.providers || []))(({ children }: ProviderProps) => {\n return <>{children}</>;\n })\n );\n }, [state.providers.length]) as ComponentWithChildren;\n\n Providers.displayName = \"Providers\";\n\n return (\n <AppContext.Provider value={appContext}>\n {children}\n <AppContainer>\n <Providers>\n <PluginsProvider>\n {state.plugins.map((plugin, index) => (\n <Fragment key={index}>{plugin}</Fragment>\n ))}\n </PluginsProvider>\n <RouterWithConfig>\n <AppRouter />\n <RouteContent />\n </RouterWithConfig>\n </Providers>\n </AppContainer>\n </AppContext.Provider>\n );\n }\n);\n\nAppBase.displayName = \"AppBase\";\n\nexport const App = ({ decorators, ...props }: AppProps) => {\n return (\n <CompositionProvider decorators={decorators}>\n <AppBase decorators={decorators} {...props} />\n </CompositionProvider>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IACRC,aAAa,EACbC,QAAQ,EACRC,WAAW,EACXC,UAAU,EACVC,SAAS,EACTC,OAAO,EACPC,QAAQ,QACL,OAAO;AACd,SACIC,OAAO,EACPC,mBAAmB,QAIhB,2BAA2B;AAClC,SAASC,eAAe;AACxB,SAASC,gBAAgB,EAAEC,eAAe;AAC1C,SAASC,YAAY;AACrB,SAASC,YAAY;AACrB,SAASC,SAAS;AAYlB,MAAMC,UAAU,gBAAGf,aAAa,CAAyBgB,SAAS,CAAC;AAEnED,UAAU,CAACE,WAAW,GAAG,YAAY;AAErC,OAAO,MAAMC,MAAM,GAAGA,CAAA,KAAM;EACxB,MAAMC,UAAU,GAAGhB,UAAU,CAACY,UAAU,CAAC;EACzC,IAAI,CAACI,UAAU,EAAE;IACb,MAAMC,KAAK,CACP,0FACJ,CAAC;EACL;EACA,OAAOD,UAAU;AACrB,CAAC;AAgBD,OAAO,MAAME,OAAO,gBAAGtB,KAAK,CAACuB,IAAI,CAC7B,CAAC;EAAEC,MAAM,GAAG,EAAE;EAAEC,OAAO,GAAG,EAAE;EAAEC,SAAS,GAAG,EAAE;EAAEC;AAAmB,CAAC,KAAK;EACnE,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGtB,QAAQ,CAAQ;IACtCkB,OAAO;IACPC;EACJ,CAAC,CAAC;EAEF,MAAMI,WAAW,GAAG3B,WAAW,CAAE4B,SAAyB,IAAK;IAC3DF,QAAQ,CAACD,KAAK,IAAI;MACd,IAAIA,KAAK,CAACF,SAAS,CAACM,SAAS,CAACC,CAAC,IAAIA,CAAC,KAAKF,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE;QACtD,OAAOH,KAAK;MAChB;MAEA,OAAO;QACH,GAAGA,KAAK;QACRF,SAAS,EAAE,CAAC,GAAGE,KAAK,CAACF,SAAS,EAAEK,SAAS;MAC7C,CAAC;IACL,CAAC,CAAC;EACN,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMG,SAAS,GAAG/B,WAAW,CAAEgC,
|
|
1
|
+
{"version":3,"names":["React","createContext","Fragment","useCallback","useContext","useEffect","useMemo","useState","compose","CompositionProvider","PluginsProvider","RouterWithConfig","useRouterConfig","AppContainer","RouteContent","useRouter","AppContext","undefined","displayName","useApp","appContext","Error","AppBase","memo","routes","plugins","providers","children","state","setState","addProvider","component","findIndex","m","addPlugin","element","AppRouter","router","routerConfig","routesFromConfig","combinedRoutes","setRoutes","length","Providers","createElement","Provider","value","map","plugin","index","key","App","decorators","props","Object","assign"],"sources":["App.tsx"],"sourcesContent":["import React, {\n createContext,\n Fragment,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState\n} from \"react\";\nimport {\n compose,\n CompositionProvider,\n Decorator,\n DecoratorsCollection,\n GenericComponent\n} from \"@webiny/react-composition\";\nimport { PluginsProvider } from \"./core/Plugins.js\";\nimport { RouterWithConfig, useRouterConfig } from \"./config/RouterConfig.js\";\nimport { AppContainer } from \"./AppContainer.js\";\nimport { RouteContent } from \"~/presentation/router/components/RouteContent.js\";\nimport { useRouter } from \"~/router.js\";\n\ninterface State {\n plugins: React.JSX.Element[];\n providers: Decorator<GenericComponent<ProviderProps>>[];\n}\n\ninterface AppContext extends State {\n addProvider(hoc: Decorator<GenericComponent<ProviderProps>>): void;\n addPlugin(plugin: React.ReactNode): void;\n}\n\nconst AppContext = createContext<AppContext | undefined>(undefined);\n\nAppContext.displayName = \"AppContext\";\n\nexport const useApp = () => {\n const appContext = useContext(AppContext);\n if (!appContext) {\n throw Error(\n `AppContext provider was not found. Are you using the \"useApp()\" hook in the right place?`\n );\n }\n return appContext;\n};\n\nexport interface AppProps {\n routes?: Array<any>;\n plugins?: any[];\n providers?: Array<Decorator<GenericComponent<ProviderProps>>>;\n decorators?: DecoratorsCollection;\n children?: React.ReactNode | React.ReactNode[];\n}\n\ninterface ProviderProps {\n children: React.ReactNode;\n}\n\ntype ComponentWithChildren = React.ComponentType<{ children?: React.ReactNode }>;\n\nexport const AppBase = React.memo(\n ({ routes = [], plugins = [], providers = [], children }: AppProps) => {\n const [state, setState] = useState<State>({\n plugins,\n providers\n });\n\n const addProvider = useCallback((component: Decorator<any>) => {\n setState(state => {\n if (state.providers.findIndex(m => m === component) > -1) {\n return state;\n }\n\n return {\n ...state,\n providers: [...state.providers, component]\n };\n });\n }, []);\n\n const addPlugin = useCallback((element: React.JSX.Element) => {\n setState(state => {\n return {\n ...state,\n plugins: [...state.plugins, element]\n };\n });\n }, []);\n\n const appContext = useMemo(\n () => ({\n ...state,\n addProvider,\n addPlugin\n }),\n [state]\n );\n\n const AppRouter = useMemo(() => {\n return function AppRouter() {\n const router = useRouter();\n const routerConfig = useRouterConfig();\n const routesFromConfig = routerConfig.routes;\n const combinedRoutes = [...routes, ...routesFromConfig];\n\n useEffect(() => {\n router.setRoutes(combinedRoutes);\n }, [combinedRoutes.length]);\n\n return null;\n };\n }, []);\n\n const Providers = useMemo(() => {\n return React.memo(\n compose(...(state.providers || []))(({ children }: ProviderProps) => {\n return <>{children}</>;\n })\n );\n }, [state.providers.length]) as ComponentWithChildren;\n\n Providers.displayName = \"Providers\";\n\n return (\n <AppContext.Provider value={appContext}>\n {children}\n <AppContainer>\n <Providers>\n <PluginsProvider>\n {state.plugins.map((plugin, index) => (\n <Fragment key={index}>{plugin}</Fragment>\n ))}\n </PluginsProvider>\n <RouterWithConfig>\n <AppRouter />\n <RouteContent />\n </RouterWithConfig>\n </Providers>\n </AppContainer>\n </AppContext.Provider>\n );\n }\n);\n\nAppBase.displayName = \"AppBase\";\n\nexport const App = ({ decorators, ...props }: AppProps) => {\n return (\n <CompositionProvider decorators={decorators}>\n <AppBase decorators={decorators} {...props} />\n </CompositionProvider>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IACRC,aAAa,EACbC,QAAQ,EACRC,WAAW,EACXC,UAAU,EACVC,SAAS,EACTC,OAAO,EACPC,QAAQ,QACL,OAAO;AACd,SACIC,OAAO,EACPC,mBAAmB,QAIhB,2BAA2B;AAClC,SAASC,eAAe;AACxB,SAASC,gBAAgB,EAAEC,eAAe;AAC1C,SAASC,YAAY;AACrB,SAASC,YAAY;AACrB,SAASC,SAAS;AAYlB,MAAMC,UAAU,gBAAGf,aAAa,CAAyBgB,SAAS,CAAC;AAEnED,UAAU,CAACE,WAAW,GAAG,YAAY;AAErC,OAAO,MAAMC,MAAM,GAAGA,CAAA,KAAM;EACxB,MAAMC,UAAU,GAAGhB,UAAU,CAACY,UAAU,CAAC;EACzC,IAAI,CAACI,UAAU,EAAE;IACb,MAAMC,KAAK,CACP,0FACJ,CAAC;EACL;EACA,OAAOD,UAAU;AACrB,CAAC;AAgBD,OAAO,MAAME,OAAO,gBAAGtB,KAAK,CAACuB,IAAI,CAC7B,CAAC;EAAEC,MAAM,GAAG,EAAE;EAAEC,OAAO,GAAG,EAAE;EAAEC,SAAS,GAAG,EAAE;EAAEC;AAAmB,CAAC,KAAK;EACnE,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGtB,QAAQ,CAAQ;IACtCkB,OAAO;IACPC;EACJ,CAAC,CAAC;EAEF,MAAMI,WAAW,GAAG3B,WAAW,CAAE4B,SAAyB,IAAK;IAC3DF,QAAQ,CAACD,KAAK,IAAI;MACd,IAAIA,KAAK,CAACF,SAAS,CAACM,SAAS,CAACC,CAAC,IAAIA,CAAC,KAAKF,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE;QACtD,OAAOH,KAAK;MAChB;MAEA,OAAO;QACH,GAAGA,KAAK;QACRF,SAAS,EAAE,CAAC,GAAGE,KAAK,CAACF,SAAS,EAAEK,SAAS;MAC7C,CAAC;IACL,CAAC,CAAC;EACN,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMG,SAAS,GAAG/B,WAAW,CAAEgC,OAA0B,IAAK;IAC1DN,QAAQ,CAACD,KAAK,IAAI;MACd,OAAO;QACH,GAAGA,KAAK;QACRH,OAAO,EAAE,CAAC,GAAGG,KAAK,CAACH,OAAO,EAAEU,OAAO;MACvC,CAAC;IACL,CAAC,CAAC;EACN,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMf,UAAU,GAAGd,OAAO,CACtB,OAAO;IACH,GAAGsB,KAAK;IACRE,WAAW;IACXI;EACJ,CAAC,CAAC,EACF,CAACN,KAAK,CACV,CAAC;EAED,MAAMQ,SAAS,GAAG9B,OAAO,CAAC,MAAM;IAC5B,OAAO,SAAS8B,SAASA,CAAA,EAAG;MACxB,MAAMC,MAAM,GAAGtB,SAAS,CAAC,CAAC;MAC1B,MAAMuB,YAAY,GAAG1B,eAAe,CAAC,CAAC;MACtC,MAAM2B,gBAAgB,GAAGD,YAAY,CAACd,MAAM;MAC5C,MAAMgB,cAAc,GAAG,CAAC,GAAGhB,MAAM,EAAE,GAAGe,gBAAgB,CAAC;MAEvDlC,SAAS,CAAC,MAAM;QACZgC,MAAM,CAACI,SAAS,CAACD,cAAc,CAAC;MACpC,CAAC,EAAE,CAACA,cAAc,CAACE,MAAM,CAAC,CAAC;MAE3B,OAAO,IAAI;IACf,CAAC;EACL,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,SAAS,GAAGrC,OAAO,CAAC,MAAM;IAC5B,oBAAON,KAAK,CAACuB,IAAI,CACbf,OAAO,CAAC,IAAIoB,KAAK,CAACF,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;MAAEC;IAAwB,CAAC,KAAK;MACjE,oBAAO3B,KAAA,CAAA4C,aAAA,CAAA5C,KAAA,CAAAE,QAAA,QAAGyB,QAAW,CAAC;IAC1B,CAAC,CACL,CAAC;EACL,CAAC,EAAE,CAACC,KAAK,CAACF,SAAS,CAACgB,MAAM,CAAC,CAA0B;EAErDC,SAAS,CAACzB,WAAW,GAAG,WAAW;EAEnC,oBACIlB,KAAA,CAAA4C,aAAA,CAAC5B,UAAU,CAAC6B,QAAQ;IAACC,KAAK,EAAE1B;EAAW,GAClCO,QAAQ,eACT3B,KAAA,CAAA4C,aAAA,CAAC/B,YAAY,qBACTb,KAAA,CAAA4C,aAAA,CAACD,SAAS,qBACN3C,KAAA,CAAA4C,aAAA,CAAClC,eAAe,QACXkB,KAAK,CAACH,OAAO,CAACsB,GAAG,CAAC,CAACC,MAAM,EAAEC,KAAK,kBAC7BjD,KAAA,CAAA4C,aAAA,CAAC1C,QAAQ;IAACgD,GAAG,EAAED;EAAM,GAAED,MAAiB,CAC3C,CACY,CAAC,eAClBhD,KAAA,CAAA4C,aAAA,CAACjC,gBAAgB,qBACbX,KAAA,CAAA4C,aAAA,CAACR,SAAS,MAAE,CAAC,eACbpC,KAAA,CAAA4C,aAAA,CAAC9B,YAAY,MAAE,CACD,CACX,CACD,CACG,CAAC;AAE9B,CACJ,CAAC;AAEDQ,OAAO,CAACJ,WAAW,GAAG,SAAS;AAE/B,OAAO,MAAMiC,GAAG,GAAGA,CAAC;EAAEC,UAAU;EAAE,GAAGC;AAAgB,CAAC,KAAK;EACvD,oBACIrD,KAAA,CAAA4C,aAAA,CAACnC,mBAAmB;IAAC2C,UAAU,EAAEA;EAAW,gBACxCpD,KAAA,CAAA4C,aAAA,CAACtB,OAAO,EAAAgC,MAAA,CAAAC,MAAA;IAACH,UAAU,EAAEA;EAAW,GAAKC,KAAK,CAAG,CAC5B,CAAC;AAE9B,CAAC","ignoreList":[]}
|
package/core/Plugins.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
export declare const PluginsContext: React.Context<boolean>;
|
|
3
3
|
interface PluginsProviderComponentProps {
|
|
4
|
-
children: JSX.Element[];
|
|
4
|
+
children: React.JSX.Element[];
|
|
5
5
|
}
|
|
6
6
|
export declare const PluginsProvider: React.MemoExoticComponent<({ children }: PluginsProviderComponentProps) => React.JSX.Element>;
|
|
7
7
|
/**
|
package/core/Plugins.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Children","createContext","Fragment","memo","useContext","useEffect","useApp","PluginsContext","displayName","PluginsProviderComponent","children","createElement","Provider","value","PluginsProvider","Plugins","addPlugin","hasParentPlugin","forEach","child"],"sources":["Plugins.tsx"],"sourcesContent":["import React, { Children, createContext, Fragment, memo, useContext, useEffect } from \"react\";\nimport { useApp } from \"~/App.js\";\n\nexport const PluginsContext = createContext<boolean>(false);\nPluginsContext.displayName = \"PluginsContext\";\n\ninterface PluginsProviderComponentProps {\n children: JSX.Element[];\n}\nconst PluginsProviderComponent = ({ children }: PluginsProviderComponentProps) => {\n /**\n * This context only serves as a safeguard. We need to warn users when they mount a plugin without using\n * the <Plugins> component. In that case, the context will not be available, and we can log warnings.\n */\n return <PluginsContext.Provider value={true}>{children}</PluginsContext.Provider>;\n};\n\nexport const PluginsProvider = memo(PluginsProviderComponent);\n\n/**\n * @param children\n * @deprecated This component should not be used directly. Use the <Plugin> component to create plugins.\n */\ninterface PluginsComponentsProps {\n children: React.ReactNode;\n}\nexport const Plugins = React.memo(({ children }: PluginsComponentsProps) => {\n const { addPlugin } = useApp();\n const hasParentPlugin = useContext(PluginsContext);\n\n useEffect(() => {\n if (hasParentPlugin) {\n return;\n }\n\n Children.forEach(children, child => addPlugin(child));\n }, []);\n\n return hasParentPlugin ? <Fragment>{children}</Fragment> : null;\n});\n\nPlugins.displayName = \"Plugins\";\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,QAAQ,EAAEC,aAAa,EAAEC,QAAQ,EAAEC,IAAI,EAAEC,UAAU,EAAEC,SAAS,QAAQ,OAAO;AAC7F,SAASC,MAAM;AAEf,OAAO,MAAMC,cAAc,gBAAGN,aAAa,CAAU,KAAK,CAAC;AAC3DM,cAAc,CAACC,WAAW,GAAG,gBAAgB;AAK7C,MAAMC,wBAAwB,GAAGA,CAAC;EAAEC;AAAwC,CAAC,KAAK;EAC9E;AACJ;AACA;AACA;EACI,oBAAOX,KAAA,CAAAY,aAAA,CAACJ,cAAc,CAACK,QAAQ;IAACC,KAAK,EAAE;EAAK,GAAEH,QAAkC,CAAC;AACrF,CAAC;AAED,OAAO,MAAMI,eAAe,gBAAGX,IAAI,CAACM,wBAAwB,CAAC;;AAE7D;AACA;AACA;AACA;;AAIA,OAAO,MAAMM,OAAO,gBAAGhB,KAAK,CAACI,IAAI,CAAC,CAAC;EAAEO;AAAiC,CAAC,KAAK;EACxE,MAAM;IAAEM;EAAU,CAAC,GAAGV,MAAM,CAAC,CAAC;EAC9B,MAAMW,eAAe,GAAGb,UAAU,CAACG,cAAc,CAAC;EAElDF,SAAS,CAAC,MAAM;IACZ,IAAIY,eAAe,EAAE;MACjB;IACJ;IAEAjB,QAAQ,CAACkB,OAAO,CAACR,QAAQ,EAAES,KAAK,IAAIH,SAAS,CAACG,KAAK,CAAC,CAAC;EACzD,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOF,eAAe,gBAAGlB,KAAA,CAAAY,aAAA,CAACT,QAAQ,QAAEQ,QAAmB,CAAC,GAAG,IAAI;AACnE,CAAC,CAAC;AAEFK,OAAO,CAACP,WAAW,GAAG,SAAS","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["React","Children","createContext","Fragment","memo","useContext","useEffect","useApp","PluginsContext","displayName","PluginsProviderComponent","children","createElement","Provider","value","PluginsProvider","Plugins","addPlugin","hasParentPlugin","forEach","child"],"sources":["Plugins.tsx"],"sourcesContent":["import React, { Children, createContext, Fragment, memo, useContext, useEffect } from \"react\";\nimport { useApp } from \"~/App.js\";\n\nexport const PluginsContext = createContext<boolean>(false);\nPluginsContext.displayName = \"PluginsContext\";\n\ninterface PluginsProviderComponentProps {\n children: React.JSX.Element[];\n}\nconst PluginsProviderComponent = ({ children }: PluginsProviderComponentProps) => {\n /**\n * This context only serves as a safeguard. We need to warn users when they mount a plugin without using\n * the <Plugins> component. In that case, the context will not be available, and we can log warnings.\n */\n return <PluginsContext.Provider value={true}>{children}</PluginsContext.Provider>;\n};\n\nexport const PluginsProvider = memo(PluginsProviderComponent);\n\n/**\n * @param children\n * @deprecated This component should not be used directly. Use the <Plugin> component to create plugins.\n */\ninterface PluginsComponentsProps {\n children: React.ReactNode;\n}\nexport const Plugins = React.memo(({ children }: PluginsComponentsProps) => {\n const { addPlugin } = useApp();\n const hasParentPlugin = useContext(PluginsContext);\n\n useEffect(() => {\n if (hasParentPlugin) {\n return;\n }\n\n Children.forEach(children, child => addPlugin(child));\n }, []);\n\n return hasParentPlugin ? <Fragment>{children}</Fragment> : null;\n});\n\nPlugins.displayName = \"Plugins\";\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,QAAQ,EAAEC,aAAa,EAAEC,QAAQ,EAAEC,IAAI,EAAEC,UAAU,EAAEC,SAAS,QAAQ,OAAO;AAC7F,SAASC,MAAM;AAEf,OAAO,MAAMC,cAAc,gBAAGN,aAAa,CAAU,KAAK,CAAC;AAC3DM,cAAc,CAACC,WAAW,GAAG,gBAAgB;AAK7C,MAAMC,wBAAwB,GAAGA,CAAC;EAAEC;AAAwC,CAAC,KAAK;EAC9E;AACJ;AACA;AACA;EACI,oBAAOX,KAAA,CAAAY,aAAA,CAACJ,cAAc,CAACK,QAAQ;IAACC,KAAK,EAAE;EAAK,GAAEH,QAAkC,CAAC;AACrF,CAAC;AAED,OAAO,MAAMI,eAAe,gBAAGX,IAAI,CAACM,wBAAwB,CAAC;;AAE7D;AACA;AACA;AACA;;AAIA,OAAO,MAAMM,OAAO,gBAAGhB,KAAK,CAACI,IAAI,CAAC,CAAC;EAAEO;AAAiC,CAAC,KAAK;EACxE,MAAM;IAAEM;EAAU,CAAC,GAAGV,MAAM,CAAC,CAAC;EAC9B,MAAMW,eAAe,GAAGb,UAAU,CAACG,cAAc,CAAC;EAElDF,SAAS,CAAC,MAAM;IACZ,IAAIY,eAAe,EAAE;MACjB;IACJ;IAEAjB,QAAQ,CAACkB,OAAO,CAACR,QAAQ,EAAES,KAAK,IAAIH,SAAS,CAACG,KAAK,CAAC,CAAC;EACzD,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOF,eAAe,gBAAGlB,KAAA,CAAAY,aAAA,CAACT,QAAQ,QAAEQ,QAAmB,CAAC,GAAG,IAAI;AACnE,CAAC,CAAC;AAEFK,OAAO,CAACP,WAAW,GAAG,SAAS","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["EnvConfig"],"sources":["env-config.ts"],"sourcesContent":["export { EnvConfig } from \"~/features/envConfig/index.js\";\n"],"mappings":"AAAA,SAASA,SAAS","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["EnvConfig","useEnvConfig"],"sources":["env-config.ts"],"sourcesContent":["export { EnvConfig } from \"~/features/envConfig/index.js\";\nexport { useEnvConfig } from \"~/presentation/envConfig/useEnvConfig.js\";\n"],"mappings":"AAAA,SAASA,SAAS;AAClB,SAASC,YAAY","ignoreList":[]}
|
|
@@ -3,4 +3,5 @@ export declare class DefaultEnvConfig implements Abstraction.Interface {
|
|
|
3
3
|
private readonly env;
|
|
4
4
|
constructor(env: Abstraction.Config);
|
|
5
5
|
get<K extends keyof Abstraction.Config>(key: K, defaultValue?: Abstraction.Config[K]): Abstraction.Config[K];
|
|
6
|
+
getAll(): Abstraction.Config;
|
|
6
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["DefaultEnvConfig","constructor","env","get","key","defaultValue","rawValue","undefined"],"sources":["EnvConfig.ts"],"sourcesContent":["import { EnvConfig as Abstraction } from \"./abstractions.js\";\n\nexport class DefaultEnvConfig implements Abstraction.Interface {\n private readonly env: Abstraction.Config;\n\n constructor(env: Abstraction.Config) {\n this.env = env;\n }\n\n public get<K extends keyof Abstraction.Config>(\n key: K,\n defaultValue?: Abstraction.Config[K]\n ): Abstraction.Config[K] {\n const rawValue = this.env[key];\n\n if ((rawValue === undefined || rawValue === null) && defaultValue !== undefined) {\n return defaultValue;\n }\n\n return rawValue;\n }\n}\n"],"mappings":"AAEA,OAAO,MAAMA,gBAAgB,CAAkC;EAG3DC,WAAWA,CAACC,GAAuB,EAAE;IACjC,IAAI,CAACA,GAAG,GAAGA,GAAG;EAClB;EAEOC,GAAGA,CACNC,GAAM,EACNC,YAAoC,EACf;IACrB,MAAMC,QAAQ,GAAG,IAAI,CAACJ,GAAG,CAACE,GAAG,CAAC;IAE9B,IAAI,CAACE,QAAQ,KAAKC,SAAS,IAAID,QAAQ,KAAK,IAAI,KAAKD,YAAY,KAAKE,SAAS,EAAE;MAC7E,OAAOF,YAAY;IACvB;IAEA,OAAOC,QAAQ;EACnB;AACJ","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["DefaultEnvConfig","constructor","env","get","key","defaultValue","rawValue","undefined","getAll"],"sources":["EnvConfig.ts"],"sourcesContent":["import { EnvConfig as Abstraction } from \"./abstractions.js\";\n\nexport class DefaultEnvConfig implements Abstraction.Interface {\n private readonly env: Abstraction.Config;\n\n constructor(env: Abstraction.Config) {\n this.env = env;\n }\n\n public get<K extends keyof Abstraction.Config>(\n key: K,\n defaultValue?: Abstraction.Config[K]\n ): Abstraction.Config[K] {\n const rawValue = this.env[key];\n\n if ((rawValue === undefined || rawValue === null) && defaultValue !== undefined) {\n return defaultValue;\n }\n\n return rawValue;\n }\n\n getAll(): Abstraction.Config {\n return this.env;\n }\n}\n"],"mappings":"AAEA,OAAO,MAAMA,gBAAgB,CAAkC;EAG3DC,WAAWA,CAACC,GAAuB,EAAE;IACjC,IAAI,CAACA,GAAG,GAAGA,GAAG;EAClB;EAEOC,GAAGA,CACNC,GAAM,EACNC,YAAoC,EACf;IACrB,MAAMC,QAAQ,GAAG,IAAI,CAACJ,GAAG,CAACE,GAAG,CAAC;IAE9B,IAAI,CAACE,QAAQ,KAAKC,SAAS,IAAID,QAAQ,KAAK,IAAI,KAAKD,YAAY,KAAKE,SAAS,EAAE;MAC7E,OAAOF,YAAY;IACvB;IAEA,OAAOC,QAAQ;EACnB;EAEAE,MAAMA,CAAA,EAAuB;IACzB,OAAO,IAAI,CAACN,GAAG;EACnB;AACJ","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Abstraction","EnvConfig"],"sources":["abstractions.ts"],"sourcesContent":["import { Abstraction } from \"@webiny/di\";\n\ntype Env = {\n apiUrl: string;\n debug: boolean;\n deploymentId: string;\n graphqlApiUrl: string;\n telemetryEnabled: boolean;\n telemetryUserId: string | undefined;\n trashBinRetentionPeriodDays: number;\n wcpProjectId: string | undefined;\n websocketUrl: string;\n graphqlClient?: {\n retries: {\n maxRetries: number;\n delayInMillis: number;\n };\n };\n};\n\nexport interface IEnvConfig {\n get<K extends keyof Env>(key: K, defaultValue?: Env[K]): Env[K];\n}\n\nexport const EnvConfig = new Abstraction<IEnvConfig>(\"EnvConfig\");\n\nexport namespace EnvConfig {\n export type Interface = IEnvConfig;\n export type Config = Env;\n}\n"],"mappings":"AAAA,SAASA,WAAW,QAAQ,YAAY;
|
|
1
|
+
{"version":3,"names":["Abstraction","EnvConfig"],"sources":["abstractions.ts"],"sourcesContent":["import { Abstraction } from \"@webiny/di\";\n\ntype Env = {\n apiUrl: string;\n debug: boolean;\n deploymentId: string;\n graphqlApiUrl: string;\n telemetryEnabled: boolean;\n telemetryUserId: string | undefined;\n trashBinRetentionPeriodDays: number;\n wcpProjectId: string | undefined;\n websocketUrl: string;\n graphqlClient?: {\n retries: {\n maxRetries: number;\n delayInMillis: number;\n };\n };\n};\n\nexport interface IEnvConfig {\n get<K extends keyof Env>(key: K, defaultValue?: Env[K]): Env[K];\n getAll(): Env;\n}\n\nexport const EnvConfig = new Abstraction<IEnvConfig>(\"EnvConfig\");\n\nexport namespace EnvConfig {\n export type Interface = IEnvConfig;\n export type Config = Env;\n}\n"],"mappings":"AAAA,SAASA,WAAW,QAAQ,YAAY;AAyBxC,OAAO,MAAMC,SAAS,GAAG,IAAID,WAAW,CAAa,WAAW,CAAC","ignoreList":[]}
|
package/features/router/Route.js
CHANGED
|
@@ -4,7 +4,7 @@ export class Route {
|
|
|
4
4
|
this.route = route;
|
|
5
5
|
const paramsSchema = route.params ? route.params(z) : undefined;
|
|
6
6
|
// @ts-expect-error
|
|
7
|
-
this.schema = paramsSchema ? z.
|
|
7
|
+
this.schema = paramsSchema ? z.looseObject(this.coerceParams(paramsSchema)) : undefined;
|
|
8
8
|
}
|
|
9
9
|
get name() {
|
|
10
10
|
return this.route.name;
|
|
@@ -23,15 +23,15 @@ export class Route {
|
|
|
23
23
|
let isNullable = false;
|
|
24
24
|
|
|
25
25
|
// unwrap optional
|
|
26
|
-
if (base
|
|
26
|
+
if (base instanceof z.ZodOptional) {
|
|
27
27
|
isOptional = true;
|
|
28
|
-
base = base.
|
|
28
|
+
base = base.unwrap();
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// unwrap nullable
|
|
32
|
-
if (base
|
|
32
|
+
if (base instanceof z.ZodNullable) {
|
|
33
33
|
isNullable = true;
|
|
34
|
-
base = base.
|
|
34
|
+
base = base.unwrap();
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// replace with coerced
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["z","Route","constructor","route","paramsSchema","params","undefined","schema","
|
|
1
|
+
{"version":3,"names":["z","Route","constructor","route","paramsSchema","params","undefined","schema","looseObject","coerceParams","name","path","shape","result","key","Object","entries","base","isOptional","isNullable","ZodOptional","unwrap","ZodNullable","ZodString","coerce","string","ZodNumber","number","ZodBoolean","boolean","nullable","optional"],"sources":["Route.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport type RouteParamsDefinition = Record<string, z.ZodTypeAny>;\n\nexport type RouteParamsInfer<T extends RouteParamsDefinition | undefined> =\n T extends RouteParamsDefinition ? z.infer<z.ZodObject<T> & { [k: string]: any }> : never;\n\nexport interface RouteParams<TParams extends RouteParamsDefinition | undefined> {\n name: string;\n path: `/${string}` | `*`;\n params?: (zod: typeof z) => TParams;\n}\n\nexport class Route<TParams extends RouteParamsDefinition | undefined = undefined> {\n private readonly route: RouteParams<TParams>;\n private readonly schema: TParams extends RouteParamsDefinition\n ? RouteParamsInfer<TParams>\n : undefined;\n\n constructor(route: RouteParams<TParams>) {\n this.route = route;\n const paramsSchema = route.params ? route.params(z) : undefined;\n // @ts-expect-error\n this.schema = paramsSchema ? z.looseObject(this.coerceParams(paramsSchema)) : undefined;\n }\n\n get name() {\n return this.route.name;\n }\n\n get path() {\n return this.route.path;\n }\n\n get params(): TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined {\n return this.schema;\n }\n\n private coerceParams<T extends Record<string, z.ZodTypeAny>>(shape: T) {\n const result: Record<string, z.ZodTypeAny> = {};\n for (const [key, schema] of Object.entries(shape)) {\n let base = schema as z.ZodTypeAny;\n let isOptional = false;\n let isNullable = false;\n\n // unwrap optional\n if (base instanceof z.ZodOptional) {\n isOptional = true;\n base = base.unwrap() as z.ZodTypeAny;\n }\n\n // unwrap nullable\n if (base instanceof z.ZodNullable) {\n isNullable = true;\n base = base.unwrap() as z.ZodTypeAny;\n }\n\n // replace with coerced\n if (base instanceof z.ZodString) {\n base = z.coerce.string();\n } else if (base instanceof z.ZodNumber) {\n base = z.coerce.number();\n } else if (base instanceof z.ZodBoolean) {\n base = z.coerce.boolean();\n }\n\n // rewrap optional/nullable\n if (isNullable) {\n base = base.nullable();\n }\n if (isOptional) {\n base = base.optional();\n }\n\n result[key] = base;\n }\n return result;\n }\n}\n"],"mappings":"AAAA,SAASA,CAAC,QAAQ,KAAK;AAavB,OAAO,MAAMC,KAAK,CAAgE;EAM9EC,WAAWA,CAACC,KAA2B,EAAE;IACrC,IAAI,CAACA,KAAK,GAAGA,KAAK;IAClB,MAAMC,YAAY,GAAGD,KAAK,CAACE,MAAM,GAAGF,KAAK,CAACE,MAAM,CAACL,CAAC,CAAC,GAAGM,SAAS;IAC/D;IACA,IAAI,CAACC,MAAM,GAAGH,YAAY,GAAGJ,CAAC,CAACQ,WAAW,CAAC,IAAI,CAACC,YAAY,CAACL,YAAY,CAAC,CAAC,GAAGE,SAAS;EAC3F;EAEA,IAAII,IAAIA,CAAA,EAAG;IACP,OAAO,IAAI,CAACP,KAAK,CAACO,IAAI;EAC1B;EAEA,IAAIC,IAAIA,CAAA,EAAG;IACP,OAAO,IAAI,CAACR,KAAK,CAACQ,IAAI;EAC1B;EAEA,IAAIN,MAAMA,CAAA,EAAkF;IACxF,OAAO,IAAI,CAACE,MAAM;EACtB;EAEQE,YAAYA,CAAyCG,KAAQ,EAAE;IACnE,MAAMC,MAAoC,GAAG,CAAC,CAAC;IAC/C,KAAK,MAAM,CAACC,GAAG,EAAEP,MAAM,CAAC,IAAIQ,MAAM,CAACC,OAAO,CAACJ,KAAK,CAAC,EAAE;MAC/C,IAAIK,IAAI,GAAGV,MAAsB;MACjC,IAAIW,UAAU,GAAG,KAAK;MACtB,IAAIC,UAAU,GAAG,KAAK;;MAEtB;MACA,IAAIF,IAAI,YAAYjB,CAAC,CAACoB,WAAW,EAAE;QAC/BF,UAAU,GAAG,IAAI;QACjBD,IAAI,GAAGA,IAAI,CAACI,MAAM,CAAC,CAAiB;MACxC;;MAEA;MACA,IAAIJ,IAAI,YAAYjB,CAAC,CAACsB,WAAW,EAAE;QAC/BH,UAAU,GAAG,IAAI;QACjBF,IAAI,GAAGA,IAAI,CAACI,MAAM,CAAC,CAAiB;MACxC;;MAEA;MACA,IAAIJ,IAAI,YAAYjB,CAAC,CAACuB,SAAS,EAAE;QAC7BN,IAAI,GAAGjB,CAAC,CAACwB,MAAM,CAACC,MAAM,CAAC,CAAC;MAC5B,CAAC,MAAM,IAAIR,IAAI,YAAYjB,CAAC,CAAC0B,SAAS,EAAE;QACpCT,IAAI,GAAGjB,CAAC,CAACwB,MAAM,CAACG,MAAM,CAAC,CAAC;MAC5B,CAAC,MAAM,IAAIV,IAAI,YAAYjB,CAAC,CAAC4B,UAAU,EAAE;QACrCX,IAAI,GAAGjB,CAAC,CAACwB,MAAM,CAACK,OAAO,CAAC,CAAC;MAC7B;;MAEA;MACA,IAAIV,UAAU,EAAE;QACZF,IAAI,GAAGA,IAAI,CAACa,QAAQ,CAAC,CAAC;MAC1B;MACA,IAAIZ,UAAU,EAAE;QACZD,IAAI,GAAGA,IAAI,CAACc,QAAQ,CAAC,CAAC;MAC1B;MAEAlB,MAAM,CAACC,GAAG,CAAC,GAAGG,IAAI;IACtB;IACA,OAAOJ,MAAM;EACjB;AACJ","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Route } from "./Route.js";
|
|
2
|
-
import { RouterRepository, RouterPresenter as Abstraction, type
|
|
2
|
+
import { RouterRepository, RouterPresenter as Abstraction, type RouteTransitionGuardConfig, type GuardDisposer } from "./abstractions.js";
|
|
3
3
|
declare class RouterPresenterImpl implements Abstraction.Interface {
|
|
4
4
|
private routerRepository;
|
|
5
5
|
constructor(routerRepository: RouterRepository.Interface);
|
|
@@ -10,7 +10,11 @@ declare class RouterPresenterImpl implements Abstraction.Interface {
|
|
|
10
10
|
goToRoute: (route: any, params?: any) => void;
|
|
11
11
|
setRouteParams: (cb: any) => void;
|
|
12
12
|
getLink: (route: any, params?: any) => string;
|
|
13
|
-
|
|
13
|
+
addTransitionGuard: (config: RouteTransitionGuardConfig) => GuardDisposer;
|
|
14
|
+
isTransitionBlocked: () => boolean;
|
|
15
|
+
unblockTransition: () => void;
|
|
16
|
+
confirmTransition: () => void;
|
|
17
|
+
cancelTransition: () => void;
|
|
14
18
|
destroy: () => void;
|
|
15
19
|
}
|
|
16
20
|
export declare const RouterPresenter: import("@webiny/di").Implementation<typeof RouterPresenterImpl>;
|
|
@@ -29,8 +29,20 @@ class RouterPresenterImpl {
|
|
|
29
29
|
getLink = (route, params) => {
|
|
30
30
|
return this.routerRepository.getLink(route, params);
|
|
31
31
|
};
|
|
32
|
-
|
|
33
|
-
this.routerRepository.
|
|
32
|
+
addTransitionGuard = config => {
|
|
33
|
+
return this.routerRepository.addGuard(config);
|
|
34
|
+
};
|
|
35
|
+
isTransitionBlocked = () => {
|
|
36
|
+
return this.routerRepository.isBlocked();
|
|
37
|
+
};
|
|
38
|
+
unblockTransition = () => {
|
|
39
|
+
this.routerRepository.unblock();
|
|
40
|
+
};
|
|
41
|
+
confirmTransition = () => {
|
|
42
|
+
this.routerRepository.confirmTransition();
|
|
43
|
+
};
|
|
44
|
+
cancelTransition = () => {
|
|
45
|
+
this.routerRepository.cancelTransition();
|
|
34
46
|
};
|
|
35
47
|
destroy = () => {
|
|
36
48
|
this.routerRepository.destroy();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["makeAutoObservable","toJS","createImplementation","RouterRepository","RouterPresenter","Abstraction","RouterPresenterImpl","constructor","routerRepository","vm","currentRoute","getMatchedRoute","bootstrap","routes","registerRoutes","goToRoute","route","params","setRouteParams","cb","getCurrentRoute","matchedRoute","newParams","getLink","
|
|
1
|
+
{"version":3,"names":["makeAutoObservable","toJS","createImplementation","RouterRepository","RouterPresenter","Abstraction","RouterPresenterImpl","constructor","routerRepository","vm","currentRoute","getMatchedRoute","bootstrap","routes","registerRoutes","goToRoute","route","params","setRouteParams","cb","getCurrentRoute","matchedRoute","newParams","getLink","addTransitionGuard","config","addGuard","isTransitionBlocked","isBlocked","unblockTransition","unblock","confirmTransition","cancelTransition","destroy","abstraction","implementation","dependencies"],"sources":["RouterPresenter.ts"],"sourcesContent":["import { makeAutoObservable, toJS } from \"mobx\";\nimport { createImplementation } from \"@webiny/di\";\nimport { Route } from \"./Route.js\";\nimport {\n RouterRepository,\n RouterPresenter as Abstraction,\n type RouteTransitionGuardConfig,\n type GuardDisposer\n} from \"./abstractions.js\";\n\nclass RouterPresenterImpl implements Abstraction.Interface {\n private routerRepository: RouterRepository.Interface;\n\n constructor(routerRepository: RouterRepository.Interface) {\n this.routerRepository = routerRepository;\n\n makeAutoObservable(this);\n }\n\n get vm() {\n return {\n currentRoute: toJS(this.routerRepository.getMatchedRoute())\n };\n }\n\n bootstrap = (routes: Route[]) => {\n this.routerRepository.registerRoutes(routes);\n };\n\n goToRoute = (route: any, params?: any) => {\n this.routerRepository.goToRoute(route, params);\n };\n\n setRouteParams = (cb: any) => {\n const currentRoute = this.routerRepository.getCurrentRoute();\n if (!currentRoute) {\n return;\n }\n\n const matchedRoute = this.routerRepository.getMatchedRoute();\n const newParams = cb(matchedRoute?.params ?? {});\n this.goToRoute(currentRoute, newParams);\n };\n\n getLink = (route: any, params?: any) => {\n return this.routerRepository.getLink(route, params);\n };\n\n addTransitionGuard = (config: RouteTransitionGuardConfig): GuardDisposer => {\n return this.routerRepository.addGuard(config);\n };\n\n isTransitionBlocked = (): boolean => {\n return this.routerRepository.isBlocked();\n };\n\n unblockTransition = (): void => {\n this.routerRepository.unblock();\n };\n\n confirmTransition = (): void => {\n this.routerRepository.confirmTransition();\n };\n\n cancelTransition = (): void => {\n this.routerRepository.cancelTransition();\n };\n\n destroy = () => {\n this.routerRepository.destroy();\n };\n}\n\nexport const RouterPresenter = createImplementation({\n abstraction: Abstraction,\n implementation: RouterPresenterImpl,\n dependencies: [RouterRepository]\n});\n"],"mappings":"AAAA,SAASA,kBAAkB,EAAEC,IAAI,QAAQ,MAAM;AAC/C,SAASC,oBAAoB,QAAQ,YAAY;AAEjD,SACIC,gBAAgB,EAChBC,eAAe,IAAIC,WAAW;AAKlC,MAAMC,mBAAmB,CAAkC;EAGvDC,WAAWA,CAACC,gBAA4C,EAAE;IACtD,IAAI,CAACA,gBAAgB,GAAGA,gBAAgB;IAExCR,kBAAkB,CAAC,IAAI,CAAC;EAC5B;EAEA,IAAIS,EAAEA,CAAA,EAAG;IACL,OAAO;MACHC,YAAY,EAAET,IAAI,CAAC,IAAI,CAACO,gBAAgB,CAACG,eAAe,CAAC,CAAC;IAC9D,CAAC;EACL;EAEAC,SAAS,GAAIC,MAAe,IAAK;IAC7B,IAAI,CAACL,gBAAgB,CAACM,cAAc,CAACD,MAAM,CAAC;EAChD,CAAC;EAEDE,SAAS,GAAGA,CAACC,KAAU,EAAEC,MAAY,KAAK;IACtC,IAAI,CAACT,gBAAgB,CAACO,SAAS,CAACC,KAAK,EAAEC,MAAM,CAAC;EAClD,CAAC;EAEDC,cAAc,GAAIC,EAAO,IAAK;IAC1B,MAAMT,YAAY,GAAG,IAAI,CAACF,gBAAgB,CAACY,eAAe,CAAC,CAAC;IAC5D,IAAI,CAACV,YAAY,EAAE;MACf;IACJ;IAEA,MAAMW,YAAY,GAAG,IAAI,CAACb,gBAAgB,CAACG,eAAe,CAAC,CAAC;IAC5D,MAAMW,SAAS,GAAGH,EAAE,CAACE,YAAY,EAAEJ,MAAM,IAAI,CAAC,CAAC,CAAC;IAChD,IAAI,CAACF,SAAS,CAACL,YAAY,EAAEY,SAAS,CAAC;EAC3C,CAAC;EAEDC,OAAO,GAAGA,CAACP,KAAU,EAAEC,MAAY,KAAK;IACpC,OAAO,IAAI,CAACT,gBAAgB,CAACe,OAAO,CAACP,KAAK,EAAEC,MAAM,CAAC;EACvD,CAAC;EAEDO,kBAAkB,GAAIC,MAAkC,IAAoB;IACxE,OAAO,IAAI,CAACjB,gBAAgB,CAACkB,QAAQ,CAACD,MAAM,CAAC;EACjD,CAAC;EAEDE,mBAAmB,GAAGA,CAAA,KAAe;IACjC,OAAO,IAAI,CAACnB,gBAAgB,CAACoB,SAAS,CAAC,CAAC;EAC5C,CAAC;EAEDC,iBAAiB,GAAGA,CAAA,KAAY;IAC5B,IAAI,CAACrB,gBAAgB,CAACsB,OAAO,CAAC,CAAC;EACnC,CAAC;EAEDC,iBAAiB,GAAGA,CAAA,KAAY;IAC5B,IAAI,CAACvB,gBAAgB,CAACuB,iBAAiB,CAAC,CAAC;EAC7C,CAAC;EAEDC,gBAAgB,GAAGA,CAAA,KAAY;IAC3B,IAAI,CAACxB,gBAAgB,CAACwB,gBAAgB,CAAC,CAAC;EAC5C,CAAC;EAEDC,OAAO,GAAGA,CAAA,KAAM;IACZ,IAAI,CAACzB,gBAAgB,CAACyB,OAAO,CAAC,CAAC;EACnC,CAAC;AACL;AAEA,OAAO,MAAM7B,eAAe,GAAGF,oBAAoB,CAAC;EAChDgC,WAAW,EAAE7B,WAAW;EACxB8B,cAAc,EAAE7B,mBAAmB;EACnC8B,YAAY,EAAE,CAACjC,gBAAgB;AACnC,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
import type { MatchedRoute,
|
|
1
|
+
import type { MatchedRoute, RouteTransitionGuardConfig, GuardDisposer } from "./abstractions.js";
|
|
2
2
|
import * as Abstractions from "./abstractions.js";
|
|
3
3
|
import { Route, RouteParamsDefinition, RouteParamsInfer } from "./Route.js";
|
|
4
4
|
declare class RouterRepositoryImpl implements Abstractions.RouterRepository.Interface {
|
|
5
5
|
private gateway;
|
|
6
6
|
private currentRoute;
|
|
7
7
|
private routes;
|
|
8
|
+
private guards;
|
|
9
|
+
private pendingTransition;
|
|
10
|
+
private forceUnblocked;
|
|
8
11
|
constructor(gateway: Abstractions.RouterGateway.Interface);
|
|
9
12
|
getMatchedRoute(): MatchedRoute<Record<string, any>> | undefined;
|
|
10
13
|
getCurrentRoute(): Route<any> | undefined;
|
|
11
14
|
registerRoutes: (routes: Route[]) => void;
|
|
12
15
|
getLink<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params?: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): string;
|
|
13
16
|
goToRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): void;
|
|
14
|
-
|
|
17
|
+
addGuard(config: RouteTransitionGuardConfig): GuardDisposer;
|
|
18
|
+
isBlocked(): boolean;
|
|
19
|
+
unblock(): void;
|
|
20
|
+
confirmTransition(): void;
|
|
21
|
+
cancelTransition(): void;
|
|
15
22
|
destroy(): void;
|
|
23
|
+
private installBlocker;
|
|
24
|
+
private findBlockingGuard;
|
|
16
25
|
private routeWithAction;
|
|
17
26
|
private transitionToRoute;
|
|
18
27
|
private getRouteByName;
|
|
@@ -11,9 +11,16 @@ const INIT_ROUTE = {
|
|
|
11
11
|
class RouterRepositoryImpl {
|
|
12
12
|
currentRoute = INIT_ROUTE;
|
|
13
13
|
routes = [];
|
|
14
|
+
guards = new Set();
|
|
15
|
+
forceUnblocked = false;
|
|
14
16
|
constructor(gateway) {
|
|
15
17
|
this.gateway = gateway;
|
|
16
|
-
|
|
18
|
+
this.installBlocker();
|
|
19
|
+
makeAutoObservable(this, {
|
|
20
|
+
guards: false,
|
|
21
|
+
pendingTransition: false,
|
|
22
|
+
forceUnblocked: false
|
|
23
|
+
});
|
|
17
24
|
}
|
|
18
25
|
getMatchedRoute() {
|
|
19
26
|
return this.currentRoute.name !== INIT_ROUTE.name ? this.currentRoute : undefined;
|
|
@@ -32,12 +39,75 @@ class RouterRepositoryImpl {
|
|
|
32
39
|
goToRoute(route, params) {
|
|
33
40
|
this.gateway.goToRoute(route.name, params);
|
|
34
41
|
}
|
|
35
|
-
|
|
36
|
-
this.
|
|
42
|
+
addGuard(config) {
|
|
43
|
+
this.guards.add(config);
|
|
44
|
+
return () => {
|
|
45
|
+
this.guards.delete(config);
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
isBlocked() {
|
|
49
|
+
return this.findBlockingGuard() !== undefined;
|
|
50
|
+
}
|
|
51
|
+
unblock() {
|
|
52
|
+
this.forceUnblocked = true;
|
|
53
|
+
if (this.pendingTransition) {
|
|
54
|
+
this.forceUnblocked = false;
|
|
55
|
+
const tx = this.pendingTransition;
|
|
56
|
+
this.pendingTransition = undefined;
|
|
57
|
+
tx.continue();
|
|
58
|
+
setTimeout(() => this.installBlocker(), 0);
|
|
59
|
+
} else {
|
|
60
|
+
// No pending transition — expire the flag after the current
|
|
61
|
+
// call stack so it only covers synchronous navigations that
|
|
62
|
+
// follow immediately (e.g. router.goToRoute on the next line).
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
this.forceUnblocked = false;
|
|
65
|
+
}, 0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
confirmTransition() {
|
|
69
|
+
const tx = this.pendingTransition;
|
|
70
|
+
this.pendingTransition = undefined;
|
|
71
|
+
if (tx) {
|
|
72
|
+
tx.continue();
|
|
73
|
+
setTimeout(() => this.installBlocker(), 0);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
cancelTransition() {
|
|
77
|
+
if (this.pendingTransition) {
|
|
78
|
+
this.pendingTransition.cancel();
|
|
79
|
+
this.pendingTransition = undefined;
|
|
80
|
+
}
|
|
37
81
|
}
|
|
38
82
|
destroy() {
|
|
39
83
|
this.gateway.destroy();
|
|
40
84
|
}
|
|
85
|
+
installBlocker() {
|
|
86
|
+
this.gateway.onRouteExit(controller => {
|
|
87
|
+
if (this.forceUnblocked) {
|
|
88
|
+
this.forceUnblocked = false;
|
|
89
|
+
controller.continue();
|
|
90
|
+
setTimeout(() => this.installBlocker(), 0);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const blockingGuard = this.findBlockingGuard();
|
|
94
|
+
if (blockingGuard) {
|
|
95
|
+
this.pendingTransition = controller;
|
|
96
|
+
blockingGuard.onBlocked();
|
|
97
|
+
} else {
|
|
98
|
+
controller.continue();
|
|
99
|
+
setTimeout(() => this.installBlocker(), 0);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
findBlockingGuard() {
|
|
104
|
+
for (const config of this.guards) {
|
|
105
|
+
if (config.guard()) {
|
|
106
|
+
return config;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
41
111
|
routeWithAction = route => {
|
|
42
112
|
return {
|
|
43
113
|
name: route.name,
|
|
@@ -50,7 +120,7 @@ class RouterRepositoryImpl {
|
|
|
50
120
|
if (!route) {
|
|
51
121
|
return;
|
|
52
122
|
}
|
|
53
|
-
const params = route.params ? route.params.parse(matchedRoute.params) : matchedRoute.params;
|
|
123
|
+
const params = typeof route.params?.parse === "function" ? route.params.parse(matchedRoute.params) : matchedRoute.params;
|
|
54
124
|
runInAction(() => {
|
|
55
125
|
Object.assign(this.currentRoute, {
|
|
56
126
|
...matchedRoute,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["makeAutoObservable","runInAction","Abstractions","createImplementation","RouteUrl","INIT_ROUTE","name","path","pathname","params","RouterRepositoryImpl","currentRoute","routes","constructor","gateway","getMatchedRoute","undefined","getCurrentRoute","find","route","registerRoutes","routesWithAction","map","routeWithAction","setRoutes","getLink","fromPattern","goToRoute","onRouteExit","cb","destroy","onMatch","transitionToRoute","bind","matchedRoute","getRouteByName","parse","Object","assign","existingRoute","RouterRepository","implementation","abstraction","dependencies","RouterGateway"],"sources":["RouterRepository.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from \"mobx\";\nimport type { MatchedRoute, RouteDefinition, OnRouteExit } from \"./abstractions.js\";\nimport * as Abstractions from \"./abstractions.js\";\nimport { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport { createImplementation } from \"@webiny/di\";\nimport { RouteUrl } from \"./RouteUrl.js\";\n\nconst INIT_ROUTE = { name: \"__init__\", path: \"\", pathname: \"\", params: {} };\n\nclass RouterRepositoryImpl implements Abstractions.RouterRepository.Interface {\n private gateway: Abstractions.RouterGateway.Interface;\n private currentRoute: MatchedRoute = INIT_ROUTE;\n private routes: Route<any>[] = [];\n\n constructor(gateway: Abstractions.RouterGateway.Interface) {\n this.gateway = gateway;\n\n makeAutoObservable(this);\n }\n\n getMatchedRoute() {\n return this.currentRoute.name !== INIT_ROUTE.name ? this.currentRoute : undefined;\n }\n\n getCurrentRoute(): Route<any> | undefined {\n return this.routes.find(route => route.name === this.currentRoute.name);\n }\n\n registerRoutes = (routes: Route[]) => {\n this.routes = routes;\n const routesWithAction = routes.map<RouteDefinition>(this.routeWithAction);\n\n this.gateway.setRoutes(routesWithAction);\n };\n\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params?: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): string {\n return RouteUrl.fromPattern(route.path, params);\n }\n\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void {\n this.gateway.goToRoute(route.name, params);\n }\n\n onRouteExit(cb: OnRouteExit): void {\n this.gateway.onRouteExit(cb);\n }\n\n destroy() {\n this.gateway.destroy();\n }\n\n private routeWithAction = (route: Route<any>) => {\n return {\n name: route.name,\n path: route.path,\n onMatch: this.transitionToRoute.bind(this)\n };\n };\n\n private async transitionToRoute(matchedRoute: MatchedRoute) {\n const route = this.getRouteByName(matchedRoute.name);\n if (!route) {\n return;\n }\n\n const params = route.params ? route.params.parse(matchedRoute.params) : matchedRoute.params;\n\n runInAction(() => {\n Object.assign(this.currentRoute, {\n ...matchedRoute,\n params\n });\n });\n }\n\n private getRouteByName(name: string) {\n return this.routes.find(existingRoute => existingRoute.name === name);\n }\n}\n\nexport const RouterRepository = createImplementation({\n implementation: RouterRepositoryImpl,\n abstraction: Abstractions.RouterRepository,\n dependencies: [Abstractions.RouterGateway]\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["makeAutoObservable","runInAction","Abstractions","createImplementation","RouteUrl","INIT_ROUTE","name","path","pathname","params","RouterRepositoryImpl","currentRoute","routes","guards","Set","forceUnblocked","constructor","gateway","installBlocker","pendingTransition","getMatchedRoute","undefined","getCurrentRoute","find","route","registerRoutes","routesWithAction","map","routeWithAction","setRoutes","getLink","fromPattern","goToRoute","addGuard","config","add","delete","isBlocked","findBlockingGuard","unblock","tx","continue","setTimeout","confirmTransition","cancelTransition","cancel","destroy","onRouteExit","controller","blockingGuard","onBlocked","guard","onMatch","transitionToRoute","bind","matchedRoute","getRouteByName","parse","Object","assign","existingRoute","RouterRepository","implementation","abstraction","dependencies","RouterGateway"],"sources":["RouterRepository.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from \"mobx\";\nimport type {\n MatchedRoute,\n RouteDefinition,\n RouteTransitionGuardConfig,\n GuardDisposer,\n TransitionController\n} from \"./abstractions.js\";\nimport * as Abstractions from \"./abstractions.js\";\nimport { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport { createImplementation } from \"@webiny/di\";\nimport { RouteUrl } from \"./RouteUrl.js\";\n\nconst INIT_ROUTE = { name: \"__init__\", path: \"\", pathname: \"\", params: {} };\n\nclass RouterRepositoryImpl implements Abstractions.RouterRepository.Interface {\n private gateway: Abstractions.RouterGateway.Interface;\n private currentRoute: MatchedRoute = INIT_ROUTE;\n private routes: Route<any>[] = [];\n private guards = new Set<RouteTransitionGuardConfig>();\n private pendingTransition: TransitionController | undefined;\n private forceUnblocked = false;\n\n constructor(gateway: Abstractions.RouterGateway.Interface) {\n this.gateway = gateway;\n this.installBlocker();\n\n makeAutoObservable(this, {\n guards: false,\n pendingTransition: false,\n forceUnblocked: false\n } as any);\n }\n\n getMatchedRoute() {\n return this.currentRoute.name !== INIT_ROUTE.name ? this.currentRoute : undefined;\n }\n\n getCurrentRoute(): Route<any> | undefined {\n return this.routes.find(route => route.name === this.currentRoute.name);\n }\n\n registerRoutes = (routes: Route[]) => {\n this.routes = routes;\n const routesWithAction = routes.map<RouteDefinition>(this.routeWithAction);\n\n this.gateway.setRoutes(routesWithAction);\n };\n\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params?: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): string {\n return RouteUrl.fromPattern(route.path, params);\n }\n\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void {\n this.gateway.goToRoute(route.name, params);\n }\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer {\n this.guards.add(config);\n return () => {\n this.guards.delete(config);\n };\n }\n\n isBlocked(): boolean {\n return this.findBlockingGuard() !== undefined;\n }\n\n unblock(): void {\n this.forceUnblocked = true;\n if (this.pendingTransition) {\n this.forceUnblocked = false;\n const tx = this.pendingTransition;\n this.pendingTransition = undefined;\n tx.continue();\n setTimeout(() => this.installBlocker(), 0);\n } else {\n // No pending transition — expire the flag after the current\n // call stack so it only covers synchronous navigations that\n // follow immediately (e.g. router.goToRoute on the next line).\n setTimeout(() => {\n this.forceUnblocked = false;\n }, 0);\n }\n }\n\n confirmTransition(): void {\n const tx = this.pendingTransition;\n this.pendingTransition = undefined;\n if (tx) {\n tx.continue();\n setTimeout(() => this.installBlocker(), 0);\n }\n }\n\n cancelTransition(): void {\n if (this.pendingTransition) {\n this.pendingTransition.cancel();\n this.pendingTransition = undefined;\n }\n }\n\n destroy() {\n this.gateway.destroy();\n }\n\n private installBlocker(): void {\n this.gateway.onRouteExit(controller => {\n if (this.forceUnblocked) {\n this.forceUnblocked = false;\n controller.continue();\n setTimeout(() => this.installBlocker(), 0);\n return;\n }\n\n const blockingGuard = this.findBlockingGuard();\n if (blockingGuard) {\n this.pendingTransition = controller;\n blockingGuard.onBlocked();\n } else {\n controller.continue();\n setTimeout(() => this.installBlocker(), 0);\n }\n });\n }\n\n private findBlockingGuard(): RouteTransitionGuardConfig | undefined {\n for (const config of this.guards) {\n if (config.guard()) {\n return config;\n }\n }\n return undefined;\n }\n\n private routeWithAction = (route: Route<any>) => {\n return {\n name: route.name,\n path: route.path,\n onMatch: this.transitionToRoute.bind(this)\n };\n };\n\n private async transitionToRoute(matchedRoute: MatchedRoute) {\n const route = this.getRouteByName(matchedRoute.name);\n if (!route) {\n return;\n }\n\n const params =\n typeof route.params?.parse === \"function\"\n ? route.params.parse(matchedRoute.params)\n : matchedRoute.params;\n\n runInAction(() => {\n Object.assign(this.currentRoute, {\n ...matchedRoute,\n params\n });\n });\n }\n\n private getRouteByName(name: string) {\n return this.routes.find(existingRoute => existingRoute.name === name);\n }\n}\n\nexport const RouterRepository = createImplementation({\n implementation: RouterRepositoryImpl,\n abstraction: Abstractions.RouterRepository,\n dependencies: [Abstractions.RouterGateway]\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -61,7 +61,7 @@ describe("Router Repository", () => {
|
|
|
61
61
|
await wait();
|
|
62
62
|
expect(repository.getMatchedRoute()).toEqual(loginRoute);
|
|
63
63
|
});
|
|
64
|
-
it("
|
|
64
|
+
it("transition guard should block route transition", async () => {
|
|
65
65
|
const {
|
|
66
66
|
repository,
|
|
67
67
|
history
|
|
@@ -70,56 +70,71 @@ describe("Router Repository", () => {
|
|
|
70
70
|
await wait();
|
|
71
71
|
|
|
72
72
|
// This guard should prevent the transition.
|
|
73
|
-
|
|
74
|
-
repository.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
cancel();
|
|
73
|
+
const onBlocked = vi.fn();
|
|
74
|
+
repository.addGuard({
|
|
75
|
+
guard: () => true,
|
|
76
|
+
onBlocked
|
|
78
77
|
});
|
|
79
78
|
|
|
80
79
|
// Trigger a history location change (imagine a click on "Back" button in the browser).
|
|
81
80
|
history.push("/users/123");
|
|
82
81
|
await wait();
|
|
83
82
|
expect(repository.getMatchedRoute()).toEqual(loginRoute);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
expect(onBlocked).toHaveBeenCalledTimes(1);
|
|
84
|
+
});
|
|
85
|
+
it("transition guard should allow route transition when guard returns false", async () => {
|
|
86
|
+
const {
|
|
87
|
+
repository,
|
|
88
|
+
history
|
|
89
|
+
} = createRepository();
|
|
90
|
+
history.push("/login");
|
|
91
|
+
await wait();
|
|
92
|
+
repository.addGuard({
|
|
93
|
+
guard: () => false,
|
|
94
|
+
onBlocked: vi.fn()
|
|
88
95
|
});
|
|
89
96
|
|
|
90
|
-
// Trigger a history location change
|
|
97
|
+
// Trigger a history location change.
|
|
91
98
|
history.push("/users/123");
|
|
92
99
|
await wait();
|
|
93
100
|
expect(repository.getMatchedRoute()).toEqual(userRoute("123"));
|
|
94
101
|
});
|
|
95
|
-
it("
|
|
96
|
-
const guardSpy = vi.fn();
|
|
102
|
+
it("confirmTransition should allow a blocked transition to proceed", async () => {
|
|
97
103
|
const {
|
|
98
104
|
repository,
|
|
99
105
|
history
|
|
100
106
|
} = createRepository();
|
|
101
107
|
history.push("/login");
|
|
102
108
|
await wait();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
guard.continue();
|
|
109
|
+
repository.addGuard({
|
|
110
|
+
guard: () => true,
|
|
111
|
+
onBlocked: () => {
|
|
112
|
+
repository.confirmTransition();
|
|
113
|
+
}
|
|
109
114
|
});
|
|
110
|
-
|
|
111
|
-
// Trigger a history location change (imagine a click on "Back" button in the browser).
|
|
112
115
|
history.push("/users/123");
|
|
113
116
|
await wait();
|
|
114
117
|
expect(repository.getMatchedRoute()).toEqual(userRoute("123"));
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
});
|
|
119
|
+
it("guard disposer should remove the guard", async () => {
|
|
120
|
+
const {
|
|
121
|
+
repository,
|
|
122
|
+
history
|
|
123
|
+
} = createRepository();
|
|
119
124
|
history.push("/login");
|
|
120
125
|
await wait();
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
const dispose = repository.addGuard({
|
|
127
|
+
guard: () => true,
|
|
128
|
+
onBlocked: vi.fn()
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Remove the guard.
|
|
132
|
+
dispose();
|
|
133
|
+
|
|
134
|
+
// Transition should now pass through.
|
|
135
|
+
history.push("/users/123");
|
|
136
|
+
await wait();
|
|
137
|
+
expect(repository.getMatchedRoute()).toEqual(userRoute("123"));
|
|
123
138
|
});
|
|
124
139
|
it("should go to the right route", async () => {
|
|
125
140
|
const {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["describe","it","beforeEach","expect","vi","createMemoryHistory","HistoryRouterGateway","RouterRepository","Route","wait","Promise","resolve","setTimeout","loginRouteDef","name","path","userRouteDef","params","zod","id","string","allRoutes","loginRoute","pathname","userRoute","createRepository","routes","history","replace","gateway","repository","registerRoutes","clearAllMocks","push","getMatchedRoute","toEqual","onRouteExit","cancel","guard","continue","guardSpy","fn","toHaveBeenCalledTimes","resetAllMocks","goToRoute","getLink"],"sources":["RouterRepository.test.ts"],"sourcesContent":["import { describe, it, beforeEach, expect, vi } from \"vitest\";\nimport { createMemoryHistory } from \"history\";\nimport { HistoryRouterGateway } from \"./HistoryRouterGateway.js\";\nimport { RouterRepository } from \"./RouterRepository.js\";\nimport { Route } from \"./Route.js\";\n\nconst wait = () => new Promise(resolve => setTimeout(resolve, 10));\n\nconst loginRouteDef = new Route({ name: \"login\", path: \"/login\" });\n\nconst userRouteDef = new Route({\n name: \"userById\",\n path: \"/users/:id\",\n params: zod => {\n return {\n id: zod.string()\n };\n }\n});\n\nconst allRoutes: Route<any>[] = [\n new Route({ name: \"home\", path: \"/\" }),\n loginRouteDef,\n userRouteDef\n];\n\nconst loginRoute = {\n name: \"login\",\n path: \"/login\",\n pathname: \"/login\",\n params: {}\n};\n\nconst userRoute = (id: string) => {\n return {\n name: \"userById\",\n path: \"/users/:id\",\n pathname: `/users/${id}`,\n params: {\n id\n }\n };\n};\n\nconst createRepository = (routes = allRoutes) => {\n const history = createMemoryHistory();\n history.replace(\"/__unknown__\");\n\n const gateway = new HistoryRouterGateway(history, \"\");\n const repository = new RouterRepository(gateway);\n\n repository.registerRoutes(routes);\n\n return { repository, history };\n};\n\ndescribe(\"Router Repository\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"state should contain current route\", async () => {\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(loginRoute);\n });\n\n it(\"route guard should allow or prevent route transition\", async () => {\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n // This guard should prevent the transition.\n // The Repository should stay where it was, and the `history` should restore the previous URL.\n repository.onRouteExit(({ cancel }) => {\n cancel();\n });\n\n // Trigger a history location change (imagine a click on \"Back\" button in the browser).\n history.push(\"/users/123\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(loginRoute);\n\n // This guard should allow the transition.\n repository.onRouteExit(guard => {\n guard.continue();\n });\n\n // Trigger a history location change (imagine a click on \"Back\" button in the browser).\n history.push(\"/users/123\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(userRoute(\"123\"));\n });\n\n it(\"route guard should be unset after route transition\", async () => {\n const guardSpy = vi.fn();\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n // This guard should prevent the transition.\n // The Repository should stay where it was, and the `history` should restore the previous URL.\n repository.onRouteExit(guard => {\n guardSpy();\n guard.continue();\n });\n\n // Trigger a history location change (imagine a click on \"Back\" button in the browser).\n history.push(\"/users/123\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(userRoute(\"123\"));\n expect(guardSpy).toHaveBeenCalledTimes(1);\n vi.resetAllMocks();\n\n // Trigger a history location change (imagine a click on \"Back\" button in the browser).\n history.push(\"/login\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(loginRoute);\n expect(guardSpy).toHaveBeenCalledTimes(0);\n });\n\n it(\"should go to the right route\", async () => {\n const { repository } = createRepository();\n repository.goToRoute(userRouteDef, { id: \"5\" });\n await wait();\n expect(repository.getMatchedRoute()).toEqual(userRoute(\"5\"));\n });\n\n it(\"should generate a valid route link\", async () => {\n const { repository } = createRepository();\n\n expect(repository.getLink(loginRouteDef)).toEqual(\"/login\");\n expect(repository.getLink(userRouteDef, { id: \"1\" })).toEqual(\"/users/1\");\n });\n\n it(\"should generate a valid route link when no routes are registered\", async () => {\n const { repository } = createRepository([]);\n\n expect(repository.getLink(loginRouteDef)).toEqual(\"/login\");\n expect(repository.getLink(userRouteDef, { id: \"1\" })).toEqual(\"/users/1\");\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["describe","it","beforeEach","expect","vi","createMemoryHistory","HistoryRouterGateway","RouterRepository","Route","wait","Promise","resolve","setTimeout","loginRouteDef","name","path","userRouteDef","params","zod","id","string","allRoutes","loginRoute","pathname","userRoute","createRepository","routes","history","replace","gateway","repository","registerRoutes","clearAllMocks","push","getMatchedRoute","toEqual","onBlocked","fn","addGuard","guard","toHaveBeenCalledTimes","confirmTransition","dispose","goToRoute","getLink"],"sources":["RouterRepository.test.ts"],"sourcesContent":["import { describe, it, beforeEach, expect, vi } from \"vitest\";\nimport { createMemoryHistory } from \"history\";\nimport { HistoryRouterGateway } from \"./HistoryRouterGateway.js\";\nimport { RouterRepository } from \"./RouterRepository.js\";\nimport { Route } from \"./Route.js\";\n\nconst wait = () => new Promise(resolve => setTimeout(resolve, 10));\n\nconst loginRouteDef = new Route({ name: \"login\", path: \"/login\" });\n\nconst userRouteDef = new Route({\n name: \"userById\",\n path: \"/users/:id\",\n params: zod => {\n return {\n id: zod.string()\n };\n }\n});\n\nconst allRoutes: Route<any>[] = [\n new Route({ name: \"home\", path: \"/\" }),\n loginRouteDef,\n userRouteDef\n];\n\nconst loginRoute = {\n name: \"login\",\n path: \"/login\",\n pathname: \"/login\",\n params: {}\n};\n\nconst userRoute = (id: string) => {\n return {\n name: \"userById\",\n path: \"/users/:id\",\n pathname: `/users/${id}`,\n params: {\n id\n }\n };\n};\n\nconst createRepository = (routes = allRoutes) => {\n const history = createMemoryHistory();\n history.replace(\"/__unknown__\");\n\n const gateway = new HistoryRouterGateway(history, \"\");\n const repository = new RouterRepository(gateway);\n\n repository.registerRoutes(routes);\n\n return { repository, history };\n};\n\ndescribe(\"Router Repository\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"state should contain current route\", async () => {\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(loginRoute);\n });\n\n it(\"transition guard should block route transition\", async () => {\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n // This guard should prevent the transition.\n const onBlocked = vi.fn();\n repository.addGuard({\n guard: () => true,\n onBlocked\n });\n\n // Trigger a history location change (imagine a click on \"Back\" button in the browser).\n history.push(\"/users/123\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(loginRoute);\n expect(onBlocked).toHaveBeenCalledTimes(1);\n });\n\n it(\"transition guard should allow route transition when guard returns false\", async () => {\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n repository.addGuard({\n guard: () => false,\n onBlocked: vi.fn()\n });\n\n // Trigger a history location change.\n history.push(\"/users/123\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(userRoute(\"123\"));\n });\n\n it(\"confirmTransition should allow a blocked transition to proceed\", async () => {\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n repository.addGuard({\n guard: () => true,\n onBlocked: () => {\n repository.confirmTransition();\n }\n });\n\n history.push(\"/users/123\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(userRoute(\"123\"));\n });\n\n it(\"guard disposer should remove the guard\", async () => {\n const { repository, history } = createRepository();\n history.push(\"/login\");\n await wait();\n\n const dispose = repository.addGuard({\n guard: () => true,\n onBlocked: vi.fn()\n });\n\n // Remove the guard.\n dispose();\n\n // Transition should now pass through.\n history.push(\"/users/123\");\n await wait();\n\n expect(repository.getMatchedRoute()).toEqual(userRoute(\"123\"));\n });\n\n it(\"should go to the right route\", async () => {\n const { repository } = createRepository();\n repository.goToRoute(userRouteDef, { id: \"5\" });\n await wait();\n expect(repository.getMatchedRoute()).toEqual(userRoute(\"5\"));\n });\n\n it(\"should generate a valid route link\", async () => {\n const { repository } = createRepository();\n\n expect(repository.getLink(loginRouteDef)).toEqual(\"/login\");\n expect(repository.getLink(userRouteDef, { id: \"1\" })).toEqual(\"/users/1\");\n });\n\n it(\"should generate a valid route link when no routes are registered\", async () => {\n const { repository } = createRepository([]);\n\n expect(repository.getLink(loginRouteDef)).toEqual(\"/login\");\n expect(repository.getLink(userRouteDef, { id: \"1\" })).toEqual(\"/users/1\");\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -12,7 +12,11 @@ export interface IRouterPresenter {
|
|
|
12
12
|
goToRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, ...args: RouteParamsArgs<TParams>): void;
|
|
13
13
|
getLink<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, ...args: RouteParamsArgs<TParams>): string;
|
|
14
14
|
setRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;
|
|
15
|
-
|
|
15
|
+
addTransitionGuard(config: RouteTransitionGuardConfig): GuardDisposer;
|
|
16
|
+
isTransitionBlocked(): boolean;
|
|
17
|
+
unblockTransition(): void;
|
|
18
|
+
confirmTransition(): void;
|
|
19
|
+
cancelTransition(): void;
|
|
16
20
|
destroy(): void;
|
|
17
21
|
}
|
|
18
22
|
export declare const RouterPresenter: Abstraction<IRouterPresenter>;
|
|
@@ -27,12 +31,16 @@ export interface MatchedRoute<TParams = Record<string, any>> {
|
|
|
27
31
|
params: TParams;
|
|
28
32
|
}
|
|
29
33
|
interface IRouterRepository {
|
|
30
|
-
onRouteExit(cb: OnRouteExit): void;
|
|
31
34
|
getMatchedRoute(): MatchedRoute | undefined;
|
|
32
35
|
getCurrentRoute(): Route<any> | undefined;
|
|
33
36
|
goToRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): void;
|
|
34
37
|
getLink<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): string;
|
|
35
38
|
registerRoutes(routes: Route[]): void;
|
|
39
|
+
addGuard(config: RouteTransitionGuardConfig): GuardDisposer;
|
|
40
|
+
isBlocked(): boolean;
|
|
41
|
+
unblock(): void;
|
|
42
|
+
confirmTransition(): void;
|
|
43
|
+
cancelTransition(): void;
|
|
36
44
|
destroy(): void;
|
|
37
45
|
}
|
|
38
46
|
export declare const RouterRepository: Abstraction<IRouterRepository>;
|
|
@@ -65,4 +73,12 @@ export declare const RouterGateway: Abstraction<IRouterGateway>;
|
|
|
65
73
|
export declare namespace RouterGateway {
|
|
66
74
|
type Interface = IRouterGateway;
|
|
67
75
|
}
|
|
76
|
+
/***** Route Transition *****/
|
|
77
|
+
export type GuardDisposer = () => void;
|
|
78
|
+
export interface RouteTransitionGuardConfig {
|
|
79
|
+
/** Return true to block the transition. */
|
|
80
|
+
guard: () => boolean;
|
|
81
|
+
/** Called when this guard blocks a transition. Show a confirmation dialog here. */
|
|
82
|
+
onBlocked: () => void;
|
|
83
|
+
}
|
|
68
84
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Abstraction","RouterPresenter","RouterRepository","RouterGateway"],"sources":["abstractions.ts"],"sourcesContent":["import { Abstraction } from \"@webiny/di\";\nimport type { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport type { RequiredKeysOf } from \"type-fest\";\n\n/***** Presenter *****/\n\nexport type RouteParamsArgs<TParams extends RouteParamsDefinition | undefined> =\n TParams extends RouteParamsDefinition\n ? RequiredKeysOf<RouteParamsInfer<TParams>> extends never\n ? [params?: RouteParamsInfer<TParams>] // all optional → param optional\n : [params: RouteParamsInfer<TParams>] // some required → param required\n : [];\n\ninterface RouterViewModel {\n currentRoute: MatchedRoute | undefined;\n}\n\nexport interface IRouterPresenter {\n vm: RouterViewModel;\n bootstrap(routes: Route[]): void;\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): void;\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): string;\n setRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;\n
|
|
1
|
+
{"version":3,"names":["Abstraction","RouterPresenter","RouterRepository","RouterGateway"],"sources":["abstractions.ts"],"sourcesContent":["import { Abstraction } from \"@webiny/di\";\nimport type { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport type { RequiredKeysOf } from \"type-fest\";\n\n/***** Presenter *****/\n\nexport type RouteParamsArgs<TParams extends RouteParamsDefinition | undefined> =\n TParams extends RouteParamsDefinition\n ? RequiredKeysOf<RouteParamsInfer<TParams>> extends never\n ? [params?: RouteParamsInfer<TParams>] // all optional → param optional\n : [params: RouteParamsInfer<TParams>] // some required → param required\n : [];\n\ninterface RouterViewModel {\n currentRoute: MatchedRoute | undefined;\n}\n\nexport interface IRouterPresenter {\n vm: RouterViewModel;\n bootstrap(routes: Route[]): void;\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): void;\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): string;\n setRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;\n addTransitionGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n isTransitionBlocked(): boolean;\n unblockTransition(): void;\n confirmTransition(): void;\n cancelTransition(): void;\n destroy(): void;\n}\nexport const RouterPresenter = new Abstraction<IRouterPresenter>(\"RouterPresenter\");\n\nexport namespace RouterPresenter {\n export type Interface = IRouterPresenter;\n}\n\n/***** Repository *****/\n\nexport interface MatchedRoute<TParams = Record<string, any>> {\n // Name of the matched route.\n name: string;\n // Pathname that was used to match the route.\n pathname: string;\n // Path pattern that matched this route.\n path: string;\n // Route params extracted from the pathname.\n params: TParams;\n}\n\ninterface IRouterRepository {\n getMatchedRoute(): MatchedRoute | undefined;\n\n getCurrentRoute(): Route<any> | undefined;\n\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void;\n\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): string;\n\n registerRoutes(routes: Route[]): void;\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n isBlocked(): boolean;\n unblock(): void;\n confirmTransition(): void;\n cancelTransition(): void;\n\n destroy(): void;\n}\n\nexport const RouterRepository = new Abstraction<IRouterRepository>(\"RouterRepository\");\n\nexport namespace RouterRepository {\n export type Interface = IRouterRepository;\n}\n\n/***** Gateway *****/\n\nexport interface RouteDefinition {\n name: string;\n path: string;\n onMatch(route: MatchedRoute): void;\n}\n\nexport type TransitionController = {\n continue: () => void;\n cancel: () => void;\n};\n\nexport interface OnRouteExit {\n (controller: TransitionController): void;\n}\n\ninterface IRouterGateway {\n setRoutes(routes: RouteDefinition[]): void;\n goToRoute(name: string, params?: { [k: string]: any }): void;\n pushState(url: string): void;\n onRouteExit(cb: OnRouteExit): void;\n destroy(): void;\n}\n\nexport const RouterGateway = new Abstraction<IRouterGateway>(\"RouterGateway\");\n\nexport namespace RouterGateway {\n export type Interface = IRouterGateway;\n}\n\n/***** Route Transition *****/\n\nexport type GuardDisposer = () => void;\n\nexport interface RouteTransitionGuardConfig {\n /** Return true to block the transition. */\n guard: () => boolean;\n /** Called when this guard blocks a transition. Show a confirmation dialog here. */\n onBlocked: () => void;\n}\n"],"mappings":"AAAA,SAASA,WAAW,QAAQ,YAAY;;AAIxC;;AAgCA,OAAO,MAAMC,eAAe,GAAG,IAAID,WAAW,CAAmB,iBAAiB,CAAC;;AAMnF;;AAuCA,OAAO,MAAME,gBAAgB,GAAG,IAAIF,WAAW,CAAoB,kBAAkB,CAAC;;AAMtF;;AAyBA,OAAO,MAAMG,aAAa,GAAG,IAAIH,WAAW,CAAiB,eAAe,CAAC;;AAM7E","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["RouterPresenter","RouterGateway"],"sources":["index.ts"],"sourcesContent":["export { RouterPresenter, RouterGateway } from \"./abstractions.js\";\n"],"mappings":"AAAA,SAASA,eAAe,EAAEC,aAAa","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["RouterPresenter","RouterGateway"],"sources":["index.ts"],"sourcesContent":["export { RouterPresenter, RouterGateway } from \"./abstractions.js\";\nexport type { RouteTransitionGuardConfig, GuardDisposer } from \"./abstractions.js\";\n"],"mappings":"AAAA,SAASA,eAAe,EAAEC,aAAa","ignoreList":[]}
|
package/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export { createFeature } from "./shared/di/createFeature.js";
|
|
|
19
19
|
export { Route } from "./features/router/Route.js";
|
|
20
20
|
export { RouteLink, type RouteLinkProps } from "./presentation/router/components/RouteLink.js";
|
|
21
21
|
export { SimpleLink, type SimpleLinkProps } from "./presentation/router/components/SimpleLink.js";
|
|
22
|
+
export { useEnvConfig } from "./presentation/envConfig/useEnvConfig.js";
|
|
22
23
|
export { useRouter, useRoute } from "./presentation/router/index.js";
|
|
23
24
|
export { useLocalStorage, useLocalStorageValue, useLocalStorageValues } from "./presentation/localStorage/index.js";
|
|
24
25
|
export * from "./helpers/InterfaceGenerator/index.js";
|
package/index.js
CHANGED
|
@@ -20,6 +20,7 @@ export { createFeature } from "./shared/di/createFeature.js";
|
|
|
20
20
|
export { Route } from "./features/router/Route.js";
|
|
21
21
|
export { RouteLink } from "./presentation/router/components/RouteLink.js";
|
|
22
22
|
export { SimpleLink } from "./presentation/router/components/SimpleLink.js";
|
|
23
|
+
export { useEnvConfig } from "./presentation/envConfig/useEnvConfig.js";
|
|
23
24
|
export { useRouter, useRoute } from "./presentation/router/index.js";
|
|
24
25
|
export { useLocalStorage, useLocalStorageValue, useLocalStorageValues } from "./presentation/localStorage/index.js";
|
|
25
26
|
export * from "./helpers/InterfaceGenerator/index.js";
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AddQuerySelectionPlugin","ApolloLinkPlugin","ApolloCacheObjectIdPlugin","useContainer","DiContainerProvider","useFeature","createFeature","Route","RouteLink","SimpleLink","useRouter","useRoute","useLocalStorage","useLocalStorageValue","useLocalStorageValues"],"sources":["index.ts"],"sourcesContent":["export { AddQuerySelectionPlugin } from \"./plugins/AddQuerySelectionPlugin.js\";\nexport { ApolloLinkPlugin } from \"./plugins/ApolloLinkPlugin.js\";\nexport {\n ApolloCacheObjectIdPlugin,\n type ApolloCacheObject\n} from \"./plugins/ApolloCacheObjectIdPlugin.js\";\n\n// Composition - we re-export this for ease of use\nexport * from \"@webiny/react-composition\";\nexport type { HigherOrderComponent, ComposeProps, ComposableFC } from \"@webiny/react-composition\";\n\n// App framework\nexport * from \"./App.js\";\nexport * from \"./AppContainer.js\";\nexport type { AppProps } from \"./App.js\";\nexport * from \"./core/Plugins.js\";\nexport * from \"./core/Plugin.js\";\nexport * from \"./core/Provider.js\";\nexport * from \"./core/createProvider.js\";\nexport * from \"./core/createProviderPlugin.js\";\nexport * from \"./renderApp.js\";\nexport * from \"./utils/createGenericContext.js\";\nexport { useContainer, DiContainerProvider } from \"./shared/di/DiContainerProvider.js\";\nexport { useFeature } from \"./shared/di/useFeature.js\";\nexport { createFeature } from \"./shared/di/createFeature.js\";\n\nexport { Route } from \"./features/router/Route.js\";\nexport { RouteLink, type RouteLinkProps } from \"./presentation/router/components/RouteLink.js\";\nexport { SimpleLink, type SimpleLinkProps } from \"./presentation/router/components/SimpleLink.js\";\n\nexport { useRouter, useRoute } from \"./presentation/router/index.js\";\nexport {\n useLocalStorage,\n useLocalStorageValue,\n useLocalStorageValues\n} from \"./presentation/localStorage/index.js\";\n\nexport * from \"./helpers/InterfaceGenerator/index.js\";\n"],"mappings":"AAAA,SAASA,uBAAuB;AAChC,SAASC,gBAAgB;AACzB,SACIC,yBAAyB;;AAI7B;AACA,cAAc,2BAA2B;AAGzC;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,YAAY,EAAEC,mBAAmB;AAC1C,SAASC,UAAU;AACnB,SAASC,aAAa;AAEtB,SAASC,KAAK;AACd,SAASC,SAAS;AAClB,SAASC,UAAU;AAEnB,SAASC,SAAS,EAAEC,QAAQ;AAC5B,SACIC,eAAe,EACfC,oBAAoB,EACpBC,qBAAqB;AAGzB","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["AddQuerySelectionPlugin","ApolloLinkPlugin","ApolloCacheObjectIdPlugin","useContainer","DiContainerProvider","useFeature","createFeature","Route","RouteLink","SimpleLink","useEnvConfig","useRouter","useRoute","useLocalStorage","useLocalStorageValue","useLocalStorageValues"],"sources":["index.ts"],"sourcesContent":["export { AddQuerySelectionPlugin } from \"./plugins/AddQuerySelectionPlugin.js\";\nexport { ApolloLinkPlugin } from \"./plugins/ApolloLinkPlugin.js\";\nexport {\n ApolloCacheObjectIdPlugin,\n type ApolloCacheObject\n} from \"./plugins/ApolloCacheObjectIdPlugin.js\";\n\n// Composition - we re-export this for ease of use\nexport * from \"@webiny/react-composition\";\nexport type { HigherOrderComponent, ComposeProps, ComposableFC } from \"@webiny/react-composition\";\n\n// App framework\nexport * from \"./App.js\";\nexport * from \"./AppContainer.js\";\nexport type { AppProps } from \"./App.js\";\nexport * from \"./core/Plugins.js\";\nexport * from \"./core/Plugin.js\";\nexport * from \"./core/Provider.js\";\nexport * from \"./core/createProvider.js\";\nexport * from \"./core/createProviderPlugin.js\";\nexport * from \"./renderApp.js\";\nexport * from \"./utils/createGenericContext.js\";\nexport { useContainer, DiContainerProvider } from \"./shared/di/DiContainerProvider.js\";\nexport { useFeature } from \"./shared/di/useFeature.js\";\nexport { createFeature } from \"./shared/di/createFeature.js\";\n\nexport { Route } from \"./features/router/Route.js\";\nexport { RouteLink, type RouteLinkProps } from \"./presentation/router/components/RouteLink.js\";\nexport { SimpleLink, type SimpleLinkProps } from \"./presentation/router/components/SimpleLink.js\";\n\nexport { useEnvConfig } from \"./presentation/envConfig/useEnvConfig.js\";\nexport { useRouter, useRoute } from \"./presentation/router/index.js\";\nexport {\n useLocalStorage,\n useLocalStorageValue,\n useLocalStorageValues\n} from \"./presentation/localStorage/index.js\";\n\nexport * from \"./helpers/InterfaceGenerator/index.js\";\n"],"mappings":"AAAA,SAASA,uBAAuB;AAChC,SAASC,gBAAgB;AACzB,SACIC,yBAAyB;;AAI7B;AACA,cAAc,2BAA2B;AAGzC;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,YAAY,EAAEC,mBAAmB;AAC1C,SAASC,UAAU;AACnB,SAASC,aAAa;AAEtB,SAASC,KAAK;AACd,SAASC,SAAS;AAClB,SAASC,UAAU;AAEnB,SAASC,YAAY;AACrB,SAASC,SAAS,EAAEC,QAAQ;AAC5B,SACIC,eAAe,EACfC,oBAAoB,EACpBC,qBAAqB;AAGzB","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app",
|
|
3
|
-
"version": "6.0.0",
|
|
3
|
+
"version": "6.1.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@apollo/react-hooks": "3.1.5",
|
|
19
|
-
"@emotion/styled": "11.
|
|
19
|
+
"@emotion/styled": "11.14.1",
|
|
20
20
|
"@types/react": "18.2.79",
|
|
21
21
|
"@webiny/di": "0.2.3",
|
|
22
|
-
"@webiny/feature": "6.0.0",
|
|
23
|
-
"@webiny/i18n": "6.0.0",
|
|
24
|
-
"@webiny/i18n-react": "6.0.0",
|
|
25
|
-
"@webiny/plugins": "6.0.0",
|
|
26
|
-
"@webiny/react-composition": "6.0.0",
|
|
27
|
-
"@webiny/react-properties": "6.0.0",
|
|
22
|
+
"@webiny/feature": "6.1.0-beta.0",
|
|
23
|
+
"@webiny/i18n": "6.1.0-beta.0",
|
|
24
|
+
"@webiny/i18n-react": "6.1.0-beta.0",
|
|
25
|
+
"@webiny/plugins": "6.1.0-beta.0",
|
|
26
|
+
"@webiny/react-composition": "6.1.0-beta.0",
|
|
27
|
+
"@webiny/react-properties": "6.1.0-beta.0",
|
|
28
28
|
"apollo-cache": "1.3.5",
|
|
29
29
|
"apollo-cache-inmemory": "1.6.6",
|
|
30
30
|
"apollo-client": "2.6.10",
|
|
@@ -35,27 +35,27 @@
|
|
|
35
35
|
"apollo-utilities": "1.3.4",
|
|
36
36
|
"boolean": "3.2.0",
|
|
37
37
|
"bytes": "3.1.2",
|
|
38
|
-
"graphql": "16.13.
|
|
38
|
+
"graphql": "16.13.2",
|
|
39
39
|
"history": "5.3.0",
|
|
40
40
|
"invariant": "2.2.4",
|
|
41
41
|
"lodash": "4.17.23",
|
|
42
42
|
"minimatch": "10.2.4",
|
|
43
43
|
"mobx": "6.15.0",
|
|
44
|
-
"nanoid": "5.1.
|
|
44
|
+
"nanoid": "5.1.7",
|
|
45
45
|
"react": "18.2.0",
|
|
46
46
|
"react-dom": "18.2.0",
|
|
47
47
|
"ts-invariant": "0.10.3",
|
|
48
48
|
"warning": "4.0.3",
|
|
49
|
-
"zod": "3.
|
|
49
|
+
"zod": "4.3.6"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/lodash": "4.17.24",
|
|
53
|
-
"@types/warning": "3.0.
|
|
54
|
-
"@webiny/build-tools": "6.0.0",
|
|
53
|
+
"@types/warning": "3.0.4",
|
|
54
|
+
"@webiny/build-tools": "6.1.0-beta.0",
|
|
55
55
|
"rimraf": "6.1.3",
|
|
56
|
-
"type-fest": "5.
|
|
56
|
+
"type-fest": "5.5.0",
|
|
57
57
|
"typescript": "5.9.3",
|
|
58
|
-
"vitest": "4.
|
|
58
|
+
"vitest": "4.1.2"
|
|
59
59
|
},
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
]
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "a3bd3695c66c79238e380d7360d9731b5fcf9c87"
|
|
72
72
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useFeature } from "../../shared/di/useFeature.js";
|
|
2
|
+
import { EnvConfigFeature } from "../../features/envConfig/feature.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns the EnvConfig instance from DI.
|
|
6
|
+
* Useful when you want to access EnvConfig inside components and hooks.
|
|
7
|
+
*/
|
|
8
|
+
export function useEnvConfig() {
|
|
9
|
+
const envConfig = useFeature(EnvConfigFeature);
|
|
10
|
+
return envConfig.getAll();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=useEnvConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useFeature","EnvConfigFeature","useEnvConfig","envConfig","getAll"],"sources":["useEnvConfig.ts"],"sourcesContent":["import { useFeature } from \"~/shared/di/useFeature.js\";\nimport { EnvConfig } from \"~/features/envConfig/index.js\";\nimport { EnvConfigFeature } from \"~/features/envConfig/feature.js\";\n\n/**\n * Returns the EnvConfig instance from DI.\n * Useful when you want to access EnvConfig inside components and hooks.\n */\nexport function useEnvConfig(): EnvConfig.Config {\n const envConfig = useFeature(EnvConfigFeature);\n\n return envConfig.getAll();\n}\n"],"mappings":"AAAA,SAASA,UAAU;AAEnB,SAASC,gBAAgB;;AAEzB;AACA;AACA;AACA;AACA,OAAO,SAASC,YAAYA,CAAA,EAAqB;EAC7C,MAAMC,SAAS,GAAGH,UAAU,CAACC,gBAAgB,CAAC;EAE9C,OAAOE,SAAS,CAACC,MAAM,CAAC,CAAC;AAC7B","ignoreList":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { DevToolsSection } from "@webiny/react-properties";
|
|
2
3
|
import { RouteElementRegistry, useRoute } from "../index.js";
|
|
3
4
|
import { useContainer } from "../../../shared/di/DiContainerProvider.js";
|
|
4
5
|
export const RouteContent = () => {
|
|
@@ -11,7 +12,12 @@ export const RouteContent = () => {
|
|
|
11
12
|
return null;
|
|
12
13
|
}
|
|
13
14
|
const element = elementRegistry.getElement(route.name);
|
|
14
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null,
|
|
15
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DevToolsSection, {
|
|
16
|
+
name: "Current Route",
|
|
17
|
+
group: "Router",
|
|
18
|
+
data: route,
|
|
19
|
+
views: "raw"
|
|
20
|
+
}), element ?? null);
|
|
15
21
|
};
|
|
16
22
|
|
|
17
23
|
//# sourceMappingURL=RouteContent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","RouteElementRegistry","useRoute","useContainer","RouteContent","route","container","elementRegistry","resolve","element","getElement","name","createElement","Fragment"],"sources":["RouteContent.tsx"],"sourcesContent":["import React from \"react\";\nimport { RouteElementRegistry, useRoute } from \"~/presentation/router/index.js\";\nimport { useContainer } from \"~/shared/di/DiContainerProvider.js\";\n\nexport const RouteContent = () => {\n const { route } = useRoute();\n const container = useContainer();\n const elementRegistry = container.resolve(RouteElementRegistry);\n\n if (!route) {\n return null;\n }\n\n const element = elementRegistry.getElement(route.name);\n\n return
|
|
1
|
+
{"version":3,"names":["React","DevToolsSection","RouteElementRegistry","useRoute","useContainer","RouteContent","route","container","elementRegistry","resolve","element","getElement","name","createElement","Fragment","group","data","views"],"sources":["RouteContent.tsx"],"sourcesContent":["import React from \"react\";\nimport { DevToolsSection } from \"@webiny/react-properties\";\nimport { RouteElementRegistry, useRoute } from \"~/presentation/router/index.js\";\nimport { useContainer } from \"~/shared/di/DiContainerProvider.js\";\n\nexport const RouteContent = () => {\n const { route } = useRoute();\n const container = useContainer();\n const elementRegistry = container.resolve(RouteElementRegistry);\n\n if (!route) {\n return null;\n }\n\n const element = elementRegistry.getElement(route.name);\n\n return (\n <>\n <DevToolsSection name={\"Current Route\"} group={\"Router\"} data={route} views={\"raw\"} />\n {element ?? null}\n </>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,eAAe,QAAQ,0BAA0B;AAC1D,SAASC,oBAAoB,EAAEC,QAAQ;AACvC,SAASC,YAAY;AAErB,OAAO,MAAMC,YAAY,GAAGA,CAAA,KAAM;EAC9B,MAAM;IAAEC;EAAM,CAAC,GAAGH,QAAQ,CAAC,CAAC;EAC5B,MAAMI,SAAS,GAAGH,YAAY,CAAC,CAAC;EAChC,MAAMI,eAAe,GAAGD,SAAS,CAACE,OAAO,CAACP,oBAAoB,CAAC;EAE/D,IAAI,CAACI,KAAK,EAAE;IACR,OAAO,IAAI;EACf;EAEA,MAAMI,OAAO,GAAGF,eAAe,CAACG,UAAU,CAACL,KAAK,CAACM,IAAI,CAAC;EAEtD,oBACIZ,KAAA,CAAAa,aAAA,CAAAb,KAAA,CAAAc,QAAA,qBACId,KAAA,CAAAa,aAAA,CAACZ,eAAe;IAACW,IAAI,EAAE,eAAgB;IAACG,KAAK,EAAE,QAAS;IAACC,IAAI,EAAEV,KAAM;IAACW,KAAK,EAAE;EAAM,CAAE,CAAC,EACrFP,OAAO,IAAI,IACd,CAAC;AAEX,CAAC","ignoreList":[]}
|
|
@@ -2,6 +2,10 @@ import { type ReactRoute } from "../../../presentation/router/index.js";
|
|
|
2
2
|
export declare const useRouter: () => {
|
|
3
3
|
goToRoute: <TParams extends import("../../../features/router/Route").RouteParamsDefinition | undefined>(route: import("../../..").Route<TParams>, ...args: import("../../../features/router/abstractions").RouteParamsArgs<TParams>) => void;
|
|
4
4
|
getLink: <TParams extends import("../../../features/router/Route").RouteParamsDefinition | undefined>(route: import("../../..").Route<TParams>, ...args: import("../../../features/router/abstractions").RouteParamsArgs<TParams>) => string;
|
|
5
|
-
|
|
5
|
+
addTransitionGuard: (config: import("../../../features/router").RouteTransitionGuardConfig) => import("../../../features/router").GuardDisposer;
|
|
6
|
+
isTransitionBlocked: () => boolean;
|
|
7
|
+
unblockTransition: () => void;
|
|
8
|
+
confirmTransition: () => void;
|
|
9
|
+
cancelTransition: () => void;
|
|
6
10
|
setRoutes: (routes: ReactRoute[]) => void;
|
|
7
11
|
};
|
|
@@ -11,7 +11,11 @@ export const useRouter = () => {
|
|
|
11
11
|
return {
|
|
12
12
|
goToRoute: presenter.goToRoute.bind(presenter),
|
|
13
13
|
getLink: presenter.getLink.bind(presenter),
|
|
14
|
-
|
|
14
|
+
addTransitionGuard: presenter.addTransitionGuard.bind(presenter),
|
|
15
|
+
isTransitionBlocked: presenter.isTransitionBlocked.bind(presenter),
|
|
16
|
+
unblockTransition: presenter.unblockTransition.bind(presenter),
|
|
17
|
+
confirmTransition: presenter.confirmTransition.bind(presenter),
|
|
18
|
+
cancelTransition: presenter.cancelTransition.bind(presenter),
|
|
15
19
|
setRoutes: routes => {
|
|
16
20
|
const cleanRoutes = [];
|
|
17
21
|
for (const route of routes) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["RouteElementRegistry","RouterFeature","useFeature","useContainer","useRouter","presenter","container","registry","resolve","goToRoute","bind","getLink","
|
|
1
|
+
{"version":3,"names":["RouteElementRegistry","RouterFeature","useFeature","useContainer","useRouter","presenter","container","registry","resolve","goToRoute","bind","getLink","addTransitionGuard","isTransitionBlocked","unblockTransition","confirmTransition","cancelTransition","setRoutes","routes","cleanRoutes","route","push","register","name","element","bootstrap"],"sources":["useRouter.ts"],"sourcesContent":["import { type ReactRoute, RouteElementRegistry } from \"~/presentation/router/index.js\";\nimport { RouterFeature } from \"~/features/router/feature.js\";\nimport { useFeature } from \"~/shared/di/useFeature.js\";\nimport { useContainer } from \"~/shared/di/DiContainerProvider.js\";\n\nexport const useRouter = () => {\n const { presenter } = useFeature(RouterFeature);\n const container = useContainer();\n const registry = container.resolve(RouteElementRegistry);\n\n return {\n goToRoute: presenter.goToRoute.bind(presenter),\n getLink: presenter.getLink.bind(presenter),\n addTransitionGuard: presenter.addTransitionGuard.bind(presenter),\n isTransitionBlocked: presenter.isTransitionBlocked.bind(presenter),\n unblockTransition: presenter.unblockTransition.bind(presenter),\n confirmTransition: presenter.confirmTransition.bind(presenter),\n cancelTransition: presenter.cancelTransition.bind(presenter),\n setRoutes: (routes: ReactRoute[]) => {\n const cleanRoutes = [];\n\n for (const route of routes) {\n cleanRoutes.push(route.route);\n registry.register(route.route.name, route.element);\n }\n\n presenter.bootstrap(cleanRoutes);\n }\n };\n};\n"],"mappings":"AAAA,SAA0BA,oBAAoB;AAC9C,SAASC,aAAa;AACtB,SAASC,UAAU;AACnB,SAASC,YAAY;AAErB,OAAO,MAAMC,SAAS,GAAGA,CAAA,KAAM;EAC3B,MAAM;IAAEC;EAAU,CAAC,GAAGH,UAAU,CAACD,aAAa,CAAC;EAC/C,MAAMK,SAAS,GAAGH,YAAY,CAAC,CAAC;EAChC,MAAMI,QAAQ,GAAGD,SAAS,CAACE,OAAO,CAACR,oBAAoB,CAAC;EAExD,OAAO;IACHS,SAAS,EAAEJ,SAAS,CAACI,SAAS,CAACC,IAAI,CAACL,SAAS,CAAC;IAC9CM,OAAO,EAAEN,SAAS,CAACM,OAAO,CAACD,IAAI,CAACL,SAAS,CAAC;IAC1CO,kBAAkB,EAAEP,SAAS,CAACO,kBAAkB,CAACF,IAAI,CAACL,SAAS,CAAC;IAChEQ,mBAAmB,EAAER,SAAS,CAACQ,mBAAmB,CAACH,IAAI,CAACL,SAAS,CAAC;IAClES,iBAAiB,EAAET,SAAS,CAACS,iBAAiB,CAACJ,IAAI,CAACL,SAAS,CAAC;IAC9DU,iBAAiB,EAAEV,SAAS,CAACU,iBAAiB,CAACL,IAAI,CAACL,SAAS,CAAC;IAC9DW,gBAAgB,EAAEX,SAAS,CAACW,gBAAgB,CAACN,IAAI,CAACL,SAAS,CAAC;IAC5DY,SAAS,EAAGC,MAAoB,IAAK;MACjC,MAAMC,WAAW,GAAG,EAAE;MAEtB,KAAK,MAAMC,KAAK,IAAIF,MAAM,EAAE;QACxBC,WAAW,CAACE,IAAI,CAACD,KAAK,CAACA,KAAK,CAAC;QAC7Bb,QAAQ,CAACe,QAAQ,CAACF,KAAK,CAACA,KAAK,CAACG,IAAI,EAAEH,KAAK,CAACI,OAAO,CAAC;MACtD;MAEAnB,SAAS,CAACoB,SAAS,CAACN,WAAW,CAAC;IACpC;EACJ,CAAC;AACL,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { Route } from \"~/features/router/Route.js\";\n\nexport type ReactRoute = {\n route: Route<any>;\n element: JSX.Element;\n};\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { Route } from \"~/features/router/Route.js\";\n\nexport type ReactRoute = {\n route: Route<any>;\n element: React.JSX.Element;\n};\n"],"mappings":"","ignoreList":[]}
|
package/renderApp.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Root } from "react-dom/client";
|
|
2
|
-
export declare const renderApp: (app: JSX.Element) => Root;
|
|
2
|
+
export declare const renderApp: (app: React.JSX.Element) => Root;
|
package/renderApp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ReactDOMClient","renderApp","app","container","document","getElementById","root","createRoot","render"],"sources":["renderApp.tsx"],"sourcesContent":["import type { Root } from \"react-dom/client\";\nimport ReactDOMClient from \"react-dom/client\";\n\nexport const renderApp = (app: JSX.Element): Root => {\n const container = document.getElementById(\"root\")!;\n\n const root = ReactDOMClient.createRoot(container);\n root.render(app);\n return root;\n};\n"],"mappings":"AACA,OAAOA,cAAc,MAAM,kBAAkB;AAE7C,OAAO,MAAMC,SAAS,GAAIC,
|
|
1
|
+
{"version":3,"names":["ReactDOMClient","renderApp","app","container","document","getElementById","root","createRoot","render"],"sources":["renderApp.tsx"],"sourcesContent":["import type { Root } from \"react-dom/client\";\nimport ReactDOMClient from \"react-dom/client\";\n\nexport const renderApp = (app: React.JSX.Element): Root => {\n const container = document.getElementById(\"root\")!;\n\n const root = ReactDOMClient.createRoot(container);\n root.render(app);\n return root;\n};\n"],"mappings":"AACA,OAAOA,cAAc,MAAM,kBAAkB;AAE7C,OAAO,MAAMC,SAAS,GAAIC,GAAsB,IAAW;EACvD,MAAMC,SAAS,GAAGC,QAAQ,CAACC,cAAc,CAAC,MAAM,CAAE;EAElD,MAAMC,IAAI,GAAGN,cAAc,CAACO,UAAU,CAACJ,SAAS,CAAC;EACjDG,IAAI,CAACE,MAAM,CAACN,GAAG,CAAC;EAChB,OAAOI,IAAI;AACf,CAAC","ignoreList":[]}
|