@expo/cli 55.0.0-canary-20260119-70f7c28 → 55.0.0-canary-20260121-a63c0dd
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/build/bin/cli +1 -1
- package/build/src/export/exportStaticAsync.js +5 -4
- package/build/src/export/exportStaticAsync.js.map +1 -1
- package/build/src/prebuild/updatePackageJson.js +2 -2
- package/build/src/prebuild/updatePackageJson.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +18 -9
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/createServerRouteMiddleware.js +5 -2
- package/build/src/start/server/metro/createServerRouteMiddleware.js.map +1 -1
- package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
- package/build/src/utils/telemetry/utils/context.js +1 -1
- package/package.json +18 -18
package/build/bin/cli
CHANGED
|
@@ -123,7 +123,7 @@ const args = (0, _arg().default)({
|
|
|
123
123
|
});
|
|
124
124
|
if (args['--version']) {
|
|
125
125
|
// Version is added in the build script.
|
|
126
|
-
console.log("55.0.0-canary-
|
|
126
|
+
console.log("55.0.0-canary-20260121-a63c0dd");
|
|
127
127
|
process.exit(0);
|
|
128
128
|
}
|
|
129
129
|
if (args['--non-interactive']) {
|
|
@@ -228,18 +228,19 @@ async function exportFromServerAsync(projectRoot, devServer, { outputDir, baseUr
|
|
|
228
228
|
const useServerLoaders = exp == null ? void 0 : (_exp_extra = exp.extra) == null ? void 0 : (_exp_extra_router = _exp_extra.router) == null ? void 0 : _exp_extra_router.unstable_useServerDataLoaders;
|
|
229
229
|
let renderOpts;
|
|
230
230
|
if (useServerLoaders) {
|
|
231
|
-
const
|
|
232
|
-
if (
|
|
231
|
+
const loaderResponse = await executeLoaderAsync(normalizedPathname, route);
|
|
232
|
+
if (loaderResponse !== undefined) {
|
|
233
|
+
const data = await loaderResponse.json();
|
|
233
234
|
const loaderPath = (0, _utils().getLoaderModulePath)(normalizedPathname);
|
|
234
235
|
const fileSystemPath = loaderPath.startsWith('/') ? loaderPath.slice(1) : loaderPath;
|
|
235
236
|
files.set(fileSystemPath, {
|
|
236
|
-
contents: JSON.stringify(
|
|
237
|
+
contents: JSON.stringify(data, null, 2),
|
|
237
238
|
targetDomain: 'client',
|
|
238
239
|
loaderId: normalizedPathname
|
|
239
240
|
});
|
|
240
241
|
renderOpts = {
|
|
241
242
|
loader: {
|
|
242
|
-
data
|
|
243
|
+
data
|
|
243
244
|
}
|
|
244
245
|
};
|
|
245
246
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/export/exportStaticAsync.ts"],"sourcesContent":["/**\n * Copyright © 2022 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport { RouteNode } from 'expo-router/build/Route';\nimport { getLoaderModulePath } from 'expo-router/build/loaders/utils';\nimport { stripGroupSegmentsFromPath } from 'expo-router/build/matchers';\nimport { shouldLinkExternally } from 'expo-router/build/utils/url';\nimport { type RoutesManifest } from 'expo-server/private';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\nimport { inspect } from 'util';\n\nimport { getVirtualFaviconAssetsAsync } from './favicon';\nimport { persistMetroAssetsAsync } from './persistMetroAssets';\nimport { ExportAssetMap, getFilesFromSerialAssets } from './saveAssets';\nimport { Log } from '../log';\nimport {\n ExpoRouterRuntimeManifest,\n MetroBundlerDevServer,\n} from '../start/server/metro/MetroBundlerDevServer';\nimport { logMetroErrorAsync } from '../start/server/metro/metroErrorInterface';\nimport { getApiRoutesForDirectory, getMiddlewareForDirectory } from '../start/server/metro/router';\nimport { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';\nimport { learnMore } from '../utils/link';\n\nconst debug = require('debug')('expo:export:generateStaticRoutes') as typeof console.log;\n\ntype ExtraScriptTag = {\n platform: string;\n src: string;\n};\n\ntype Options = {\n mode: 'production' | 'development';\n files?: ExportAssetMap;\n outputDir: string;\n minify: boolean;\n exportServer: boolean;\n baseUrl: string;\n includeSourceMaps: boolean;\n entryPoint?: string;\n clear: boolean;\n routerRoot: string;\n reactCompiler: boolean;\n maxWorkers?: number;\n isExporting: boolean;\n exp?: ExpoConfig;\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n scriptTags?: ExtraScriptTag[];\n};\n\ntype HtmlRequestLocation = {\n /** The output file path name to use relative to the static folder. */\n filePath: string;\n /** The pathname to make requests to in order to fetch the HTML. */\n pathname: string;\n /** The runtime route node object, used to associate async modules with the static HTML. */\n route: RouteNode;\n};\n\nexport function injectScriptTags(html: string, scriptTags: ExtraScriptTag[]): string {\n const scriptTagsHtml = scriptTags\n .map((tag) =>\n tag.platform === 'web'\n ? `<script src=\"${tag.src}\"></script>`\n : `<script type=\"type/expo\" src=\"${tag.src}\" data-platform=\"${tag.platform}\"></script>`\n )\n .join('\\n');\n html = html.replace('</head>', `${scriptTagsHtml}\\n</head>`);\n return html;\n}\n\n/** Match `(page)` -> `page` */\nfunction matchGroupName(name: string): string | undefined {\n return name.match(/^\\(([^/]+?)\\)$/)?.[1];\n}\n\nexport async function getFilesToExportFromServerAsync(\n projectRoot: string,\n {\n manifest,\n serverManifest,\n renderAsync,\n // Servers can handle group routes automatically and therefore\n // don't require the build-time generation of every possible group\n // variation.\n exportServer,\n skipHtmlPrerendering,\n // name : contents\n files = new Map(),\n }: {\n manifest: ExpoRouterRuntimeManifest;\n serverManifest: RoutesManifest;\n renderAsync: (requestLocation: HtmlRequestLocation) => Promise<string>;\n exportServer?: boolean;\n /**\n * Skip HTML pre-rendering when SSR is enabled (HTML will be rendered at runtime).\n *\n * This is separate from `exportServer` because RSC mode also uses `exportServer: true`,\n * but still needs placeholder HTML files.\n */\n skipHtmlPrerendering?: boolean;\n files?: ExportAssetMap;\n }\n): Promise<ExportAssetMap> {\n if (!exportServer && serverManifest) {\n // When we're not exporting a `server` output, we provide a `_expo/.routes.json` for\n // EAS Hosting to recognize the `headers` and `redirects` configs\n const subsetServerManifest = {\n headers: serverManifest.headers,\n redirects: serverManifest.redirects,\n };\n files.set('_expo/.routes.json', {\n contents: JSON.stringify(subsetServerManifest, null, 2),\n targetDomain: 'client',\n });\n }\n\n // Skip HTML pre-rendering in SSR mode since HTML will be rendered at runtime.\n if (skipHtmlPrerendering) {\n return files;\n }\n\n await Promise.all(\n getHtmlFiles({ manifest, includeGroupVariations: !exportServer }).map(\n async ({ route, filePath, pathname }) => {\n // Rewrite routes should not be statically generated\n if (route.type === 'rewrite') {\n return;\n }\n\n try {\n const targetDomain = exportServer ? 'server' : 'client';\n files.set(filePath, { contents: '', targetDomain });\n const data = await renderAsync({ route, filePath, pathname });\n files.set(filePath, {\n contents: data,\n routeId: pathname,\n targetDomain,\n });\n } catch (e: any) {\n await logMetroErrorAsync({ error: e, projectRoot });\n throw new Error('Failed to statically export route: ' + pathname);\n }\n }\n )\n );\n\n return files;\n}\n\nfunction modifyRouteNodeInRuntimeManifest(\n manifest: ExpoRouterRuntimeManifest,\n callback: (route: RouteNode) => any\n) {\n const iterateScreens = (screens: ExpoRouterRuntimeManifest['screens']) => {\n Object.values(screens).map((value) => {\n if (typeof value !== 'string') {\n if (value._route) callback(value._route);\n iterateScreens(value.screens);\n }\n });\n };\n\n iterateScreens(manifest.screens);\n}\n\n// TODO: Do this earlier in the process.\nfunction makeRuntimeEntryPointsAbsolute(manifest: ExpoRouterRuntimeManifest, appDir: string) {\n modifyRouteNodeInRuntimeManifest(manifest, (route) => {\n if (Array.isArray(route.entryPoints)) {\n route.entryPoints = route.entryPoints.map((entryPoint) => {\n // TODO(@hassankhan): ENG-16577\n if (shouldLinkExternally(entryPoint)) {\n return entryPoint;\n }\n\n if (entryPoint.startsWith('.')) {\n return path.resolve(appDir, entryPoint);\n } else if (!path.isAbsolute(entryPoint)) {\n return resolveFrom(appDir, entryPoint);\n }\n return entryPoint;\n });\n }\n });\n}\n\n/** Perform all fs commits */\nexport async function exportFromServerAsync(\n projectRoot: string,\n devServer: MetroBundlerDevServer,\n {\n outputDir,\n baseUrl,\n exportServer,\n includeSourceMaps,\n routerRoot,\n files = new Map(),\n exp,\n scriptTags,\n }: Options\n): Promise<ExportAssetMap> {\n const useServerRendering = exp?.extra?.router?.unstable_useServerRendering ?? false;\n\n const logOutput =\n exp?.web?.output === 'server' && useServerRendering\n ? `Server rendering is enabled. ${learnMore('https://docs.expo.dev/router/web/server-rendering/')}`\n : `Static rendering is enabled. ${learnMore('https://docs.expo.dev/router/web/static-rendering/')}`;\n Log.log(logOutput);\n\n const platform = 'web';\n const isExporting = true;\n const isExportingWithSSR =\n exportServer && useServerRendering && !devServer.isReactServerComponentsEnabled;\n const appDir = path.join(projectRoot, routerRoot);\n const injectFaviconTag = await getVirtualFaviconAssetsAsync(projectRoot, {\n outputDir,\n baseUrl,\n files,\n exp,\n });\n\n const [resources, { manifest, serverManifest, renderAsync, executeLoaderAsync }] =\n await Promise.all([\n devServer.getStaticResourcesAsync({\n includeSourceMaps,\n }),\n devServer.getStaticRenderFunctionAsync(),\n ]);\n\n makeRuntimeEntryPointsAbsolute(manifest, appDir);\n\n debug('Routes:\\n', inspect(manifest, { colors: true, depth: null }));\n\n await getFilesToExportFromServerAsync(projectRoot, {\n files,\n manifest,\n serverManifest,\n exportServer,\n skipHtmlPrerendering: isExportingWithSSR,\n async renderAsync({ pathname, route }) {\n const normalizedPathname =\n pathname === '' ? '/' : pathname.startsWith('/') ? pathname : `/${pathname}`;\n\n const useServerLoaders = exp?.extra?.router?.unstable_useServerDataLoaders;\n let renderOpts;\n\n if (useServerLoaders) {\n const loaderResult = await executeLoaderAsync(normalizedPathname, route);\n\n if (loaderResult !== undefined) {\n const loaderPath = getLoaderModulePath(normalizedPathname);\n const fileSystemPath = loaderPath.startsWith('/') ? loaderPath.slice(1) : loaderPath;\n files.set(fileSystemPath, {\n contents: JSON.stringify(loaderResult.data, null, 2),\n targetDomain: 'client',\n loaderId: normalizedPathname,\n });\n\n renderOpts = { loader: { data: loaderResult.data } };\n }\n }\n\n const template = await renderAsync(normalizedPathname, route, renderOpts);\n let html = serializeHtmlWithAssets({\n isExporting,\n resources: resources.artifacts,\n template,\n baseUrl,\n route,\n hydrate: true,\n });\n\n if (injectFaviconTag) {\n html = injectFaviconTag(html);\n }\n\n if (scriptTags) {\n // Inject script tags into the HTML.\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n html = injectScriptTags(html, scriptTags);\n }\n\n return html;\n },\n });\n\n getFilesFromSerialAssets(resources.artifacts, {\n platform,\n includeSourceMaps,\n files,\n isServerHosted: true,\n });\n\n if (resources.assets) {\n // TODO: Collect files without writing to disk.\n // NOTE(kitten): Re. above, this is now using `files` except for iOS catalog output, which isn't used here\n await persistMetroAssetsAsync(projectRoot, resources.assets, {\n files,\n platform,\n outputDirectory: outputDir,\n baseUrl,\n });\n }\n\n if (exportServer) {\n const apiRoutes = await exportApiRoutesAsync({\n platform: 'web',\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n\n // Export SSR render module and add SSR configuration to routes manifest\n if (isExportingWithSSR) {\n await devServer.exportExpoRouterRenderModuleAsync({\n files,\n includeSourceMaps: true,\n platform: 'web',\n });\n\n // Export loader bundles for routes that have loader exports\n const useServerLoaders = exp?.extra?.router?.unstable_useServerDataLoaders;\n if (useServerLoaders) {\n // Get `loaderReferences` from client bundle metadata to determine which routes have loaders\n const loaderReferences = resources.artifacts?.flatMap(\n (artifact) => artifact.metadata?.loaderReferences ?? []\n );\n\n await exportLoadersAsync({\n devServer,\n serverManifest,\n appDir,\n files,\n platform: 'web',\n loaderReferences,\n });\n }\n\n const cssAssets = resources.artifacts\n .filter((asset) => asset.type === 'css')\n .map((asset) => (baseUrl ? `${baseUrl}/${asset.filename}` : `/${asset.filename}`));\n const jsAssets = resources.artifacts\n .filter((asset) => asset.type === 'js')\n .map((asset) => (baseUrl ? `${baseUrl}/${asset.filename}` : `/${asset.filename}`));\n\n // Add assets and rendering config to the routes manifest\n updateExportManifestInFiles({\n files,\n callback: (manifest) => {\n manifest.assets = { css: cssAssets, js: jsAssets };\n manifest.rendering = {\n mode: 'ssr',\n file: '_expo/server/render.js',\n };\n },\n });\n }\n } else {\n warnPossibleInvalidExportType(appDir);\n }\n\n return files;\n}\n\nexport function getHtmlFiles({\n manifest,\n includeGroupVariations,\n}: {\n manifest: ExpoRouterRuntimeManifest;\n includeGroupVariations?: boolean;\n}): HtmlRequestLocation[] {\n const htmlFiles = new Set<Omit<HtmlRequestLocation, 'pathname'>>();\n\n function traverseScreens(\n screens: ExpoRouterRuntimeManifest['screens'],\n route: RouteNode | null,\n baseUrl = ''\n ) {\n for (const [key, value] of Object.entries(screens)) {\n let leaf: string | null = null;\n if (typeof value === 'string') {\n leaf = value;\n } else if (value.screens && Object.keys(value.screens).length === 0) {\n // Ensure the trailing index is accounted for.\n if (key === value.path + '/index') {\n leaf = key;\n } else {\n leaf = value.path;\n }\n\n route = value._route ?? null;\n }\n\n if (leaf != null) {\n let filePath = baseUrl + leaf;\n\n if (leaf === '') {\n filePath =\n baseUrl === ''\n ? 'index'\n : baseUrl.endsWith('/')\n ? baseUrl + 'index'\n : baseUrl.slice(0, -1);\n } else if (\n // If the path is a collection of group segments leading to an index route, append `/index`.\n stripGroupSegmentsFromPath(filePath) === ''\n ) {\n filePath += '/index';\n }\n\n // This should never happen, the type of `string | object` originally comes from React Navigation.\n if (!route) {\n throw new Error(\n `Internal error: Route not found for \"${filePath}\" while collecting static export paths.`\n );\n }\n\n if (includeGroupVariations) {\n // TODO: Dedupe requests for alias routes.\n addOptionalGroups(filePath, route);\n } else {\n htmlFiles.add({\n filePath,\n route,\n });\n }\n } else if (typeof value === 'object' && value?.screens) {\n // The __root slot has no path.\n const newPath = value.path ? baseUrl + value.path + '/' : baseUrl;\n traverseScreens(value.screens, value._route ?? null, newPath);\n }\n }\n }\n\n function addOptionalGroups(path: string, route: RouteNode) {\n const variations = getPathVariations(path);\n for (const variation of variations) {\n htmlFiles.add({ filePath: variation, route });\n }\n }\n\n traverseScreens(manifest.screens, null);\n\n return uniqueBy(Array.from(htmlFiles), (value) => value.filePath).map((value) => {\n const parts = value.filePath.split('/');\n // Replace `:foo` with `[foo]` and `*foo` with `[...foo]`\n const partsWithGroups = parts.map((part) => {\n if (part === '*not-found') {\n return `+not-found`;\n } else if (part.startsWith(':')) {\n return `[${part.slice(1)}]`;\n } else if (part.startsWith('*')) {\n return `[...${part.slice(1)}]`;\n }\n return part;\n });\n const filePathLocation = partsWithGroups.join('/');\n const filePath = filePathLocation + '.html';\n return {\n ...value,\n filePath,\n pathname: filePathLocation.replace(/(\\/?index)?$/, ''),\n };\n });\n}\n\nfunction uniqueBy<T>(array: T[], key: (value: T) => string): T[] {\n const seen = new Set<string>();\n const result: T[] = [];\n for (const value of array) {\n const id = key(value);\n if (!seen.has(id)) {\n seen.add(id);\n result.push(value);\n }\n }\n return result;\n}\n\n// Given a route like `(foo)/bar/(baz)`, return all possible variations of the route.\n// e.g. `(foo)/bar/(baz)`, `(foo)/bar/baz`, `foo/bar/(baz)`, `foo/bar/baz`,\nexport function getPathVariations(routePath: string): string[] {\n const variations = new Set<string>();\n const segments = routePath.split('/');\n\n function generateVariations(segments: string[], current = ''): void {\n if (segments.length === 0) {\n if (current) variations.add(current);\n return;\n }\n\n const [head, ...rest] = segments;\n\n if (matchGroupName(head)) {\n const groups = head.slice(1, -1).split(',');\n\n if (groups.length > 1) {\n for (const group of groups) {\n // If there are multiple groups, recurse on each group.\n generateVariations([`(${group.trim()})`, ...rest], current);\n }\n return;\n } else {\n // Start a fork where this group is included\n generateVariations(rest, current ? `${current}/(${groups[0]})` : `(${groups[0]})`);\n // This code will continue and add paths without this group included`\n }\n } else if (current) {\n current = `${current}/${head}`;\n } else {\n current = head;\n }\n\n generateVariations(rest, current);\n }\n\n generateVariations(segments);\n\n return Array.from(variations);\n}\n\nexport async function exportApiRoutesStandaloneAsync(\n devServer: MetroBundlerDevServer,\n {\n files = new Map(),\n platform,\n apiRoutesOnly,\n templateHtml,\n }: {\n files?: ExportAssetMap;\n platform: string;\n apiRoutesOnly: boolean;\n templateHtml?: string;\n }\n) {\n const { serverManifest, htmlManifest } = await devServer.getServerManifestAsync();\n\n const apiRoutes = await exportApiRoutesAsync({\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n platform,\n apiRoutesOnly,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n\n if (templateHtml && devServer.isReactServerComponentsEnabled) {\n // TODO: Export an HTML entry for each file. This is a temporary solution until we have SSR/SSG for RSC.\n await getFilesToExportFromServerAsync(devServer.projectRoot, {\n manifest: htmlManifest,\n serverManifest,\n exportServer: true,\n files,\n renderAsync: async ({ pathname, filePath }) => {\n files.set(filePath, {\n contents: templateHtml!,\n routeId: pathname,\n targetDomain: 'server',\n });\n return templateHtml!;\n },\n });\n }\n\n return files;\n}\n\nasync function exportApiRoutesAsync({\n includeSourceMaps,\n server,\n platform,\n apiRoutesOnly,\n ...props\n}: Pick<Options, 'includeSourceMaps'> & {\n server: MetroBundlerDevServer;\n manifest: RoutesManifest<string>;\n platform: string;\n apiRoutesOnly?: boolean;\n}): Promise<ExportAssetMap> {\n const { manifest, files } = await server.exportExpoRouterApiRoutesAsync({\n outputDir: '_expo/functions',\n prerenderManifest: props.manifest,\n includeSourceMaps,\n platform,\n });\n\n // HACK: Clear out the HTML and 404 routes if we're only exporting API routes. This is used for native apps that are using API routes but haven't implemented web support yet.\n if (apiRoutesOnly) {\n manifest.htmlRoutes = [];\n manifest.notFoundRoutes = [];\n }\n\n files.set('_expo/routes.json', {\n contents: JSON.stringify(manifest, null, 2),\n targetDomain: 'server',\n });\n\n return files;\n}\n\nfunction warnPossibleInvalidExportType(appDir: string) {\n const apiRoutes = getApiRoutesForDirectory(appDir);\n if (apiRoutes.length) {\n // TODO: Allow API Routes for native-only.\n Log.warn(\n chalk.yellow`Skipping export for API routes because \\`web.output\\` is not \"server\". You may want to remove the routes: ${apiRoutes\n .map((v) => path.relative(appDir, v))\n .join(', ')}`\n );\n }\n\n const middlewareFile = getMiddlewareForDirectory(appDir);\n if (middlewareFile) {\n Log.warn(\n chalk.yellow`Skipping export for middleware because \\`web.output\\` is not \"server\". You may want to remove ${path.relative(appDir, middlewareFile)}`\n );\n }\n}\n\n/**\n * Export loader bundles for routes that have loader exports and updates routes in the manifest\n * with a `loader` property.\n */\nasync function exportLoadersAsync({\n devServer,\n serverManifest,\n appDir,\n files,\n platform,\n loaderReferences,\n}: {\n devServer: MetroBundlerDevServer;\n serverManifest: RoutesManifest<string>;\n appDir: string;\n files: ExportAssetMap;\n platform: string;\n /** File paths of modules with loader exports from client bundle metadata */\n loaderReferences: string[];\n}): Promise<void> {\n const entryPoints: { file: string; page: string }[] = [];\n\n for (const route of serverManifest.htmlRoutes) {\n // Skip generated routes\n if (route.generated) {\n continue;\n }\n\n const filePath = path.isAbsolute(route.file) ? route.file : path.join(appDir, route.file);\n\n if (loaderReferences.includes(filePath)) {\n entryPoints.push({\n file: filePath,\n page: route.page,\n });\n }\n }\n\n if (entryPoints.length === 0) {\n debug('No routes with loaders to bundle');\n return;\n }\n\n const entryPointModules = entryPoints.map((e) => e.page);\n debug('Bundling loaders for routes:', entryPointModules);\n\n await devServer.exportExpoRouterLoadersAsync({\n platform,\n entryPoints,\n files,\n outputDir: '_expo/loaders',\n includeSourceMaps: true,\n });\n\n // Update `htmlRoutes` in routes manifest for routes that have loaders\n updateExportManifestInFiles({\n files,\n callback: (manifest) => {\n const routesWithLoaders = new Set(entryPointModules);\n for (const route of manifest.htmlRoutes) {\n if (routesWithLoaders.has(route.page)) {\n route.loader = `_expo/loaders${route.page}.js`;\n }\n }\n },\n });\n\n debug('Exported loaders for routes:', entryPointModules);\n}\n\n// NOTE(@hassankhan): We should ideally persist the manifest to `files` only once instead of\n// modifying it afterwards.\nfunction updateExportManifestInFiles({\n files,\n callback,\n}: {\n files: ExportAssetMap;\n callback: (manifest: RoutesManifest<string>) => void;\n}) {\n const routesJsonEntry = files.get('_expo/routes.json');\n if (routesJsonEntry) {\n const manifest = JSON.parse(routesJsonEntry.contents as string);\n callback(manifest);\n\n files.set('_expo/routes.json', {\n ...routesJsonEntry,\n contents: JSON.stringify(manifest, null, 2),\n });\n }\n}\n"],"names":["exportApiRoutesStandaloneAsync","exportFromServerAsync","getFilesToExportFromServerAsync","getHtmlFiles","getPathVariations","injectScriptTags","debug","require","html","scriptTags","scriptTagsHtml","map","tag","platform","src","join","replace","matchGroupName","name","match","projectRoot","manifest","serverManifest","renderAsync","exportServer","skipHtmlPrerendering","files","Map","subsetServerManifest","headers","redirects","set","contents","JSON","stringify","targetDomain","Promise","all","includeGroupVariations","route","filePath","pathname","type","data","routeId","e","logMetroErrorAsync","error","Error","modifyRouteNodeInRuntimeManifest","callback","iterateScreens","screens","Object","values","value","_route","makeRuntimeEntryPointsAbsolute","appDir","Array","isArray","entryPoints","entryPoint","shouldLinkExternally","startsWith","path","resolve","isAbsolute","resolveFrom","devServer","outputDir","baseUrl","includeSourceMaps","routerRoot","exp","useServerRendering","extra","router","unstable_useServerRendering","logOutput","web","output","learnMore","Log","log","isExporting","isExportingWithSSR","isReactServerComponentsEnabled","injectFaviconTag","getVirtualFaviconAssetsAsync","resources","executeLoaderAsync","getStaticResourcesAsync","getStaticRenderFunctionAsync","inspect","colors","depth","normalizedPathname","useServerLoaders","unstable_useServerDataLoaders","renderOpts","loaderResult","undefined","loaderPath","getLoaderModulePath","fileSystemPath","slice","loaderId","loader","template","serializeHtmlWithAssets","artifacts","hydrate","getFilesFromSerialAssets","isServerHosted","assets","persistMetroAssetsAsync","outputDirectory","apiRoutes","exportApiRoutesAsync","server","exportExpoRouterRenderModuleAsync","loaderReferences","flatMap","artifact","metadata","exportLoadersAsync","cssAssets","filter","asset","filename","jsAssets","updateExportManifestInFiles","css","js","rendering","mode","file","warnPossibleInvalidExportType","htmlFiles","Set","traverseScreens","key","entries","leaf","keys","length","endsWith","stripGroupSegmentsFromPath","addOptionalGroups","add","newPath","variations","variation","uniqueBy","from","parts","split","partsWithGroups","part","filePathLocation","array","seen","result","id","has","push","routePath","segments","generateVariations","current","head","rest","groups","group","trim","apiRoutesOnly","templateHtml","htmlManifest","getServerManifestAsync","props","exportExpoRouterApiRoutesAsync","prerenderManifest","htmlRoutes","notFoundRoutes","getApiRoutesForDirectory","warn","chalk","yellow","v","relative","middlewareFile","getMiddlewareForDirectory","generated","includes","page","entryPointModules","exportExpoRouterLoadersAsync","routesWithLoaders","routesJsonEntry","get","parse"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/export/exportStaticAsync.ts"],"sourcesContent":["/**\n * Copyright © 2022 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport { RouteNode } from 'expo-router/build/Route';\nimport { getLoaderModulePath } from 'expo-router/build/loaders/utils';\nimport { stripGroupSegmentsFromPath } from 'expo-router/build/matchers';\nimport { shouldLinkExternally } from 'expo-router/build/utils/url';\nimport { type RoutesManifest } from 'expo-server/private';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\nimport { inspect } from 'util';\n\nimport { getVirtualFaviconAssetsAsync } from './favicon';\nimport { persistMetroAssetsAsync } from './persistMetroAssets';\nimport { ExportAssetMap, getFilesFromSerialAssets } from './saveAssets';\nimport { Log } from '../log';\nimport {\n ExpoRouterRuntimeManifest,\n MetroBundlerDevServer,\n} from '../start/server/metro/MetroBundlerDevServer';\nimport { logMetroErrorAsync } from '../start/server/metro/metroErrorInterface';\nimport { getApiRoutesForDirectory, getMiddlewareForDirectory } from '../start/server/metro/router';\nimport { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';\nimport { learnMore } from '../utils/link';\n\nconst debug = require('debug')('expo:export:generateStaticRoutes') as typeof console.log;\n\ntype ExtraScriptTag = {\n platform: string;\n src: string;\n};\n\ntype Options = {\n mode: 'production' | 'development';\n files?: ExportAssetMap;\n outputDir: string;\n minify: boolean;\n exportServer: boolean;\n baseUrl: string;\n includeSourceMaps: boolean;\n entryPoint?: string;\n clear: boolean;\n routerRoot: string;\n reactCompiler: boolean;\n maxWorkers?: number;\n isExporting: boolean;\n exp?: ExpoConfig;\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n scriptTags?: ExtraScriptTag[];\n};\n\ntype HtmlRequestLocation = {\n /** The output file path name to use relative to the static folder. */\n filePath: string;\n /** The pathname to make requests to in order to fetch the HTML. */\n pathname: string;\n /** The runtime route node object, used to associate async modules with the static HTML. */\n route: RouteNode;\n};\n\nexport function injectScriptTags(html: string, scriptTags: ExtraScriptTag[]): string {\n const scriptTagsHtml = scriptTags\n .map((tag) =>\n tag.platform === 'web'\n ? `<script src=\"${tag.src}\"></script>`\n : `<script type=\"type/expo\" src=\"${tag.src}\" data-platform=\"${tag.platform}\"></script>`\n )\n .join('\\n');\n html = html.replace('</head>', `${scriptTagsHtml}\\n</head>`);\n return html;\n}\n\n/** Match `(page)` -> `page` */\nfunction matchGroupName(name: string): string | undefined {\n return name.match(/^\\(([^/]+?)\\)$/)?.[1];\n}\n\nexport async function getFilesToExportFromServerAsync(\n projectRoot: string,\n {\n manifest,\n serverManifest,\n renderAsync,\n // Servers can handle group routes automatically and therefore\n // don't require the build-time generation of every possible group\n // variation.\n exportServer,\n skipHtmlPrerendering,\n // name : contents\n files = new Map(),\n }: {\n manifest: ExpoRouterRuntimeManifest;\n serverManifest: RoutesManifest;\n renderAsync: (requestLocation: HtmlRequestLocation) => Promise<string>;\n exportServer?: boolean;\n /**\n * Skip HTML pre-rendering when SSR is enabled (HTML will be rendered at runtime).\n *\n * This is separate from `exportServer` because RSC mode also uses `exportServer: true`,\n * but still needs placeholder HTML files.\n */\n skipHtmlPrerendering?: boolean;\n files?: ExportAssetMap;\n }\n): Promise<ExportAssetMap> {\n if (!exportServer && serverManifest) {\n // When we're not exporting a `server` output, we provide a `_expo/.routes.json` for\n // EAS Hosting to recognize the `headers` and `redirects` configs\n const subsetServerManifest = {\n headers: serverManifest.headers,\n redirects: serverManifest.redirects,\n };\n files.set('_expo/.routes.json', {\n contents: JSON.stringify(subsetServerManifest, null, 2),\n targetDomain: 'client',\n });\n }\n\n // Skip HTML pre-rendering in SSR mode since HTML will be rendered at runtime.\n if (skipHtmlPrerendering) {\n return files;\n }\n\n await Promise.all(\n getHtmlFiles({ manifest, includeGroupVariations: !exportServer }).map(\n async ({ route, filePath, pathname }) => {\n // Rewrite routes should not be statically generated\n if (route.type === 'rewrite') {\n return;\n }\n\n try {\n const targetDomain = exportServer ? 'server' : 'client';\n files.set(filePath, { contents: '', targetDomain });\n const data = await renderAsync({ route, filePath, pathname });\n files.set(filePath, {\n contents: data,\n routeId: pathname,\n targetDomain,\n });\n } catch (e: any) {\n await logMetroErrorAsync({ error: e, projectRoot });\n throw new Error('Failed to statically export route: ' + pathname);\n }\n }\n )\n );\n\n return files;\n}\n\nfunction modifyRouteNodeInRuntimeManifest(\n manifest: ExpoRouterRuntimeManifest,\n callback: (route: RouteNode) => any\n) {\n const iterateScreens = (screens: ExpoRouterRuntimeManifest['screens']) => {\n Object.values(screens).map((value) => {\n if (typeof value !== 'string') {\n if (value._route) callback(value._route);\n iterateScreens(value.screens);\n }\n });\n };\n\n iterateScreens(manifest.screens);\n}\n\n// TODO: Do this earlier in the process.\nfunction makeRuntimeEntryPointsAbsolute(manifest: ExpoRouterRuntimeManifest, appDir: string) {\n modifyRouteNodeInRuntimeManifest(manifest, (route) => {\n if (Array.isArray(route.entryPoints)) {\n route.entryPoints = route.entryPoints.map((entryPoint) => {\n // TODO(@hassankhan): ENG-16577\n if (shouldLinkExternally(entryPoint)) {\n return entryPoint;\n }\n\n if (entryPoint.startsWith('.')) {\n return path.resolve(appDir, entryPoint);\n } else if (!path.isAbsolute(entryPoint)) {\n return resolveFrom(appDir, entryPoint);\n }\n return entryPoint;\n });\n }\n });\n}\n\n/** Perform all fs commits */\nexport async function exportFromServerAsync(\n projectRoot: string,\n devServer: MetroBundlerDevServer,\n {\n outputDir,\n baseUrl,\n exportServer,\n includeSourceMaps,\n routerRoot,\n files = new Map(),\n exp,\n scriptTags,\n }: Options\n): Promise<ExportAssetMap> {\n const useServerRendering = exp?.extra?.router?.unstable_useServerRendering ?? false;\n\n const logOutput =\n exp?.web?.output === 'server' && useServerRendering\n ? `Server rendering is enabled. ${learnMore('https://docs.expo.dev/router/web/server-rendering/')}`\n : `Static rendering is enabled. ${learnMore('https://docs.expo.dev/router/web/static-rendering/')}`;\n Log.log(logOutput);\n\n const platform = 'web';\n const isExporting = true;\n const isExportingWithSSR =\n exportServer && useServerRendering && !devServer.isReactServerComponentsEnabled;\n const appDir = path.join(projectRoot, routerRoot);\n const injectFaviconTag = await getVirtualFaviconAssetsAsync(projectRoot, {\n outputDir,\n baseUrl,\n files,\n exp,\n });\n\n const [resources, { manifest, serverManifest, renderAsync, executeLoaderAsync }] =\n await Promise.all([\n devServer.getStaticResourcesAsync({\n includeSourceMaps,\n }),\n devServer.getStaticRenderFunctionAsync(),\n ]);\n\n makeRuntimeEntryPointsAbsolute(manifest, appDir);\n\n debug('Routes:\\n', inspect(manifest, { colors: true, depth: null }));\n\n await getFilesToExportFromServerAsync(projectRoot, {\n files,\n manifest,\n serverManifest,\n exportServer,\n skipHtmlPrerendering: isExportingWithSSR,\n async renderAsync({ pathname, route }) {\n const normalizedPathname =\n pathname === '' ? '/' : pathname.startsWith('/') ? pathname : `/${pathname}`;\n\n const useServerLoaders = exp?.extra?.router?.unstable_useServerDataLoaders;\n let renderOpts;\n\n if (useServerLoaders) {\n const loaderResponse = await executeLoaderAsync(normalizedPathname, route);\n\n if (loaderResponse !== undefined) {\n const data = await loaderResponse.json();\n const loaderPath = getLoaderModulePath(normalizedPathname);\n const fileSystemPath = loaderPath.startsWith('/') ? loaderPath.slice(1) : loaderPath;\n files.set(fileSystemPath, {\n contents: JSON.stringify(data, null, 2),\n targetDomain: 'client',\n loaderId: normalizedPathname,\n });\n\n renderOpts = { loader: { data } };\n }\n }\n\n const template = await renderAsync(normalizedPathname, route, renderOpts);\n let html = serializeHtmlWithAssets({\n isExporting,\n resources: resources.artifacts,\n template,\n baseUrl,\n route,\n hydrate: true,\n });\n\n if (injectFaviconTag) {\n html = injectFaviconTag(html);\n }\n\n if (scriptTags) {\n // Inject script tags into the HTML.\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n html = injectScriptTags(html, scriptTags);\n }\n\n return html;\n },\n });\n\n getFilesFromSerialAssets(resources.artifacts, {\n platform,\n includeSourceMaps,\n files,\n isServerHosted: true,\n });\n\n if (resources.assets) {\n // TODO: Collect files without writing to disk.\n // NOTE(kitten): Re. above, this is now using `files` except for iOS catalog output, which isn't used here\n await persistMetroAssetsAsync(projectRoot, resources.assets, {\n files,\n platform,\n outputDirectory: outputDir,\n baseUrl,\n });\n }\n\n if (exportServer) {\n const apiRoutes = await exportApiRoutesAsync({\n platform: 'web',\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n\n // Export SSR render module and add SSR configuration to routes manifest\n if (isExportingWithSSR) {\n await devServer.exportExpoRouterRenderModuleAsync({\n files,\n includeSourceMaps: true,\n platform: 'web',\n });\n\n // Export loader bundles for routes that have loader exports\n const useServerLoaders = exp?.extra?.router?.unstable_useServerDataLoaders;\n if (useServerLoaders) {\n // Get `loaderReferences` from client bundle metadata to determine which routes have loaders\n const loaderReferences = resources.artifacts?.flatMap(\n (artifact) => artifact.metadata?.loaderReferences ?? []\n );\n\n await exportLoadersAsync({\n devServer,\n serverManifest,\n appDir,\n files,\n platform: 'web',\n loaderReferences,\n });\n }\n\n const cssAssets = resources.artifacts\n .filter((asset) => asset.type === 'css')\n .map((asset) => (baseUrl ? `${baseUrl}/${asset.filename}` : `/${asset.filename}`));\n const jsAssets = resources.artifacts\n .filter((asset) => asset.type === 'js')\n .map((asset) => (baseUrl ? `${baseUrl}/${asset.filename}` : `/${asset.filename}`));\n\n // Add assets and rendering config to the routes manifest\n updateExportManifestInFiles({\n files,\n callback: (manifest) => {\n manifest.assets = { css: cssAssets, js: jsAssets };\n manifest.rendering = {\n mode: 'ssr',\n file: '_expo/server/render.js',\n };\n },\n });\n }\n } else {\n warnPossibleInvalidExportType(appDir);\n }\n\n return files;\n}\n\nexport function getHtmlFiles({\n manifest,\n includeGroupVariations,\n}: {\n manifest: ExpoRouterRuntimeManifest;\n includeGroupVariations?: boolean;\n}): HtmlRequestLocation[] {\n const htmlFiles = new Set<Omit<HtmlRequestLocation, 'pathname'>>();\n\n function traverseScreens(\n screens: ExpoRouterRuntimeManifest['screens'],\n route: RouteNode | null,\n baseUrl = ''\n ) {\n for (const [key, value] of Object.entries(screens)) {\n let leaf: string | null = null;\n if (typeof value === 'string') {\n leaf = value;\n } else if (value.screens && Object.keys(value.screens).length === 0) {\n // Ensure the trailing index is accounted for.\n if (key === value.path + '/index') {\n leaf = key;\n } else {\n leaf = value.path;\n }\n\n route = value._route ?? null;\n }\n\n if (leaf != null) {\n let filePath = baseUrl + leaf;\n\n if (leaf === '') {\n filePath =\n baseUrl === ''\n ? 'index'\n : baseUrl.endsWith('/')\n ? baseUrl + 'index'\n : baseUrl.slice(0, -1);\n } else if (\n // If the path is a collection of group segments leading to an index route, append `/index`.\n stripGroupSegmentsFromPath(filePath) === ''\n ) {\n filePath += '/index';\n }\n\n // This should never happen, the type of `string | object` originally comes from React Navigation.\n if (!route) {\n throw new Error(\n `Internal error: Route not found for \"${filePath}\" while collecting static export paths.`\n );\n }\n\n if (includeGroupVariations) {\n // TODO: Dedupe requests for alias routes.\n addOptionalGroups(filePath, route);\n } else {\n htmlFiles.add({\n filePath,\n route,\n });\n }\n } else if (typeof value === 'object' && value?.screens) {\n // The __root slot has no path.\n const newPath = value.path ? baseUrl + value.path + '/' : baseUrl;\n traverseScreens(value.screens, value._route ?? null, newPath);\n }\n }\n }\n\n function addOptionalGroups(path: string, route: RouteNode) {\n const variations = getPathVariations(path);\n for (const variation of variations) {\n htmlFiles.add({ filePath: variation, route });\n }\n }\n\n traverseScreens(manifest.screens, null);\n\n return uniqueBy(Array.from(htmlFiles), (value) => value.filePath).map((value) => {\n const parts = value.filePath.split('/');\n // Replace `:foo` with `[foo]` and `*foo` with `[...foo]`\n const partsWithGroups = parts.map((part) => {\n if (part === '*not-found') {\n return `+not-found`;\n } else if (part.startsWith(':')) {\n return `[${part.slice(1)}]`;\n } else if (part.startsWith('*')) {\n return `[...${part.slice(1)}]`;\n }\n return part;\n });\n const filePathLocation = partsWithGroups.join('/');\n const filePath = filePathLocation + '.html';\n return {\n ...value,\n filePath,\n pathname: filePathLocation.replace(/(\\/?index)?$/, ''),\n };\n });\n}\n\nfunction uniqueBy<T>(array: T[], key: (value: T) => string): T[] {\n const seen = new Set<string>();\n const result: T[] = [];\n for (const value of array) {\n const id = key(value);\n if (!seen.has(id)) {\n seen.add(id);\n result.push(value);\n }\n }\n return result;\n}\n\n// Given a route like `(foo)/bar/(baz)`, return all possible variations of the route.\n// e.g. `(foo)/bar/(baz)`, `(foo)/bar/baz`, `foo/bar/(baz)`, `foo/bar/baz`,\nexport function getPathVariations(routePath: string): string[] {\n const variations = new Set<string>();\n const segments = routePath.split('/');\n\n function generateVariations(segments: string[], current = ''): void {\n if (segments.length === 0) {\n if (current) variations.add(current);\n return;\n }\n\n const [head, ...rest] = segments;\n\n if (matchGroupName(head)) {\n const groups = head.slice(1, -1).split(',');\n\n if (groups.length > 1) {\n for (const group of groups) {\n // If there are multiple groups, recurse on each group.\n generateVariations([`(${group.trim()})`, ...rest], current);\n }\n return;\n } else {\n // Start a fork where this group is included\n generateVariations(rest, current ? `${current}/(${groups[0]})` : `(${groups[0]})`);\n // This code will continue and add paths without this group included`\n }\n } else if (current) {\n current = `${current}/${head}`;\n } else {\n current = head;\n }\n\n generateVariations(rest, current);\n }\n\n generateVariations(segments);\n\n return Array.from(variations);\n}\n\nexport async function exportApiRoutesStandaloneAsync(\n devServer: MetroBundlerDevServer,\n {\n files = new Map(),\n platform,\n apiRoutesOnly,\n templateHtml,\n }: {\n files?: ExportAssetMap;\n platform: string;\n apiRoutesOnly: boolean;\n templateHtml?: string;\n }\n) {\n const { serverManifest, htmlManifest } = await devServer.getServerManifestAsync();\n\n const apiRoutes = await exportApiRoutesAsync({\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n platform,\n apiRoutesOnly,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n\n if (templateHtml && devServer.isReactServerComponentsEnabled) {\n // TODO: Export an HTML entry for each file. This is a temporary solution until we have SSR/SSG for RSC.\n await getFilesToExportFromServerAsync(devServer.projectRoot, {\n manifest: htmlManifest,\n serverManifest,\n exportServer: true,\n files,\n renderAsync: async ({ pathname, filePath }) => {\n files.set(filePath, {\n contents: templateHtml!,\n routeId: pathname,\n targetDomain: 'server',\n });\n return templateHtml!;\n },\n });\n }\n\n return files;\n}\n\nasync function exportApiRoutesAsync({\n includeSourceMaps,\n server,\n platform,\n apiRoutesOnly,\n ...props\n}: Pick<Options, 'includeSourceMaps'> & {\n server: MetroBundlerDevServer;\n manifest: RoutesManifest<string>;\n platform: string;\n apiRoutesOnly?: boolean;\n}): Promise<ExportAssetMap> {\n const { manifest, files } = await server.exportExpoRouterApiRoutesAsync({\n outputDir: '_expo/functions',\n prerenderManifest: props.manifest,\n includeSourceMaps,\n platform,\n });\n\n // HACK: Clear out the HTML and 404 routes if we're only exporting API routes. This is used for native apps that are using API routes but haven't implemented web support yet.\n if (apiRoutesOnly) {\n manifest.htmlRoutes = [];\n manifest.notFoundRoutes = [];\n }\n\n files.set('_expo/routes.json', {\n contents: JSON.stringify(manifest, null, 2),\n targetDomain: 'server',\n });\n\n return files;\n}\n\nfunction warnPossibleInvalidExportType(appDir: string) {\n const apiRoutes = getApiRoutesForDirectory(appDir);\n if (apiRoutes.length) {\n // TODO: Allow API Routes for native-only.\n Log.warn(\n chalk.yellow`Skipping export for API routes because \\`web.output\\` is not \"server\". You may want to remove the routes: ${apiRoutes\n .map((v) => path.relative(appDir, v))\n .join(', ')}`\n );\n }\n\n const middlewareFile = getMiddlewareForDirectory(appDir);\n if (middlewareFile) {\n Log.warn(\n chalk.yellow`Skipping export for middleware because \\`web.output\\` is not \"server\". You may want to remove ${path.relative(appDir, middlewareFile)}`\n );\n }\n}\n\n/**\n * Export loader bundles for routes that have loader exports and updates routes in the manifest\n * with a `loader` property.\n */\nasync function exportLoadersAsync({\n devServer,\n serverManifest,\n appDir,\n files,\n platform,\n loaderReferences,\n}: {\n devServer: MetroBundlerDevServer;\n serverManifest: RoutesManifest<string>;\n appDir: string;\n files: ExportAssetMap;\n platform: string;\n /** File paths of modules with loader exports from client bundle metadata */\n loaderReferences: string[];\n}): Promise<void> {\n const entryPoints: { file: string; page: string }[] = [];\n\n for (const route of serverManifest.htmlRoutes) {\n // Skip generated routes\n if (route.generated) {\n continue;\n }\n\n const filePath = path.isAbsolute(route.file) ? route.file : path.join(appDir, route.file);\n\n if (loaderReferences.includes(filePath)) {\n entryPoints.push({\n file: filePath,\n page: route.page,\n });\n }\n }\n\n if (entryPoints.length === 0) {\n debug('No routes with loaders to bundle');\n return;\n }\n\n const entryPointModules = entryPoints.map((e) => e.page);\n debug('Bundling loaders for routes:', entryPointModules);\n\n await devServer.exportExpoRouterLoadersAsync({\n platform,\n entryPoints,\n files,\n outputDir: '_expo/loaders',\n includeSourceMaps: true,\n });\n\n // Update `htmlRoutes` in routes manifest for routes that have loaders\n updateExportManifestInFiles({\n files,\n callback: (manifest) => {\n const routesWithLoaders = new Set(entryPointModules);\n for (const route of manifest.htmlRoutes) {\n if (routesWithLoaders.has(route.page)) {\n route.loader = `_expo/loaders${route.page}.js`;\n }\n }\n },\n });\n\n debug('Exported loaders for routes:', entryPointModules);\n}\n\n// NOTE(@hassankhan): We should ideally persist the manifest to `files` only once instead of\n// modifying it afterwards.\nfunction updateExportManifestInFiles({\n files,\n callback,\n}: {\n files: ExportAssetMap;\n callback: (manifest: RoutesManifest<string>) => void;\n}) {\n const routesJsonEntry = files.get('_expo/routes.json');\n if (routesJsonEntry) {\n const manifest = JSON.parse(routesJsonEntry.contents as string);\n callback(manifest);\n\n files.set('_expo/routes.json', {\n ...routesJsonEntry,\n contents: JSON.stringify(manifest, null, 2),\n });\n }\n}\n"],"names":["exportApiRoutesStandaloneAsync","exportFromServerAsync","getFilesToExportFromServerAsync","getHtmlFiles","getPathVariations","injectScriptTags","debug","require","html","scriptTags","scriptTagsHtml","map","tag","platform","src","join","replace","matchGroupName","name","match","projectRoot","manifest","serverManifest","renderAsync","exportServer","skipHtmlPrerendering","files","Map","subsetServerManifest","headers","redirects","set","contents","JSON","stringify","targetDomain","Promise","all","includeGroupVariations","route","filePath","pathname","type","data","routeId","e","logMetroErrorAsync","error","Error","modifyRouteNodeInRuntimeManifest","callback","iterateScreens","screens","Object","values","value","_route","makeRuntimeEntryPointsAbsolute","appDir","Array","isArray","entryPoints","entryPoint","shouldLinkExternally","startsWith","path","resolve","isAbsolute","resolveFrom","devServer","outputDir","baseUrl","includeSourceMaps","routerRoot","exp","useServerRendering","extra","router","unstable_useServerRendering","logOutput","web","output","learnMore","Log","log","isExporting","isExportingWithSSR","isReactServerComponentsEnabled","injectFaviconTag","getVirtualFaviconAssetsAsync","resources","executeLoaderAsync","getStaticResourcesAsync","getStaticRenderFunctionAsync","inspect","colors","depth","normalizedPathname","useServerLoaders","unstable_useServerDataLoaders","renderOpts","loaderResponse","undefined","json","loaderPath","getLoaderModulePath","fileSystemPath","slice","loaderId","loader","template","serializeHtmlWithAssets","artifacts","hydrate","getFilesFromSerialAssets","isServerHosted","assets","persistMetroAssetsAsync","outputDirectory","apiRoutes","exportApiRoutesAsync","server","exportExpoRouterRenderModuleAsync","loaderReferences","flatMap","artifact","metadata","exportLoadersAsync","cssAssets","filter","asset","filename","jsAssets","updateExportManifestInFiles","css","js","rendering","mode","file","warnPossibleInvalidExportType","htmlFiles","Set","traverseScreens","key","entries","leaf","keys","length","endsWith","stripGroupSegmentsFromPath","addOptionalGroups","add","newPath","variations","variation","uniqueBy","from","parts","split","partsWithGroups","part","filePathLocation","array","seen","result","id","has","push","routePath","segments","generateVariations","current","head","rest","groups","group","trim","apiRoutesOnly","templateHtml","htmlManifest","getServerManifestAsync","props","exportExpoRouterApiRoutesAsync","prerenderManifest","htmlRoutes","notFoundRoutes","getApiRoutesForDirectory","warn","chalk","yellow","v","relative","middlewareFile","getMiddlewareForDirectory","generated","includes","page","entryPointModules","exportExpoRouterLoadersAsync","routesWithLoaders","routesJsonEntry","get","parse"],"mappings":"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"}
|
|
@@ -267,11 +267,11 @@ function updatePkgScripts({ pkg }) {
|
|
|
267
267
|
if (!pkg.scripts) {
|
|
268
268
|
pkg.scripts = {};
|
|
269
269
|
}
|
|
270
|
-
if (
|
|
270
|
+
if (pkg.scripts.android === 'expo start --android' || pkg.scripts.android === 'react-native run-android') {
|
|
271
271
|
pkg.scripts.android = 'expo run:android';
|
|
272
272
|
hasChanged = true;
|
|
273
273
|
}
|
|
274
|
-
if (
|
|
274
|
+
if (pkg.scripts.ios === 'expo start --ios' || pkg.scripts.ios === 'react-native run-ios') {
|
|
275
275
|
pkg.scripts.ios = 'expo run:ios';
|
|
276
276
|
hasChanged = true;
|
|
277
277
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/prebuild/updatePackageJson.ts"],"sourcesContent":["import { getPackageJson, PackageJSONConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport { intersects as semverIntersects, Range as SemverRange } from 'semver';\n\nimport * as Log from '../log';\nimport { isModuleSymlinked } from '../utils/isModuleSymlinked';\nimport { logNewSection } from '../utils/ora';\n\nexport type DependenciesMap = { [key: string]: string | number };\n\nexport type DependenciesModificationResults = {\n /** A list of new values were added to the `dependencies` object in the `package.json`. */\n changedDependencies: string[];\n};\n\n/** Modifies the `package.json` with `modifyPackageJson` and format/displays the results. */\nexport async function updatePackageJSONAsync(\n projectRoot: string,\n {\n templateDirectory,\n templatePkg = getPackageJson(templateDirectory),\n pkg,\n skipDependencyUpdate,\n }: {\n templateDirectory: string;\n templatePkg?: PackageJSONConfig;\n pkg: PackageJSONConfig;\n skipDependencyUpdate?: string[];\n }\n): Promise<DependenciesModificationResults> {\n const updatingPackageJsonStep = logNewSection('Updating package.json');\n\n const results = modifyPackageJson(projectRoot, {\n templatePkg,\n pkg,\n skipDependencyUpdate,\n });\n\n const hasChanges = results.changedDependencies.length || results.scriptsChanged;\n\n // NOTE: This is effectively bundler caching and subject to breakage if the inputs don't match the mutations.\n if (hasChanges) {\n await fs.promises.writeFile(\n path.resolve(projectRoot, 'package.json'),\n // Add new line to match the format of running yarn.\n // This prevents the `package.json` from changing when running `prebuild --no-install` multiple times.\n JSON.stringify(pkg, null, 2) + '\\n'\n );\n }\n\n updatingPackageJsonStep.succeed(\n 'Updated package.json' + (hasChanges ? '' : chalk.dim(` | no changes`))\n );\n\n return results;\n}\n\n/**\n * Make required modifications to the `package.json` file as a JSON object.\n *\n * 1. Update `package.json` `scripts`.\n * 2. Update `package.json` `dependencies` (not `devDependencies`).\n * 3. Update `package.json` `main`.\n *\n * @param projectRoot The root directory of the project.\n * @param templatePkg Template project package.json as JSON.\n * @param pkg Current package.json as JSON.\n * @param skipDependencyUpdate Array of dependencies to skip updating.\n * @returns\n */\nfunction modifyPackageJson(\n projectRoot: string,\n {\n templatePkg,\n pkg,\n skipDependencyUpdate,\n }: {\n templatePkg: PackageJSONConfig;\n pkg: PackageJSONConfig;\n /** @deprecated Required packages are not overwritten, only added when missing */\n skipDependencyUpdate?: string[];\n }\n) {\n const scriptsChanged = updatePkgScripts({ pkg });\n\n // TODO: Move to `npx expo-doctor`\n return {\n scriptsChanged,\n ...updatePkgDependencies(projectRoot, {\n pkg,\n templatePkg,\n skipDependencyUpdate,\n }),\n };\n}\n\n/**\n * Update `package.json` dependencies by combining the `dependencies` in the\n * project we are creating with the dependencies in the template project.\n *\n * > Exposed for testing.\n */\nexport function updatePkgDependencies(\n projectRoot: string,\n {\n pkg,\n templatePkg,\n skipDependencyUpdate = [],\n }: {\n pkg: PackageJSONConfig;\n templatePkg: PackageJSONConfig;\n /** @deprecated Required packages are not overwritten, only added when missing */\n skipDependencyUpdate?: string[];\n }\n): DependenciesModificationResults {\n const { dependencies } = templatePkg;\n // The default values come from the bare-minimum template's package.json.\n // Users can change this by using different templates with the `--template` flag.\n // The main reason for allowing the changing of dependencies would be to include\n // dependencies that are required for the native project to build. For example,\n // it does not need to include dependencies that are used in the JS-code only.\n const defaultDependencies = createDependenciesMap(dependencies);\n\n // NOTE: This is a hack to ensure this doesn't trigger an extraneous change in the `package.json`\n // it isn't required for anything in the `ios` and `android` folders.\n delete defaultDependencies['expo-status-bar'];\n // NOTE: Expo splash screen is installed by default in the template but the config plugin also lives in prebuild-config\n // so we can delete it to prevent an extraneous change in the `package.json`.\n delete defaultDependencies['expo-splash-screen'];\n\n const combinedDependencies: DependenciesMap = createDependenciesMap({\n ...defaultDependencies,\n ...pkg.dependencies,\n });\n\n // These dependencies are only added, not overwritten from the project\n const requiredDependencies = [\n // TODO: This is no longer required because it's this same package.\n 'expo',\n // TODO: Drop this somehow.\n 'react-native',\n ].filter((depKey) => !!defaultDependencies[depKey]);\n\n const symlinkedPackages: [string, string][] = [];\n const nonRecommendedPackages: [string, string][] = [];\n\n for (const dependencyKey of requiredDependencies) {\n // If the local package.json defined the dependency that we want to overwrite...\n if (pkg.dependencies?.[dependencyKey]) {\n // Then ensure it isn't symlinked (i.e. the user has a custom version in their yarn workspace).\n if (isModuleSymlinked(projectRoot, { moduleId: dependencyKey, isSilent: true })) {\n // If the package is in the project's package.json and it's symlinked, then skip overwriting it.\n symlinkedPackages.push([\n `${dependencyKey}`,\n `${dependencyKey}@${defaultDependencies[dependencyKey]}`,\n ]);\n continue;\n }\n\n // Do not modify manually skipped dependencies\n if (skipDependencyUpdate.includes(dependencyKey)) {\n continue;\n }\n\n // Warn users for outdated dependencies when prebuilding\n const hasRecommendedVersion = versionRangesIntersect(\n pkg.dependencies[dependencyKey],\n String(defaultDependencies[dependencyKey]),\n true\n );\n if (!hasRecommendedVersion) {\n nonRecommendedPackages.push([\n `${dependencyKey}@${pkg.dependencies[dependencyKey]}`,\n `${dependencyKey}@${defaultDependencies[dependencyKey]}`,\n ]);\n }\n }\n }\n\n if (symlinkedPackages.length) {\n symlinkedPackages.forEach(([current, recommended]) => {\n Log.log(\n `\\u203A Using symlinked ${chalk.bold(current)} instead of recommended ${chalk.bold(recommended)}.`\n );\n });\n }\n\n if (nonRecommendedPackages.length) {\n nonRecommendedPackages.forEach(([current, recommended]) => {\n Log.warn(\n `\\u203A Using ${chalk.bold(current)} instead of recommended ${chalk.bold(recommended)}.`\n );\n });\n }\n\n // Only change the dependencies if the normalized hash changes, this helps to reduce meaningless changes.\n const hasNewDependencies =\n hashForDependencyMap(pkg.dependencies) !== hashForDependencyMap(combinedDependencies);\n // Save the dependencies\n let changedDependencies: string[] = [];\n if (hasNewDependencies) {\n changedDependencies = diffKeys(combinedDependencies, pkg.dependencies ?? {}).sort();\n // Use Object.assign to preserve the original order of dependencies, this makes it easier to see what changed in the git diff.\n pkg.dependencies = Object.assign(pkg.dependencies ?? {}, combinedDependencies);\n }\n\n return {\n changedDependencies,\n };\n}\n\nfunction diffKeys(a: Record<string, any>, b: Record<string, any>): string[] {\n return Object.keys(a).filter((key) => a[key] !== b[key]);\n}\n\n/**\n * Create an object of type DependenciesMap a dependencies object or throw if not valid.\n *\n * @param dependencies - ideally an object of type {[key]: string} - if not then this will error.\n */\nexport function createDependenciesMap(dependencies: any): DependenciesMap {\n if (typeof dependencies !== 'object') {\n throw new Error(`Dependency map is invalid, expected object but got ${typeof dependencies}`);\n } else if (!dependencies) {\n return {};\n }\n\n const outputMap: DependenciesMap = {};\n\n for (const key of Object.keys(dependencies)) {\n const value = dependencies[key];\n if (typeof value === 'string') {\n outputMap[key] = value;\n } else {\n throw new Error(\n `Dependency for key \\`${key}\\` should be a \\`string\\`, instead got: \\`{ ${key}: ${JSON.stringify(\n value\n )} }\\``\n );\n }\n }\n return outputMap;\n}\n\n/**\n * Updates the package.json scripts for prebuild if the scripts match\n * the default values used in project templates.\n */\nexport function updatePkgScripts({ pkg }: { pkg: PackageJSONConfig }) {\n let hasChanged = false;\n if (!pkg.scripts) {\n pkg.scripts = {};\n }\n if (\n !pkg.scripts.android ||\n pkg.scripts.android === 'expo start --android' ||\n pkg.scripts.android === 'react-native run-android'\n ) {\n pkg.scripts.android = 'expo run:android';\n hasChanged = true;\n }\n if (\n !pkg.scripts.ios ||\n pkg.scripts.ios === 'expo start --ios' ||\n pkg.scripts.ios === 'react-native run-ios'\n ) {\n pkg.scripts.ios = 'expo run:ios';\n hasChanged = true;\n }\n return hasChanged;\n}\n\nfunction normalizeDependencyMap(deps: DependenciesMap): string[] {\n return Object.keys(deps)\n .map((dependency) => `${dependency}@${deps[dependency]}`)\n .sort();\n}\n\nexport function hashForDependencyMap(deps: DependenciesMap = {}): string {\n const depsList = normalizeDependencyMap(deps);\n const depsString = depsList.join('\\n');\n return createFileHash(depsString);\n}\n\nexport function createFileHash(contents: string): string {\n // this doesn't need to be secure, the shorter the better.\n return crypto.createHash('sha1').update(contents).digest('hex');\n}\n\n/**\n * Determine if two semver ranges are overlapping or intersecting.\n * This is a safe version of `semver.intersects` that does not throw.\n */\nfunction versionRangesIntersect(\n rangeA: string | SemverRange,\n rangeB: string | SemverRange,\n includePrerelease: boolean = false\n) {\n try {\n return semverIntersects(rangeA, rangeB, { includePrerelease });\n } catch {\n return false;\n }\n}\n"],"names":["createDependenciesMap","createFileHash","hashForDependencyMap","updatePackageJSONAsync","updatePkgDependencies","updatePkgScripts","projectRoot","templateDirectory","templatePkg","getPackageJson","pkg","skipDependencyUpdate","updatingPackageJsonStep","logNewSection","results","modifyPackageJson","hasChanges","changedDependencies","length","scriptsChanged","fs","promises","writeFile","path","resolve","JSON","stringify","succeed","chalk","dim","dependencies","defaultDependencies","combinedDependencies","requiredDependencies","filter","depKey","symlinkedPackages","nonRecommendedPackages","dependencyKey","isModuleSymlinked","moduleId","isSilent","push","includes","hasRecommendedVersion","versionRangesIntersect","String","forEach","current","recommended","Log","log","bold","warn","hasNewDependencies","diffKeys","sort","Object","assign","a","b","keys","key","Error","outputMap","value","hasChanged","scripts","android","ios","normalizeDependencyMap","deps","map","dependency","depsList","depsString","join","contents","crypto","createHash","update","digest","rangeA","rangeB","includePrerelease","semverIntersects"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/prebuild/updatePackageJson.ts"],"sourcesContent":["import { getPackageJson, PackageJSONConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport { intersects as semverIntersects, Range as SemverRange } from 'semver';\n\nimport * as Log from '../log';\nimport { isModuleSymlinked } from '../utils/isModuleSymlinked';\nimport { logNewSection } from '../utils/ora';\n\nexport type DependenciesMap = { [key: string]: string | number };\n\nexport type DependenciesModificationResults = {\n /** A list of new values were added to the `dependencies` object in the `package.json`. */\n changedDependencies: string[];\n};\n\n/** Modifies the `package.json` with `modifyPackageJson` and format/displays the results. */\nexport async function updatePackageJSONAsync(\n projectRoot: string,\n {\n templateDirectory,\n templatePkg = getPackageJson(templateDirectory),\n pkg,\n skipDependencyUpdate,\n }: {\n templateDirectory: string;\n templatePkg?: PackageJSONConfig;\n pkg: PackageJSONConfig;\n skipDependencyUpdate?: string[];\n }\n): Promise<DependenciesModificationResults> {\n const updatingPackageJsonStep = logNewSection('Updating package.json');\n\n const results = modifyPackageJson(projectRoot, {\n templatePkg,\n pkg,\n skipDependencyUpdate,\n });\n\n const hasChanges = results.changedDependencies.length || results.scriptsChanged;\n\n // NOTE: This is effectively bundler caching and subject to breakage if the inputs don't match the mutations.\n if (hasChanges) {\n await fs.promises.writeFile(\n path.resolve(projectRoot, 'package.json'),\n // Add new line to match the format of running yarn.\n // This prevents the `package.json` from changing when running `prebuild --no-install` multiple times.\n JSON.stringify(pkg, null, 2) + '\\n'\n );\n }\n\n updatingPackageJsonStep.succeed(\n 'Updated package.json' + (hasChanges ? '' : chalk.dim(` | no changes`))\n );\n\n return results;\n}\n\n/**\n * Make required modifications to the `package.json` file as a JSON object.\n *\n * 1. Update `package.json` `scripts`.\n * 2. Update `package.json` `dependencies` (not `devDependencies`).\n * 3. Update `package.json` `main`.\n *\n * @param projectRoot The root directory of the project.\n * @param templatePkg Template project package.json as JSON.\n * @param pkg Current package.json as JSON.\n * @param skipDependencyUpdate Array of dependencies to skip updating.\n * @returns\n */\nfunction modifyPackageJson(\n projectRoot: string,\n {\n templatePkg,\n pkg,\n skipDependencyUpdate,\n }: {\n templatePkg: PackageJSONConfig;\n pkg: PackageJSONConfig;\n /** @deprecated Required packages are not overwritten, only added when missing */\n skipDependencyUpdate?: string[];\n }\n) {\n const scriptsChanged = updatePkgScripts({ pkg });\n\n // TODO: Move to `npx expo-doctor`\n return {\n scriptsChanged,\n ...updatePkgDependencies(projectRoot, {\n pkg,\n templatePkg,\n skipDependencyUpdate,\n }),\n };\n}\n\n/**\n * Update `package.json` dependencies by combining the `dependencies` in the\n * project we are creating with the dependencies in the template project.\n *\n * > Exposed for testing.\n */\nexport function updatePkgDependencies(\n projectRoot: string,\n {\n pkg,\n templatePkg,\n skipDependencyUpdate = [],\n }: {\n pkg: PackageJSONConfig;\n templatePkg: PackageJSONConfig;\n /** @deprecated Required packages are not overwritten, only added when missing */\n skipDependencyUpdate?: string[];\n }\n): DependenciesModificationResults {\n const { dependencies } = templatePkg;\n // The default values come from the bare-minimum template's package.json.\n // Users can change this by using different templates with the `--template` flag.\n // The main reason for allowing the changing of dependencies would be to include\n // dependencies that are required for the native project to build. For example,\n // it does not need to include dependencies that are used in the JS-code only.\n const defaultDependencies = createDependenciesMap(dependencies);\n\n // NOTE: This is a hack to ensure this doesn't trigger an extraneous change in the `package.json`\n // it isn't required for anything in the `ios` and `android` folders.\n delete defaultDependencies['expo-status-bar'];\n // NOTE: Expo splash screen is installed by default in the template but the config plugin also lives in prebuild-config\n // so we can delete it to prevent an extraneous change in the `package.json`.\n delete defaultDependencies['expo-splash-screen'];\n\n const combinedDependencies: DependenciesMap = createDependenciesMap({\n ...defaultDependencies,\n ...pkg.dependencies,\n });\n\n // These dependencies are only added, not overwritten from the project\n const requiredDependencies = [\n // TODO: This is no longer required because it's this same package.\n 'expo',\n // TODO: Drop this somehow.\n 'react-native',\n ].filter((depKey) => !!defaultDependencies[depKey]);\n\n const symlinkedPackages: [string, string][] = [];\n const nonRecommendedPackages: [string, string][] = [];\n\n for (const dependencyKey of requiredDependencies) {\n // If the local package.json defined the dependency that we want to overwrite...\n if (pkg.dependencies?.[dependencyKey]) {\n // Then ensure it isn't symlinked (i.e. the user has a custom version in their yarn workspace).\n if (isModuleSymlinked(projectRoot, { moduleId: dependencyKey, isSilent: true })) {\n // If the package is in the project's package.json and it's symlinked, then skip overwriting it.\n symlinkedPackages.push([\n `${dependencyKey}`,\n `${dependencyKey}@${defaultDependencies[dependencyKey]}`,\n ]);\n continue;\n }\n\n // Do not modify manually skipped dependencies\n if (skipDependencyUpdate.includes(dependencyKey)) {\n continue;\n }\n\n // Warn users for outdated dependencies when prebuilding\n const hasRecommendedVersion = versionRangesIntersect(\n pkg.dependencies[dependencyKey],\n String(defaultDependencies[dependencyKey]),\n true\n );\n if (!hasRecommendedVersion) {\n nonRecommendedPackages.push([\n `${dependencyKey}@${pkg.dependencies[dependencyKey]}`,\n `${dependencyKey}@${defaultDependencies[dependencyKey]}`,\n ]);\n }\n }\n }\n\n if (symlinkedPackages.length) {\n symlinkedPackages.forEach(([current, recommended]) => {\n Log.log(\n `\\u203A Using symlinked ${chalk.bold(current)} instead of recommended ${chalk.bold(recommended)}.`\n );\n });\n }\n\n if (nonRecommendedPackages.length) {\n nonRecommendedPackages.forEach(([current, recommended]) => {\n Log.warn(\n `\\u203A Using ${chalk.bold(current)} instead of recommended ${chalk.bold(recommended)}.`\n );\n });\n }\n\n // Only change the dependencies if the normalized hash changes, this helps to reduce meaningless changes.\n const hasNewDependencies =\n hashForDependencyMap(pkg.dependencies) !== hashForDependencyMap(combinedDependencies);\n // Save the dependencies\n let changedDependencies: string[] = [];\n if (hasNewDependencies) {\n changedDependencies = diffKeys(combinedDependencies, pkg.dependencies ?? {}).sort();\n // Use Object.assign to preserve the original order of dependencies, this makes it easier to see what changed in the git diff.\n pkg.dependencies = Object.assign(pkg.dependencies ?? {}, combinedDependencies);\n }\n\n return {\n changedDependencies,\n };\n}\n\nfunction diffKeys(a: Record<string, any>, b: Record<string, any>): string[] {\n return Object.keys(a).filter((key) => a[key] !== b[key]);\n}\n\n/**\n * Create an object of type DependenciesMap a dependencies object or throw if not valid.\n *\n * @param dependencies - ideally an object of type {[key]: string} - if not then this will error.\n */\nexport function createDependenciesMap(dependencies: any): DependenciesMap {\n if (typeof dependencies !== 'object') {\n throw new Error(`Dependency map is invalid, expected object but got ${typeof dependencies}`);\n } else if (!dependencies) {\n return {};\n }\n\n const outputMap: DependenciesMap = {};\n\n for (const key of Object.keys(dependencies)) {\n const value = dependencies[key];\n if (typeof value === 'string') {\n outputMap[key] = value;\n } else {\n throw new Error(\n `Dependency for key \\`${key}\\` should be a \\`string\\`, instead got: \\`{ ${key}: ${JSON.stringify(\n value\n )} }\\``\n );\n }\n }\n return outputMap;\n}\n\n/**\n * Updates the package.json scripts for prebuild if the scripts match\n * the default values used in project templates.\n */\nexport function updatePkgScripts({ pkg }: { pkg: PackageJSONConfig }) {\n let hasChanged = false;\n if (!pkg.scripts) {\n pkg.scripts = {};\n }\n if (\n pkg.scripts.android === 'expo start --android' ||\n pkg.scripts.android === 'react-native run-android'\n ) {\n pkg.scripts.android = 'expo run:android';\n hasChanged = true;\n }\n if (pkg.scripts.ios === 'expo start --ios' || pkg.scripts.ios === 'react-native run-ios') {\n pkg.scripts.ios = 'expo run:ios';\n hasChanged = true;\n }\n return hasChanged;\n}\n\nfunction normalizeDependencyMap(deps: DependenciesMap): string[] {\n return Object.keys(deps)\n .map((dependency) => `${dependency}@${deps[dependency]}`)\n .sort();\n}\n\nexport function hashForDependencyMap(deps: DependenciesMap = {}): string {\n const depsList = normalizeDependencyMap(deps);\n const depsString = depsList.join('\\n');\n return createFileHash(depsString);\n}\n\nexport function createFileHash(contents: string): string {\n // this doesn't need to be secure, the shorter the better.\n return crypto.createHash('sha1').update(contents).digest('hex');\n}\n\n/**\n * Determine if two semver ranges are overlapping or intersecting.\n * This is a safe version of `semver.intersects` that does not throw.\n */\nfunction versionRangesIntersect(\n rangeA: string | SemverRange,\n rangeB: string | SemverRange,\n includePrerelease: boolean = false\n) {\n try {\n return semverIntersects(rangeA, rangeB, { includePrerelease });\n } catch {\n return false;\n }\n}\n"],"names":["createDependenciesMap","createFileHash","hashForDependencyMap","updatePackageJSONAsync","updatePkgDependencies","updatePkgScripts","projectRoot","templateDirectory","templatePkg","getPackageJson","pkg","skipDependencyUpdate","updatingPackageJsonStep","logNewSection","results","modifyPackageJson","hasChanges","changedDependencies","length","scriptsChanged","fs","promises","writeFile","path","resolve","JSON","stringify","succeed","chalk","dim","dependencies","defaultDependencies","combinedDependencies","requiredDependencies","filter","depKey","symlinkedPackages","nonRecommendedPackages","dependencyKey","isModuleSymlinked","moduleId","isSilent","push","includes","hasRecommendedVersion","versionRangesIntersect","String","forEach","current","recommended","Log","log","bold","warn","hasNewDependencies","diffKeys","sort","Object","assign","a","b","keys","key","Error","outputMap","value","hasChanged","scripts","android","ios","normalizeDependencyMap","deps","map","dependency","depsList","depsString","join","contents","crypto","createHash","update","digest","rangeA","rangeB","includePrerelease","semverIntersects"],"mappings":"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"}
|
|
@@ -477,9 +477,10 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
|
|
|
477
477
|
if (!loaderResult) {
|
|
478
478
|
return await getStaticContent(location);
|
|
479
479
|
}
|
|
480
|
+
const loaderData = await loaderResult.json();
|
|
480
481
|
return await getStaticContent(location, {
|
|
481
482
|
loader: {
|
|
482
|
-
data:
|
|
483
|
+
data: loaderData
|
|
483
484
|
}
|
|
484
485
|
});
|
|
485
486
|
};
|
|
@@ -1244,7 +1245,7 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
|
|
|
1244
1245
|
request) {
|
|
1245
1246
|
var _exp_extra;
|
|
1246
1247
|
const { exp } = (0, _config().getConfig)(this.projectRoot);
|
|
1247
|
-
const { unstable_useServerDataLoaders } = (_exp_extra = exp.extra) == null ? void 0 : _exp_extra.router;
|
|
1248
|
+
const { unstable_useServerDataLoaders, unstable_useServerRendering } = (_exp_extra = exp.extra) == null ? void 0 : _exp_extra.router;
|
|
1248
1249
|
if (!unstable_useServerDataLoaders) {
|
|
1249
1250
|
throw new _errors.CommandError('LOADERS_NOT_ENABLED', 'Server data loaders are not enabled. Add `unstable_useServerDataLoaders` to your `expo-router` plugin config.');
|
|
1250
1251
|
}
|
|
@@ -1264,15 +1265,23 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
|
|
|
1264
1265
|
if (routeModule.loader) {
|
|
1265
1266
|
// Register this module for loader HMR
|
|
1266
1267
|
this.setupLoaderHmr(modulePath);
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1268
|
+
const maybeResponse = await routeModule.loader(request, route.params);
|
|
1269
|
+
let data;
|
|
1270
|
+
if (maybeResponse instanceof Response) {
|
|
1271
|
+
var _exp_web;
|
|
1272
|
+
debug('Loader returned Response for location:', location.pathname);
|
|
1273
|
+
// In SSR, preserve `Response` from the loader
|
|
1274
|
+
if (((_exp_web = exp.web) == null ? void 0 : _exp_web.output) === 'server' && unstable_useServerRendering) {
|
|
1275
|
+
return maybeResponse;
|
|
1276
|
+
}
|
|
1277
|
+
// In SSG, extract body
|
|
1278
|
+
data = await maybeResponse.json();
|
|
1279
|
+
} else {
|
|
1280
|
+
data = maybeResponse;
|
|
1281
|
+
}
|
|
1271
1282
|
const normalizedData = data === undefined ? {} : data;
|
|
1272
1283
|
debug('Loader data:', normalizedData, ' for location:', location.pathname);
|
|
1273
|
-
return
|
|
1274
|
-
data: normalizedData
|
|
1275
|
-
};
|
|
1284
|
+
return Response.json(normalizedData);
|
|
1276
1285
|
}
|
|
1277
1286
|
debug('No loader found for location:', location.pathname);
|
|
1278
1287
|
return undefined;
|