@lomray/vite-ssr-boost 6.0.0 → 6.1.0-beta.1
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/components/render-client.d.ts +6 -2
- package/components/render-client.js +1 -1
- package/components/render-client.js.map +1 -1
- package/helpers/import-route.d.ts +2 -1
- package/helpers/import-route.js +1 -1
- package/helpers/import-route.js.map +1 -1
- package/interfaces/route-object.d.ts +3 -2
- package/package.json +1 -1
- package/services/parse-routes.js +1 -1
- package/services/parse-routes.js.map +1 -1
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
2
|
import { FCAny } from "../interfaces/fc.js";
|
|
3
3
|
/**
|
|
4
4
|
* HOC: Render component only on client side
|
|
5
5
|
*/
|
|
6
|
-
declare const renderClient: <T extends Record<string, any>>(Component: FCAny<T> | null | undefined
|
|
6
|
+
declare const renderClient: <T extends Record<string, any>>(Component: FCAny<T> | null | undefined, Fallback?: {
|
|
7
|
+
element: ReactNode;
|
|
8
|
+
} | {
|
|
9
|
+
Component: FC | null;
|
|
10
|
+
} | undefined) => FC<T>;
|
|
7
11
|
export { renderClient as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"hoist-non-react-statics";import t,{useState as n,useEffect as o}from"react";const r=(r,m)=>{const l=e=>{const[l,c]=n(!1);return o((()=>{c(!0)}),[]),l&&r?t.createElement(r,{...e}):m&&"element"in m?m.element:m&&"Component"in m&&m.Component?t.createElement(m.Component,null):null};return e(l,r),l};export{r as default};
|
|
2
2
|
//# sourceMappingURL=render-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-client.js","sources":["../../src/components/render-client.tsx"],"sourcesContent":["import hoistNonReactStatics from 'hoist-non-react-statics';\nimport type { FC } from 'react';\nimport React, { useEffect, useState } from 'react';\nimport type { FCAny } from '@interfaces/fc';\n\n/**\n * HOC: Render component only on client side\n */\nconst renderClient = <T extends Record<string, any>>(\n Component: FCAny<T> | null | undefined,\n): FC<T> => {\n const Element: FC<T> = (props) => {\n const [shouldRender, setShouldRender] = useState(false);\n\n useEffect(() => {\n setShouldRender(true);\n }, []);\n\n if (shouldRender && Component) {\n return <Component {...props} />;\n }\n\n return null;\n };\n\n hoistNonReactStatics(Element, Component);\n\n return Element;\n};\n\nexport default renderClient;\n"],"names":["renderClient","Component","Element","props","shouldRender","setShouldRender","useState","useEffect","React","createElement","hoistNonReactStatics"],"mappings":"0FAQA,MAAMA,
|
|
1
|
+
{"version":3,"file":"render-client.js","sources":["../../src/components/render-client.tsx"],"sourcesContent":["import hoistNonReactStatics from 'hoist-non-react-statics';\nimport type { FC, ReactNode } from 'react';\nimport React, { useEffect, useState } from 'react';\nimport type { FCAny } from '@interfaces/fc';\n\n/**\n * HOC: Render component only on client side\n */\nconst renderClient = <T extends Record<string, any>>(\n Component: FCAny<T> | null | undefined,\n Fallback?: { element: ReactNode } | { Component: FC | null },\n): FC<T> => {\n const Element: FC<T> = (props) => {\n const [shouldRender, setShouldRender] = useState(false);\n\n useEffect(() => {\n setShouldRender(true);\n }, []);\n\n if (shouldRender && Component) {\n return <Component {...props} />;\n }\n\n if (Fallback && 'element' in Fallback) {\n return Fallback.element;\n }\n\n if (Fallback && 'Component' in Fallback && Fallback.Component) {\n return <Fallback.Component />;\n }\n\n return null;\n };\n\n hoistNonReactStatics(Element, Component);\n\n return Element;\n};\n\nexport default renderClient;\n"],"names":["renderClient","Component","Fallback","Element","props","shouldRender","setShouldRender","useState","useEffect","React","createElement","element","hoistNonReactStatics"],"mappings":"0FAQA,MAAMA,EAAe,CACnBC,EACAC,KAEA,MAAMC,EAAkBC,IACtB,MAAOC,EAAcC,GAAmBC,GAAS,GAMjD,OAJAC,GAAU,KACRF,GAAgB,EAAK,GACpB,IAECD,GAAgBJ,EACXQ,EAACC,cAAAT,EAAc,IAAAG,IAGpBF,GAAY,YAAaA,EACpBA,EAASS,QAGdT,GAAY,cAAeA,GAAYA,EAASD,UAC3CQ,EAACC,cAAAR,EAASD,gBAGZ,IAAI,EAKb,OAFAW,EAAqBT,EAASF,GAEvBE,CAAO"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IndexRouteObject, NonIndexRouteObject } from 'react-router';
|
|
2
2
|
import { FCCRoute, FCRoute } from "../interfaces/fc-route.js";
|
|
3
|
+
import { TOnlyClientProp } from "../interfaces/route-object.js";
|
|
3
4
|
type IDynamicRoute = () => Promise<{
|
|
4
5
|
default: FCRoute | FCCRoute<any>;
|
|
5
6
|
}>;
|
|
@@ -10,5 +11,5 @@ type IAsyncRoute = {
|
|
|
10
11
|
/**
|
|
11
12
|
* Import dynamic route
|
|
12
13
|
*/
|
|
13
|
-
declare const importRoute: (route: IDynamicRoute,
|
|
14
|
+
declare const importRoute: (route: IDynamicRoute, onlyClient?: TOnlyClientProp) => (() => Promise<IAsyncRoute>);
|
|
14
15
|
export { importRoute as default, IDynamicRoute, ImmutableRouteKey, IAsyncRoute };
|
package/helpers/import-route.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import n from"../components/render-client.js";import
|
|
1
|
+
import{isValidElement as o}from"react";import n from"../components/render-client.js";import t from"../components/with-suspense.js";import{IS_SERVER as e}from"../constants/common.js";import{keys as m}from"../interfaces/fc-route.js";const p=(p,r)=>async()=>{const s=(n=>o(n)?{element:n}:"function"!=typeof n&&"object"!=typeof n||null===n?{Component:null}:{Component:n})(r);if(r&&e)return s;const c=await p();if("Component"in c){const o=r?n(c.Component,s):c.Component;return{...c,Component:o}}const f=c.default,i={Component:f};return m.forEach((o=>{f[o]&&(i[o]=f[o])})),f.Suspense&&(i.Component=t(f,f.Suspense)),r&&(i.Component=n(i.Component,s)),i};export{p as default};
|
|
2
2
|
//# sourceMappingURL=import-route.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-route.js","sources":["../../src/helpers/import-route.ts"],"sourcesContent":["import type { IndexRouteObject, NonIndexRouteObject } from 'react-router';\nimport renderClient from '@components/render-client';\nimport withSuspense from '@components/with-suspense';\nimport { IS_SERVER } from '@constants/common';\nimport type { FCCRoute, FCRoute } from '@interfaces/fc-route';\nimport { keys } from '@interfaces/fc-route';\n\nexport type IDynamicRoute = () => Promise<{ default: FCRoute | FCCRoute<any> }>;\n\nexport type ImmutableRouteKey = 'lazy' | 'caseSensitive' | 'path' | 'id' | 'index' | 'children';\n\nexport type IAsyncRoute = { pathId?: string } & (\n | Omit<IndexRouteObject, ImmutableRouteKey>\n | Omit<NonIndexRouteObject, ImmutableRouteKey>\n);\n\n/**\n * Import dynamic route\n */\nconst importRoute = (route: IDynamicRoute
|
|
1
|
+
{"version":3,"file":"import-route.js","sources":["../../src/helpers/import-route.ts"],"sourcesContent":["import type { FC, ReactNode } from 'react';\nimport { isValidElement } from 'react';\nimport type { IndexRouteObject, NonIndexRouteObject } from 'react-router';\nimport renderClient from '@components/render-client';\nimport withSuspense from '@components/with-suspense';\nimport { IS_SERVER } from '@constants/common';\nimport type { FCCRoute, FCRoute } from '@interfaces/fc-route';\nimport { keys } from '@interfaces/fc-route';\nimport type { TOnlyClientProp } from '@interfaces/route-object';\n\nexport type IDynamicRoute = () => Promise<{ default: FCRoute | FCCRoute<any> }>;\n\nexport type ImmutableRouteKey = 'lazy' | 'caseSensitive' | 'path' | 'id' | 'index' | 'children';\n\nexport type IAsyncRoute = { pathId?: string } & (\n | Omit<IndexRouteObject, ImmutableRouteKey>\n | Omit<NonIndexRouteObject, ImmutableRouteKey>\n);\n\n/**\n * Return right fallback syntax\n */\nconst getFallback = (\n Fallback?: TOnlyClientProp,\n): { element: ReactNode } | { Component: FC | null } => {\n if (isValidElement(Fallback)) {\n return { element: Fallback };\n }\n\n if ((typeof Fallback === 'function' || typeof Fallback === 'object') && Fallback !== null) {\n return { Component: Fallback as FC };\n }\n\n return { Component: null };\n};\n\n/**\n * Import dynamic route\n */\nconst importRoute = (\n route: IDynamicRoute,\n onlyClient?: TOnlyClientProp,\n): (() => Promise<IAsyncRoute>) => {\n return async (): Promise<IAsyncRoute> => {\n const Fallback = getFallback(onlyClient);\n\n if (onlyClient && IS_SERVER) {\n return Fallback;\n }\n\n const resolved = await route();\n\n // fallback to react router export style\n if ('Component' in resolved) {\n const Component = onlyClient\n ? renderClient(resolved.Component as FCRoute | FCCRoute<any>, Fallback)\n : resolved.Component;\n\n return { ...resolved, Component } as IAsyncRoute;\n }\n\n const Component = resolved.default;\n const result: IAsyncRoute = { Component };\n\n keys.forEach((key) => {\n if (Component[key]) {\n // @ts-ignore\n result[key] = Component[key] as NonNullable<IAsyncRoute[typeof key]>;\n }\n });\n\n if (Component.Suspense) {\n result.Component = withSuspense(Component, Component.Suspense);\n }\n\n if (onlyClient) {\n result.Component = renderClient(result.Component as FCRoute | FCCRoute<any>, Fallback);\n }\n\n return result;\n };\n};\n\nexport default importRoute;\n"],"names":["importRoute","route","onlyClient","async","Fallback","isValidElement","element","Component","getFallback","IS_SERVER","resolved","renderClient","default","result","keys","forEach","key","Suspense","withSuspense"],"mappings":"uOAsBA,MAiBMA,EAAc,CAClBC,EACAC,IAEOC,UACL,MAAMC,EAtBU,CAClBA,GAEIC,EAAeD,GACV,CAAEE,QAASF,GAGK,mBAAbA,GAA+C,iBAAbA,GAAuC,OAAbA,EAIjE,CAAEG,UAAW,MAHX,CAAEA,UAAWH,GAcHI,CAAYN,GAE7B,GAAIA,GAAcO,EAChB,OAAOL,EAGT,MAAMM,QAAiBT,IAGvB,GAAI,cAAeS,EAAU,CAC3B,MAAMH,EAAYL,EACdS,EAAaD,EAASH,UAAsCH,GAC5DM,EAASH,UAEb,MAAO,IAAKG,EAAUH,aAGxB,MAAMA,EAAYG,EAASE,QACrBC,EAAsB,CAAEN,aAiB9B,OAfAO,EAAKC,SAASC,IACRT,EAAUS,KAEZH,EAAOG,GAAOT,EAAUS,OAIxBT,EAAUU,WACZJ,EAAON,UAAYW,EAAaX,EAAWA,EAAUU,WAGnDf,IACFW,EAAON,UAAYI,EAAaE,EAAON,UAAsCH,IAGxES,CAAM"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { RouteObject } from 'react-router';
|
|
2
2
|
import { IDynamicRoute } from "../helpers/import-route.js";
|
|
3
|
+
type TOnlyClientProp = RouteObject['Component'] | RouteObject['element'];
|
|
3
4
|
type TRouteObjectNR = Omit<RouteObject, 'lazy' | 'children'> & {
|
|
4
5
|
lazy?: IDynamicRoute | RouteObject['lazy'];
|
|
5
|
-
|
|
6
|
+
onlyClient?: TOnlyClientProp;
|
|
6
7
|
children?: TRouteObject[];
|
|
7
8
|
};
|
|
8
9
|
type TRouteObject = RouteObject | TRouteObjectNR;
|
|
9
|
-
export { TRouteObjectNR, TRouteObject };
|
|
10
|
+
export { TOnlyClientProp, TRouteObjectNR, TRouteObject };
|
package/package.json
CHANGED
package/services/parse-routes.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"fs";import{resolve as t}from"node:path";import r from"path";import n from"@babel/generator";import*as a from"@babel/parser";import
|
|
1
|
+
import e from"fs";import{resolve as t}from"node:path";import r from"path";import n from"@babel/generator";import*as a from"@babel/parser";import o from"@babel/traverse";import{isObjectProperty as i,isIdentifier as l,isBooleanLiteral as s,isJSXElement as p,isFunction as u,isArrayExpression as c,objectProperty as m,identifier as f,stringLiteral as d,isJSXIdentifier as h,isObjectExpression as y}from"@babel/types";import v from"../constants/plugin-name.js";import g from"./path-normalize.js";const E=n.default??n,x=o.default??o;class I{pathNormalize;config;constructor(e,t){this.config=e,this.pathNormalize=new g(e,t)}parse(){const{clientFile:e,root:r}=this.config.getParams(),n=t(r,e),a=this.findRoutesEntrypoint(n);if(!a?.routesPath)throw new Error(`Unable to find routes file import in ${e}`);const{routesPath:o,exportName:i}=a,l=this.resolveFilename(o,n);return this.recursiveBuildRoutesTree(l,i)}parseFile(t){try{const r=e.readFileSync(t,"utf-8");return a.parse(r,{sourceType:"module",plugins:["typescript","jsx"]})}catch(e){return null}}getImportPath(e,t){let r=null,n=null;return x(e,{ImportDeclaration(e){const a=e.node;a.specifiers.forEach((e=>{e.local.name===t&&(n="ImportDefaultSpecifier"===e.type?null:t,r=a.source.value)}))}}),{routesPath:r,exportName:n}}findRoutesDefinition(e,t){let r=t;if(x(e,{ExportNamedDeclaration({node:e}){!e.declaration&&e.specifiers.length>0&&e.specifiers.forEach((e=>{const n=e.exported.name;null===t&&"ExportSpecifier"===e.type?"default"===e.local.name&&(r=n):n===t&&(r=e.local.name)}))},ExportDefaultDeclaration({node:e}){null===t&&("Identifier"===e.declaration.type?r=e.declaration.name:"VariableDeclaration"===e.declaration.type&&(r=e.declaration.declarations[0].id.name))}}),r){let t=null;return x(e,{VariableDeclaration({node:e}){e.declarations.forEach((n=>{n.id.name===r&&(t=e)}))}}),t}return null}findRoutesEntrypoint(e){const t=this.parseFile(e);let r=null;return t?(x(t,{CallExpression({node:e}){"entryClient"===e.callee.name&&e.arguments.length>=2&&"Identifier"===e.arguments[1].type&&(r=e.arguments[1].name)}}),this.getImportPath(t,r)):r}resolveFilename(e,t){let n=e;(e.startsWith("./")||e.startsWith("../"))&&t&&(n=r.resolve(r.dirname(t),e));const a=this.pathNormalize.getAppPath(n,!0);return this.pathNormalize.findAppFile(a)}parseRoutesArray(e,t,r){const n=[];return e.forEach(((e,a)=>{if("ObjectExpression"===e.type){const o={index:a,import:"",children:[]};e.properties.forEach((e=>{const n=e;if("children"===n.key.name&&"ArrayExpression"===n.value.type&&(o.children=this.parseRoutesArray(n.value.elements,t,r)),"lazy"===n.key.name&&"ArrowFunctionExpression"===n.value.type){const e=n.value.body;if("CallExpression"===e.type&&"Import"===e.callee.type){const[t]=e.arguments;"StringLiteral"===t.type&&(o.import=t.value)}}if("Component"===n.key.name&&"Identifier"===n.value.type){const e=n.value.name,{path:r}=t[e]??{};r&&(o.import=r)}if("element"===n.key.name&&"JSXElement"===n.value.type){const e=n.value?.openingElement?.name?.name,{path:r}=t[e]??{};r&&(o.import=r)}if("children"===n.key.name&&"Identifier"===n.value.type){const e=n.value.name,{path:a,isDefault:i}=t[e]??{};if(a){const t=this.resolveFilename(a,r);t&&(o.children=this.recursiveBuildRoutesTree(t,i?null:e))}}})),(o.import||o.children.length>0)&&n.push(o)}})),n}static parseImportsMap(e){const t={};return x(e,{ImportDeclaration(e){const r=e.node;r.specifiers.forEach((e=>{t[e.local.name]={path:r.source.value,isDefault:"ImportDefaultSpecifier"===e.type}}))}}),t}recursiveBuildRoutesTree(e,t=null){if(!e)return[];const r=this.parseFile(e);if(!r)return[];const n=this.findRoutesDefinition(r,t),a=[];if(!n)return a;const o=I.parseImportsMap(r),i=n.declarations[0].init?.elements;return a.push(...this.parseRoutesArray(i,o,e)),a}static processRouteFileCode(e,t,r,n){e.node.properties.forEach((a=>{if(i(a)&&l(a.key)){if("lazy"===a.key.name&&"ArrowFunctionExpression"===a.value.type){const t=a.value.body,o=e.node.properties.find((e=>i(e)&&l(e.key)&&"onlyClient"===e.key.name));if(a.value={type:"CallExpression",callee:{type:"Identifier",name:"n"},arguments:i(o)&&(s(o.value)||p(o.value)||u(o.value)||l(o.value))?[a.value,o.value]:[a.value]},o&&(e.node.properties=e.node.properties.filter((e=>e!==o))),n(),"CallExpression"===t.type&&"Import"===t.callee.type){const[n]=t.arguments,o=e.findParent?.((e=>c(e.node)));if(o&&"StringLiteral"===n.type&&n.value&&r){const t=m(f("pathId"),d(n.value));e.node.properties.splice(e.node.properties.indexOf(a)+1,0,t)}}}if("element"===a.key.name||"Component"===a.key.name){let n="";p(a.value)&&h(a.value.openingElement.name)?n=a.value.openingElement.name.name:l(a.value)&&(n=a.value.name);const o=e.findParent?.((e=>c(e.node))),i=t[n]?.path;if(o&&i&&r){const t=m(f("pathId"),d(i));e.node.properties.splice(e.node.properties.indexOf(a)+1,0,t)}}"children"===a.key.name&&c(a.value)&&a.value.elements.forEach((e=>{y(e)&&I.processRouteFileCode({node:e},t,r,n)}))}}))}static handleRoutes(e,t){if(!e)return e;const r=a.parse(e,{sourceType:"module",plugins:["typescript","jsx"]});if(!r)return e;const n=I.parseImportsMap(r);let o=!1;return x(r,{ObjectExpression(e){I.processRouteFileCode(e,n,t,(()=>{o=!0}))}}),o&&r.program.body.unshift({type:"ImportDeclaration",specifiers:[{type:"ImportDefaultSpecifier",local:{type:"Identifier",name:"n"}}],source:{type:"StringLiteral",value:`${v}/helpers/import-route`}}),E(r,{retainLines:!0}).code}}export{I as default};
|
|
2
2
|
//# sourceMappingURL=parse-routes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-routes.js","sources":["../../src/services/parse-routes.ts"],"sourcesContent":["import fs from 'fs';\nimport { resolve } from 'node:path';\nimport path from 'path';\nimport babelGenerate from '@babel/generator';\nimport type * as GenerateTypes from '@babel/generator';\nimport * as parser from '@babel/parser';\nimport type { ParseResult } from '@babel/parser';\nimport babelTraverse from '@babel/traverse';\nimport type * as TraverseTypes from '@babel/traverse';\nimport type {\n CallExpression,\n File as BabelFile,\n VariableDeclaration,\n ObjectExpression,\n} from '@babel/types';\nimport {\n isObjectProperty,\n isIdentifier,\n identifier,\n isBooleanLiteral,\n stringLiteral,\n booleanLiteral,\n objectProperty,\n isArrayExpression,\n isJSXElement,\n isJSXIdentifier,\n isObjectExpression,\n} from '@babel/types';\nimport type { Alias } from 'vite';\nimport PLUGIN_NAME from '@constants/plugin-name';\nimport PathNormalize from '@services/path-normalize';\nimport type ServerConfig from '@services/server-config';\n//\n// @ts-expect-error known import problem\nconst generate = (babelGenerate.default ?? babelGenerate) as (typeof GenerateTypes)['default'];\n// @ts-expect-error known import problem\nconst traverse = (babelTraverse.default ?? babelTraverse) as (typeof TraverseTypes)['default'];\n\ninterface IPathImport {\n routesPath: string | null;\n exportName: string | null;\n}\n\ninterface IMapImports {\n [name: string]: {\n path: string;\n isDefault: boolean; // is default import?\n };\n}\n\nexport type TRoutesTree = {\n index: number;\n import: string;\n children: TRoutesTree[];\n};\n\n/**\n * Parse react router routes array\n */\nclass ParseRoutes {\n /**\n * Path normalize service\n */\n protected readonly pathNormalize: PathNormalize;\n\n /**\n * Server config\n */\n protected readonly config: ServerConfig;\n\n /**\n * @constructor\n */\n constructor(config: ServerConfig, viteAliases?: Alias[]) {\n this.config = config;\n this.pathNormalize = new PathNormalize(config, viteAliases);\n }\n\n /**\n * Parse routes\n */\n public parse(): TRoutesTree[] {\n const { clientFile, root } = this.config.getParams();\n\n const clientEntrypoint = resolve(root, clientFile);\n const routesEntrypoint = this.findRoutesEntrypoint(clientEntrypoint);\n\n if (!routesEntrypoint?.routesPath) {\n throw new Error(`Unable to find routes file import in ${clientFile}`);\n }\n\n const { routesPath, exportName } = routesEntrypoint;\n const routeFilepath = this.resolveFilename(routesPath, clientEntrypoint);\n\n return this.recursiveBuildRoutesTree(routeFilepath, exportName);\n }\n\n /**\n * Parse file and return ast\n */\n private parseFile(filename: string): ParseResult<BabelFile> | null {\n try {\n const code = fs.readFileSync(filename, 'utf-8');\n\n return parser.parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n });\n } catch (e) {\n return null;\n }\n }\n\n /**\n * Find route import filepath\n */\n private getImportPath(\n ast: ParseResult<BabelFile>,\n importName: string | null,\n ): IPathImport | null {\n let routesPath: string | null = null;\n let exportName: string | null = null;\n\n traverse(ast, {\n ImportDeclaration(nodePath) {\n const importNode = nodePath.node;\n\n importNode.specifiers.forEach((specifier) => {\n if (specifier.local.name === importName) {\n exportName = specifier.type === 'ImportDefaultSpecifier' ? null : importName;\n routesPath = importNode.source.value;\n }\n });\n },\n });\n\n return {\n routesPath,\n exportName,\n };\n }\n\n /**\n * Find routes array inside code\n */\n private findRoutesDefinition(\n ast: ParseResult<BabelFile>,\n exportName: string | null,\n ): null | VariableDeclaration {\n let exportNameResolved = exportName;\n\n // noinspection JSUnusedGlobalSymbols\n traverse(ast, {\n ExportNamedDeclaration({ node }) {\n if (!node.declaration && node.specifiers.length > 0) {\n node.specifiers.forEach((specifier) => {\n // @ts-expect-error missing in types\n const exportedName = specifier.exported.name as string;\n\n if (exportName === null && specifier.type === 'ExportSpecifier') {\n if (specifier.local.name === 'default') {\n exportNameResolved = exportedName;\n }\n } else if (exportedName === exportName) {\n // @ts-expect-error missing in types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n exportNameResolved = specifier.local.name as string;\n }\n });\n }\n },\n ExportDefaultDeclaration({ node }) {\n if (exportName === null) {\n if (node.declaration.type === 'Identifier') {\n exportNameResolved = node.declaration.name;\n // @ts-expect-error missing in types\n } else if (node.declaration.type === 'VariableDeclaration') {\n // @ts-expect-error missing in types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n exportNameResolved = node.declaration.declarations[0].id.name as string;\n }\n }\n },\n });\n\n if (exportNameResolved) {\n let variableNode: VariableDeclaration | null = null;\n\n traverse(ast, {\n VariableDeclaration({ node }) {\n node.declarations.forEach((declaration) => {\n // @ts-expect-error missing in types\n if (declaration.id.name === exportNameResolved) {\n variableNode = node;\n }\n });\n },\n });\n\n return variableNode;\n }\n\n return null;\n }\n\n /**\n * Entrypoint routes file\n */\n private findRoutesEntrypoint(clientEntrypoint: string): IPathImport | null {\n const ast = this.parseFile(clientEntrypoint);\n\n let routesVariable: string | null = null;\n\n if (!ast) {\n return routesVariable;\n }\n\n traverse(ast, {\n CallExpression({ node }) {\n if (\n // @ts-expect-error missing in types\n node.callee.name === 'entryClient' &&\n node.arguments.length >= 2 &&\n node.arguments[1].type === 'Identifier'\n ) {\n routesVariable = node.arguments[1].name;\n }\n },\n });\n\n return this.getImportPath(ast, routesVariable);\n }\n\n /**\n * Resolve route filename import\n */\n private resolveFilename(filename: string, relativeFile?: string): string | null {\n let resolvedFilename = filename;\n\n if ((filename.startsWith('./') || filename.startsWith('../')) && relativeFile) {\n resolvedFilename = path.resolve(path.dirname(relativeFile), filename);\n }\n\n const filepath = this.pathNormalize.getAppPath(resolvedFilename, true);\n\n return this.pathNormalize.findAppFile(filepath!);\n }\n\n /**\n * Parse ast array routes objects\n */\n private parseRoutesArray(\n elements: TraverseTypes.Node[],\n importsMap: IMapImports,\n relativeFile: string,\n ): TRoutesTree[] {\n const results: TRoutesTree[] = [];\n\n elements.forEach((node, index) => {\n if (node.type === 'ObjectExpression') {\n const routeInfo: TRoutesTree = { index, import: '', children: [] };\n\n node.properties.forEach((prop) => {\n const objectProp = prop as {\n key: { name: string };\n value: { type: string; elements: TraverseTypes.Node[] };\n };\n\n if (objectProp.key.name === 'children' && objectProp.value.type === 'ArrayExpression') {\n routeInfo.children = this.parseRoutesArray(\n objectProp.value.elements,\n importsMap,\n relativeFile,\n );\n }\n\n // async routes\n if (\n objectProp.key.name === 'lazy' &&\n objectProp.value.type === 'ArrowFunctionExpression'\n ) {\n // @ts-expect-error incorrect types\n const importCall = objectProp.value.body as CallExpression;\n\n if (importCall.type === 'CallExpression' && importCall.callee.type === 'Import') {\n const [importArg] = importCall.arguments;\n\n if (importArg.type === 'StringLiteral') {\n routeInfo.import = importArg.value;\n }\n }\n }\n\n // static routes: Component\n if (objectProp.key.name === 'Component' && objectProp.value.type === 'Identifier') {\n // @ts-expect-error incorrect types\n const importName = objectProp.value.name as string;\n const { path: importPath } = importsMap[importName] ?? {};\n\n if (importPath) {\n routeInfo.import = importPath;\n }\n }\n\n // static routes: element\n if (objectProp.key.name === 'element' && objectProp.value.type === 'JSXElement') {\n // @ts-expect-error incorrect types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const importName = objectProp.value?.openingElement?.name?.name as string;\n const { path: importPath } = importsMap[importName] ?? {};\n\n if (importPath) {\n routeInfo.import = importPath;\n }\n }\n\n if (objectProp.key.name === 'children' && objectProp.value.type === 'Identifier') {\n // @ts-expect-error incorrect types\n const importName = objectProp.value.name as string;\n const { path: importPath, isDefault } = importsMap[importName] ?? {};\n\n if (importPath) {\n const childrenFilePath = this.resolveFilename(importPath, relativeFile);\n\n if (childrenFilePath) {\n routeInfo.children = this.recursiveBuildRoutesTree(\n childrenFilePath,\n isDefault ? null : importName,\n );\n }\n }\n }\n });\n\n if (routeInfo.import || routeInfo.children.length > 0) {\n results.push(routeInfo);\n }\n }\n });\n\n return results;\n }\n\n /**\n * Parse imports map from ast\n */\n private static parseImportsMap(ast: ParseResult<BabelFile>): IMapImports {\n const importsMap: IMapImports = {};\n\n traverse(ast, {\n ImportDeclaration(nodePath) {\n const importNode = nodePath.node;\n\n importNode.specifiers.forEach((specifier) => {\n importsMap[specifier.local.name] = {\n path: importNode.source.value,\n isDefault: specifier.type === 'ImportDefaultSpecifier',\n };\n });\n },\n });\n\n return importsMap;\n }\n\n /**\n * Recursive build routes tree with dynamic imports\n */\n private recursiveBuildRoutesTree(\n filename: string | null,\n exportName: string | null = null,\n ): TRoutesTree[] {\n if (!filename) {\n return [];\n }\n\n const ast = this.parseFile(filename);\n\n if (!ast) {\n return [];\n }\n\n const routesNode = this.findRoutesDefinition(ast, exportName);\n const results: TRoutesTree[] = [];\n\n if (!routesNode) {\n return results;\n }\n\n const importsMap = ParseRoutes.parseImportsMap(ast);\n\n // @ts-expect-error missing types\n const elements = routesNode.declarations[0].init?.elements as TraverseTypes.Node[];\n\n results.push(...this.parseRoutesArray(elements, importsMap, filename));\n\n return results;\n }\n\n /**\n * Add pathId to static routes\n */\n private static processRouteFileCode(\n nodePath: TraverseTypes.NodePath<ObjectExpression>,\n importsMap: IMapImports,\n shouldAddPathId: boolean,\n addImportRouteWrapper: () => void,\n ): void {\n nodePath.node.properties.forEach((property) => {\n if (isObjectProperty(property) && isIdentifier(property.key)) {\n // async routes\n if (property.key.name === 'lazy' && property.value.type === 'ArrowFunctionExpression') {\n const importCall = property.value.body as CallExpression;\n const isOnlyClientPropIndex = nodePath.node.properties.findIndex(\n (p) =>\n isObjectProperty(p) &&\n isIdentifier(p.key) &&\n isBooleanLiteral(p.value) &&\n p.key.name === 'isOnlyClient' &&\n p.value.value,\n );\n\n /**\n * Wrap lazy import with:\n * @see importRoute\n */\n property.value = {\n type: 'CallExpression',\n callee: {\n type: 'Identifier',\n name: 'n',\n },\n arguments:\n isOnlyClientPropIndex !== -1\n ? [property.value, booleanLiteral(true)]\n : [property.value],\n };\n\n if (isOnlyClientPropIndex !== -1) {\n nodePath.node.properties.splice(isOnlyClientPropIndex, 1);\n }\n\n addImportRouteWrapper();\n\n if (importCall.type === 'CallExpression' && importCall.callee.type === 'Import') {\n const [importArg] = importCall.arguments;\n // current object has part of array (inside array)\n const parent = nodePath.findParent?.((p) => isArrayExpression(p.node));\n\n if (\n parent &&\n importArg.type === 'StringLiteral' &&\n importArg.value &&\n shouldAddPathId\n ) {\n const pathIdProperty = objectProperty(\n identifier('pathId'),\n stringLiteral(importArg.value),\n );\n\n // Insert the pathId property right after the element property\n nodePath.node.properties.splice(\n nodePath.node.properties.indexOf(property) + 1,\n 0,\n pathIdProperty,\n );\n }\n }\n }\n\n if (property.key.name === 'element' || property.key.name === 'Component') {\n let componentName = '';\n\n if (isJSXElement(property.value) && isJSXIdentifier(property.value.openingElement.name)) {\n componentName = property.value.openingElement.name.name;\n } else if (isIdentifier(property.value)) {\n componentName = property.value.name;\n }\n\n // current object has part of array (inside array)\n const parent = nodePath.findParent?.((p) => isArrayExpression(p.node));\n const importName = importsMap[componentName]?.path;\n\n if (parent && importName && shouldAddPathId) {\n const pathIdProperty = objectProperty(identifier('pathId'), stringLiteral(importName));\n\n // Insert the pathId property right after the element property\n nodePath.node.properties.splice(\n nodePath.node.properties.indexOf(property) + 1,\n 0,\n pathIdProperty,\n );\n }\n }\n\n if (property.key.name === 'children' && isArrayExpression(property.value)) {\n // Process each object in the children array recursively\n property.value.elements.forEach((element) => {\n if (isObjectExpression(element)) {\n ParseRoutes.processRouteFileCode(\n { node: element } as TraverseTypes.NodePath<ObjectExpression>,\n importsMap,\n shouldAddPathId,\n addImportRouteWrapper,\n );\n }\n });\n }\n }\n });\n }\n\n /**\n * Inject pathId to sync/async routes\n * Add async wrapper (see import-routes)\n */\n public static handleRoutes(code: string, shouldAddPathId: boolean): string {\n if (!code) {\n return code;\n }\n\n const ast = parser.parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n });\n\n if (!ast) {\n return code;\n }\n\n const importsMap = ParseRoutes.parseImportsMap(ast);\n let shouldAddRoutesImport = false;\n\n traverse(ast, {\n ObjectExpression(nodePath): void {\n ParseRoutes.processRouteFileCode(nodePath, importsMap, shouldAddPathId, () => {\n shouldAddRoutesImport = true;\n });\n },\n });\n\n if (shouldAddRoutesImport) {\n ast.program.body.unshift({\n type: 'ImportDeclaration',\n specifiers: [\n {\n type: 'ImportDefaultSpecifier',\n local: {\n type: 'Identifier',\n name: 'n',\n },\n },\n ],\n source: {\n type: 'StringLiteral',\n value: `${PLUGIN_NAME}/helpers/import-route`,\n },\n });\n }\n\n return generate(ast, {\n retainLines: true,\n }).code;\n }\n}\n\nexport default ParseRoutes;\n"],"names":["generate","babelGenerate","default","traverse","babelTraverse","ParseRoutes","pathNormalize","config","constructor","viteAliases","this","PathNormalize","parse","clientFile","root","getParams","clientEntrypoint","resolve","routesEntrypoint","findRoutesEntrypoint","routesPath","Error","exportName","routeFilepath","resolveFilename","recursiveBuildRoutesTree","parseFile","filename","code","fs","readFileSync","parser","sourceType","plugins","e","getImportPath","ast","importName","ImportDeclaration","nodePath","importNode","node","specifiers","forEach","specifier","local","name","type","source","value","findRoutesDefinition","exportNameResolved","ExportNamedDeclaration","declaration","length","exportedName","exported","ExportDefaultDeclaration","declarations","id","variableNode","VariableDeclaration","routesVariable","CallExpression","callee","arguments","relativeFile","resolvedFilename","startsWith","path","dirname","filepath","getAppPath","findAppFile","parseRoutesArray","elements","importsMap","results","index","routeInfo","import","children","properties","prop","objectProp","key","importCall","body","importArg","importPath","openingElement","isDefault","childrenFilePath","push","static","routesNode","parseImportsMap","init","shouldAddPathId","addImportRouteWrapper","property","isObjectProperty","isIdentifier","isOnlyClientPropIndex","findIndex","p","isBooleanLiteral","booleanLiteral","splice","parent","findParent","isArrayExpression","pathIdProperty","objectProperty","identifier","stringLiteral","indexOf","componentName","isJSXElement","isJSXIdentifier","element","isObjectExpression","processRouteFileCode","shouldAddRoutesImport","ObjectExpression","program","unshift","PLUGIN_NAME","retainLines"],"mappings":"gfAkCA,MAAMA,EAAYC,EAAcC,SAAWD,EAErCE,EAAYC,EAAcF,SAAWE,EAuB3C,MAAMC,EAIeC,cAKAC,OAKnBC,YAAYD,EAAsBE,GAChCC,KAAKH,OAASA,EACdG,KAAKJ,cAAgB,IAAIK,EAAcJ,EAAQE,GAM1CG,QACL,MAAMC,WAAEA,EAAUC,KAAEA,GAASJ,KAAKH,OAAOQ,YAEnCC,EAAmBC,EAAQH,EAAMD,GACjCK,EAAmBR,KAAKS,qBAAqBH,GAEnD,IAAKE,GAAkBE,WACrB,MAAM,IAAIC,MAAM,wCAAwCR,KAG1D,MAAMO,WAAEA,EAAUE,WAAEA,GAAeJ,EAC7BK,EAAgBb,KAAKc,gBAAgBJ,EAAYJ,GAEvD,OAAON,KAAKe,yBAAyBF,EAAeD,GAM9CI,UAAUC,GAChB,IACE,MAAMC,EAAOC,EAAGC,aAAaH,EAAU,SAEvC,OAAOI,EAAOnB,MAAMgB,EAAM,CACxBI,WAAY,SACZC,QAAS,CAAC,aAAc,SAE1B,MAAOC,GACP,OAAO,MAOHC,cACNC,EACAC,GAEA,IAAIjB,EAA4B,KAC5BE,EAA4B,KAehC,OAbAnB,EAASiC,EAAK,CACZE,kBAAkBC,GAChB,MAAMC,EAAaD,EAASE,KAE5BD,EAAWE,WAAWC,SAASC,IACzBA,EAAUC,MAAMC,OAAST,IAC3Bf,EAAgC,2BAAnBsB,EAAUG,KAAoC,KAAOV,EAClEjB,EAAaoB,EAAWQ,OAAOC,SAGpC,IAGI,CACL7B,aACAE,cAOI4B,qBACNd,EACAd,GAEA,IAAI6B,EAAqB7B,EAoCzB,GAjCAnB,EAASiC,EAAK,CACZgB,wBAAuBX,KAAEA,KAClBA,EAAKY,aAAeZ,EAAKC,WAAWY,OAAS,GAChDb,EAAKC,WAAWC,SAASC,IAEvB,MAAMW,EAAeX,EAAUY,SAASV,KAErB,OAAfxB,GAA0C,oBAAnBsB,EAAUG,KACN,YAAzBH,EAAUC,MAAMC,OAClBK,EAAqBI,GAEdA,IAAiBjC,IAG1B6B,EAAqBP,EAAUC,MAAMC,QAI5C,EACDW,0BAAyBhB,KAAEA,IACN,OAAfnB,IAC4B,eAA1BmB,EAAKY,YAAYN,KACnBI,EAAqBV,EAAKY,YAAYP,KAEH,wBAA1BL,EAAKY,YAAYN,OAG1BI,EAAqBV,EAAKY,YAAYK,aAAa,GAAGC,GAAGb,MAG9D,IAGCK,EAAoB,CACtB,IAAIS,EAA2C,KAa/C,OAXAzD,EAASiC,EAAK,CACZyB,qBAAoBpB,KAAEA,IACpBA,EAAKiB,aAAaf,SAASU,IAErBA,EAAYM,GAAGb,OAASK,IAC1BS,EAAenB,KAGpB,IAGImB,EAGT,OAAO,KAMDzC,qBAAqBH,GAC3B,MAAMoB,EAAM1B,KAAKgB,UAAUV,GAE3B,IAAI8C,EAAgC,KAEpC,OAAK1B,GAILjC,EAASiC,EAAK,CACZ2B,gBAAetB,KAAEA,IAGQ,gBAArBA,EAAKuB,OAAOlB,MACZL,EAAKwB,UAAUX,QAAU,GACE,eAA3Bb,EAAKwB,UAAU,GAAGlB,OAElBe,EAAiBrB,EAAKwB,UAAU,GAAGnB,KAEtC,IAGIpC,KAAKyB,cAAcC,EAAK0B,IAhBtBA,EAsBHtC,gBAAgBG,EAAkBuC,GACxC,IAAIC,EAAmBxC,GAElBA,EAASyC,WAAW,OAASzC,EAASyC,WAAW,SAAWF,IAC/DC,EAAmBE,EAAKpD,QAAQoD,EAAKC,QAAQJ,GAAevC,IAG9D,MAAM4C,EAAW7D,KAAKJ,cAAckE,WAAWL,GAAkB,GAEjE,OAAOzD,KAAKJ,cAAcmE,YAAYF,GAMhCG,iBACNC,EACAC,EACAV,GAEA,MAAMW,EAAyB,GAoF/B,OAlFAF,EAAShC,SAAQ,CAACF,EAAMqC,KACtB,GAAkB,qBAAdrC,EAAKM,KAA6B,CACpC,MAAMgC,EAAyB,CAAED,QAAOE,OAAQ,GAAIC,SAAU,IAE9DxC,EAAKyC,WAAWvC,SAASwC,IACvB,MAAMC,EAAaD,EAcnB,GAT4B,aAAxBC,EAAWC,IAAIvC,MAAiD,oBAA1BsC,EAAWnC,MAAMF,OACzDgC,EAAUE,SAAWvE,KAAKgE,iBACxBU,EAAWnC,MAAM0B,SACjBC,EACAV,IAMsB,SAAxBkB,EAAWC,IAAIvC,MACW,4BAA1BsC,EAAWnC,MAAMF,KACjB,CAEA,MAAMuC,EAAaF,EAAWnC,MAAMsC,KAEpC,GAAwB,mBAApBD,EAAWvC,MAAwD,WAA3BuC,EAAWtB,OAAOjB,KAAmB,CAC/E,MAAOyC,GAAaF,EAAWrB,UAER,kBAAnBuB,EAAUzC,OACZgC,EAAUC,OAASQ,EAAUvC,QAMnC,GAA4B,cAAxBmC,EAAWC,IAAIvC,MAAkD,eAA1BsC,EAAWnC,MAAMF,KAAuB,CAEjF,MAAMV,EAAa+C,EAAWnC,MAAMH,MAC5BuB,KAAMoB,GAAeb,EAAWvC,IAAe,CAAE,EAErDoD,IACFV,EAAUC,OAASS,GAKvB,GAA4B,YAAxBL,EAAWC,IAAIvC,MAAgD,eAA1BsC,EAAWnC,MAAMF,KAAuB,CAG/E,MAAMV,EAAa+C,EAAWnC,OAAOyC,gBAAgB5C,MAAMA,MACnDuB,KAAMoB,GAAeb,EAAWvC,IAAe,CAAE,EAErDoD,IACFV,EAAUC,OAASS,GAIvB,GAA4B,aAAxBL,EAAWC,IAAIvC,MAAiD,eAA1BsC,EAAWnC,MAAMF,KAAuB,CAEhF,MAAMV,EAAa+C,EAAWnC,MAAMH,MAC5BuB,KAAMoB,EAAUE,UAAEA,GAAcf,EAAWvC,IAAe,CAAE,EAEpE,GAAIoD,EAAY,CACd,MAAMG,EAAmBlF,KAAKc,gBAAgBiE,EAAYvB,GAEtD0B,IACFb,EAAUE,SAAWvE,KAAKe,yBACxBmE,EACAD,EAAY,KAAOtD,UAOzB0C,EAAUC,QAAUD,EAAUE,SAAS3B,OAAS,IAClDuB,EAAQgB,KAAKd,OAKZF,EAMDiB,uBAAuB1D,GAC7B,MAAMwC,EAA0B,CAAE,EAelC,OAbAzE,EAASiC,EAAK,CACZE,kBAAkBC,GAChB,MAAMC,EAAaD,EAASE,KAE5BD,EAAWE,WAAWC,SAASC,IAC7BgC,EAAWhC,EAAUC,MAAMC,MAAQ,CACjCuB,KAAM7B,EAAWQ,OAAOC,MACxB0C,UAA8B,2BAAnB/C,EAAUG,KACtB,GAEJ,IAGI6B,EAMDnD,yBACNE,EACAL,EAA4B,MAE5B,IAAKK,EACH,MAAO,GAGT,MAAMS,EAAM1B,KAAKgB,UAAUC,GAE3B,IAAKS,EACH,MAAO,GAGT,MAAM2D,EAAarF,KAAKwC,qBAAqBd,EAAKd,GAC5CuD,EAAyB,GAE/B,IAAKkB,EACH,OAAOlB,EAGT,MAAMD,EAAavE,EAAY2F,gBAAgB5D,GAGzCuC,EAAWoB,EAAWrC,aAAa,GAAGuC,MAAMtB,SAIlD,OAFAE,EAAQgB,QAAQnF,KAAKgE,iBAAiBC,EAAUC,EAAYjD,IAErDkD,EAMDiB,4BACNvD,EACAqC,EACAsB,EACAC,GAEA5D,EAASE,KAAKyC,WAAWvC,SAASyD,IAChC,GAAIC,EAAiBD,IAAaE,EAAaF,EAASf,KAAM,CAE5D,GAA0B,SAAtBe,EAASf,IAAIvC,MAA2C,4BAAxBsD,EAASnD,MAAMF,KAAoC,CACrF,MAAMuC,EAAac,EAASnD,MAAMsC,KAC5BgB,EAAwBhE,EAASE,KAAKyC,WAAWsB,WACpDC,GACCJ,EAAiBI,IACjBH,EAAaG,EAAEpB,MACfqB,EAAiBD,EAAExD,QACJ,iBAAfwD,EAAEpB,IAAIvC,MACN2D,EAAExD,MAAMA,QAyBZ,GAlBAmD,EAASnD,MAAQ,CACfF,KAAM,iBACNiB,OAAQ,CACNjB,KAAM,aACND,KAAM,KAERmB,WAC4B,IAA1BsC,EACI,CAACH,EAASnD,MAAO0D,GAAe,IAChC,CAACP,EAASnD,SAGY,IAA1BsD,GACFhE,EAASE,KAAKyC,WAAW0B,OAAOL,EAAuB,GAGzDJ,IAEwB,mBAApBb,EAAWvC,MAAwD,WAA3BuC,EAAWtB,OAAOjB,KAAmB,CAC/E,MAAOyC,GAAaF,EAAWrB,UAEzB4C,EAAStE,EAASuE,cAAcL,GAAMM,EAAkBN,EAAEhE,QAEhE,GACEoE,GACmB,kBAAnBrB,EAAUzC,MACVyC,EAAUvC,OACViD,EACA,CACA,MAAMc,EAAiBC,EACrBC,EAAW,UACXC,EAAc3B,EAAUvC,QAI1BV,EAASE,KAAKyC,WAAW0B,OACvBrE,EAASE,KAAKyC,WAAWkC,QAAQhB,GAAY,EAC7C,EACAY,KAMR,GAA0B,YAAtBZ,EAASf,IAAIvC,MAA4C,cAAtBsD,EAASf,IAAIvC,KAAsB,CACxE,IAAIuE,EAAgB,GAEhBC,EAAalB,EAASnD,QAAUsE,EAAgBnB,EAASnD,MAAMyC,eAAe5C,MAChFuE,EAAgBjB,EAASnD,MAAMyC,eAAe5C,KAAKA,KAC1CwD,EAAaF,EAASnD,SAC/BoE,EAAgBjB,EAASnD,MAAMH,MAIjC,MAAM+D,EAAStE,EAASuE,cAAcL,GAAMM,EAAkBN,EAAEhE,QAC1DJ,EAAauC,EAAWyC,IAAgBhD,KAE9C,GAAIwC,GAAUxE,GAAc6D,EAAiB,CAC3C,MAAMc,EAAiBC,EAAeC,EAAW,UAAWC,EAAc9E,IAG1EE,EAASE,KAAKyC,WAAW0B,OACvBrE,EAASE,KAAKyC,WAAWkC,QAAQhB,GAAY,EAC7C,EACAY,IAKoB,aAAtBZ,EAASf,IAAIvC,MAAuBiE,EAAkBX,EAASnD,QAEjEmD,EAASnD,MAAM0B,SAAShC,SAAS6E,IAC3BC,EAAmBD,IACrBnH,EAAYqH,qBACV,CAAEjF,KAAM+E,GACR5C,EACAsB,EACAC,UAaPL,oBAAoBlE,EAAcsE,GACvC,IAAKtE,EACH,OAAOA,EAGT,MAAMQ,EAAML,EAAOnB,MAAMgB,EAAM,CAC7BI,WAAY,SACZC,QAAS,CAAC,aAAc,SAG1B,IAAKG,EACH,OAAOR,EAGT,MAAMgD,EAAavE,EAAY2F,gBAAgB5D,GAC/C,IAAIuF,GAAwB,EA6B5B,OA3BAxH,EAASiC,EAAK,CACZwF,iBAAiBrF,GACflC,EAAYqH,qBAAqBnF,EAAUqC,EAAYsB,GAAiB,KACtEyB,GAAwB,CAAI,GAE/B,IAGCA,GACFvF,EAAIyF,QAAQtC,KAAKuC,QAAQ,CACvB/E,KAAM,oBACNL,WAAY,CACV,CACEK,KAAM,yBACNF,MAAO,CACLE,KAAM,aACND,KAAM,OAIZE,OAAQ,CACND,KAAM,gBACNE,MAAO,GAAG8E,4BAKT/H,EAASoC,EAAK,CACnB4F,aAAa,IACZpG"}
|
|
1
|
+
{"version":3,"file":"parse-routes.js","sources":["../../src/services/parse-routes.ts"],"sourcesContent":["import fs from 'fs';\nimport { resolve } from 'node:path';\nimport path from 'path';\nimport babelGenerate from '@babel/generator';\nimport type * as GenerateTypes from '@babel/generator';\nimport * as parser from '@babel/parser';\nimport type { ParseResult } from '@babel/parser';\nimport babelTraverse from '@babel/traverse';\nimport type * as TraverseTypes from '@babel/traverse';\nimport type {\n CallExpression,\n File as BabelFile,\n VariableDeclaration,\n ObjectExpression,\n} from '@babel/types';\nimport {\n isObjectProperty,\n isIdentifier,\n identifier,\n isBooleanLiteral,\n stringLiteral,\n isFunction,\n objectProperty,\n isArrayExpression,\n isJSXElement,\n isJSXIdentifier,\n isObjectExpression,\n} from '@babel/types';\nimport type { Alias } from 'vite';\nimport PLUGIN_NAME from '@constants/plugin-name';\nimport PathNormalize from '@services/path-normalize';\nimport type ServerConfig from '@services/server-config';\n//\n// @ts-expect-error known import problem\nconst generate = (babelGenerate.default ?? babelGenerate) as (typeof GenerateTypes)['default'];\n// @ts-expect-error known import problem\nconst traverse = (babelTraverse.default ?? babelTraverse) as (typeof TraverseTypes)['default'];\n\ninterface IPathImport {\n routesPath: string | null;\n exportName: string | null;\n}\n\ninterface IMapImports {\n [name: string]: {\n path: string;\n isDefault: boolean; // is default import?\n };\n}\n\nexport type TRoutesTree = {\n index: number;\n import: string;\n children: TRoutesTree[];\n};\n\n/**\n * Parse react router routes array\n */\nclass ParseRoutes {\n /**\n * Path normalize service\n */\n protected readonly pathNormalize: PathNormalize;\n\n /**\n * Server config\n */\n protected readonly config: ServerConfig;\n\n /**\n * @constructor\n */\n constructor(config: ServerConfig, viteAliases?: Alias[]) {\n this.config = config;\n this.pathNormalize = new PathNormalize(config, viteAliases);\n }\n\n /**\n * Parse routes\n */\n public parse(): TRoutesTree[] {\n const { clientFile, root } = this.config.getParams();\n\n const clientEntrypoint = resolve(root, clientFile);\n const routesEntrypoint = this.findRoutesEntrypoint(clientEntrypoint);\n\n if (!routesEntrypoint?.routesPath) {\n throw new Error(`Unable to find routes file import in ${clientFile}`);\n }\n\n const { routesPath, exportName } = routesEntrypoint;\n const routeFilepath = this.resolveFilename(routesPath, clientEntrypoint);\n\n return this.recursiveBuildRoutesTree(routeFilepath, exportName);\n }\n\n /**\n * Parse file and return ast\n */\n private parseFile(filename: string): ParseResult<BabelFile> | null {\n try {\n const code = fs.readFileSync(filename, 'utf-8');\n\n return parser.parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n });\n } catch (e) {\n return null;\n }\n }\n\n /**\n * Find route import filepath\n */\n private getImportPath(\n ast: ParseResult<BabelFile>,\n importName: string | null,\n ): IPathImport | null {\n let routesPath: string | null = null;\n let exportName: string | null = null;\n\n traverse(ast, {\n ImportDeclaration(nodePath) {\n const importNode = nodePath.node;\n\n importNode.specifiers.forEach((specifier) => {\n if (specifier.local.name === importName) {\n exportName = specifier.type === 'ImportDefaultSpecifier' ? null : importName;\n routesPath = importNode.source.value;\n }\n });\n },\n });\n\n return {\n routesPath,\n exportName,\n };\n }\n\n /**\n * Find routes array inside code\n */\n private findRoutesDefinition(\n ast: ParseResult<BabelFile>,\n exportName: string | null,\n ): null | VariableDeclaration {\n let exportNameResolved = exportName;\n\n // noinspection JSUnusedGlobalSymbols\n traverse(ast, {\n ExportNamedDeclaration({ node }) {\n if (!node.declaration && node.specifiers.length > 0) {\n node.specifiers.forEach((specifier) => {\n // @ts-expect-error missing in types\n const exportedName = specifier.exported.name as string;\n\n if (exportName === null && specifier.type === 'ExportSpecifier') {\n if (specifier.local.name === 'default') {\n exportNameResolved = exportedName;\n }\n } else if (exportedName === exportName) {\n // @ts-expect-error missing in types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n exportNameResolved = specifier.local.name as string;\n }\n });\n }\n },\n ExportDefaultDeclaration({ node }) {\n if (exportName === null) {\n if (node.declaration.type === 'Identifier') {\n exportNameResolved = node.declaration.name;\n // @ts-expect-error missing in types\n } else if (node.declaration.type === 'VariableDeclaration') {\n // @ts-expect-error missing in types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n exportNameResolved = node.declaration.declarations[0].id.name as string;\n }\n }\n },\n });\n\n if (exportNameResolved) {\n let variableNode: VariableDeclaration | null = null;\n\n traverse(ast, {\n VariableDeclaration({ node }) {\n node.declarations.forEach((declaration) => {\n // @ts-expect-error missing in types\n if (declaration.id.name === exportNameResolved) {\n variableNode = node;\n }\n });\n },\n });\n\n return variableNode;\n }\n\n return null;\n }\n\n /**\n * Entrypoint routes file\n */\n private findRoutesEntrypoint(clientEntrypoint: string): IPathImport | null {\n const ast = this.parseFile(clientEntrypoint);\n\n let routesVariable: string | null = null;\n\n if (!ast) {\n return routesVariable;\n }\n\n traverse(ast, {\n CallExpression({ node }) {\n if (\n // @ts-expect-error missing in types\n node.callee.name === 'entryClient' &&\n node.arguments.length >= 2 &&\n node.arguments[1].type === 'Identifier'\n ) {\n routesVariable = node.arguments[1].name;\n }\n },\n });\n\n return this.getImportPath(ast, routesVariable);\n }\n\n /**\n * Resolve route filename import\n */\n private resolveFilename(filename: string, relativeFile?: string): string | null {\n let resolvedFilename = filename;\n\n if ((filename.startsWith('./') || filename.startsWith('../')) && relativeFile) {\n resolvedFilename = path.resolve(path.dirname(relativeFile), filename);\n }\n\n const filepath = this.pathNormalize.getAppPath(resolvedFilename, true);\n\n return this.pathNormalize.findAppFile(filepath!);\n }\n\n /**\n * Parse ast array routes objects\n */\n private parseRoutesArray(\n elements: TraverseTypes.Node[],\n importsMap: IMapImports,\n relativeFile: string,\n ): TRoutesTree[] {\n const results: TRoutesTree[] = [];\n\n elements.forEach((node, index) => {\n if (node.type === 'ObjectExpression') {\n const routeInfo: TRoutesTree = { index, import: '', children: [] };\n\n node.properties.forEach((prop) => {\n const objectProp = prop as {\n key: { name: string };\n value: { type: string; elements: TraverseTypes.Node[] };\n };\n\n if (objectProp.key.name === 'children' && objectProp.value.type === 'ArrayExpression') {\n routeInfo.children = this.parseRoutesArray(\n objectProp.value.elements,\n importsMap,\n relativeFile,\n );\n }\n\n // async routes\n if (\n objectProp.key.name === 'lazy' &&\n objectProp.value.type === 'ArrowFunctionExpression'\n ) {\n // @ts-expect-error incorrect types\n const importCall = objectProp.value.body as CallExpression;\n\n if (importCall.type === 'CallExpression' && importCall.callee.type === 'Import') {\n const [importArg] = importCall.arguments;\n\n if (importArg.type === 'StringLiteral') {\n routeInfo.import = importArg.value;\n }\n }\n }\n\n // static routes: Component\n if (objectProp.key.name === 'Component' && objectProp.value.type === 'Identifier') {\n // @ts-expect-error incorrect types\n const importName = objectProp.value.name as string;\n const { path: importPath } = importsMap[importName] ?? {};\n\n if (importPath) {\n routeInfo.import = importPath;\n }\n }\n\n // static routes: element\n if (objectProp.key.name === 'element' && objectProp.value.type === 'JSXElement') {\n // @ts-expect-error incorrect types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const importName = objectProp.value?.openingElement?.name?.name as string;\n const { path: importPath } = importsMap[importName] ?? {};\n\n if (importPath) {\n routeInfo.import = importPath;\n }\n }\n\n if (objectProp.key.name === 'children' && objectProp.value.type === 'Identifier') {\n // @ts-expect-error incorrect types\n const importName = objectProp.value.name as string;\n const { path: importPath, isDefault } = importsMap[importName] ?? {};\n\n if (importPath) {\n const childrenFilePath = this.resolveFilename(importPath, relativeFile);\n\n if (childrenFilePath) {\n routeInfo.children = this.recursiveBuildRoutesTree(\n childrenFilePath,\n isDefault ? null : importName,\n );\n }\n }\n }\n });\n\n if (routeInfo.import || routeInfo.children.length > 0) {\n results.push(routeInfo);\n }\n }\n });\n\n return results;\n }\n\n /**\n * Parse imports map from ast\n */\n private static parseImportsMap(ast: ParseResult<BabelFile>): IMapImports {\n const importsMap: IMapImports = {};\n\n traverse(ast, {\n ImportDeclaration(nodePath) {\n const importNode = nodePath.node;\n\n importNode.specifiers.forEach((specifier) => {\n importsMap[specifier.local.name] = {\n path: importNode.source.value,\n isDefault: specifier.type === 'ImportDefaultSpecifier',\n };\n });\n },\n });\n\n return importsMap;\n }\n\n /**\n * Recursive build routes tree with dynamic imports\n */\n private recursiveBuildRoutesTree(\n filename: string | null,\n exportName: string | null = null,\n ): TRoutesTree[] {\n if (!filename) {\n return [];\n }\n\n const ast = this.parseFile(filename);\n\n if (!ast) {\n return [];\n }\n\n const routesNode = this.findRoutesDefinition(ast, exportName);\n const results: TRoutesTree[] = [];\n\n if (!routesNode) {\n return results;\n }\n\n const importsMap = ParseRoutes.parseImportsMap(ast);\n\n // @ts-expect-error missing types\n const elements = routesNode.declarations[0].init?.elements as TraverseTypes.Node[];\n\n results.push(...this.parseRoutesArray(elements, importsMap, filename));\n\n return results;\n }\n\n /**\n * Add pathId to static routes\n */\n private static processRouteFileCode(\n nodePath: TraverseTypes.NodePath<ObjectExpression>,\n importsMap: IMapImports,\n shouldAddPathId: boolean,\n addImportRouteWrapper: () => void,\n ): void {\n nodePath.node.properties.forEach((property) => {\n if (isObjectProperty(property) && isIdentifier(property.key)) {\n // async routes\n if (property.key.name === 'lazy' && property.value.type === 'ArrowFunctionExpression') {\n const importCall = property.value.body as CallExpression;\n const onlyClientProp = nodePath.node.properties.find(\n (p) => isObjectProperty(p) && isIdentifier(p.key) && p.key.name === 'onlyClient',\n );\n\n /**\n * Wrap lazy import with:\n * @see importRoute\n */\n property.value = {\n type: 'CallExpression',\n callee: {\n type: 'Identifier',\n name: 'n',\n },\n arguments:\n isObjectProperty(onlyClientProp) &&\n (isBooleanLiteral(onlyClientProp.value) ||\n isJSXElement(onlyClientProp.value) ||\n isFunction(onlyClientProp.value) ||\n isIdentifier(onlyClientProp.value))\n ? [property.value, onlyClientProp.value]\n : [property.value],\n };\n\n if (onlyClientProp) {\n nodePath.node.properties = nodePath.node.properties.filter((p) => p !== onlyClientProp);\n }\n\n addImportRouteWrapper();\n\n if (importCall.type === 'CallExpression' && importCall.callee.type === 'Import') {\n const [importArg] = importCall.arguments;\n // current object has part of array (inside array)\n const parent = nodePath.findParent?.((p) => isArrayExpression(p.node));\n\n if (\n parent &&\n importArg.type === 'StringLiteral' &&\n importArg.value &&\n shouldAddPathId\n ) {\n const pathIdProperty = objectProperty(\n identifier('pathId'),\n stringLiteral(importArg.value),\n );\n\n // Insert the pathId property right after the element property\n nodePath.node.properties.splice(\n nodePath.node.properties.indexOf(property) + 1,\n 0,\n pathIdProperty,\n );\n }\n }\n }\n\n if (property.key.name === 'element' || property.key.name === 'Component') {\n let componentName = '';\n\n if (isJSXElement(property.value) && isJSXIdentifier(property.value.openingElement.name)) {\n componentName = property.value.openingElement.name.name;\n } else if (isIdentifier(property.value)) {\n componentName = property.value.name;\n }\n\n // current object has part of array (inside array)\n const parent = nodePath.findParent?.((p) => isArrayExpression(p.node));\n const importName = importsMap[componentName]?.path;\n\n if (parent && importName && shouldAddPathId) {\n const pathIdProperty = objectProperty(identifier('pathId'), stringLiteral(importName));\n\n // Insert the pathId property right after the element property\n nodePath.node.properties.splice(\n nodePath.node.properties.indexOf(property) + 1,\n 0,\n pathIdProperty,\n );\n }\n }\n\n if (property.key.name === 'children' && isArrayExpression(property.value)) {\n // Process each object in the children array recursively\n property.value.elements.forEach((element) => {\n if (isObjectExpression(element)) {\n ParseRoutes.processRouteFileCode(\n { node: element } as TraverseTypes.NodePath<ObjectExpression>,\n importsMap,\n shouldAddPathId,\n addImportRouteWrapper,\n );\n }\n });\n }\n }\n });\n }\n\n /**\n * Inject pathId to sync/async routes\n * Add async wrapper (see import-routes)\n */\n public static handleRoutes(code: string, shouldAddPathId: boolean): string {\n if (!code) {\n return code;\n }\n\n const ast = parser.parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n });\n\n if (!ast) {\n return code;\n }\n\n const importsMap = ParseRoutes.parseImportsMap(ast);\n let shouldAddRoutesImport = false;\n\n traverse(ast, {\n ObjectExpression(nodePath): void {\n ParseRoutes.processRouteFileCode(nodePath, importsMap, shouldAddPathId, () => {\n shouldAddRoutesImport = true;\n });\n },\n });\n\n if (shouldAddRoutesImport) {\n ast.program.body.unshift({\n type: 'ImportDeclaration',\n specifiers: [\n {\n type: 'ImportDefaultSpecifier',\n local: {\n type: 'Identifier',\n name: 'n',\n },\n },\n ],\n source: {\n type: 'StringLiteral',\n value: `${PLUGIN_NAME}/helpers/import-route`,\n },\n });\n }\n\n return generate(ast, {\n retainLines: true,\n }).code;\n }\n}\n\nexport default ParseRoutes;\n"],"names":["generate","babelGenerate","default","traverse","babelTraverse","ParseRoutes","pathNormalize","config","constructor","viteAliases","this","PathNormalize","parse","clientFile","root","getParams","clientEntrypoint","resolve","routesEntrypoint","findRoutesEntrypoint","routesPath","Error","exportName","routeFilepath","resolveFilename","recursiveBuildRoutesTree","parseFile","filename","code","fs","readFileSync","parser","sourceType","plugins","e","getImportPath","ast","importName","ImportDeclaration","nodePath","importNode","node","specifiers","forEach","specifier","local","name","type","source","value","findRoutesDefinition","exportNameResolved","ExportNamedDeclaration","declaration","length","exportedName","exported","ExportDefaultDeclaration","declarations","id","variableNode","VariableDeclaration","routesVariable","CallExpression","callee","arguments","relativeFile","resolvedFilename","startsWith","path","dirname","filepath","getAppPath","findAppFile","parseRoutesArray","elements","importsMap","results","index","routeInfo","import","children","properties","prop","objectProp","key","importCall","body","importArg","importPath","openingElement","isDefault","childrenFilePath","push","static","routesNode","parseImportsMap","init","shouldAddPathId","addImportRouteWrapper","property","isObjectProperty","isIdentifier","onlyClientProp","find","p","isBooleanLiteral","isJSXElement","isFunction","filter","parent","findParent","isArrayExpression","pathIdProperty","objectProperty","identifier","stringLiteral","splice","indexOf","componentName","isJSXIdentifier","element","isObjectExpression","processRouteFileCode","shouldAddRoutesImport","ObjectExpression","program","unshift","PLUGIN_NAME","retainLines"],"mappings":"4eAkCA,MAAMA,EAAYC,EAAcC,SAAWD,EAErCE,EAAYC,EAAcF,SAAWE,EAuB3C,MAAMC,EAIeC,cAKAC,OAKnBC,YAAYD,EAAsBE,GAChCC,KAAKH,OAASA,EACdG,KAAKJ,cAAgB,IAAIK,EAAcJ,EAAQE,GAM1CG,QACL,MAAMC,WAAEA,EAAUC,KAAEA,GAASJ,KAAKH,OAAOQ,YAEnCC,EAAmBC,EAAQH,EAAMD,GACjCK,EAAmBR,KAAKS,qBAAqBH,GAEnD,IAAKE,GAAkBE,WACrB,MAAM,IAAIC,MAAM,wCAAwCR,KAG1D,MAAMO,WAAEA,EAAUE,WAAEA,GAAeJ,EAC7BK,EAAgBb,KAAKc,gBAAgBJ,EAAYJ,GAEvD,OAAON,KAAKe,yBAAyBF,EAAeD,GAM9CI,UAAUC,GAChB,IACE,MAAMC,EAAOC,EAAGC,aAAaH,EAAU,SAEvC,OAAOI,EAAOnB,MAAMgB,EAAM,CACxBI,WAAY,SACZC,QAAS,CAAC,aAAc,SAE1B,MAAOC,GACP,OAAO,MAOHC,cACNC,EACAC,GAEA,IAAIjB,EAA4B,KAC5BE,EAA4B,KAehC,OAbAnB,EAASiC,EAAK,CACZE,kBAAkBC,GAChB,MAAMC,EAAaD,EAASE,KAE5BD,EAAWE,WAAWC,SAASC,IACzBA,EAAUC,MAAMC,OAAST,IAC3Bf,EAAgC,2BAAnBsB,EAAUG,KAAoC,KAAOV,EAClEjB,EAAaoB,EAAWQ,OAAOC,SAGpC,IAGI,CACL7B,aACAE,cAOI4B,qBACNd,EACAd,GAEA,IAAI6B,EAAqB7B,EAoCzB,GAjCAnB,EAASiC,EAAK,CACZgB,wBAAuBX,KAAEA,KAClBA,EAAKY,aAAeZ,EAAKC,WAAWY,OAAS,GAChDb,EAAKC,WAAWC,SAASC,IAEvB,MAAMW,EAAeX,EAAUY,SAASV,KAErB,OAAfxB,GAA0C,oBAAnBsB,EAAUG,KACN,YAAzBH,EAAUC,MAAMC,OAClBK,EAAqBI,GAEdA,IAAiBjC,IAG1B6B,EAAqBP,EAAUC,MAAMC,QAI5C,EACDW,0BAAyBhB,KAAEA,IACN,OAAfnB,IAC4B,eAA1BmB,EAAKY,YAAYN,KACnBI,EAAqBV,EAAKY,YAAYP,KAEH,wBAA1BL,EAAKY,YAAYN,OAG1BI,EAAqBV,EAAKY,YAAYK,aAAa,GAAGC,GAAGb,MAG9D,IAGCK,EAAoB,CACtB,IAAIS,EAA2C,KAa/C,OAXAzD,EAASiC,EAAK,CACZyB,qBAAoBpB,KAAEA,IACpBA,EAAKiB,aAAaf,SAASU,IAErBA,EAAYM,GAAGb,OAASK,IAC1BS,EAAenB,KAGpB,IAGImB,EAGT,OAAO,KAMDzC,qBAAqBH,GAC3B,MAAMoB,EAAM1B,KAAKgB,UAAUV,GAE3B,IAAI8C,EAAgC,KAEpC,OAAK1B,GAILjC,EAASiC,EAAK,CACZ2B,gBAAetB,KAAEA,IAGQ,gBAArBA,EAAKuB,OAAOlB,MACZL,EAAKwB,UAAUX,QAAU,GACE,eAA3Bb,EAAKwB,UAAU,GAAGlB,OAElBe,EAAiBrB,EAAKwB,UAAU,GAAGnB,KAEtC,IAGIpC,KAAKyB,cAAcC,EAAK0B,IAhBtBA,EAsBHtC,gBAAgBG,EAAkBuC,GACxC,IAAIC,EAAmBxC,GAElBA,EAASyC,WAAW,OAASzC,EAASyC,WAAW,SAAWF,IAC/DC,EAAmBE,EAAKpD,QAAQoD,EAAKC,QAAQJ,GAAevC,IAG9D,MAAM4C,EAAW7D,KAAKJ,cAAckE,WAAWL,GAAkB,GAEjE,OAAOzD,KAAKJ,cAAcmE,YAAYF,GAMhCG,iBACNC,EACAC,EACAV,GAEA,MAAMW,EAAyB,GAoF/B,OAlFAF,EAAShC,SAAQ,CAACF,EAAMqC,KACtB,GAAkB,qBAAdrC,EAAKM,KAA6B,CACpC,MAAMgC,EAAyB,CAAED,QAAOE,OAAQ,GAAIC,SAAU,IAE9DxC,EAAKyC,WAAWvC,SAASwC,IACvB,MAAMC,EAAaD,EAcnB,GAT4B,aAAxBC,EAAWC,IAAIvC,MAAiD,oBAA1BsC,EAAWnC,MAAMF,OACzDgC,EAAUE,SAAWvE,KAAKgE,iBACxBU,EAAWnC,MAAM0B,SACjBC,EACAV,IAMsB,SAAxBkB,EAAWC,IAAIvC,MACW,4BAA1BsC,EAAWnC,MAAMF,KACjB,CAEA,MAAMuC,EAAaF,EAAWnC,MAAMsC,KAEpC,GAAwB,mBAApBD,EAAWvC,MAAwD,WAA3BuC,EAAWtB,OAAOjB,KAAmB,CAC/E,MAAOyC,GAAaF,EAAWrB,UAER,kBAAnBuB,EAAUzC,OACZgC,EAAUC,OAASQ,EAAUvC,QAMnC,GAA4B,cAAxBmC,EAAWC,IAAIvC,MAAkD,eAA1BsC,EAAWnC,MAAMF,KAAuB,CAEjF,MAAMV,EAAa+C,EAAWnC,MAAMH,MAC5BuB,KAAMoB,GAAeb,EAAWvC,IAAe,CAAE,EAErDoD,IACFV,EAAUC,OAASS,GAKvB,GAA4B,YAAxBL,EAAWC,IAAIvC,MAAgD,eAA1BsC,EAAWnC,MAAMF,KAAuB,CAG/E,MAAMV,EAAa+C,EAAWnC,OAAOyC,gBAAgB5C,MAAMA,MACnDuB,KAAMoB,GAAeb,EAAWvC,IAAe,CAAE,EAErDoD,IACFV,EAAUC,OAASS,GAIvB,GAA4B,aAAxBL,EAAWC,IAAIvC,MAAiD,eAA1BsC,EAAWnC,MAAMF,KAAuB,CAEhF,MAAMV,EAAa+C,EAAWnC,MAAMH,MAC5BuB,KAAMoB,EAAUE,UAAEA,GAAcf,EAAWvC,IAAe,CAAE,EAEpE,GAAIoD,EAAY,CACd,MAAMG,EAAmBlF,KAAKc,gBAAgBiE,EAAYvB,GAEtD0B,IACFb,EAAUE,SAAWvE,KAAKe,yBACxBmE,EACAD,EAAY,KAAOtD,UAOzB0C,EAAUC,QAAUD,EAAUE,SAAS3B,OAAS,IAClDuB,EAAQgB,KAAKd,OAKZF,EAMDiB,uBAAuB1D,GAC7B,MAAMwC,EAA0B,CAAE,EAelC,OAbAzE,EAASiC,EAAK,CACZE,kBAAkBC,GAChB,MAAMC,EAAaD,EAASE,KAE5BD,EAAWE,WAAWC,SAASC,IAC7BgC,EAAWhC,EAAUC,MAAMC,MAAQ,CACjCuB,KAAM7B,EAAWQ,OAAOC,MACxB0C,UAA8B,2BAAnB/C,EAAUG,KACtB,GAEJ,IAGI6B,EAMDnD,yBACNE,EACAL,EAA4B,MAE5B,IAAKK,EACH,MAAO,GAGT,MAAMS,EAAM1B,KAAKgB,UAAUC,GAE3B,IAAKS,EACH,MAAO,GAGT,MAAM2D,EAAarF,KAAKwC,qBAAqBd,EAAKd,GAC5CuD,EAAyB,GAE/B,IAAKkB,EACH,OAAOlB,EAGT,MAAMD,EAAavE,EAAY2F,gBAAgB5D,GAGzCuC,EAAWoB,EAAWrC,aAAa,GAAGuC,MAAMtB,SAIlD,OAFAE,EAAQgB,QAAQnF,KAAKgE,iBAAiBC,EAAUC,EAAYjD,IAErDkD,EAMDiB,4BACNvD,EACAqC,EACAsB,EACAC,GAEA5D,EAASE,KAAKyC,WAAWvC,SAASyD,IAChC,GAAIC,EAAiBD,IAAaE,EAAaF,EAASf,KAAM,CAE5D,GAA0B,SAAtBe,EAASf,IAAIvC,MAA2C,4BAAxBsD,EAASnD,MAAMF,KAAoC,CACrF,MAAMuC,EAAac,EAASnD,MAAMsC,KAC5BgB,EAAiBhE,EAASE,KAAKyC,WAAWsB,MAC7CC,GAAMJ,EAAiBI,IAAMH,EAAaG,EAAEpB,MAAuB,eAAfoB,EAAEpB,IAAIvC,OA6B7D,GAtBAsD,EAASnD,MAAQ,CACfF,KAAM,iBACNiB,OAAQ,CACNjB,KAAM,aACND,KAAM,KAERmB,UACEoC,EAAiBE,KAChBG,EAAiBH,EAAetD,QAC/B0D,EAAaJ,EAAetD,QAC5B2D,EAAWL,EAAetD,QAC1BqD,EAAaC,EAAetD,QAC1B,CAACmD,EAASnD,MAAOsD,EAAetD,OAChC,CAACmD,EAASnD,QAGdsD,IACFhE,EAASE,KAAKyC,WAAa3C,EAASE,KAAKyC,WAAW2B,QAAQJ,GAAMA,IAAMF,KAG1EJ,IAEwB,mBAApBb,EAAWvC,MAAwD,WAA3BuC,EAAWtB,OAAOjB,KAAmB,CAC/E,MAAOyC,GAAaF,EAAWrB,UAEzB6C,EAASvE,EAASwE,cAAcN,GAAMO,EAAkBP,EAAEhE,QAEhE,GACEqE,GACmB,kBAAnBtB,EAAUzC,MACVyC,EAAUvC,OACViD,EACA,CACA,MAAMe,EAAiBC,EACrBC,EAAW,UACXC,EAAc5B,EAAUvC,QAI1BV,EAASE,KAAKyC,WAAWmC,OACvB9E,EAASE,KAAKyC,WAAWoC,QAAQlB,GAAY,EAC7C,EACAa,KAMR,GAA0B,YAAtBb,EAASf,IAAIvC,MAA4C,cAAtBsD,EAASf,IAAIvC,KAAsB,CACxE,IAAIyE,EAAgB,GAEhBZ,EAAaP,EAASnD,QAAUuE,EAAgBpB,EAASnD,MAAMyC,eAAe5C,MAChFyE,EAAgBnB,EAASnD,MAAMyC,eAAe5C,KAAKA,KAC1CwD,EAAaF,EAASnD,SAC/BsE,EAAgBnB,EAASnD,MAAMH,MAIjC,MAAMgE,EAASvE,EAASwE,cAAcN,GAAMO,EAAkBP,EAAEhE,QAC1DJ,EAAauC,EAAW2C,IAAgBlD,KAE9C,GAAIyC,GAAUzE,GAAc6D,EAAiB,CAC3C,MAAMe,EAAiBC,EAAeC,EAAW,UAAWC,EAAc/E,IAG1EE,EAASE,KAAKyC,WAAWmC,OACvB9E,EAASE,KAAKyC,WAAWoC,QAAQlB,GAAY,EAC7C,EACAa,IAKoB,aAAtBb,EAASf,IAAIvC,MAAuBkE,EAAkBZ,EAASnD,QAEjEmD,EAASnD,MAAM0B,SAAShC,SAAS8E,IAC3BC,EAAmBD,IACrBpH,EAAYsH,qBACV,CAAElF,KAAMgF,GACR7C,EACAsB,EACAC,UAaPL,oBAAoBlE,EAAcsE,GACvC,IAAKtE,EACH,OAAOA,EAGT,MAAMQ,EAAML,EAAOnB,MAAMgB,EAAM,CAC7BI,WAAY,SACZC,QAAS,CAAC,aAAc,SAG1B,IAAKG,EACH,OAAOR,EAGT,MAAMgD,EAAavE,EAAY2F,gBAAgB5D,GAC/C,IAAIwF,GAAwB,EA6B5B,OA3BAzH,EAASiC,EAAK,CACZyF,iBAAiBtF,GACflC,EAAYsH,qBAAqBpF,EAAUqC,EAAYsB,GAAiB,KACtE0B,GAAwB,CAAI,GAE/B,IAGCA,GACFxF,EAAI0F,QAAQvC,KAAKwC,QAAQ,CACvBhF,KAAM,oBACNL,WAAY,CACV,CACEK,KAAM,yBACNF,MAAO,CACLE,KAAM,aACND,KAAM,OAIZE,OAAQ,CACND,KAAM,gBACNE,MAAO,GAAG+E,4BAKThI,EAASoC,EAAK,CACnB6F,aAAa,IACZrG"}
|