import { getRoutePath } from './path'; import { routeMap } from '../BedrockRoute'; import { RequireContext, RouteScreen } from '../types'; /** * @kind function * @name getRouteScreens * @description * pages 폴더 내에 있는 화면들을 가져옵니다. * * @param {RequireContext} context - Router 내의 화면들에 대한 정보를 담은 객체 * @returns {RouteScreen[]} screens - 이동할 수 있는 화면들의 목록을 반환합니다. * * @example * ```tsx * import { getRouteScreens } from 'react-native-bedrock'; * * const context = require.context('../pages'); * const screens = getRouteScreens(context); * ``` */ export function getRouteScreens(context: RequireContext): RouteScreen[] { const screens = context.keys().map((key) => { const path = getRoutePath(key); /** * backward compatibility를 위해 export default 옵션도 남겨둡니다. * type-safe로 마이그레이션 된다면 export Route만 필요합니다. */ const component = context(key)?.default ?? routeMap.get(context(key)?.Route?._path)?.component; if (component == null) { throw new Error(`${key} 의 페이지 컴포넌트가 없습니다.`); } return { path, component, }; }); return screens; } /** * @kind function * @name getScreenPathMapConfig * @description 화면들의 path 를 매핑합니다. * * @param {RouteScreen[]} routeScreens - 이동할 수 있는 화면들의 목록 * * @example * ```tsx * import { registerPage, getRouteScreens, getScreenPathMapConfig, Router } from 'react-native-bedrock'; * import { context } from '../require.context'; * * function App() { * return ; * } * * export default registerPage( * App, * 'minibench', * getScreenPathMapConfig(getRouteScreens(context)) * ); * ``` */ export function getScreenPathMapConfig(routeScreens: RouteScreen[]) { const screensConfig: ScreenPath = {}; routeScreens.forEach((routeScreen) => { const routePath = routeScreen.path; if (screensConfig[routePath] != null) { throw new Error(`${routePath}는 이미 등록되었습니다. 중복된 path 가 있는지 확인해주세요.`); } screensConfig[routePath] = { path: routePath, }; }); // @see https://reactnavigation.org/docs/configuring-links/#matching-exact-paths // 딥링크 처리를 위한 루트 경로('/') 매핑입니다. // 예: intoss://{서비스명}?name=John 과 같은 URL을 처리하기 위해 // 루트 경로를 빈 문자열로 매핑하여 쿼리 파라미터를 올바르게 추출할 수 있도록 합니다. screensConfig['/'] = { path: '', }; // https://reactnavigation.org/docs/configuring-links/#handling-unmatched-routes-or-404 screensConfig['/_404'] = { path: '*', }; return screensConfig; } /** * @name ScreenPath * @description * 화면 경로를 나타내는 타입이에요. * * @typedef {Record} ScreenPath */ export type ScreenPath = Record< string, { path?: string; } >;