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;
}
>;