1/** 2 * Copyright © 2022 650 Industries. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 */ 7import resolveFrom from 'resolve-from'; 8 9import { getRoutePaths } from './router'; 10 11export type ExpoRouterServerManifestV1Route<TRegex = string> = { 12 page: string; 13 routeKeys: Record<string, string>; 14 namedRegex: TRegex; 15 generated?: boolean; 16}; 17 18export type ExpoRouterServerManifestV1<TRegex = string> = { 19 apiRoutes: ExpoRouterServerManifestV1Route<TRegex>[]; 20 htmlRoutes: ExpoRouterServerManifestV1Route<TRegex>[]; 21 notFoundRoutes: ExpoRouterServerManifestV1Route<TRegex>[]; 22}; 23 24function getExpoRouteManifestBuilderAsync(projectRoot: string) { 25 return require(resolveFrom(projectRoot, 'expo-router/build/routes-manifest')) 26 .createRoutesManifest as typeof import('expo-router/build/routes-manifest').createRoutesManifest; 27} 28 29// TODO: Simplify this now that we use Node.js directly, no need for the Metro bundler caching layer. 30export async function fetchManifest<TRegex = string>( 31 projectRoot: string, 32 options: { asJson?: boolean; appDir: string } 33): Promise<ExpoRouterServerManifestV1<TRegex> | null> { 34 const getManifest = getExpoRouteManifestBuilderAsync(projectRoot); 35 const paths = getRoutePaths(options.appDir); 36 // Get the serialized manifest 37 const jsonManifest = getManifest(paths); 38 39 if (!jsonManifest) { 40 return null; 41 } 42 43 if (!jsonManifest.htmlRoutes || !jsonManifest.apiRoutes) { 44 throw new Error('Routes manifest is malformed: ' + JSON.stringify(jsonManifest, null, 2)); 45 } 46 47 if (!options.asJson) { 48 // @ts-expect-error 49 return inflateManifest(jsonManifest); 50 } 51 // @ts-expect-error 52 return jsonManifest; 53} 54 55// Convert the serialized manifest to a usable format 56export function inflateManifest( 57 json: ExpoRouterServerManifestV1<string> 58): ExpoRouterServerManifestV1<RegExp> { 59 return { 60 ...json, 61 htmlRoutes: json.htmlRoutes?.map((value) => { 62 return { 63 ...value, 64 namedRegex: new RegExp(value.namedRegex), 65 }; 66 }), 67 apiRoutes: json.apiRoutes?.map((value) => { 68 return { 69 ...value, 70 namedRegex: new RegExp(value.namedRegex), 71 }; 72 }), 73 notFoundRoutes: json.notFoundRoutes?.map((value) => { 74 return { 75 ...value, 76 namedRegex: new RegExp(value.namedRegex), 77 }; 78 }), 79 }; 80} 81