UNPKG

29.7 kBSource Map (JSON)View Raw
1{"version":3,"names":["getStateFromPath","path","options","validatePathConfig","initialRoutes","initialRouteName","push","parentScreens","screens","remaining","replace","endsWith","undefined","routes","split","filter","Boolean","map","segment","name","decodeURIComponent","length","createNestedStateObject","configs","concat","Object","keys","key","createNormalizedConfigs","sort","a","b","pattern","routeNames","join","localeCompare","startsWith","aParts","bParts","i","Math","max","aWildCard","bWildCard","reduce","acc","config","intersects","every","it","Error","assign","match","find","c","screen","result","current","remainingPath","matchAgainstConfigs","regex","RegExp","source","joinPaths","paths","p","matchedParams","params","value","parse","routeConfig","initials","parentPattern","createConfigItem","exact","forEach","nestedConfig","pop","escape","findParseConfigForRoute","routeName","flatConfig","findInitialRoute","sameParents","createStateObject","initialRoute","route","isEmpty","index","state","shift","nestedState","nestedStateIndex","findFocusedRoute","parseQueryParams","parseConfig","query","queryString","hasOwnProperty","call"],"sources":["getStateFromPath.tsx"],"sourcesContent":["import type {\n InitialState,\n NavigationState,\n PartialState,\n} from '@react-navigation/routers';\nimport escape from 'escape-string-regexp';\nimport * as queryString from 'query-string';\n\nimport findFocusedRoute from './findFocusedRoute';\nimport type { PathConfigMap } from './types';\nimport validatePathConfig from './validatePathConfig';\n\ntype Options<ParamList extends {}> = {\n initialRouteName?: string;\n screens: PathConfigMap<ParamList>;\n};\n\ntype ParseConfig = Record<string, (value: string) => any>;\n\ntype RouteConfig = {\n screen: string;\n regex?: RegExp;\n path: string;\n pattern: string;\n routeNames: string[];\n parse?: ParseConfig;\n};\n\ntype InitialRouteConfig = {\n initialRouteName: string;\n parentScreens: string[];\n};\n\ntype ResultState = PartialState<NavigationState> & {\n state?: ResultState;\n};\n\ntype ParsedRoute = {\n name: string;\n path?: string;\n params?: Record<string, any> | undefined;\n};\n\n/**\n * Utility to parse a path string to initial state object accepted by the container.\n * This is useful for deep linking when we need to handle the incoming URL.\n *\n * @example\n * ```js\n * getStateFromPath(\n * '/chat/jane/42',\n * {\n * screens: {\n * Chat: {\n * path: 'chat/:author/:id',\n * parse: { id: Number }\n * }\n * }\n * }\n * )\n * ```\n * @param path Path string to parse and convert, e.g. /foo/bar?count=42.\n * @param options Extra options to fine-tune how to parse the path.\n */\nexport default function getStateFromPath<ParamList extends {}>(\n path: string,\n options?: Options<ParamList>\n): ResultState | undefined {\n if (options) {\n validatePathConfig(options);\n }\n\n let initialRoutes: InitialRouteConfig[] = [];\n\n if (options?.initialRouteName) {\n initialRoutes.push({\n initialRouteName: options.initialRouteName,\n parentScreens: [],\n });\n }\n\n const screens = options?.screens;\n\n let remaining = path\n .replace(/\\/+/g, '/') // Replace multiple slash (//) with single ones\n .replace(/^\\//, '') // Remove extra leading slash\n .replace(/\\?.*$/, ''); // Remove query params which we will handle later\n\n // Make sure there is a trailing slash\n remaining = remaining.endsWith('/') ? remaining : `${remaining}/`;\n\n if (screens === undefined) {\n // When no config is specified, use the path segments as route names\n const routes = remaining\n .split('/')\n .filter(Boolean)\n .map((segment) => {\n const name = decodeURIComponent(segment);\n return { name };\n });\n\n if (routes.length) {\n return createNestedStateObject(path, routes, initialRoutes);\n }\n\n return undefined;\n }\n\n // Create a normalized configs array which will be easier to use\n const configs = ([] as RouteConfig[])\n .concat(\n ...Object.keys(screens).map((key) =>\n createNormalizedConfigs(\n key,\n screens as PathConfigMap<object>,\n [],\n initialRoutes,\n []\n )\n )\n )\n .sort((a, b) => {\n // Sort config so that:\n // - the most exhaustive ones are always at the beginning\n // - patterns with wildcard are always at the end\n\n // If 2 patterns are same, move the one with less route names up\n // This is an error state, so it's only useful for consistent error messages\n if (a.pattern === b.pattern) {\n return b.routeNames.join('>').localeCompare(a.routeNames.join('>'));\n }\n\n // If one of the patterns starts with the other, it's more exhaustive\n // So move it up\n if (a.pattern.startsWith(b.pattern)) {\n return -1;\n }\n\n if (b.pattern.startsWith(a.pattern)) {\n return 1;\n }\n\n const aParts = a.pattern.split('/');\n const bParts = b.pattern.split('/');\n\n for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {\n // if b is longer, b get higher priority\n if (aParts[i] == null) {\n return 1;\n }\n // if a is longer, a get higher priority\n if (bParts[i] == null) {\n return -1;\n }\n const aWildCard = aParts[i] === '*' || aParts[i].startsWith(':');\n const bWildCard = bParts[i] === '*' || bParts[i].startsWith(':');\n // if both are wildcard we compare next component\n if (aWildCard && bWildCard) {\n continue;\n }\n // if only a is wild card, b get higher priority\n if (aWildCard) {\n return 1;\n }\n // if only b is wild card, a get higher priority\n if (bWildCard) {\n return -1;\n }\n }\n return bParts.length - aParts.length;\n });\n\n // Check for duplicate patterns in the config\n configs.reduce<Record<string, RouteConfig>>((acc, config) => {\n if (acc[config.pattern]) {\n const a = acc[config.pattern].routeNames;\n const b = config.routeNames;\n\n // It's not a problem if the path string omitted from a inner most screen\n // For example, it's ok if a path resolves to `A > B > C` or `A > B`\n const intersects =\n a.length > b.length\n ? b.every((it, i) => a[i] === it)\n : a.every((it, i) => b[i] === it);\n\n if (!intersects) {\n throw new Error(\n `Found conflicting screens with the same pattern. The pattern '${\n config.pattern\n }' resolves to both '${a.join(' > ')}' and '${b.join(\n ' > '\n )}'. Patterns must be unique and cannot resolve to more than one screen.`\n );\n }\n }\n\n return Object.assign(acc, {\n [config.pattern]: config,\n });\n }, {});\n\n if (remaining === '/') {\n // We need to add special handling of empty path so navigation to empty path also works\n // When handling empty path, we should only look at the root level config\n const match = configs.find(\n (config) =>\n config.path === '' &&\n config.routeNames.every(\n // Make sure that none of the parent configs have a non-empty path defined\n (name) => !configs.find((c) => c.screen === name)?.path\n )\n );\n\n if (match) {\n return createNestedStateObject(\n path,\n match.routeNames.map((name) => ({ name })),\n initialRoutes,\n configs\n );\n }\n\n return undefined;\n }\n\n let result: PartialState<NavigationState> | undefined;\n let current: PartialState<NavigationState> | undefined;\n\n // We match the whole path against the regex instead of segments\n // This makes sure matches such as wildcard will catch any unmatched routes, even if nested\n const { routes, remainingPath } = matchAgainstConfigs(\n remaining,\n configs.map((c) => ({\n ...c,\n // Add `$` to the regex to make sure it matches till end of the path and not just beginning\n regex: c.regex ? new RegExp(c.regex.source + '$') : undefined,\n }))\n );\n\n if (routes !== undefined) {\n // This will always be empty if full path matched\n current = createNestedStateObject(path, routes, initialRoutes, configs);\n remaining = remainingPath;\n result = current;\n }\n\n if (current == null || result == null) {\n return undefined;\n }\n\n return result;\n}\n\nconst joinPaths = (...paths: string[]): string =>\n ([] as string[])\n .concat(...paths.map((p) => p.split('/')))\n .filter(Boolean)\n .join('/');\n\nconst matchAgainstConfigs = (remaining: string, configs: RouteConfig[]) => {\n let routes: ParsedRoute[] | undefined;\n let remainingPath = remaining;\n\n // Go through all configs, and see if the next path segment matches our regex\n for (const config of configs) {\n if (!config.regex) {\n continue;\n }\n\n const match = remainingPath.match(config.regex);\n\n // If our regex matches, we need to extract params from the path\n if (match) {\n const matchedParams = config.pattern\n ?.split('/')\n .filter((p) => p.startsWith(':'))\n .reduce<Record<string, any>>(\n (acc, p, i) =>\n Object.assign(acc, {\n // The param segments appear every second item starting from 2 in the regex match result\n [p]: match![(i + 1) * 2].replace(/\\//, ''),\n }),\n {}\n );\n\n routes = config.routeNames.map((name) => {\n const config = configs.find((c) => c.screen === name);\n const params = config?.path\n ?.split('/')\n .filter((p) => p.startsWith(':'))\n .reduce<Record<string, any>>((acc, p) => {\n const value = matchedParams[p];\n\n if (value) {\n const key = p.replace(/^:/, '').replace(/\\?$/, '');\n acc[key] = config.parse?.[key] ? config.parse[key](value) : value;\n }\n\n return acc;\n }, {});\n\n if (params && Object.keys(params).length) {\n return { name, params };\n }\n\n return { name };\n });\n\n remainingPath = remainingPath.replace(match[1], '');\n\n break;\n }\n }\n\n return { routes, remainingPath };\n};\n\nconst createNormalizedConfigs = (\n screen: string,\n routeConfig: PathConfigMap<object>,\n routeNames: string[] = [],\n initials: InitialRouteConfig[],\n parentScreens: string[],\n parentPattern?: string\n): RouteConfig[] => {\n const configs: RouteConfig[] = [];\n\n routeNames.push(screen);\n\n parentScreens.push(screen);\n\n // @ts-expect-error: we can't strongly typecheck this for now\n const config = routeConfig[screen];\n\n if (typeof config === 'string') {\n // If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern\n const pattern = parentPattern ? joinPaths(parentPattern, config) : config;\n\n configs.push(createConfigItem(screen, routeNames, pattern, config));\n } else if (typeof config === 'object') {\n let pattern: string | undefined;\n\n // if an object is specified as the value (e.g. Foo: { ... }),\n // it can have `path` property and\n // it could have `screens` prop which has nested configs\n if (typeof config.path === 'string') {\n if (config.exact && config.path === undefined) {\n throw new Error(\n \"A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`.\"\n );\n }\n\n pattern =\n config.exact !== true\n ? joinPaths(parentPattern || '', config.path || '')\n : config.path || '';\n\n configs.push(\n createConfigItem(\n screen,\n routeNames,\n pattern!,\n config.path,\n config.parse\n )\n );\n }\n\n if (config.screens) {\n // property `initialRouteName` without `screens` has no purpose\n if (config.initialRouteName) {\n initials.push({\n initialRouteName: config.initialRouteName,\n parentScreens,\n });\n }\n\n Object.keys(config.screens).forEach((nestedConfig) => {\n const result = createNormalizedConfigs(\n nestedConfig,\n config.screens as PathConfigMap<object>,\n routeNames,\n initials,\n [...parentScreens],\n pattern ?? parentPattern\n );\n\n configs.push(...result);\n });\n }\n }\n\n routeNames.pop();\n\n return configs;\n};\n\nconst createConfigItem = (\n screen: string,\n routeNames: string[],\n pattern: string,\n path: string,\n parse?: ParseConfig\n): RouteConfig => {\n // Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.\n pattern = pattern.split('/').filter(Boolean).join('/');\n\n const regex = pattern\n ? new RegExp(\n `^(${pattern\n .split('/')\n .map((it) => {\n if (it.startsWith(':')) {\n return `(([^/]+\\\\/)${it.endsWith('?') ? '?' : ''})`;\n }\n\n return `${it === '*' ? '.*' : escape(it)}\\\\/`;\n })\n .join('')})`\n )\n : undefined;\n\n return {\n screen,\n regex,\n pattern,\n path,\n // The routeNames array is mutated, so copy it to keep the current state\n routeNames: [...routeNames],\n parse,\n };\n};\n\nconst findParseConfigForRoute = (\n routeName: string,\n flatConfig: RouteConfig[]\n): ParseConfig | undefined => {\n for (const config of flatConfig) {\n if (routeName === config.routeNames[config.routeNames.length - 1]) {\n return config.parse;\n }\n }\n\n return undefined;\n};\n\n// Try to find an initial route connected with the one passed\nconst findInitialRoute = (\n routeName: string,\n parentScreens: string[],\n initialRoutes: InitialRouteConfig[]\n): string | undefined => {\n for (const config of initialRoutes) {\n if (parentScreens.length === config.parentScreens.length) {\n let sameParents = true;\n for (let i = 0; i < parentScreens.length; i++) {\n if (parentScreens[i].localeCompare(config.parentScreens[i]) !== 0) {\n sameParents = false;\n break;\n }\n }\n if (sameParents) {\n return routeName !== config.initialRouteName\n ? config.initialRouteName\n : undefined;\n }\n }\n }\n return undefined;\n};\n\n// returns state object with values depending on whether\n// it is the end of state and if there is initialRoute for this level\nconst createStateObject = (\n initialRoute: string | undefined,\n route: ParsedRoute,\n isEmpty: boolean\n): InitialState => {\n if (isEmpty) {\n if (initialRoute) {\n return {\n index: 1,\n routes: [{ name: initialRoute }, route],\n };\n } else {\n return {\n routes: [route],\n };\n }\n } else {\n if (initialRoute) {\n return {\n index: 1,\n routes: [{ name: initialRoute }, { ...route, state: { routes: [] } }],\n };\n } else {\n return {\n routes: [{ ...route, state: { routes: [] } }],\n };\n }\n }\n};\n\nconst createNestedStateObject = (\n path: string,\n routes: ParsedRoute[],\n initialRoutes: InitialRouteConfig[],\n flatConfig?: RouteConfig[]\n) => {\n let state: InitialState;\n let route = routes.shift() as ParsedRoute;\n const parentScreens: string[] = [];\n\n let initialRoute = findInitialRoute(route.name, parentScreens, initialRoutes);\n\n parentScreens.push(route.name);\n\n state = createStateObject(initialRoute, route, routes.length === 0);\n\n if (routes.length > 0) {\n let nestedState = state;\n\n while ((route = routes.shift() as ParsedRoute)) {\n initialRoute = findInitialRoute(route.name, parentScreens, initialRoutes);\n\n const nestedStateIndex =\n nestedState.index || nestedState.routes.length - 1;\n\n nestedState.routes[nestedStateIndex].state = createStateObject(\n initialRoute,\n route,\n routes.length === 0\n );\n\n if (routes.length > 0) {\n nestedState = nestedState.routes[nestedStateIndex]\n .state as InitialState;\n }\n\n parentScreens.push(route.name);\n }\n }\n\n route = findFocusedRoute(state) as ParsedRoute;\n route.path = path;\n\n const params = parseQueryParams(\n path,\n flatConfig ? findParseConfigForRoute(route.name, flatConfig) : undefined\n );\n\n if (params) {\n route.params = { ...route.params, ...params };\n }\n\n return state;\n};\n\nconst parseQueryParams = (\n path: string,\n parseConfig?: Record<string, (value: string) => any>\n) => {\n const query = path.split('?')[1];\n const params = queryString.parse(query);\n\n if (parseConfig) {\n Object.keys(params).forEach((name) => {\n if (\n Object.hasOwnProperty.call(parseConfig, name) &&\n typeof params[name] === 'string'\n ) {\n params[name] = parseConfig[name](params[name] as string);\n }\n });\n }\n\n return Object.keys(params).length ? params : undefined;\n};\n"],"mappings":"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"}
\No newline at end of file