@expo/cli 55.0.3 → 56.0.0-canary-20260128-67ce8d5
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 +3 -1
- package/build/bin/cli.map +1 -1
- package/build/src/start/interface/interactiveActions.js +2 -1
- package/build/src/start/interface/interactiveActions.js.map +1 -1
- package/build/src/start/server/UrlCreator.js +1 -1
- package/build/src/start/server/UrlCreator.js.map +1 -1
- package/build/src/start/server/metro/DevToolsPluginWebsocketEndpoint.js +1 -1
- package/build/src/start/server/metro/DevToolsPluginWebsocketEndpoint.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +4 -4
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/MetroTerminalReporter.js +144 -33
- package/build/src/start/server/metro/MetroTerminalReporter.js.map +1 -1
- package/build/src/start/server/metro/createServerComponentsMiddleware.js +2 -2
- package/build/src/start/server/metro/createServerComponentsMiddleware.js.map +1 -1
- package/build/src/start/server/metro/fetchRouterManifest.js +1 -13
- package/build/src/start/server/metro/fetchRouterManifest.js.map +1 -1
- package/build/src/start/server/metro/instantiateMetro.js +53 -0
- package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js +3 -1
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/ManifestMiddleware.js +14 -9
- package/build/src/start/server/middleware/ManifestMiddleware.js.map +1 -1
- package/build/src/start/server/type-generation/routes.js +2 -62
- package/build/src/start/server/type-generation/routes.js.map +1 -1
- package/build/src/utils/build-cache-providers/index.js +1 -1
- package/build/src/utils/build-cache-providers/index.js.map +1 -1
- package/build/src/utils/env.js +28 -0
- package/build/src/utils/env.js.map +1 -1
- package/build/src/utils/freeport.js +21 -5
- package/build/src/utils/freeport.js.map +1 -1
- package/build/src/utils/interactive.js +1 -1
- package/build/src/utils/interactive.js.map +1 -1
- package/build/src/utils/jsonl.js +243 -0
- package/build/src/utils/jsonl.js.map +1 -0
- package/build/src/utils/port.js +4 -4
- package/build/src/utils/port.js.map +1 -1
- package/build/src/utils/progress.js +5 -0
- package/build/src/utils/progress.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/build/src/utils/url.js +4 -8
- package/build/src/utils/url.js.map +1 -1
- package/package.json +19 -20
|
@@ -140,7 +140,7 @@ class ManifestMiddleware extends _ExpoMiddleware.ExpoMiddleware {
|
|
|
140
140
|
this.initialProjectConfig = (0, _config().getConfig)(projectRoot);
|
|
141
141
|
this.platformBundlers = (0, _platformBundlers.getPlatformBundlers)(projectRoot, this.initialProjectConfig.exp);
|
|
142
142
|
}
|
|
143
|
-
/** Exposed for testing. */ async _resolveProjectSettingsAsync({ platform, hostname, protocol }) {
|
|
143
|
+
/** Exposed for testing. */ async _resolveProjectSettingsAsync({ platform, hostname, protocol, port }) {
|
|
144
144
|
var _projectConfig_exp_experiments;
|
|
145
145
|
// Read the config
|
|
146
146
|
const projectConfig = (0, _config().getConfig)(this.projectRoot);
|
|
@@ -153,11 +153,13 @@ class ManifestMiddleware extends _ExpoMiddleware.ExpoMiddleware {
|
|
|
153
153
|
// Create the manifest and set fields within it
|
|
154
154
|
const expoGoConfig = this.getExpoGoConfig({
|
|
155
155
|
mainModuleName,
|
|
156
|
-
hostname
|
|
156
|
+
hostname,
|
|
157
|
+
port
|
|
157
158
|
});
|
|
158
159
|
const hostUri = this.options.constructUrl({
|
|
159
|
-
scheme:
|
|
160
|
-
hostname
|
|
160
|
+
scheme: protocol,
|
|
161
|
+
hostname,
|
|
162
|
+
port
|
|
161
163
|
});
|
|
162
164
|
const bundleUrl = this._getBundleUrl({
|
|
163
165
|
platform,
|
|
@@ -168,7 +170,8 @@ class ManifestMiddleware extends _ExpoMiddleware.ExpoMiddleware {
|
|
|
168
170
|
asyncRoutes: (0, _metroOptions.getAsyncRoutesFromExpoConfig)(projectConfig.exp, this.options.mode ?? 'development', platform),
|
|
169
171
|
routerRoot: (0, _router.getRouterDirectoryModuleIdWithManifest)(this.projectRoot, projectConfig.exp),
|
|
170
172
|
protocol,
|
|
171
|
-
reactCompiler: !!((_projectConfig_exp_experiments = projectConfig.exp.experiments) == null ? void 0 : _projectConfig_exp_experiments.reactCompiler)
|
|
173
|
+
reactCompiler: !!((_projectConfig_exp_experiments = projectConfig.exp.experiments) == null ? void 0 : _projectConfig_exp_experiments.reactCompiler),
|
|
174
|
+
port
|
|
172
175
|
});
|
|
173
176
|
// Resolve all assets and set them on the manifest as URLs
|
|
174
177
|
await this.mutateManifestWithAssetsAsync(projectConfig.exp, bundleUrl);
|
|
@@ -200,7 +203,7 @@ class ManifestMiddleware extends _ExpoMiddleware.ExpoMiddleware {
|
|
|
200
203
|
await _devices.saveDevicesAsync(this.projectRoot, deviceIds).catch((e)=>_log.exception(e));
|
|
201
204
|
}
|
|
202
205
|
}
|
|
203
|
-
/** Create the bundle URL (points to the single JS entry file). Exposed for testing. */ _getBundleUrl({ platform, mainModuleName, hostname, engine, baseUrl, isExporting, asyncRoutes, routerRoot, protocol, reactCompiler }) {
|
|
206
|
+
/** Create the bundle URL (points to the single JS entry file). Exposed for testing. */ _getBundleUrl({ platform, mainModuleName, hostname, engine, baseUrl, isExporting, asyncRoutes, routerRoot, protocol, reactCompiler, port }) {
|
|
204
207
|
const path = (0, _metroOptions.createBundleUrlPath)({
|
|
205
208
|
mode: this.options.mode ?? 'development',
|
|
206
209
|
minify: this.options.minify,
|
|
@@ -218,15 +221,17 @@ class ManifestMiddleware extends _ExpoMiddleware.ExpoMiddleware {
|
|
|
218
221
|
return this.options.constructUrl({
|
|
219
222
|
scheme: protocol ?? 'http',
|
|
220
223
|
// hostType: this.options.location.hostType,
|
|
221
|
-
hostname
|
|
224
|
+
hostname,
|
|
225
|
+
port
|
|
222
226
|
}) + path;
|
|
223
227
|
}
|
|
224
|
-
getExpoGoConfig({ mainModuleName, hostname }) {
|
|
228
|
+
getExpoGoConfig({ mainModuleName, hostname, port }) {
|
|
225
229
|
return {
|
|
226
230
|
// localhost:8081
|
|
227
231
|
debuggerHost: this.options.constructUrl({
|
|
228
232
|
scheme: '',
|
|
229
|
-
hostname
|
|
233
|
+
hostname,
|
|
234
|
+
port
|
|
230
235
|
}),
|
|
231
236
|
// Required for Expo Go to function.
|
|
232
237
|
developer: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/middleware/ManifestMiddleware.ts"],"sourcesContent":["import {\n ExpoConfig,\n ExpoGoConfig,\n getConfig,\n PackageJSONConfig,\n ProjectConfig,\n} from '@expo/config';\nimport { resolveEntryPoint, getMetroServerRoot } from '@expo/config/paths';\nimport path from 'path';\nimport { resolve } from 'url';\n\nimport { ExpoMiddleware } from './ExpoMiddleware';\nimport {\n createBundleUrlPath,\n getBaseUrlFromExpoConfig,\n getAsyncRoutesFromExpoConfig,\n createBundleUrlPathFromExpoConfig,\n convertPathToModuleSpecifier,\n} from './metroOptions';\nimport { resolveGoogleServicesFile, resolveManifestAssets } from './resolveAssets';\nimport { parsePlatformHeader, RuntimePlatform } from './resolvePlatform';\nimport { ServerHeaders, ServerNext, ServerRequest, ServerResponse } from './server.types';\nimport { isEnableHermesManaged } from '../../../export/exportHermes';\nimport * as Log from '../../../log';\nimport { env } from '../../../utils/env';\nimport { CommandError } from '../../../utils/errors';\nimport { stripExtension } from '../../../utils/url';\nimport * as ProjectDevices from '../../project/devices';\nimport { UrlCreator } from '../UrlCreator';\nimport { getRouterDirectoryModuleIdWithManifest } from '../metro/router';\nimport { getPlatformBundlers, PlatformBundlers } from '../platformBundlers';\nimport { createTemplateHtmlFromExpoConfigAsync } from '../webTemplate';\n\nconst debug = require('debug')('expo:start:server:middleware:manifest') as typeof console.log;\n\nconst supportedPlatforms = ['ios', 'android', 'web', 'none'];\n\nexport function getEntryWithServerRoot(\n projectRoot: string,\n props: { platform: string; pkg?: PackageJSONConfig }\n) {\n if (!supportedPlatforms.includes(props.platform)) {\n throw new CommandError(\n `Failed to resolve the project's entry file: The platform \"${props.platform}\" is not supported.`\n );\n }\n return convertPathToModuleSpecifier(\n path.relative(getMetroServerRoot(projectRoot), resolveEntryPoint(projectRoot, props))\n );\n}\n\n/** Get the main entry module ID (file) relative to the project root. */\nexport function resolveMainModuleName(\n projectRoot: string,\n props: { platform: string; pkg?: PackageJSONConfig }\n): string {\n const entryPoint = getEntryWithServerRoot(projectRoot, props);\n\n debug(`Resolved entry point: ${entryPoint} (project root: ${projectRoot})`);\n\n return convertPathToModuleSpecifier(stripExtension(entryPoint, 'js'));\n}\n\n/** Info about the computer hosting the dev server. */\nexport interface HostInfo {\n host: string;\n server: 'expo';\n serverVersion: string;\n serverDriver: string | null;\n serverOS: NodeJS.Platform;\n serverOSVersion: string;\n}\n\n/** Parsed values from the supported request headers. */\nexport interface ManifestRequestInfo {\n /** Platform to serve. */\n platform: RuntimePlatform;\n /** Requested host name. */\n hostname?: string | null;\n /** The protocol used to request the manifest */\n protocol?: 'http' | 'https';\n}\n\n/** Project related info. */\nexport type ResponseProjectSettings = {\n expoGoConfig: ExpoGoConfig;\n hostUri: string;\n bundleUrl: string;\n exp: ExpoConfig;\n};\n\nexport const DEVELOPER_TOOL = 'expo-cli';\n\nexport type ManifestMiddlewareOptions = {\n /** Should start the dev servers in development mode (minify). */\n mode?: 'development' | 'production';\n /** Should instruct the bundler to create minified bundles. */\n minify?: boolean;\n constructUrl: UrlCreator['constructUrl'];\n isNativeWebpack?: boolean;\n privateKeyPath?: string;\n};\n\n/** Base middleware creator for serving the Expo manifest (like the index.html but for native runtimes). */\nexport abstract class ManifestMiddleware<\n TManifestRequestInfo extends ManifestRequestInfo,\n> extends ExpoMiddleware {\n private initialProjectConfig: ProjectConfig;\n private platformBundlers: PlatformBundlers;\n\n constructor(\n protected projectRoot: string,\n protected options: ManifestMiddlewareOptions\n ) {\n super(\n projectRoot,\n /**\n * Only support `/`, `/manifest`, `/index.exp` for the manifest middleware.\n */\n ['/', '/manifest', '/index.exp']\n );\n this.initialProjectConfig = getConfig(projectRoot);\n this.platformBundlers = getPlatformBundlers(projectRoot, this.initialProjectConfig.exp);\n }\n\n /** Exposed for testing. */\n public async _resolveProjectSettingsAsync({\n platform,\n hostname,\n protocol,\n }: Pick<\n TManifestRequestInfo,\n 'hostname' | 'platform' | 'protocol'\n >): Promise<ResponseProjectSettings> {\n // Read the config\n const projectConfig = getConfig(this.projectRoot);\n\n // Read from headers\n const mainModuleName = this.resolveMainModuleName({\n pkg: projectConfig.pkg,\n platform,\n });\n\n const isHermesEnabled = isEnableHermesManaged(projectConfig.exp, platform);\n\n // Create the manifest and set fields within it\n const expoGoConfig = this.getExpoGoConfig({\n mainModuleName,\n hostname,\n });\n\n const hostUri = this.options.constructUrl({ scheme: '', hostname });\n\n const bundleUrl = this._getBundleUrl({\n platform,\n mainModuleName,\n hostname,\n engine: isHermesEnabled ? 'hermes' : undefined,\n baseUrl: getBaseUrlFromExpoConfig(projectConfig.exp),\n asyncRoutes: getAsyncRoutesFromExpoConfig(\n projectConfig.exp,\n this.options.mode ?? 'development',\n platform\n ),\n routerRoot: getRouterDirectoryModuleIdWithManifest(this.projectRoot, projectConfig.exp),\n protocol,\n reactCompiler: !!projectConfig.exp.experiments?.reactCompiler,\n });\n\n // Resolve all assets and set them on the manifest as URLs\n await this.mutateManifestWithAssetsAsync(projectConfig.exp, bundleUrl);\n\n return {\n expoGoConfig,\n hostUri,\n bundleUrl,\n exp: projectConfig.exp,\n };\n }\n\n /** Get the main entry module ID (file) relative to the project root. */\n private resolveMainModuleName(props: { pkg: PackageJSONConfig; platform: string }): string {\n let entryPoint = getEntryWithServerRoot(this.projectRoot, props);\n\n debug(`Resolved entry point: ${entryPoint} (project root: ${this.projectRoot})`);\n\n // NOTE(Bacon): Webpack is currently hardcoded to index.bundle on native\n // in the future (TODO) we should move this logic into a Webpack plugin and use\n // a generated file name like we do on web.\n // const server = getDefaultDevServer();\n // // TODO: Move this into BundlerDevServer and read this info from self.\n // const isNativeWebpack = server instanceof WebpackBundlerDevServer && server.isTargetingNative();\n if (this.options.isNativeWebpack) {\n entryPoint = 'index.js';\n }\n\n return stripExtension(entryPoint, 'js');\n }\n\n /** Parse request headers into options. */\n public abstract getParsedHeaders(req: ServerRequest): TManifestRequestInfo;\n\n /** Store device IDs that were sent in the request headers. */\n private async saveDevicesAsync(req: ServerRequest) {\n const deviceIds = req.headers?.['expo-dev-client-id'];\n if (deviceIds) {\n await ProjectDevices.saveDevicesAsync(this.projectRoot, deviceIds).catch((e) =>\n Log.exception(e)\n );\n }\n }\n\n /** Create the bundle URL (points to the single JS entry file). Exposed for testing. */\n public _getBundleUrl({\n platform,\n mainModuleName,\n hostname,\n engine,\n baseUrl,\n isExporting,\n asyncRoutes,\n routerRoot,\n protocol,\n reactCompiler,\n }: {\n platform: string;\n hostname?: string | null;\n mainModuleName: string;\n engine?: 'hermes';\n baseUrl?: string;\n asyncRoutes: boolean;\n isExporting?: boolean;\n routerRoot: string;\n protocol?: 'http' | 'https';\n reactCompiler: boolean;\n }): string {\n const path = createBundleUrlPath({\n mode: this.options.mode ?? 'development',\n minify: this.options.minify,\n platform,\n mainModuleName,\n lazy: !env.EXPO_NO_METRO_LAZY,\n engine,\n bytecode: engine === 'hermes',\n baseUrl,\n isExporting: !!isExporting,\n asyncRoutes,\n routerRoot,\n reactCompiler,\n });\n\n return (\n this.options.constructUrl({\n scheme: protocol ?? 'http',\n // hostType: this.options.location.hostType,\n hostname,\n }) + path\n );\n }\n\n /** Get the manifest response to return to the runtime. This file contains info regarding where the assets can be loaded from. Exposed for testing. */\n public abstract _getManifestResponseAsync(options: TManifestRequestInfo): Promise<{\n body: string;\n version: string;\n headers: ServerHeaders;\n }>;\n\n private getExpoGoConfig({\n mainModuleName,\n hostname,\n }: {\n mainModuleName: string;\n hostname?: string | null;\n }): ExpoGoConfig {\n return {\n // localhost:8081\n debuggerHost: this.options.constructUrl({ scheme: '', hostname }),\n // Required for Expo Go to function.\n developer: {\n tool: DEVELOPER_TOOL,\n projectRoot: this.projectRoot,\n },\n packagerOpts: {\n // Required for dev client.\n dev: this.options.mode !== 'production',\n },\n // Indicates the name of the main bundle.\n mainModuleName,\n };\n }\n\n /** Resolve all assets and set them on the manifest as URLs */\n private async mutateManifestWithAssetsAsync(manifest: ExpoConfig, bundleUrl: string) {\n await resolveManifestAssets(this.projectRoot, {\n manifest,\n resolver: async (path) => {\n if (this.options.isNativeWebpack) {\n // When using our custom dev server, just do assets normally\n // without the `assets/` subpath redirect.\n return resolve(bundleUrl!.match(/^https?:\\/\\/.*?\\//)![0], path);\n }\n return bundleUrl!.match(/^https?:\\/\\/.*?\\//)![0] + 'assets/' + path;\n },\n });\n // The server normally inserts this but if we're offline we'll do it here\n await resolveGoogleServicesFile(this.projectRoot, manifest);\n }\n\n public getWebBundleUrl() {\n const platform = 'web';\n // Read from headers\n const mainModuleName = this.resolveMainModuleName({\n pkg: this.initialProjectConfig.pkg,\n platform,\n });\n\n return createBundleUrlPathFromExpoConfig(this.projectRoot, this.initialProjectConfig.exp, {\n platform,\n mainModuleName,\n minify: this.options.minify,\n lazy: !env.EXPO_NO_METRO_LAZY,\n mode: this.options.mode ?? 'development',\n // Hermes doesn't support more modern JS features than most, if not all, modern browser.\n engine: 'hermes',\n isExporting: false,\n bytecode: false,\n });\n }\n\n /**\n * Web platforms should create an index.html response using the same script resolution as native.\n *\n * Instead of adding a `bundleUrl` to a `manifest.json` (native) we'll add a `<script src=\"\">`\n * to an `index.html`, this enables the web platform to load JavaScript from the server.\n */\n private async handleWebRequestAsync(req: ServerRequest, res: ServerResponse) {\n res.setHeader('Content-Type', 'text/html');\n\n res.end(await this.getSingleHtmlTemplateAsync());\n }\n\n getSingleHtmlTemplateAsync() {\n // Read from headers\n const bundleUrl = this.getWebBundleUrl();\n\n return createTemplateHtmlFromExpoConfigAsync(this.projectRoot, {\n exp: this.initialProjectConfig.exp,\n scripts: [bundleUrl],\n });\n }\n\n /** Exposed for testing. */\n async checkBrowserRequestAsync(req: ServerRequest, res: ServerResponse, next: ServerNext) {\n if (\n this.platformBundlers.web === 'metro' &&\n this.initialProjectConfig.exp.platforms?.includes('web')\n ) {\n // NOTE(EvanBacon): This effectively disables the safety check we do on custom runtimes to ensure\n // the `expo-platform` header is included. When `web.bundler=web`, if the user has non-standard Expo\n // code loading then they'll get a web bundle without a clear assertion of platform support.\n const platform = parsePlatformHeader(req);\n // On web, serve the public folder\n if (!platform || platform === 'web') {\n if (['static', 'server'].includes(this.initialProjectConfig.exp.web?.output ?? '')) {\n // Skip the spa-styled index.html when static generation is enabled.\n next();\n return true;\n } else {\n await this.handleWebRequestAsync(req, res);\n return true;\n }\n }\n }\n return false;\n }\n\n async handleRequestAsync(\n req: ServerRequest,\n res: ServerResponse,\n next: ServerNext\n ): Promise<void> {\n // First check for standard JavaScript runtimes (aka legacy browsers like Chrome).\n if (await this.checkBrowserRequestAsync(req, res, next)) {\n return;\n }\n\n // Save device IDs for dev client.\n await this.saveDevicesAsync(req);\n\n // Read from headers\n const options = this.getParsedHeaders(req);\n const { body, headers } = await this._getManifestResponseAsync(options);\n for (const [headerName, headerValue] of headers) {\n res.setHeader(headerName, headerValue);\n }\n res.end(body);\n }\n}\n"],"names":["DEVELOPER_TOOL","ManifestMiddleware","getEntryWithServerRoot","resolveMainModuleName","debug","require","supportedPlatforms","projectRoot","props","includes","platform","CommandError","convertPathToModuleSpecifier","path","relative","getMetroServerRoot","resolveEntryPoint","entryPoint","stripExtension","ExpoMiddleware","constructor","options","initialProjectConfig","getConfig","platformBundlers","getPlatformBundlers","exp","_resolveProjectSettingsAsync","hostname","protocol","projectConfig","mainModuleName","pkg","isHermesEnabled","isEnableHermesManaged","expoGoConfig","getExpoGoConfig","hostUri","constructUrl","scheme","bundleUrl","_getBundleUrl","engine","undefined","baseUrl","getBaseUrlFromExpoConfig","asyncRoutes","getAsyncRoutesFromExpoConfig","mode","routerRoot","getRouterDirectoryModuleIdWithManifest","reactCompiler","experiments","mutateManifestWithAssetsAsync","isNativeWebpack","saveDevicesAsync","req","deviceIds","headers","ProjectDevices","catch","e","Log","exception","isExporting","createBundleUrlPath","minify","lazy","env","EXPO_NO_METRO_LAZY","bytecode","debuggerHost","developer","tool","packagerOpts","dev","manifest","resolveManifestAssets","resolver","resolve","match","resolveGoogleServicesFile","getWebBundleUrl","createBundleUrlPathFromExpoConfig","handleWebRequestAsync","res","setHeader","end","getSingleHtmlTemplateAsync","createTemplateHtmlFromExpoConfigAsync","scripts","checkBrowserRequestAsync","next","web","platforms","parsePlatformHeader","output","handleRequestAsync","getParsedHeaders","body","_getManifestResponseAsync","headerName","headerValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/middleware/ManifestMiddleware.ts"],"sourcesContent":["import {\n ExpoConfig,\n ExpoGoConfig,\n getConfig,\n PackageJSONConfig,\n ProjectConfig,\n} from '@expo/config';\nimport { resolveEntryPoint, getMetroServerRoot } from '@expo/config/paths';\nimport path from 'path';\nimport { resolve } from 'url';\n\nimport { ExpoMiddleware } from './ExpoMiddleware';\nimport {\n createBundleUrlPath,\n getBaseUrlFromExpoConfig,\n getAsyncRoutesFromExpoConfig,\n createBundleUrlPathFromExpoConfig,\n convertPathToModuleSpecifier,\n} from './metroOptions';\nimport { resolveGoogleServicesFile, resolveManifestAssets } from './resolveAssets';\nimport { parsePlatformHeader, RuntimePlatform } from './resolvePlatform';\nimport { ServerHeaders, ServerNext, ServerRequest, ServerResponse } from './server.types';\nimport { isEnableHermesManaged } from '../../../export/exportHermes';\nimport * as Log from '../../../log';\nimport { env } from '../../../utils/env';\nimport { CommandError } from '../../../utils/errors';\nimport { stripExtension } from '../../../utils/url';\nimport * as ProjectDevices from '../../project/devices';\nimport { UrlCreator } from '../UrlCreator';\nimport { getRouterDirectoryModuleIdWithManifest } from '../metro/router';\nimport { getPlatformBundlers, PlatformBundlers } from '../platformBundlers';\nimport { createTemplateHtmlFromExpoConfigAsync } from '../webTemplate';\n\nconst debug = require('debug')('expo:start:server:middleware:manifest') as typeof console.log;\n\nconst supportedPlatforms = ['ios', 'android', 'web', 'none'];\n\nexport function getEntryWithServerRoot(\n projectRoot: string,\n props: { platform: string; pkg?: PackageJSONConfig }\n) {\n if (!supportedPlatforms.includes(props.platform)) {\n throw new CommandError(\n `Failed to resolve the project's entry file: The platform \"${props.platform}\" is not supported.`\n );\n }\n return convertPathToModuleSpecifier(\n path.relative(getMetroServerRoot(projectRoot), resolveEntryPoint(projectRoot, props))\n );\n}\n\n/** Get the main entry module ID (file) relative to the project root. */\nexport function resolveMainModuleName(\n projectRoot: string,\n props: { platform: string; pkg?: PackageJSONConfig }\n): string {\n const entryPoint = getEntryWithServerRoot(projectRoot, props);\n\n debug(`Resolved entry point: ${entryPoint} (project root: ${projectRoot})`);\n\n return convertPathToModuleSpecifier(stripExtension(entryPoint, 'js'));\n}\n\n/** Info about the computer hosting the dev server. */\nexport interface HostInfo {\n host: string;\n server: 'expo';\n serverVersion: string;\n serverDriver: string | null;\n serverOS: NodeJS.Platform;\n serverOSVersion: string;\n}\n\n/** Parsed values from the supported request headers. */\nexport interface ManifestRequestInfo {\n /** Platform to serve. */\n platform: RuntimePlatform;\n /** Requested host name. */\n hostname?: string | null;\n /** The protocol used to request the manifest */\n protocol?: 'http' | 'https';\n /** The port used to request the manifest */\n port?: string | null;\n}\n\n/** Project related info. */\nexport type ResponseProjectSettings = {\n expoGoConfig: ExpoGoConfig;\n hostUri: string;\n bundleUrl: string;\n exp: ExpoConfig;\n};\n\nexport const DEVELOPER_TOOL = 'expo-cli';\n\nexport type ManifestMiddlewareOptions = {\n /** Should start the dev servers in development mode (minify). */\n mode?: 'development' | 'production';\n /** Should instruct the bundler to create minified bundles. */\n minify?: boolean;\n constructUrl: UrlCreator['constructUrl'];\n isNativeWebpack?: boolean;\n privateKeyPath?: string;\n};\n\n/** Base middleware creator for serving the Expo manifest (like the index.html but for native runtimes). */\nexport abstract class ManifestMiddleware<\n TManifestRequestInfo extends ManifestRequestInfo,\n> extends ExpoMiddleware {\n private initialProjectConfig: ProjectConfig;\n private platformBundlers: PlatformBundlers;\n\n constructor(\n protected projectRoot: string,\n protected options: ManifestMiddlewareOptions\n ) {\n super(\n projectRoot,\n /**\n * Only support `/`, `/manifest`, `/index.exp` for the manifest middleware.\n */\n ['/', '/manifest', '/index.exp']\n );\n this.initialProjectConfig = getConfig(projectRoot);\n this.platformBundlers = getPlatformBundlers(projectRoot, this.initialProjectConfig.exp);\n }\n\n /** Exposed for testing. */\n public async _resolveProjectSettingsAsync({\n platform,\n hostname,\n protocol,\n port,\n }: Pick<\n TManifestRequestInfo,\n 'hostname' | 'platform' | 'protocol' | 'port'\n >): Promise<ResponseProjectSettings> {\n // Read the config\n const projectConfig = getConfig(this.projectRoot);\n\n // Read from headers\n const mainModuleName = this.resolveMainModuleName({\n pkg: projectConfig.pkg,\n platform,\n });\n\n const isHermesEnabled = isEnableHermesManaged(projectConfig.exp, platform);\n\n // Create the manifest and set fields within it\n const expoGoConfig = this.getExpoGoConfig({\n mainModuleName,\n hostname,\n port,\n });\n\n const hostUri = this.options.constructUrl({\n scheme: protocol,\n hostname,\n port,\n });\n\n const bundleUrl = this._getBundleUrl({\n platform,\n mainModuleName,\n hostname,\n engine: isHermesEnabled ? 'hermes' : undefined,\n baseUrl: getBaseUrlFromExpoConfig(projectConfig.exp),\n asyncRoutes: getAsyncRoutesFromExpoConfig(\n projectConfig.exp,\n this.options.mode ?? 'development',\n platform\n ),\n routerRoot: getRouterDirectoryModuleIdWithManifest(this.projectRoot, projectConfig.exp),\n protocol,\n reactCompiler: !!projectConfig.exp.experiments?.reactCompiler,\n port,\n });\n\n // Resolve all assets and set them on the manifest as URLs\n await this.mutateManifestWithAssetsAsync(projectConfig.exp, bundleUrl);\n\n return {\n expoGoConfig,\n hostUri,\n bundleUrl,\n exp: projectConfig.exp,\n };\n }\n\n /** Get the main entry module ID (file) relative to the project root. */\n private resolveMainModuleName(props: { pkg: PackageJSONConfig; platform: string }): string {\n let entryPoint = getEntryWithServerRoot(this.projectRoot, props);\n\n debug(`Resolved entry point: ${entryPoint} (project root: ${this.projectRoot})`);\n\n // NOTE(Bacon): Webpack is currently hardcoded to index.bundle on native\n // in the future (TODO) we should move this logic into a Webpack plugin and use\n // a generated file name like we do on web.\n // const server = getDefaultDevServer();\n // // TODO: Move this into BundlerDevServer and read this info from self.\n // const isNativeWebpack = server instanceof WebpackBundlerDevServer && server.isTargetingNative();\n if (this.options.isNativeWebpack) {\n entryPoint = 'index.js';\n }\n\n return stripExtension(entryPoint, 'js');\n }\n\n /** Parse request headers into options. */\n public abstract getParsedHeaders(req: ServerRequest): TManifestRequestInfo;\n\n /** Store device IDs that were sent in the request headers. */\n private async saveDevicesAsync(req: ServerRequest) {\n const deviceIds = req.headers?.['expo-dev-client-id'];\n if (deviceIds) {\n await ProjectDevices.saveDevicesAsync(this.projectRoot, deviceIds).catch((e) =>\n Log.exception(e)\n );\n }\n }\n\n /** Create the bundle URL (points to the single JS entry file). Exposed for testing. */\n public _getBundleUrl({\n platform,\n mainModuleName,\n hostname,\n engine,\n baseUrl,\n isExporting,\n asyncRoutes,\n routerRoot,\n protocol,\n reactCompiler,\n port,\n }: {\n platform: string;\n hostname?: string | null;\n mainModuleName: string;\n engine?: 'hermes';\n baseUrl?: string;\n asyncRoutes: boolean;\n isExporting?: boolean;\n routerRoot: string;\n protocol?: 'http' | 'https';\n reactCompiler: boolean;\n port?: string | null;\n }): string {\n const path = createBundleUrlPath({\n mode: this.options.mode ?? 'development',\n minify: this.options.minify,\n platform,\n mainModuleName,\n lazy: !env.EXPO_NO_METRO_LAZY,\n engine,\n bytecode: engine === 'hermes',\n baseUrl,\n isExporting: !!isExporting,\n asyncRoutes,\n routerRoot,\n reactCompiler,\n });\n\n return (\n this.options.constructUrl({\n scheme: protocol ?? 'http',\n // hostType: this.options.location.hostType,\n hostname,\n port,\n }) + path\n );\n }\n\n /** Get the manifest response to return to the runtime. This file contains info regarding where the assets can be loaded from. Exposed for testing. */\n public abstract _getManifestResponseAsync(options: TManifestRequestInfo): Promise<{\n body: string;\n version: string;\n headers: ServerHeaders;\n }>;\n\n private getExpoGoConfig({\n mainModuleName,\n hostname,\n port,\n }: {\n mainModuleName: string;\n hostname?: string | null;\n port?: string | null;\n }): ExpoGoConfig {\n return {\n // localhost:8081\n debuggerHost: this.options.constructUrl({ scheme: '', hostname, port }),\n // Required for Expo Go to function.\n developer: {\n tool: DEVELOPER_TOOL,\n projectRoot: this.projectRoot,\n },\n packagerOpts: {\n // Required for dev client.\n dev: this.options.mode !== 'production',\n },\n // Indicates the name of the main bundle.\n mainModuleName,\n };\n }\n\n /** Resolve all assets and set them on the manifest as URLs */\n private async mutateManifestWithAssetsAsync(manifest: ExpoConfig, bundleUrl: string) {\n await resolveManifestAssets(this.projectRoot, {\n manifest,\n resolver: async (path) => {\n if (this.options.isNativeWebpack) {\n // When using our custom dev server, just do assets normally\n // without the `assets/` subpath redirect.\n return resolve(bundleUrl!.match(/^https?:\\/\\/.*?\\//)![0], path);\n }\n return bundleUrl!.match(/^https?:\\/\\/.*?\\//)![0] + 'assets/' + path;\n },\n });\n // The server normally inserts this but if we're offline we'll do it here\n await resolveGoogleServicesFile(this.projectRoot, manifest);\n }\n\n public getWebBundleUrl() {\n const platform = 'web';\n // Read from headers\n const mainModuleName = this.resolveMainModuleName({\n pkg: this.initialProjectConfig.pkg,\n platform,\n });\n\n return createBundleUrlPathFromExpoConfig(this.projectRoot, this.initialProjectConfig.exp, {\n platform,\n mainModuleName,\n minify: this.options.minify,\n lazy: !env.EXPO_NO_METRO_LAZY,\n mode: this.options.mode ?? 'development',\n // Hermes doesn't support more modern JS features than most, if not all, modern browser.\n engine: 'hermes',\n isExporting: false,\n bytecode: false,\n });\n }\n\n /**\n * Web platforms should create an index.html response using the same script resolution as native.\n *\n * Instead of adding a `bundleUrl` to a `manifest.json` (native) we'll add a `<script src=\"\">`\n * to an `index.html`, this enables the web platform to load JavaScript from the server.\n */\n private async handleWebRequestAsync(req: ServerRequest, res: ServerResponse) {\n res.setHeader('Content-Type', 'text/html');\n\n res.end(await this.getSingleHtmlTemplateAsync());\n }\n\n getSingleHtmlTemplateAsync() {\n // Read from headers\n const bundleUrl = this.getWebBundleUrl();\n\n return createTemplateHtmlFromExpoConfigAsync(this.projectRoot, {\n exp: this.initialProjectConfig.exp,\n scripts: [bundleUrl],\n });\n }\n\n /** Exposed for testing. */\n async checkBrowserRequestAsync(req: ServerRequest, res: ServerResponse, next: ServerNext) {\n if (\n this.platformBundlers.web === 'metro' &&\n this.initialProjectConfig.exp.platforms?.includes('web')\n ) {\n // NOTE(EvanBacon): This effectively disables the safety check we do on custom runtimes to ensure\n // the `expo-platform` header is included. When `web.bundler=web`, if the user has non-standard Expo\n // code loading then they'll get a web bundle without a clear assertion of platform support.\n const platform = parsePlatformHeader(req);\n // On web, serve the public folder\n if (!platform || platform === 'web') {\n if (['static', 'server'].includes(this.initialProjectConfig.exp.web?.output ?? '')) {\n // Skip the spa-styled index.html when static generation is enabled.\n next();\n return true;\n } else {\n await this.handleWebRequestAsync(req, res);\n return true;\n }\n }\n }\n return false;\n }\n\n async handleRequestAsync(\n req: ServerRequest,\n res: ServerResponse,\n next: ServerNext\n ): Promise<void> {\n // First check for standard JavaScript runtimes (aka legacy browsers like Chrome).\n if (await this.checkBrowserRequestAsync(req, res, next)) {\n return;\n }\n\n // Save device IDs for dev client.\n await this.saveDevicesAsync(req);\n\n // Read from headers\n const options = this.getParsedHeaders(req);\n const { body, headers } = await this._getManifestResponseAsync(options);\n for (const [headerName, headerValue] of headers) {\n res.setHeader(headerName, headerValue);\n }\n res.end(body);\n }\n}\n"],"names":["DEVELOPER_TOOL","ManifestMiddleware","getEntryWithServerRoot","resolveMainModuleName","debug","require","supportedPlatforms","projectRoot","props","includes","platform","CommandError","convertPathToModuleSpecifier","path","relative","getMetroServerRoot","resolveEntryPoint","entryPoint","stripExtension","ExpoMiddleware","constructor","options","initialProjectConfig","getConfig","platformBundlers","getPlatformBundlers","exp","_resolveProjectSettingsAsync","hostname","protocol","port","projectConfig","mainModuleName","pkg","isHermesEnabled","isEnableHermesManaged","expoGoConfig","getExpoGoConfig","hostUri","constructUrl","scheme","bundleUrl","_getBundleUrl","engine","undefined","baseUrl","getBaseUrlFromExpoConfig","asyncRoutes","getAsyncRoutesFromExpoConfig","mode","routerRoot","getRouterDirectoryModuleIdWithManifest","reactCompiler","experiments","mutateManifestWithAssetsAsync","isNativeWebpack","saveDevicesAsync","req","deviceIds","headers","ProjectDevices","catch","e","Log","exception","isExporting","createBundleUrlPath","minify","lazy","env","EXPO_NO_METRO_LAZY","bytecode","debuggerHost","developer","tool","packagerOpts","dev","manifest","resolveManifestAssets","resolver","resolve","match","resolveGoogleServicesFile","getWebBundleUrl","createBundleUrlPathFromExpoConfig","handleWebRequestAsync","res","setHeader","end","getSingleHtmlTemplateAsync","createTemplateHtmlFromExpoConfigAsync","scripts","checkBrowserRequestAsync","next","web","platforms","parsePlatformHeader","output","handleRequestAsync","getParsedHeaders","body","_getManifestResponseAsync","headerName","headerValue"],"mappings":";;;;;;;;;;;IA6FaA,cAAc;eAAdA;;IAaSC,kBAAkB;eAAlBA;;IArENC,sBAAsB;eAAtBA;;IAeAC,qBAAqB;eAArBA;;;;yBA9CT;;;;;;;yBAC+C;;;;;;;gEACrC;;;;;;;yBACO;;;;;;gCAEO;8BAOxB;+BAC0D;iCACZ;8BAEf;6DACjB;qBACD;wBACS;sBACE;iEACC;wBAEuB;kCACD;6BACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEtD,MAAMC,QAAQC,QAAQ,SAAS;AAE/B,MAAMC,qBAAqB;IAAC;IAAO;IAAW;IAAO;CAAO;AAErD,SAASJ,uBACdK,WAAmB,EACnBC,KAAoD;IAEpD,IAAI,CAACF,mBAAmBG,QAAQ,CAACD,MAAME,QAAQ,GAAG;QAChD,MAAM,IAAIC,oBAAY,CACpB,CAAC,0DAA0D,EAAEH,MAAME,QAAQ,CAAC,mBAAmB,CAAC;IAEpG;IACA,OAAOE,IAAAA,0CAA4B,EACjCC,eAAI,CAACC,QAAQ,CAACC,IAAAA,2BAAkB,EAACR,cAAcS,IAAAA,0BAAiB,EAACT,aAAaC;AAElF;AAGO,SAASL,sBACdI,WAAmB,EACnBC,KAAoD;IAEpD,MAAMS,aAAaf,uBAAuBK,aAAaC;IAEvDJ,MAAM,CAAC,sBAAsB,EAAEa,WAAW,gBAAgB,EAAEV,YAAY,CAAC,CAAC;IAE1E,OAAOK,IAAAA,0CAA4B,EAACM,IAAAA,oBAAc,EAACD,YAAY;AACjE;AAgCO,MAAMjB,iBAAiB;AAavB,MAAeC,2BAEZkB,8BAAc;IAItBC,YACE,AAAUb,WAAmB,EAC7B,AAAUc,OAAkC,CAC5C;QACA,KAAK,CACHd,aACA;;OAEC,GACD;YAAC;YAAK;YAAa;SAAa,QARxBA,cAAAA,kBACAc,UAAAA;QASV,IAAI,CAACC,oBAAoB,GAAGC,IAAAA,mBAAS,EAAChB;QACtC,IAAI,CAACiB,gBAAgB,GAAGC,IAAAA,qCAAmB,EAAClB,aAAa,IAAI,CAACe,oBAAoB,CAACI,GAAG;IACxF;IAEA,yBAAyB,GACzB,MAAaC,6BAA6B,EACxCjB,QAAQ,EACRkB,QAAQ,EACRC,QAAQ,EACRC,IAAI,EAIL,EAAoC;YAsChBC;QArCnB,kBAAkB;QAClB,MAAMA,gBAAgBR,IAAAA,mBAAS,EAAC,IAAI,CAAChB,WAAW;QAEhD,oBAAoB;QACpB,MAAMyB,iBAAiB,IAAI,CAAC7B,qBAAqB,CAAC;YAChD8B,KAAKF,cAAcE,GAAG;YACtBvB;QACF;QAEA,MAAMwB,kBAAkBC,IAAAA,mCAAqB,EAACJ,cAAcL,GAAG,EAAEhB;QAEjE,+CAA+C;QAC/C,MAAM0B,eAAe,IAAI,CAACC,eAAe,CAAC;YACxCL;YACAJ;YACAE;QACF;QAEA,MAAMQ,UAAU,IAAI,CAACjB,OAAO,CAACkB,YAAY,CAAC;YACxCC,QAAQX;YACRD;YACAE;QACF;QAEA,MAAMW,YAAY,IAAI,CAACC,aAAa,CAAC;YACnChC;YACAsB;YACAJ;YACAe,QAAQT,kBAAkB,WAAWU;YACrCC,SAASC,IAAAA,sCAAwB,EAACf,cAAcL,GAAG;YACnDqB,aAAaC,IAAAA,0CAA4B,EACvCjB,cAAcL,GAAG,EACjB,IAAI,CAACL,OAAO,CAAC4B,IAAI,IAAI,eACrBvC;YAEFwC,YAAYC,IAAAA,8CAAsC,EAAC,IAAI,CAAC5C,WAAW,EAAEwB,cAAcL,GAAG;YACtFG;YACAuB,eAAe,CAAC,GAACrB,iCAAAA,cAAcL,GAAG,CAAC2B,WAAW,qBAA7BtB,+BAA+BqB,aAAa;YAC7DtB;QACF;QAEA,0DAA0D;QAC1D,MAAM,IAAI,CAACwB,6BAA6B,CAACvB,cAAcL,GAAG,EAAEe;QAE5D,OAAO;YACLL;YACAE;YACAG;YACAf,KAAKK,cAAcL,GAAG;QACxB;IACF;IAEA,sEAAsE,GACtE,AAAQvB,sBAAsBK,KAAmD,EAAU;QACzF,IAAIS,aAAaf,uBAAuB,IAAI,CAACK,WAAW,EAAEC;QAE1DJ,MAAM,CAAC,sBAAsB,EAAEa,WAAW,gBAAgB,EAAE,IAAI,CAACV,WAAW,CAAC,CAAC,CAAC;QAE/E,wEAAwE;QACxE,+EAA+E;QAC/E,2CAA2C;QAC3C,wCAAwC;QACxC,yEAAyE;QACzE,mGAAmG;QACnG,IAAI,IAAI,CAACc,OAAO,CAACkC,eAAe,EAAE;YAChCtC,aAAa;QACf;QAEA,OAAOC,IAAAA,oBAAc,EAACD,YAAY;IACpC;IAKA,4DAA4D,GAC5D,MAAcuC,iBAAiBC,GAAkB,EAAE;YAC/BA;QAAlB,MAAMC,aAAYD,eAAAA,IAAIE,OAAO,qBAAXF,YAAa,CAAC,qBAAqB;QACrD,IAAIC,WAAW;YACb,MAAME,SAAeJ,gBAAgB,CAAC,IAAI,CAACjD,WAAW,EAAEmD,WAAWG,KAAK,CAAC,CAACC,IACxEC,KAAIC,SAAS,CAACF;QAElB;IACF;IAEA,qFAAqF,GACrF,AAAOpB,cAAc,EACnBhC,QAAQ,EACRsB,cAAc,EACdJ,QAAQ,EACRe,MAAM,EACNE,OAAO,EACPoB,WAAW,EACXlB,WAAW,EACXG,UAAU,EACVrB,QAAQ,EACRuB,aAAa,EACbtB,IAAI,EAaL,EAAU;QACT,MAAMjB,OAAOqD,IAAAA,iCAAmB,EAAC;YAC/BjB,MAAM,IAAI,CAAC5B,OAAO,CAAC4B,IAAI,IAAI;YAC3BkB,QAAQ,IAAI,CAAC9C,OAAO,CAAC8C,MAAM;YAC3BzD;YACAsB;YACAoC,MAAM,CAACC,QAAG,CAACC,kBAAkB;YAC7B3B;YACA4B,UAAU5B,WAAW;YACrBE;YACAoB,aAAa,CAAC,CAACA;YACflB;YACAG;YACAE;QACF;QAEA,OACE,IAAI,CAAC/B,OAAO,CAACkB,YAAY,CAAC;YACxBC,QAAQX,YAAY;YACpB,4CAA4C;YAC5CD;YACAE;QACF,KAAKjB;IAET;IASQwB,gBAAgB,EACtBL,cAAc,EACdJ,QAAQ,EACRE,IAAI,EAKL,EAAgB;QACf,OAAO;YACL,iBAAiB;YACjB0C,cAAc,IAAI,CAACnD,OAAO,CAACkB,YAAY,CAAC;gBAAEC,QAAQ;gBAAIZ;gBAAUE;YAAK;YACrE,oCAAoC;YACpC2C,WAAW;gBACTC,MAAM1E;gBACNO,aAAa,IAAI,CAACA,WAAW;YAC/B;YACAoE,cAAc;gBACZ,2BAA2B;gBAC3BC,KAAK,IAAI,CAACvD,OAAO,CAAC4B,IAAI,KAAK;YAC7B;YACA,yCAAyC;YACzCjB;QACF;IACF;IAEA,4DAA4D,GAC5D,MAAcsB,8BAA8BuB,QAAoB,EAAEpC,SAAiB,EAAE;QACnF,MAAMqC,IAAAA,oCAAqB,EAAC,IAAI,CAACvE,WAAW,EAAE;YAC5CsE;YACAE,UAAU,OAAOlE;gBACf,IAAI,IAAI,CAACQ,OAAO,CAACkC,eAAe,EAAE;oBAChC,4DAA4D;oBAC5D,0CAA0C;oBAC1C,OAAOyB,IAAAA,cAAO,EAACvC,UAAWwC,KAAK,CAAC,oBAAqB,CAAC,EAAE,EAAEpE;gBAC5D;gBACA,OAAO4B,UAAWwC,KAAK,CAAC,oBAAqB,CAAC,EAAE,GAAG,YAAYpE;YACjE;QACF;QACA,yEAAyE;QACzE,MAAMqE,IAAAA,wCAAyB,EAAC,IAAI,CAAC3E,WAAW,EAAEsE;IACpD;IAEOM,kBAAkB;QACvB,MAAMzE,WAAW;QACjB,oBAAoB;QACpB,MAAMsB,iBAAiB,IAAI,CAAC7B,qBAAqB,CAAC;YAChD8B,KAAK,IAAI,CAACX,oBAAoB,CAACW,GAAG;YAClCvB;QACF;QAEA,OAAO0E,IAAAA,+CAAiC,EAAC,IAAI,CAAC7E,WAAW,EAAE,IAAI,CAACe,oBAAoB,CAACI,GAAG,EAAE;YACxFhB;YACAsB;YACAmC,QAAQ,IAAI,CAAC9C,OAAO,CAAC8C,MAAM;YAC3BC,MAAM,CAACC,QAAG,CAACC,kBAAkB;YAC7BrB,MAAM,IAAI,CAAC5B,OAAO,CAAC4B,IAAI,IAAI;YAC3B,wFAAwF;YACxFN,QAAQ;YACRsB,aAAa;YACbM,UAAU;QACZ;IACF;IAEA;;;;;GAKC,GACD,MAAcc,sBAAsB5B,GAAkB,EAAE6B,GAAmB,EAAE;QAC3EA,IAAIC,SAAS,CAAC,gBAAgB;QAE9BD,IAAIE,GAAG,CAAC,MAAM,IAAI,CAACC,0BAA0B;IAC/C;IAEAA,6BAA6B;QAC3B,oBAAoB;QACpB,MAAMhD,YAAY,IAAI,CAAC0C,eAAe;QAEtC,OAAOO,IAAAA,kDAAqC,EAAC,IAAI,CAACnF,WAAW,EAAE;YAC7DmB,KAAK,IAAI,CAACJ,oBAAoB,CAACI,GAAG;YAClCiE,SAAS;gBAAClD;aAAU;QACtB;IACF;IAEA,yBAAyB,GACzB,MAAMmD,yBAAyBnC,GAAkB,EAAE6B,GAAmB,EAAEO,IAAgB,EAAE;YAGtF;QAFF,IACE,IAAI,CAACrE,gBAAgB,CAACsE,GAAG,KAAK,aAC9B,2CAAA,IAAI,CAACxE,oBAAoB,CAACI,GAAG,CAACqE,SAAS,qBAAvC,yCAAyCtF,QAAQ,CAAC,SAClD;YACA,iGAAiG;YACjG,oGAAoG;YACpG,4FAA4F;YAC5F,MAAMC,WAAWsF,IAAAA,oCAAmB,EAACvC;YACrC,kCAAkC;YAClC,IAAI,CAAC/C,YAAYA,aAAa,OAAO;oBACD;gBAAlC,IAAI;oBAAC;oBAAU;iBAAS,CAACD,QAAQ,CAAC,EAAA,qCAAA,IAAI,CAACa,oBAAoB,CAACI,GAAG,CAACoE,GAAG,qBAAjC,mCAAmCG,MAAM,KAAI,KAAK;oBAClF,oEAAoE;oBACpEJ;oBACA,OAAO;gBACT,OAAO;oBACL,MAAM,IAAI,CAACR,qBAAqB,CAAC5B,KAAK6B;oBACtC,OAAO;gBACT;YACF;QACF;QACA,OAAO;IACT;IAEA,MAAMY,mBACJzC,GAAkB,EAClB6B,GAAmB,EACnBO,IAAgB,EACD;QACf,kFAAkF;QAClF,IAAI,MAAM,IAAI,CAACD,wBAAwB,CAACnC,KAAK6B,KAAKO,OAAO;YACvD;QACF;QAEA,kCAAkC;QAClC,MAAM,IAAI,CAACrC,gBAAgB,CAACC;QAE5B,oBAAoB;QACpB,MAAMpC,UAAU,IAAI,CAAC8E,gBAAgB,CAAC1C;QACtC,MAAM,EAAE2C,IAAI,EAAEzC,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC0C,yBAAyB,CAAChF;QAC/D,KAAK,MAAM,CAACiF,YAAYC,YAAY,IAAI5C,QAAS;YAC/C2B,IAAIC,SAAS,CAACe,YAAYC;QAC5B;QACAjB,IAAIE,GAAG,CAACY;IACV;AACF"}
|
|
@@ -57,14 +57,6 @@ function _path() {
|
|
|
57
57
|
};
|
|
58
58
|
return data;
|
|
59
59
|
}
|
|
60
|
-
function _resolvefrom() {
|
|
61
|
-
const data = /*#__PURE__*/ _interop_require_default(require("resolve-from"));
|
|
62
|
-
_resolvefrom = function() {
|
|
63
|
-
return data;
|
|
64
|
-
};
|
|
65
|
-
return data;
|
|
66
|
-
}
|
|
67
|
-
const _dir = require("../../../utils/dir");
|
|
68
60
|
const _template = require("../../../utils/template");
|
|
69
61
|
const _metroWatchTypeScriptFiles = require("../metro/metroWatchTypeScriptFiles");
|
|
70
62
|
function _interop_require_default(obj) {
|
|
@@ -79,13 +71,8 @@ const ARRAY_GROUP_REGEX = /\(\s*\w[\w\s]*?,.*?\)/g;
|
|
|
79
71
|
const CAPTURE_GROUP_REGEX = /[\\(,]\s*(\w[\w\s]*?)\s*(?=[,\\)])/g;
|
|
80
72
|
const TYPED_ROUTES_EXCLUSION_REGEX = /(_layout|[^/]*?\+[^/]*?)\.[tj]sx?$/;
|
|
81
73
|
async function setupTypedRoutes(options) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
* the legacy and new versions of TypedRoutes.
|
|
85
|
-
*
|
|
86
|
-
* TODO (@marklawlor): Remove this check in SDK 53, only support Expo Router v4 and above.
|
|
87
|
-
*/ const typedRoutesModule = _resolvefrom().default.silent(options.projectRoot, '@expo/router-server/build/typed-routes');
|
|
88
|
-
return typedRoutesModule ? typedRoutes(typedRoutesModule, options) : legacyTypedRoutes(options);
|
|
74
|
+
const typedRoutesModule = require.resolve('@expo/router-server/build/typed-routes');
|
|
75
|
+
return typedRoutes(typedRoutesModule, options);
|
|
89
76
|
}
|
|
90
77
|
async function typedRoutes(typedRoutesModulePath, { server, metro, typesDirectory, projectRoot, routerDirectory, plugin }) {
|
|
91
78
|
/*
|
|
@@ -122,53 +109,6 @@ async function typedRoutes(typedRoutesModulePath, { server, metro, typesDirector
|
|
|
122
109
|
typedRoutesModule.regenerateDeclarations(typesDirectory);
|
|
123
110
|
}
|
|
124
111
|
}
|
|
125
|
-
async function legacyTypedRoutes({ server, metro, typesDirectory, projectRoot, routerDirectory }) {
|
|
126
|
-
const { filePathToRoute, staticRoutes, dynamicRoutes, addFilePath, isRouteFile } = getTypedRoutesUtils(routerDirectory);
|
|
127
|
-
// Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`
|
|
128
|
-
if (metro && server) {
|
|
129
|
-
(0, _metroWatchTypeScriptFiles.metroWatchTypeScriptFiles)({
|
|
130
|
-
projectRoot,
|
|
131
|
-
server,
|
|
132
|
-
metro,
|
|
133
|
-
eventTypes: [
|
|
134
|
-
'add',
|
|
135
|
-
'delete',
|
|
136
|
-
'change'
|
|
137
|
-
],
|
|
138
|
-
async callback ({ filePath, type }) {
|
|
139
|
-
if (!isRouteFile(filePath)) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
let shouldRegenerate = false;
|
|
143
|
-
if (type === 'delete') {
|
|
144
|
-
const route = filePathToRoute(filePath);
|
|
145
|
-
staticRoutes.delete(route);
|
|
146
|
-
dynamicRoutes.delete(route);
|
|
147
|
-
shouldRegenerate = true;
|
|
148
|
-
} else {
|
|
149
|
-
shouldRegenerate = addFilePath(filePath);
|
|
150
|
-
}
|
|
151
|
-
if (shouldRegenerate) {
|
|
152
|
-
regenerateRouterDotTS(typesDirectory, new Set([
|
|
153
|
-
...staticRoutes.values()
|
|
154
|
-
].flatMap((v)=>Array.from(v))), new Set([
|
|
155
|
-
...dynamicRoutes.values()
|
|
156
|
-
].flatMap((v)=>Array.from(v))), new Set(dynamicRoutes.keys()));
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
if (await (0, _dir.directoryExistsAsync)(routerDirectory)) {
|
|
162
|
-
// Do we need to walk the entire tree on startup?
|
|
163
|
-
// Idea: Store the list of files in the last write, then simply check Git for what files have changed
|
|
164
|
-
await walk(routerDirectory, addFilePath);
|
|
165
|
-
}
|
|
166
|
-
regenerateRouterDotTS(typesDirectory, new Set([
|
|
167
|
-
...staticRoutes.values()
|
|
168
|
-
].flatMap((v)=>Array.from(v))), new Set([
|
|
169
|
-
...dynamicRoutes.values()
|
|
170
|
-
].flatMap((v)=>Array.from(v))), new Set(dynamicRoutes.keys()));
|
|
171
|
-
}
|
|
172
112
|
function debounce(fn, delay) {
|
|
173
113
|
let timeoutId;
|
|
174
114
|
return function(...args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/type-generation/routes.ts"],"sourcesContent":["import type Server from '@expo/metro/metro/Server';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { directoryExistsAsync } from '../../../utils/dir';\nimport { unsafeTemplate } from '../../../utils/template';\nimport { ServerLike } from '../BundlerDevServer';\nimport { metroWatchTypeScriptFiles } from '../metro/metroWatchTypeScriptFiles';\n\n// /test/[...param1]/[param2]/[param3] - captures [\"param1\", \"param2\", \"param3\"]\nexport const CAPTURE_DYNAMIC_PARAMS = /\\[(?:\\.{3})?(\\w*?)[\\]$]/g;\n// /[...param1]/ - Match [...param1]\nexport const CATCH_ALL = /\\[\\.\\.\\..+?\\]/g;\n// /[param1] - Match [param1]\nexport const SLUG = /\\[.+?\\]/g;\n// /(group1,group2,group3)/test - match (group1,group2,group3)\nexport const ARRAY_GROUP_REGEX = /\\(\\s*\\w[\\w\\s]*?,.*?\\)/g;\n// /(group1,group2,group3)/test - captures [\"group1\", \"group2\", \"group3\"]\nexport const CAPTURE_GROUP_REGEX = /[\\\\(,]\\s*(\\w[\\w\\s]*?)\\s*(?=[,\\\\)])/g;\n/**\n * Match:\n * - _layout files, +html, +not-found, string+api, etc\n * - Routes can still use `+`, but it cannot be in the last segment.\n */\nexport const TYPED_ROUTES_EXCLUSION_REGEX = /(_layout|[^/]*?\\+[^/]*?)\\.[tj]sx?$/;\n\nexport interface SetupTypedRoutesOptions {\n server?: ServerLike;\n metro?: Server | null;\n typesDirectory: string;\n projectRoot: string;\n /** Absolute expo router routes directory. */\n routerDirectory: string;\n plugin?: Record<string, any>;\n}\n\nexport async function setupTypedRoutes(options: SetupTypedRoutesOptions) {\n /*\n * In SDK 51, TypedRoutes was moved out of cli and into expo-router. For now we need to support both\n * the legacy and new versions of TypedRoutes.\n *\n * TODO (@marklawlor): Remove this check in SDK 53, only support Expo Router v4 and above.\n */\n const typedRoutesModule = resolveFrom.silent(\n options.projectRoot,\n '@expo/router-server/build/typed-routes'\n );\n return typedRoutesModule ? typedRoutes(typedRoutesModule, options) : legacyTypedRoutes(options);\n}\n\nasync function typedRoutes(\n typedRoutesModulePath: any,\n { server, metro, typesDirectory, projectRoot, routerDirectory, plugin }: SetupTypedRoutesOptions\n) {\n /*\n * Expo Router uses EXPO_ROUTER_APP_ROOT in multiple places to determine the root of the project.\n * In apps compiled by Metro, this code is compiled away. But Typed Routes run in NodeJS with no compilation\n * so we need to explicitly set it.\n */\n process.env.EXPO_ROUTER_APP_ROOT = routerDirectory;\n\n const typedRoutesModule = require(typedRoutesModulePath);\n\n /*\n * Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`\n */\n if (metro && server) {\n // Setup out watcher first\n metroWatchTypeScriptFiles({\n projectRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n callback: typedRoutesModule.getWatchHandler(typesDirectory),\n });\n }\n\n /*\n * In SDK 52, the `regenerateDeclarations` was changed to accept plugin options.\n * This function has an optional parameter that we cannot override, so we need to ensure the user\n * is using a compatible version of `expo-router`. Otherwise, we will fallback to the old method.\n *\n * TODO(@marklawlor): In SDK53+ we should remove this check and always use the new method.\n */\n if ('version' in typedRoutesModule && typedRoutesModule.version >= 52) {\n typedRoutesModule.regenerateDeclarations(typesDirectory, plugin);\n } else {\n typedRoutesModule.regenerateDeclarations(typesDirectory);\n }\n}\n\nasync function legacyTypedRoutes({\n server,\n metro,\n typesDirectory,\n projectRoot,\n routerDirectory,\n}: SetupTypedRoutesOptions) {\n const { filePathToRoute, staticRoutes, dynamicRoutes, addFilePath, isRouteFile } =\n getTypedRoutesUtils(routerDirectory);\n\n // Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`\n if (metro && server) {\n metroWatchTypeScriptFiles({\n projectRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n async callback({ filePath, type }) {\n if (!isRouteFile(filePath)) {\n return;\n }\n\n let shouldRegenerate = false;\n\n if (type === 'delete') {\n const route = filePathToRoute(filePath);\n staticRoutes.delete(route);\n dynamicRoutes.delete(route);\n shouldRegenerate = true;\n } else {\n shouldRegenerate = addFilePath(filePath);\n }\n\n if (shouldRegenerate) {\n regenerateRouterDotTS(\n typesDirectory,\n new Set([...staticRoutes.values()].flatMap((v) => Array.from(v))),\n new Set([...dynamicRoutes.values()].flatMap((v) => Array.from(v))),\n new Set(dynamicRoutes.keys())\n );\n }\n },\n });\n }\n\n if (await directoryExistsAsync(routerDirectory)) {\n // Do we need to walk the entire tree on startup?\n // Idea: Store the list of files in the last write, then simply check Git for what files have changed\n await walk(routerDirectory, addFilePath);\n }\n\n regenerateRouterDotTS(\n typesDirectory,\n new Set([...staticRoutes.values()].flatMap((v) => Array.from(v))),\n new Set([...dynamicRoutes.values()].flatMap((v) => Array.from(v))),\n new Set(dynamicRoutes.keys())\n );\n}\n\nfunction debounce<U, T extends (this: U, ...args: any[]) => void>(fn: T, delay: number): T {\n let timeoutId: NodeJS.Timeout | undefined;\n return function (this: U, ...args: any[]) {\n clearTimeout(timeoutId);\n // NOTE(@hassankhan): The cast to `NodeJS.Timeout` below is a hack to work around an issue\n // with TypeScript where React Native's types are being imported before Node types\n timeoutId = setTimeout(() => fn.apply(this, args), delay) as unknown as NodeJS.Timeout;\n } as T;\n}\n\n/**\n * Generate a router.d.ts file that contains all of the routes in the project.\n * Should be debounced as its very common for developers to make changes to multiple files at once (eg Save All)\n */\nconst regenerateRouterDotTS = debounce(\n async (\n typesDir: string,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n ) => {\n await fs.mkdir(typesDir, { recursive: true });\n await fs.writeFile(\n path.resolve(typesDir, './router.d.ts'),\n getTemplateString(staticRoutes, dynamicRoutes, dynamicRouteTemplates)\n );\n },\n 100\n);\n\n/*\n * This is exported for testing purposes\n */\nexport function getTemplateString(\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n) {\n return routerDotTSTemplate({\n staticRoutes: setToUnionType(staticRoutes),\n dynamicRoutes: setToUnionType(dynamicRoutes),\n dynamicRouteParams: setToUnionType(dynamicRouteTemplates),\n });\n}\n\n/**\n * Utility functions for typed routes\n *\n * These are extracted for easier testing\n */\nexport function getTypedRoutesUtils(appRoot: string, filePathSeperator = path.sep) {\n /*\n * staticRoutes are a map where the key if the route without groups and the value\n * is another set of all group versions of the route. e.g,\n * Map([\n * [\"/\", [\"/(app)/(notes)\", \"/(app)/(profile)\"]\n * ])\n */\n const staticRoutes = new Map<string, Set<string>>([['/', new Set('/')]]);\n /*\n * dynamicRoutes are the same as staticRoutes (key if the resolved route,\n * and the value is a set of possible routes). e.g:\n *\n * /[...fruits] -> /${CatchAllRoutePart<T>}\n * /color/[color] -> /color/${SingleRoutePart<T>}\n *\n * The keys of this map are also important, as they can be used as \"static\" types\n * <Link href={{ pathname: \"/[...fruits]\",params: { fruits: [\"apple\"] } }} />\n */\n const dynamicRoutes = new Map<string, Set<string>>();\n\n function normalizedFilePath(filePath: string) {\n return filePath.replaceAll(filePathSeperator, '/');\n }\n\n const normalizedAppRoot = normalizedFilePath(appRoot);\n\n const filePathToRoute = (filePath: string) => {\n return normalizedFilePath(filePath)\n .replace(normalizedAppRoot, '')\n .replace(/index\\.[jt]sx?/, '')\n .replace(/\\.[jt]sx?$/, '');\n };\n\n const isRouteFile = (filePath: string) => {\n if (filePath.match(TYPED_ROUTES_EXCLUSION_REGEX)) {\n return false;\n }\n\n // Route files must be nested with in the appRoot\n const relative = path.relative(appRoot, filePath);\n return relative && !relative.startsWith('..') && !path.isAbsolute(relative);\n };\n\n const addFilePath = (filePath: string): boolean => {\n if (!isRouteFile(filePath)) {\n return false;\n }\n\n const route = filePathToRoute(filePath);\n\n // We have already processed this file\n if (staticRoutes.has(route) || dynamicRoutes.has(route)) {\n return false;\n }\n\n const dynamicParams = new Set(\n [...route.matchAll(CAPTURE_DYNAMIC_PARAMS)].map((match) => match[1])\n );\n const isDynamic = dynamicParams.size > 0;\n\n const addRoute = (originalRoute: string, route: string) => {\n if (isDynamic) {\n let set = dynamicRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n dynamicRoutes.set(originalRoute, set);\n }\n\n set.add(\n route\n .replaceAll(CATCH_ALL, '${CatchAllRoutePart<T>}')\n .replaceAll(SLUG, '${SingleRoutePart<T>}')\n );\n } else {\n let set = staticRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n staticRoutes.set(originalRoute, set);\n }\n\n set.add(route);\n }\n };\n\n if (!route.match(ARRAY_GROUP_REGEX)) {\n addRoute(route, route);\n }\n\n // Does this route have a group? eg /(group)\n if (route.includes('/(')) {\n const routeWithoutGroups = route.replace(/\\/\\(.+?\\)/g, '');\n addRoute(route, routeWithoutGroups);\n\n // If there are multiple groups, we need to expand them\n // eg /(test1,test2)/page => /test1/page & /test2/page\n for (const routeWithSingleGroup of extrapolateGroupRoutes(route)) {\n addRoute(route, routeWithSingleGroup);\n }\n }\n\n return true;\n };\n\n return {\n staticRoutes,\n dynamicRoutes,\n filePathToRoute,\n addFilePath,\n isRouteFile,\n };\n}\n\nexport const setToUnionType = <T>(set: Set<T>) => {\n return set.size > 0 ? [...set].map((s) => `\\`${s}\\``).join(' | ') : 'never';\n};\n\n/**\n * Recursively walk a directory and call the callback with the file path.\n */\nasync function walk(directory: string, callback: (filePath: string) => void) {\n const files = await fs.readdir(directory);\n for (const file of files) {\n const p = path.join(directory, file);\n if ((await fs.stat(p)).isDirectory()) {\n await walk(p, callback);\n } else {\n // Normalise the paths so they are easier to convert to URLs\n const normalizedPath = p.replaceAll(path.sep, '/');\n callback(normalizedPath);\n }\n }\n}\n\n/**\n * Given a route, return all possible routes that could be generated from it.\n */\nexport function extrapolateGroupRoutes(\n route: string,\n routes: Set<string> = new Set()\n): Set<string> {\n // Create a version with no groups. We will then need to cleanup double and/or trailing slashes\n routes.add(route.replaceAll(ARRAY_GROUP_REGEX, '').replaceAll(/\\/+/g, '/').replace(/\\/$/, ''));\n\n const match = route.match(ARRAY_GROUP_REGEX);\n\n if (!match) {\n routes.add(route);\n return routes;\n }\n\n const groupsMatch = match[0];\n\n for (const group of groupsMatch.matchAll(CAPTURE_GROUP_REGEX)) {\n extrapolateGroupRoutes(route.replace(groupsMatch, `(${group[1].trim()})`), routes);\n }\n\n return routes;\n}\n\n/**\n * NOTE: This code refers to a specific version of `expo-router` and is therefore unsafe to\n * mix with arbitrary versions.\n * TODO: Version this code with `expo-router` or version expo-router with `@expo/cli`.\n */\nconst routerDotTSTemplate = unsafeTemplate`/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable import/export */\n/* eslint-disable @typescript-eslint/ban-types */\ndeclare module \"expo-router\" {\n import type { LinkProps as OriginalLinkProps } from 'expo-router/build/link/Link';\n import type { Router as OriginalRouter } from 'expo-router/build/types';\n export * from 'expo-router/build';\n\n // prettier-ignore\n type StaticRoutes = ${'staticRoutes'};\n // prettier-ignore\n type DynamicRoutes<T extends string> = ${'dynamicRoutes'};\n // prettier-ignore\n type DynamicRouteTemplate = ${'dynamicRouteParams'};\n\n type RelativePathString = \\`./\\${string}\\` | \\`../\\${string}\\` | '..';\n type AbsoluteRoute = DynamicRouteTemplate | StaticRoutes;\n type ExternalPathString = \\`\\${string}:\\${string}\\`;\n\n type ExpoRouterRoutes = DynamicRouteTemplate | StaticRoutes | RelativePathString;\n export type AllRoutes = ExpoRouterRoutes | ExternalPathString;\n\n /****************\n * Route Utils *\n ****************/\n\n type SearchOrHash = \\`?\\${string}\\` | \\`#\\${string}\\`;\n type UnknownInputParams = Record<string, string | number | (string | number)[]>;\n type UnknownOutputParams = Record<string, string | string[]>;\n\n /**\n * Return only the RoutePart of a string. If the string has multiple parts return never\n *\n * string | type\n * ---------|------\n * 123 | 123\n * /123/abc | never\n * 123?abc | never\n * ./123 | never\n * /123 | never\n * 123/../ | never\n */\n type SingleRoutePart<S extends string> = S extends \\`\\${string}/\\${string}\\`\n ? never\n : S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`(\\${string})\\`\n ? never\n : S extends \\`[\\${string}]\\`\n ? never\n : S;\n\n /**\n * Return only the CatchAll router part. If the string has search parameters or a hash return never\n */\n type CatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`\\${string}(\\${string})\\${string}\\`\n ? never\n : S extends \\`\\${string}[\\${string}]\\${string}\\`\n ? never\n : S;\n\n // type OptionalCatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\` ? never : S\n\n /**\n * Return the name of a route parameter\n * '[test]' -> 'test'\n * 'test' -> never\n * '[...test]' -> '...test'\n */\n type IsParameter<Part> = Part extends \\`[\\${infer ParamName}]\\` ? ParamName : never;\n\n /**\n * Return a union of all parameter names. If there are no names return never\n *\n * /[test] -> 'test'\n * /[abc]/[...def] -> 'abc'|'...def'\n */\n type ParameterNames<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? IsParameter<PartA> | ParameterNames<PartB>\n : IsParameter<Path>;\n\n /**\n * Returns all segements of a route.\n *\n * /(group)/123/abc/[id]/[...rest] -> ['(group)', '123', 'abc', '[id]', '[...rest]'\n */\n type RouteSegments<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? PartA extends '' | '.'\n ? [...RouteSegments<PartB>]\n : [PartA, ...RouteSegments<PartB>]\n : Path extends ''\n ? []\n : [Path];\n\n /**\n * Returns a Record of the routes parameters as strings and CatchAll parameters\n *\n * There are two versions, input and output, as you can input 'string | number' but\n * the output will always be 'string'\n *\n * /[id]/[...rest] -> { id: string, rest: string[] }\n * /no-params -> {}\n */\n type InputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? (string | number)[] : string | number;\n } & UnknownInputParams;\n\n type OutputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? string[] : string;\n } & UnknownOutputParams;\n\n /**\n * Returns the search parameters for a route.\n */\n export type SearchParams<T extends AllRoutes> = T extends DynamicRouteTemplate\n ? OutputRouteParams<T>\n : T extends StaticRoutes\n ? never\n : UnknownOutputParams;\n\n /**\n * Route is mostly used as part of Href to ensure that a valid route is provided\n *\n * Given a dynamic route, this will return never. This is helpful for conditional logic\n *\n * /test -> /test, /test2, etc\n * /test/[abc] -> never\n * /test/resolve -> /test, /test2, etc\n *\n * Note that if we provide a value for [abc] then the route is allowed\n *\n * This is named Route to prevent confusion, as users they will often see it in tooltips\n */\n export type Route<T> = T extends string\n ? T extends DynamicRouteTemplate\n ? never\n :\n | StaticRoutes\n | RelativePathString\n | ExternalPathString\n | (T extends \\`\\${infer P}\\${SearchOrHash}\\`\n ? P extends DynamicRoutes<infer _>\n ? T\n : never\n : T extends DynamicRoutes<infer _>\n ? T\n : never)\n : never;\n\n /*********\n * Href *\n *********/\n\n export type Href<T> = T extends Record<'pathname', string> ? HrefObject<T> : Route<T>;\n\n export type HrefObject<\n R extends Record<'pathname', string>,\n P = R['pathname'],\n > = P extends DynamicRouteTemplate\n ? { pathname: P; params: InputRouteParams<P> }\n : P extends Route<P>\n ? { pathname: Route<P> | DynamicRouteTemplate; params?: never | InputRouteParams<never> }\n : never;\n\n /***********************\n * Expo Router Exports *\n ***********************/\n\n export type Router = Omit<OriginalRouter, 'push' | 'replace' | 'setParams'> & {\n /** Navigate to the provided href. */\n push: <T>(href: Href<T>) => void;\n /** Navigate to route without appending to the history. */\n replace: <T>(href: Href<T>) => void;\n /** Update the current route query params. */\n setParams: <T = ''>(params?: T extends '' ? Record<string, string> : InputRouteParams<T>) => void;\n };\n\n /** The imperative router. */\n export const router: Router;\n\n /************\n * <Link /> *\n ************/\n export interface LinkProps<T> extends OriginalLinkProps {\n href: Href<T>;\n }\n\n export interface LinkComponent {\n <T>(props: React.PropsWithChildren<LinkProps<T>>): JSX.Element;\n /** Helper method to resolve an Href object into a string. */\n resolveHref: <T>(href: Href<T>) => string;\n }\n\n /**\n * Component to render link to another route using a path.\n * Uses an anchor tag on the web.\n *\n * @param props.href Absolute path to route (e.g. \\`/feeds/hot\\`).\n * @param props.replace Should replace the current route without adding to the history.\n * @param props.asChild Forward props to child component. Useful for custom buttons.\n * @param props.children Child elements to render the content.\n * @param props.className On web, this sets the HTML \\`class\\` directly. On native, this can be used with CSS interop tools like Nativewind.\n */\n export const Link: LinkComponent;\n\n /** Redirects to the href as soon as the component is mounted. */\n export const Redirect: <T>(\n props: React.PropsWithChildren<{ href: Href<T> }>\n ) => JSX.Element;\n\n /************\n * Hooks *\n ************/\n export function useRouter(): Router;\n\n export function useLocalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n /** @deprecated renamed to \\`useGlobalSearchParams\\` */\n export function useSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useGlobalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useSegments<\n T extends AbsoluteRoute | RouteSegments<AbsoluteRoute> | RelativePathString,\n >(): T extends AbsoluteRoute ? RouteSegments<T> : T extends string ? string[] : T;\n}\n`;\n"],"names":["ARRAY_GROUP_REGEX","CAPTURE_DYNAMIC_PARAMS","CAPTURE_GROUP_REGEX","CATCH_ALL","SLUG","TYPED_ROUTES_EXCLUSION_REGEX","extrapolateGroupRoutes","getTemplateString","getTypedRoutesUtils","setToUnionType","setupTypedRoutes","options","typedRoutesModule","resolveFrom","silent","projectRoot","typedRoutes","legacyTypedRoutes","typedRoutesModulePath","server","metro","typesDirectory","routerDirectory","plugin","process","env","EXPO_ROUTER_APP_ROOT","require","metroWatchTypeScriptFiles","eventTypes","callback","getWatchHandler","version","regenerateDeclarations","filePathToRoute","staticRoutes","dynamicRoutes","addFilePath","isRouteFile","filePath","type","shouldRegenerate","route","delete","regenerateRouterDotTS","Set","values","flatMap","v","Array","from","keys","directoryExistsAsync","walk","debounce","fn","delay","timeoutId","args","clearTimeout","setTimeout","apply","typesDir","dynamicRouteTemplates","fs","mkdir","recursive","writeFile","path","resolve","routerDotTSTemplate","dynamicRouteParams","appRoot","filePathSeperator","sep","Map","normalizedFilePath","replaceAll","normalizedAppRoot","replace","match","relative","startsWith","isAbsolute","has","dynamicParams","matchAll","map","isDynamic","size","addRoute","originalRoute","set","get","add","includes","routeWithoutGroups","routeWithSingleGroup","s","join","directory","files","readdir","file","p","stat","isDirectory","normalizedPath","routes","groupsMatch","group","trim","unsafeTemplate"],"mappings":";;;;;;;;;;;IAiBaA,iBAAiB;eAAjBA;;IANAC,sBAAsB;eAAtBA;;IAQAC,mBAAmB;eAAnBA;;IANAC,SAAS;eAATA;;IAEAC,IAAI;eAAJA;;IAUAC,4BAA4B;eAA5BA;;IA2TGC,sBAAsB;eAAtBA;;IA5JAC,iBAAiB;eAAjBA;;IAiBAC,mBAAmB;eAAnBA;;IAmHHC,cAAc;eAAdA;;IAvRSC,gBAAgB;eAAhBA;;;;gEApCP;;;;;;;gEACE;;;;;;;gEACO;;;;;;qBAEa;0BACN;2CAEW;;;;;;AAGnC,MAAMT,yBAAyB;AAE/B,MAAME,YAAY;AAElB,MAAMC,OAAO;AAEb,MAAMJ,oBAAoB;AAE1B,MAAME,sBAAsB;AAM5B,MAAMG,+BAA+B;AAYrC,eAAeK,iBAAiBC,OAAgC;IACrE;;;;;GAKC,GACD,MAAMC,oBAAoBC,sBAAW,CAACC,MAAM,CAC1CH,QAAQI,WAAW,EACnB;IAEF,OAAOH,oBAAoBI,YAAYJ,mBAAmBD,WAAWM,kBAAkBN;AACzF;AAEA,eAAeK,YACbE,qBAA0B,EAC1B,EAAEC,MAAM,EAAEC,KAAK,EAAEC,cAAc,EAAEN,WAAW,EAAEO,eAAe,EAAEC,MAAM,EAA2B;IAEhG;;;;GAIC,GACDC,QAAQC,GAAG,CAACC,oBAAoB,GAAGJ;IAEnC,MAAMV,oBAAoBe,QAAQT;IAElC;;GAEC,GACD,IAAIE,SAASD,QAAQ;QACnB,0BAA0B;QAC1BS,IAAAA,oDAAyB,EAAC;YACxBb;YACAI;YACAC;YACAS,YAAY;gBAAC;gBAAO;gBAAU;aAAS;YACvCC,UAAUlB,kBAAkBmB,eAAe,CAACV;QAC9C;IACF;IAEA;;;;;;GAMC,GACD,IAAI,aAAaT,qBAAqBA,kBAAkBoB,OAAO,IAAI,IAAI;QACrEpB,kBAAkBqB,sBAAsB,CAACZ,gBAAgBE;IAC3D,OAAO;QACLX,kBAAkBqB,sBAAsB,CAACZ;IAC3C;AACF;AAEA,eAAeJ,kBAAkB,EAC/BE,MAAM,EACNC,KAAK,EACLC,cAAc,EACdN,WAAW,EACXO,eAAe,EACS;IACxB,MAAM,EAAEY,eAAe,EAAEC,YAAY,EAAEC,aAAa,EAAEC,WAAW,EAAEC,WAAW,EAAE,GAC9E9B,oBAAoBc;IAEtB,0FAA0F;IAC1F,IAAIF,SAASD,QAAQ;QACnBS,IAAAA,oDAAyB,EAAC;YACxBb;YACAI;YACAC;YACAS,YAAY;gBAAC;gBAAO;gBAAU;aAAS;YACvC,MAAMC,UAAS,EAAES,QAAQ,EAAEC,IAAI,EAAE;gBAC/B,IAAI,CAACF,YAAYC,WAAW;oBAC1B;gBACF;gBAEA,IAAIE,mBAAmB;gBAEvB,IAAID,SAAS,UAAU;oBACrB,MAAME,QAAQR,gBAAgBK;oBAC9BJ,aAAaQ,MAAM,CAACD;oBACpBN,cAAcO,MAAM,CAACD;oBACrBD,mBAAmB;gBACrB,OAAO;oBACLA,mBAAmBJ,YAAYE;gBACjC;gBAEA,IAAIE,kBAAkB;oBACpBG,sBACEvB,gBACA,IAAIwB,IAAI;2BAAIV,aAAaW,MAAM;qBAAG,CAACC,OAAO,CAAC,CAACC,IAAMC,MAAMC,IAAI,CAACF,MAC7D,IAAIH,IAAI;2BAAIT,cAAcU,MAAM;qBAAG,CAACC,OAAO,CAAC,CAACC,IAAMC,MAAMC,IAAI,CAACF,MAC9D,IAAIH,IAAIT,cAAce,IAAI;gBAE9B;YACF;QACF;IACF;IAEA,IAAI,MAAMC,IAAAA,yBAAoB,EAAC9B,kBAAkB;QAC/C,iDAAiD;QACjD,qGAAqG;QACrG,MAAM+B,KAAK/B,iBAAiBe;IAC9B;IAEAO,sBACEvB,gBACA,IAAIwB,IAAI;WAAIV,aAAaW,MAAM;KAAG,CAACC,OAAO,CAAC,CAACC,IAAMC,MAAMC,IAAI,CAACF,MAC7D,IAAIH,IAAI;WAAIT,cAAcU,MAAM;KAAG,CAACC,OAAO,CAAC,CAACC,IAAMC,MAAMC,IAAI,CAACF,MAC9D,IAAIH,IAAIT,cAAce,IAAI;AAE9B;AAEA,SAASG,SAAyDC,EAAK,EAAEC,KAAa;IACpF,IAAIC;IACJ,OAAO,SAAmB,GAAGC,IAAW;QACtCC,aAAaF;QACb,0FAA0F;QAC1F,kFAAkF;QAClFA,YAAYG,WAAW,IAAML,GAAGM,KAAK,CAAC,IAAI,EAAEH,OAAOF;IACrD;AACF;AAEA;;;CAGC,GACD,MAAMZ,wBAAwBU,SAC5B,OACEQ,UACA3B,cACAC,eACA2B;IAEA,MAAMC,mBAAE,CAACC,KAAK,CAACH,UAAU;QAAEI,WAAW;IAAK;IAC3C,MAAMF,mBAAE,CAACG,SAAS,CAChBC,eAAI,CAACC,OAAO,CAACP,UAAU,kBACvBvD,kBAAkB4B,cAAcC,eAAe2B;AAEnD,GACA;AAMK,SAASxD,kBACd4B,YAAyB,EACzBC,aAA0B,EAC1B2B,qBAAkC;IAElC,OAAOO,oBAAoB;QACzBnC,cAAc1B,eAAe0B;QAC7BC,eAAe3B,eAAe2B;QAC9BmC,oBAAoB9D,eAAesD;IACrC;AACF;AAOO,SAASvD,oBAAoBgE,OAAe,EAAEC,oBAAoBL,eAAI,CAACM,GAAG;IAC/E;;;;;;GAMC,GACD,MAAMvC,eAAe,IAAIwC,IAAyB;QAAC;YAAC;YAAK,IAAI9B,IAAI;SAAK;KAAC;IACvE;;;;;;;;;GASC,GACD,MAAMT,gBAAgB,IAAIuC;IAE1B,SAASC,mBAAmBrC,QAAgB;QAC1C,OAAOA,SAASsC,UAAU,CAACJ,mBAAmB;IAChD;IAEA,MAAMK,oBAAoBF,mBAAmBJ;IAE7C,MAAMtC,kBAAkB,CAACK;QACvB,OAAOqC,mBAAmBrC,UACvBwC,OAAO,CAACD,mBAAmB,IAC3BC,OAAO,CAAC,kBAAkB,IAC1BA,OAAO,CAAC,cAAc;IAC3B;IAEA,MAAMzC,cAAc,CAACC;QACnB,IAAIA,SAASyC,KAAK,CAAC3E,+BAA+B;YAChD,OAAO;QACT;QAEA,iDAAiD;QACjD,MAAM4E,WAAWb,eAAI,CAACa,QAAQ,CAACT,SAASjC;QACxC,OAAO0C,YAAY,CAACA,SAASC,UAAU,CAAC,SAAS,CAACd,eAAI,CAACe,UAAU,CAACF;IACpE;IAEA,MAAM5C,cAAc,CAACE;QACnB,IAAI,CAACD,YAAYC,WAAW;YAC1B,OAAO;QACT;QAEA,MAAMG,QAAQR,gBAAgBK;QAE9B,sCAAsC;QACtC,IAAIJ,aAAaiD,GAAG,CAAC1C,UAAUN,cAAcgD,GAAG,CAAC1C,QAAQ;YACvD,OAAO;QACT;QAEA,MAAM2C,gBAAgB,IAAIxC,IACxB;eAAIH,MAAM4C,QAAQ,CAACrF;SAAwB,CAACsF,GAAG,CAAC,CAACP,QAAUA,KAAK,CAAC,EAAE;QAErE,MAAMQ,YAAYH,cAAcI,IAAI,GAAG;QAEvC,MAAMC,WAAW,CAACC,eAAuBjD;YACvC,IAAI8C,WAAW;gBACb,IAAII,MAAMxD,cAAcyD,GAAG,CAACF;gBAE5B,IAAI,CAACC,KAAK;oBACRA,MAAM,IAAI/C;oBACVT,cAAcwD,GAAG,CAACD,eAAeC;gBACnC;gBAEAA,IAAIE,GAAG,CACLpD,MACGmC,UAAU,CAAC1E,WAAW,2BACtB0E,UAAU,CAACzE,MAAM;YAExB,OAAO;gBACL,IAAIwF,MAAMzD,aAAa0D,GAAG,CAACF;gBAE3B,IAAI,CAACC,KAAK;oBACRA,MAAM,IAAI/C;oBACVV,aAAayD,GAAG,CAACD,eAAeC;gBAClC;gBAEAA,IAAIE,GAAG,CAACpD;YACV;QACF;QAEA,IAAI,CAACA,MAAMsC,KAAK,CAAChF,oBAAoB;YACnC0F,SAAShD,OAAOA;QAClB;QAEA,4CAA4C;QAC5C,IAAIA,MAAMqD,QAAQ,CAAC,OAAO;YACxB,MAAMC,qBAAqBtD,MAAMqC,OAAO,CAAC,cAAc;YACvDW,SAAShD,OAAOsD;YAEhB,uDAAuD;YACvD,sDAAsD;YACtD,KAAK,MAAMC,wBAAwB3F,uBAAuBoC,OAAQ;gBAChEgD,SAAShD,OAAOuD;YAClB;QACF;QAEA,OAAO;IACT;IAEA,OAAO;QACL9D;QACAC;QACAF;QACAG;QACAC;IACF;AACF;AAEO,MAAM7B,iBAAiB,CAAImF;IAChC,OAAOA,IAAIH,IAAI,GAAG,IAAI;WAAIG;KAAI,CAACL,GAAG,CAAC,CAACW,IAAM,CAAC,EAAE,EAAEA,EAAE,EAAE,CAAC,EAAEC,IAAI,CAAC,SAAS;AACtE;AAEA;;CAEC,GACD,eAAe9C,KAAK+C,SAAiB,EAAEtE,QAAoC;IACzE,MAAMuE,QAAQ,MAAMrC,mBAAE,CAACsC,OAAO,CAACF;IAC/B,KAAK,MAAMG,QAAQF,MAAO;QACxB,MAAMG,IAAIpC,eAAI,CAAC+B,IAAI,CAACC,WAAWG;QAC/B,IAAI,AAAC,CAAA,MAAMvC,mBAAE,CAACyC,IAAI,CAACD,EAAC,EAAGE,WAAW,IAAI;YACpC,MAAMrD,KAAKmD,GAAG1E;QAChB,OAAO;YACL,4DAA4D;YAC5D,MAAM6E,iBAAiBH,EAAE3B,UAAU,CAACT,eAAI,CAACM,GAAG,EAAE;YAC9C5C,SAAS6E;QACX;IACF;AACF;AAKO,SAASrG,uBACdoC,KAAa,EACbkE,SAAsB,IAAI/D,KAAK;IAE/B,+FAA+F;IAC/F+D,OAAOd,GAAG,CAACpD,MAAMmC,UAAU,CAAC7E,mBAAmB,IAAI6E,UAAU,CAAC,QAAQ,KAAKE,OAAO,CAAC,OAAO;IAE1F,MAAMC,QAAQtC,MAAMsC,KAAK,CAAChF;IAE1B,IAAI,CAACgF,OAAO;QACV4B,OAAOd,GAAG,CAACpD;QACX,OAAOkE;IACT;IAEA,MAAMC,cAAc7B,KAAK,CAAC,EAAE;IAE5B,KAAK,MAAM8B,SAASD,YAAYvB,QAAQ,CAACpF,qBAAsB;QAC7DI,uBAAuBoC,MAAMqC,OAAO,CAAC8B,aAAa,CAAC,CAAC,EAAEC,KAAK,CAAC,EAAE,CAACC,IAAI,GAAG,CAAC,CAAC,GAAGH;IAC7E;IAEA,OAAOA;AACT;AAEA;;;;CAIC,GACD,MAAMtC,sBAAsB0C,IAAAA,wBAAc,CAAA,CAAC;;;;;;;;;sBASrB,EAAE,eAAe;;yCAEE,EAAE,gBAAgB;;8BAE7B,EAAE,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqOrD,CAAC"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/type-generation/routes.ts"],"sourcesContent":["import type Server from '@expo/metro/metro/Server';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nimport { directoryExistsAsync } from '../../../utils/dir';\nimport { unsafeTemplate } from '../../../utils/template';\nimport { ServerLike } from '../BundlerDevServer';\nimport { metroWatchTypeScriptFiles } from '../metro/metroWatchTypeScriptFiles';\n\n// /test/[...param1]/[param2]/[param3] - captures [\"param1\", \"param2\", \"param3\"]\nexport const CAPTURE_DYNAMIC_PARAMS = /\\[(?:\\.{3})?(\\w*?)[\\]$]/g;\n// /[...param1]/ - Match [...param1]\nexport const CATCH_ALL = /\\[\\.\\.\\..+?\\]/g;\n// /[param1] - Match [param1]\nexport const SLUG = /\\[.+?\\]/g;\n// /(group1,group2,group3)/test - match (group1,group2,group3)\nexport const ARRAY_GROUP_REGEX = /\\(\\s*\\w[\\w\\s]*?,.*?\\)/g;\n// /(group1,group2,group3)/test - captures [\"group1\", \"group2\", \"group3\"]\nexport const CAPTURE_GROUP_REGEX = /[\\\\(,]\\s*(\\w[\\w\\s]*?)\\s*(?=[,\\\\)])/g;\n/**\n * Match:\n * - _layout files, +html, +not-found, string+api, etc\n * - Routes can still use `+`, but it cannot be in the last segment.\n */\nexport const TYPED_ROUTES_EXCLUSION_REGEX = /(_layout|[^/]*?\\+[^/]*?)\\.[tj]sx?$/;\n\nexport interface SetupTypedRoutesOptions {\n server?: ServerLike;\n metro?: Server | null;\n typesDirectory: string;\n projectRoot: string;\n /** Absolute expo router routes directory. */\n routerDirectory: string;\n plugin?: Record<string, any>;\n}\n\nexport async function setupTypedRoutes(options: SetupTypedRoutesOptions) {\n const typedRoutesModule = require.resolve('@expo/router-server/build/typed-routes');\n return typedRoutes(typedRoutesModule, options);\n}\n\nasync function typedRoutes(\n typedRoutesModulePath: any,\n { server, metro, typesDirectory, projectRoot, routerDirectory, plugin }: SetupTypedRoutesOptions\n) {\n /*\n * Expo Router uses EXPO_ROUTER_APP_ROOT in multiple places to determine the root of the project.\n * In apps compiled by Metro, this code is compiled away. But Typed Routes run in NodeJS with no compilation\n * so we need to explicitly set it.\n */\n process.env.EXPO_ROUTER_APP_ROOT = routerDirectory;\n\n const typedRoutesModule = require(typedRoutesModulePath);\n\n /*\n * Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`\n */\n if (metro && server) {\n // Setup out watcher first\n metroWatchTypeScriptFiles({\n projectRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n callback: typedRoutesModule.getWatchHandler(typesDirectory),\n });\n }\n\n /*\n * In SDK 52, the `regenerateDeclarations` was changed to accept plugin options.\n * This function has an optional parameter that we cannot override, so we need to ensure the user\n * is using a compatible version of `expo-router`. Otherwise, we will fallback to the old method.\n *\n * TODO(@marklawlor): In SDK53+ we should remove this check and always use the new method.\n */\n if ('version' in typedRoutesModule && typedRoutesModule.version >= 52) {\n typedRoutesModule.regenerateDeclarations(typesDirectory, plugin);\n } else {\n typedRoutesModule.regenerateDeclarations(typesDirectory);\n }\n}\n\nfunction debounce<U, T extends (this: U, ...args: any[]) => void>(fn: T, delay: number): T {\n let timeoutId: NodeJS.Timeout | undefined;\n return function (this: U, ...args: any[]) {\n clearTimeout(timeoutId);\n // NOTE(@hassankhan): The cast to `NodeJS.Timeout` below is a hack to work around an issue\n // with TypeScript where React Native's types are being imported before Node types\n timeoutId = setTimeout(() => fn.apply(this, args), delay) as unknown as NodeJS.Timeout;\n } as T;\n}\n\n/**\n * Generate a router.d.ts file that contains all of the routes in the project.\n * Should be debounced as its very common for developers to make changes to multiple files at once (eg Save All)\n */\nconst regenerateRouterDotTS = debounce(\n async (\n typesDir: string,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n ) => {\n await fs.mkdir(typesDir, { recursive: true });\n await fs.writeFile(\n path.resolve(typesDir, './router.d.ts'),\n getTemplateString(staticRoutes, dynamicRoutes, dynamicRouteTemplates)\n );\n },\n 100\n);\n\n/*\n * This is exported for testing purposes\n */\nexport function getTemplateString(\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n) {\n return routerDotTSTemplate({\n staticRoutes: setToUnionType(staticRoutes),\n dynamicRoutes: setToUnionType(dynamicRoutes),\n dynamicRouteParams: setToUnionType(dynamicRouteTemplates),\n });\n}\n\n/**\n * Utility functions for typed routes\n *\n * These are extracted for easier testing\n */\nexport function getTypedRoutesUtils(appRoot: string, filePathSeperator = path.sep) {\n /*\n * staticRoutes are a map where the key if the route without groups and the value\n * is another set of all group versions of the route. e.g,\n * Map([\n * [\"/\", [\"/(app)/(notes)\", \"/(app)/(profile)\"]\n * ])\n */\n const staticRoutes = new Map<string, Set<string>>([['/', new Set('/')]]);\n /*\n * dynamicRoutes are the same as staticRoutes (key if the resolved route,\n * and the value is a set of possible routes). e.g:\n *\n * /[...fruits] -> /${CatchAllRoutePart<T>}\n * /color/[color] -> /color/${SingleRoutePart<T>}\n *\n * The keys of this map are also important, as they can be used as \"static\" types\n * <Link href={{ pathname: \"/[...fruits]\",params: { fruits: [\"apple\"] } }} />\n */\n const dynamicRoutes = new Map<string, Set<string>>();\n\n function normalizedFilePath(filePath: string) {\n return filePath.replaceAll(filePathSeperator, '/');\n }\n\n const normalizedAppRoot = normalizedFilePath(appRoot);\n\n const filePathToRoute = (filePath: string) => {\n return normalizedFilePath(filePath)\n .replace(normalizedAppRoot, '')\n .replace(/index\\.[jt]sx?/, '')\n .replace(/\\.[jt]sx?$/, '');\n };\n\n const isRouteFile = (filePath: string) => {\n if (filePath.match(TYPED_ROUTES_EXCLUSION_REGEX)) {\n return false;\n }\n\n // Route files must be nested with in the appRoot\n const relative = path.relative(appRoot, filePath);\n return relative && !relative.startsWith('..') && !path.isAbsolute(relative);\n };\n\n const addFilePath = (filePath: string): boolean => {\n if (!isRouteFile(filePath)) {\n return false;\n }\n\n const route = filePathToRoute(filePath);\n\n // We have already processed this file\n if (staticRoutes.has(route) || dynamicRoutes.has(route)) {\n return false;\n }\n\n const dynamicParams = new Set(\n [...route.matchAll(CAPTURE_DYNAMIC_PARAMS)].map((match) => match[1])\n );\n const isDynamic = dynamicParams.size > 0;\n\n const addRoute = (originalRoute: string, route: string) => {\n if (isDynamic) {\n let set = dynamicRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n dynamicRoutes.set(originalRoute, set);\n }\n\n set.add(\n route\n .replaceAll(CATCH_ALL, '${CatchAllRoutePart<T>}')\n .replaceAll(SLUG, '${SingleRoutePart<T>}')\n );\n } else {\n let set = staticRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n staticRoutes.set(originalRoute, set);\n }\n\n set.add(route);\n }\n };\n\n if (!route.match(ARRAY_GROUP_REGEX)) {\n addRoute(route, route);\n }\n\n // Does this route have a group? eg /(group)\n if (route.includes('/(')) {\n const routeWithoutGroups = route.replace(/\\/\\(.+?\\)/g, '');\n addRoute(route, routeWithoutGroups);\n\n // If there are multiple groups, we need to expand them\n // eg /(test1,test2)/page => /test1/page & /test2/page\n for (const routeWithSingleGroup of extrapolateGroupRoutes(route)) {\n addRoute(route, routeWithSingleGroup);\n }\n }\n\n return true;\n };\n\n return {\n staticRoutes,\n dynamicRoutes,\n filePathToRoute,\n addFilePath,\n isRouteFile,\n };\n}\n\nexport const setToUnionType = <T>(set: Set<T>) => {\n return set.size > 0 ? [...set].map((s) => `\\`${s}\\``).join(' | ') : 'never';\n};\n\n/**\n * Recursively walk a directory and call the callback with the file path.\n */\nasync function walk(directory: string, callback: (filePath: string) => void) {\n const files = await fs.readdir(directory);\n for (const file of files) {\n const p = path.join(directory, file);\n if ((await fs.stat(p)).isDirectory()) {\n await walk(p, callback);\n } else {\n // Normalise the paths so they are easier to convert to URLs\n const normalizedPath = p.replaceAll(path.sep, '/');\n callback(normalizedPath);\n }\n }\n}\n\n/**\n * Given a route, return all possible routes that could be generated from it.\n */\nexport function extrapolateGroupRoutes(\n route: string,\n routes: Set<string> = new Set()\n): Set<string> {\n // Create a version with no groups. We will then need to cleanup double and/or trailing slashes\n routes.add(route.replaceAll(ARRAY_GROUP_REGEX, '').replaceAll(/\\/+/g, '/').replace(/\\/$/, ''));\n\n const match = route.match(ARRAY_GROUP_REGEX);\n\n if (!match) {\n routes.add(route);\n return routes;\n }\n\n const groupsMatch = match[0];\n\n for (const group of groupsMatch.matchAll(CAPTURE_GROUP_REGEX)) {\n extrapolateGroupRoutes(route.replace(groupsMatch, `(${group[1].trim()})`), routes);\n }\n\n return routes;\n}\n\n/**\n * NOTE: This code refers to a specific version of `expo-router` and is therefore unsafe to\n * mix with arbitrary versions.\n * TODO: Version this code with `expo-router` or version expo-router with `@expo/cli`.\n */\nconst routerDotTSTemplate = unsafeTemplate`/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable import/export */\n/* eslint-disable @typescript-eslint/ban-types */\ndeclare module \"expo-router\" {\n import type { LinkProps as OriginalLinkProps } from 'expo-router/build/link/Link';\n import type { Router as OriginalRouter } from 'expo-router/build/types';\n export * from 'expo-router/build';\n\n // prettier-ignore\n type StaticRoutes = ${'staticRoutes'};\n // prettier-ignore\n type DynamicRoutes<T extends string> = ${'dynamicRoutes'};\n // prettier-ignore\n type DynamicRouteTemplate = ${'dynamicRouteParams'};\n\n type RelativePathString = \\`./\\${string}\\` | \\`../\\${string}\\` | '..';\n type AbsoluteRoute = DynamicRouteTemplate | StaticRoutes;\n type ExternalPathString = \\`\\${string}:\\${string}\\`;\n\n type ExpoRouterRoutes = DynamicRouteTemplate | StaticRoutes | RelativePathString;\n export type AllRoutes = ExpoRouterRoutes | ExternalPathString;\n\n /****************\n * Route Utils *\n ****************/\n\n type SearchOrHash = \\`?\\${string}\\` | \\`#\\${string}\\`;\n type UnknownInputParams = Record<string, string | number | (string | number)[]>;\n type UnknownOutputParams = Record<string, string | string[]>;\n\n /**\n * Return only the RoutePart of a string. If the string has multiple parts return never\n *\n * string | type\n * ---------|------\n * 123 | 123\n * /123/abc | never\n * 123?abc | never\n * ./123 | never\n * /123 | never\n * 123/../ | never\n */\n type SingleRoutePart<S extends string> = S extends \\`\\${string}/\\${string}\\`\n ? never\n : S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`(\\${string})\\`\n ? never\n : S extends \\`[\\${string}]\\`\n ? never\n : S;\n\n /**\n * Return only the CatchAll router part. If the string has search parameters or a hash return never\n */\n type CatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`\\${string}(\\${string})\\${string}\\`\n ? never\n : S extends \\`\\${string}[\\${string}]\\${string}\\`\n ? never\n : S;\n\n // type OptionalCatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\` ? never : S\n\n /**\n * Return the name of a route parameter\n * '[test]' -> 'test'\n * 'test' -> never\n * '[...test]' -> '...test'\n */\n type IsParameter<Part> = Part extends \\`[\\${infer ParamName}]\\` ? ParamName : never;\n\n /**\n * Return a union of all parameter names. If there are no names return never\n *\n * /[test] -> 'test'\n * /[abc]/[...def] -> 'abc'|'...def'\n */\n type ParameterNames<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? IsParameter<PartA> | ParameterNames<PartB>\n : IsParameter<Path>;\n\n /**\n * Returns all segements of a route.\n *\n * /(group)/123/abc/[id]/[...rest] -> ['(group)', '123', 'abc', '[id]', '[...rest]'\n */\n type RouteSegments<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? PartA extends '' | '.'\n ? [...RouteSegments<PartB>]\n : [PartA, ...RouteSegments<PartB>]\n : Path extends ''\n ? []\n : [Path];\n\n /**\n * Returns a Record of the routes parameters as strings and CatchAll parameters\n *\n * There are two versions, input and output, as you can input 'string | number' but\n * the output will always be 'string'\n *\n * /[id]/[...rest] -> { id: string, rest: string[] }\n * /no-params -> {}\n */\n type InputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? (string | number)[] : string | number;\n } & UnknownInputParams;\n\n type OutputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? string[] : string;\n } & UnknownOutputParams;\n\n /**\n * Returns the search parameters for a route.\n */\n export type SearchParams<T extends AllRoutes> = T extends DynamicRouteTemplate\n ? OutputRouteParams<T>\n : T extends StaticRoutes\n ? never\n : UnknownOutputParams;\n\n /**\n * Route is mostly used as part of Href to ensure that a valid route is provided\n *\n * Given a dynamic route, this will return never. This is helpful for conditional logic\n *\n * /test -> /test, /test2, etc\n * /test/[abc] -> never\n * /test/resolve -> /test, /test2, etc\n *\n * Note that if we provide a value for [abc] then the route is allowed\n *\n * This is named Route to prevent confusion, as users they will often see it in tooltips\n */\n export type Route<T> = T extends string\n ? T extends DynamicRouteTemplate\n ? never\n :\n | StaticRoutes\n | RelativePathString\n | ExternalPathString\n | (T extends \\`\\${infer P}\\${SearchOrHash}\\`\n ? P extends DynamicRoutes<infer _>\n ? T\n : never\n : T extends DynamicRoutes<infer _>\n ? T\n : never)\n : never;\n\n /*********\n * Href *\n *********/\n\n export type Href<T> = T extends Record<'pathname', string> ? HrefObject<T> : Route<T>;\n\n export type HrefObject<\n R extends Record<'pathname', string>,\n P = R['pathname'],\n > = P extends DynamicRouteTemplate\n ? { pathname: P; params: InputRouteParams<P> }\n : P extends Route<P>\n ? { pathname: Route<P> | DynamicRouteTemplate; params?: never | InputRouteParams<never> }\n : never;\n\n /***********************\n * Expo Router Exports *\n ***********************/\n\n export type Router = Omit<OriginalRouter, 'push' | 'replace' | 'setParams'> & {\n /** Navigate to the provided href. */\n push: <T>(href: Href<T>) => void;\n /** Navigate to route without appending to the history. */\n replace: <T>(href: Href<T>) => void;\n /** Update the current route query params. */\n setParams: <T = ''>(params?: T extends '' ? Record<string, string> : InputRouteParams<T>) => void;\n };\n\n /** The imperative router. */\n export const router: Router;\n\n /************\n * <Link /> *\n ************/\n export interface LinkProps<T> extends OriginalLinkProps {\n href: Href<T>;\n }\n\n export interface LinkComponent {\n <T>(props: React.PropsWithChildren<LinkProps<T>>): JSX.Element;\n /** Helper method to resolve an Href object into a string. */\n resolveHref: <T>(href: Href<T>) => string;\n }\n\n /**\n * Component to render link to another route using a path.\n * Uses an anchor tag on the web.\n *\n * @param props.href Absolute path to route (e.g. \\`/feeds/hot\\`).\n * @param props.replace Should replace the current route without adding to the history.\n * @param props.asChild Forward props to child component. Useful for custom buttons.\n * @param props.children Child elements to render the content.\n * @param props.className On web, this sets the HTML \\`class\\` directly. On native, this can be used with CSS interop tools like Nativewind.\n */\n export const Link: LinkComponent;\n\n /** Redirects to the href as soon as the component is mounted. */\n export const Redirect: <T>(\n props: React.PropsWithChildren<{ href: Href<T> }>\n ) => JSX.Element;\n\n /************\n * Hooks *\n ************/\n export function useRouter(): Router;\n\n export function useLocalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n /** @deprecated renamed to \\`useGlobalSearchParams\\` */\n export function useSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useGlobalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useSegments<\n T extends AbsoluteRoute | RouteSegments<AbsoluteRoute> | RelativePathString,\n >(): T extends AbsoluteRoute ? RouteSegments<T> : T extends string ? string[] : T;\n}\n`;\n"],"names":["ARRAY_GROUP_REGEX","CAPTURE_DYNAMIC_PARAMS","CAPTURE_GROUP_REGEX","CATCH_ALL","SLUG","TYPED_ROUTES_EXCLUSION_REGEX","extrapolateGroupRoutes","getTemplateString","getTypedRoutesUtils","setToUnionType","setupTypedRoutes","options","typedRoutesModule","require","resolve","typedRoutes","typedRoutesModulePath","server","metro","typesDirectory","projectRoot","routerDirectory","plugin","process","env","EXPO_ROUTER_APP_ROOT","metroWatchTypeScriptFiles","eventTypes","callback","getWatchHandler","version","regenerateDeclarations","debounce","fn","delay","timeoutId","args","clearTimeout","setTimeout","apply","regenerateRouterDotTS","typesDir","staticRoutes","dynamicRoutes","dynamicRouteTemplates","fs","mkdir","recursive","writeFile","path","routerDotTSTemplate","dynamicRouteParams","appRoot","filePathSeperator","sep","Map","Set","normalizedFilePath","filePath","replaceAll","normalizedAppRoot","filePathToRoute","replace","isRouteFile","match","relative","startsWith","isAbsolute","addFilePath","route","has","dynamicParams","matchAll","map","isDynamic","size","addRoute","originalRoute","set","get","add","includes","routeWithoutGroups","routeWithSingleGroup","s","join","walk","directory","files","readdir","file","p","stat","isDirectory","normalizedPath","routes","groupsMatch","group","trim","unsafeTemplate"],"mappings":"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"}
|
|
@@ -202,7 +202,7 @@ async function calculateFingerprintHashAsync({ projectRoot, platform, provider,
|
|
|
202
202
|
}
|
|
203
203
|
const Fingerprint = importFingerprintForDev(projectRoot);
|
|
204
204
|
if (!Fingerprint) {
|
|
205
|
-
|
|
205
|
+
_log.warn('@expo/fingerprint is not installed in the project, skipping build cache.');
|
|
206
206
|
return null;
|
|
207
207
|
}
|
|
208
208
|
const fingerprint = await Fingerprint.createFingerprintAsync(projectRoot);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/utils/build-cache-providers/index.ts"],"sourcesContent":["import { ExpoConfig, BuildCacheProviderPlugin, BuildCacheProvider, RunOptions } from '@expo/config';\nimport fs from 'fs';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { moduleNameIsDirectFileReference, moduleNameIsPackageReference } from './helpers';\nimport * as Log from '../../log';\nimport { ensureDependenciesAsync } from '../../start/doctor/dependencies/ensureDependenciesAsync';\nimport { CommandError } from '../errors';\n\nconst debug = require('debug')('expo:run:build-cache-provider') as typeof console.log;\n\nexport const resolveBuildCacheProvider = async (\n provider: Required<ExpoConfig>['buildCacheProvider'] | undefined,\n projectRoot: string\n): Promise<BuildCacheProvider | undefined> => {\n if (!provider) {\n return;\n }\n\n if (provider === 'eas') {\n try {\n await ensureDependenciesAsync(projectRoot, {\n isProjectMutable: true,\n installMessage:\n 'eas-build-cache-provider package is required to use the EAS build cache.\\n',\n warningMessage: 'Unable to to use the EAS remote build cache.',\n requiredPackages: [\n {\n pkg: 'eas-build-cache-provider',\n file: 'eas-build-cache-provider/package.json',\n dev: true,\n },\n ],\n });\n\n // We need to manually load dependencies installed on the fly\n const plugin = await manuallyLoadDependency(projectRoot, 'eas-build-cache-provider');\n\n return {\n plugin: plugin.default ?? plugin,\n options: {},\n };\n } catch (error: any) {\n if (error instanceof CommandError) {\n Log.warn(error.message);\n } else {\n throw error;\n }\n return undefined;\n }\n }\n\n if (typeof provider === 'object' && typeof provider.plugin === 'string') {\n const plugin = resolvePluginFunction(projectRoot, provider.plugin);\n\n return { plugin, options: provider.options };\n }\n\n throw new Error('Invalid build cache provider');\n};\n\nexport async function resolveBuildCache({\n projectRoot,\n platform,\n provider,\n runOptions,\n}: {\n projectRoot: string;\n platform: 'android' | 'ios';\n provider: BuildCacheProvider;\n runOptions: RunOptions;\n}): Promise<string | null> {\n const fingerprintHash = await calculateFingerprintHashAsync({\n projectRoot,\n platform,\n provider,\n runOptions,\n });\n if (!fingerprintHash) {\n return null;\n }\n\n if ('resolveRemoteBuildCache' in provider.plugin) {\n Log.warn('The resolveRemoteBuildCache function is deprecated. Use resolveBuildCache instead.');\n return await provider.plugin.resolveRemoteBuildCache(\n { fingerprintHash, platform, runOptions, projectRoot },\n provider.options\n );\n }\n return await provider.plugin.resolveBuildCache(\n { fingerprintHash, platform, runOptions, projectRoot },\n provider.options\n );\n}\n\nexport async function uploadBuildCache({\n projectRoot,\n platform,\n provider,\n buildPath,\n runOptions,\n}: {\n projectRoot: string;\n platform: 'android' | 'ios';\n provider: BuildCacheProvider;\n buildPath: string;\n runOptions: RunOptions;\n}): Promise<void> {\n const fingerprintHash = await calculateFingerprintHashAsync({\n projectRoot,\n platform,\n provider,\n runOptions,\n });\n if (!fingerprintHash) {\n debug('No fingerprint hash found, skipping upload');\n return;\n }\n\n if ('uploadRemoteBuildCache' in provider.plugin) {\n Log.warn('The uploadRemoteBuildCache function is deprecated. Use uploadBuildCache instead.');\n await provider.plugin.uploadRemoteBuildCache(\n {\n projectRoot,\n platform,\n fingerprintHash,\n buildPath,\n runOptions,\n },\n provider.options\n );\n } else {\n await provider.plugin.uploadBuildCache(\n {\n projectRoot,\n platform,\n fingerprintHash,\n buildPath,\n runOptions,\n },\n provider.options\n );\n }\n}\n\nasync function calculateFingerprintHashAsync({\n projectRoot,\n platform,\n provider,\n runOptions,\n}: {\n projectRoot: string;\n platform: 'android' | 'ios';\n provider: BuildCacheProvider;\n runOptions: RunOptions;\n}): Promise<string | null> {\n if (provider.plugin.calculateFingerprintHash) {\n return await provider.plugin.calculateFingerprintHash(\n { projectRoot, platform, runOptions },\n provider.options\n );\n }\n\n const Fingerprint = importFingerprintForDev(projectRoot);\n if (!Fingerprint) {\n debug('@expo/fingerprint is not installed in the project, unable to calculate fingerprint');\n return null;\n }\n const fingerprint = await Fingerprint.createFingerprintAsync(projectRoot);\n\n return fingerprint.hash;\n}\n\nfunction importFingerprintForDev(projectRoot: string): null | typeof import('@expo/fingerprint') {\n try {\n return require(require.resolve('@expo/fingerprint', { paths: [projectRoot] }));\n } catch (error: any) {\n if ('code' in error && error.code === 'MODULE_NOT_FOUND') {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Resolve the provider plugin from a node module or package.\n * If the module or package does not include a provider plugin, this function throws.\n * The resolution is done in following order:\n * 1. Is the reference a relative file path or an import specifier with file path? e.g. `./file.js`, `pkg/file.js` or `@org/pkg/file.js`?\n * - Resolve the provider plugin as-is\n * 2. Does the module have a valid provider plugin in the `main` field?\n * - Resolve the `main` entry point as provider plugin\n */\nfunction resolvePluginFilePathForModule(projectRoot: string, pluginReference: string) {\n if (moduleNameIsDirectFileReference(pluginReference)) {\n // Only resolve `./file.js`, `package/file.js`, `@org/package/file.js`\n const pluginScriptFile = resolveFrom.silent(projectRoot, pluginReference);\n if (pluginScriptFile) {\n return pluginScriptFile;\n }\n } else if (moduleNameIsPackageReference(pluginReference)) {\n // Try to resole the `main` entry as config plugin\n return resolveFrom(projectRoot, pluginReference);\n }\n\n throw new Error(\n `Failed to resolve provider plugin for module \"${pluginReference}\" relative to \"${projectRoot}\". Do you have node modules installed?`\n );\n}\n\n// Resolve the module function and assert type\nexport function resolvePluginFunction(\n projectRoot: string,\n pluginReference: string\n): BuildCacheProviderPlugin {\n const pluginFile = resolvePluginFilePathForModule(projectRoot, pluginReference);\n\n try {\n let plugin = require(pluginFile);\n if (plugin?.default != null) {\n plugin = plugin.default;\n }\n\n if (\n typeof plugin !== 'object' ||\n (typeof plugin.resolveRemoteBuildCache !== 'function' &&\n typeof plugin.resolveBuildCache !== 'function') ||\n (typeof plugin.uploadRemoteBuildCache !== 'function' &&\n typeof plugin.uploadBuildCache !== 'function')\n ) {\n throw new Error(`\n The provider plugin \"${pluginReference}\" must export an object containing\n the resolveBuildCache and uploadBuildCache functions.\n `);\n }\n return plugin;\n } catch (error) {\n if (error instanceof SyntaxError) {\n // Add error linking to the docs of how create a valid provider plugin\n }\n throw error;\n }\n}\n\nasync function manuallyLoadDependency(projectRoot: string, packageName: string) {\n const possiblePaths = [\n path.join(projectRoot, 'node_modules'),\n ...(require.resolve.paths(packageName) ?? []),\n ];\n const nodeModulesFolder = possiblePaths?.find((p) => {\n const packagePath = path.join(p, packageName);\n return fs.existsSync(packagePath);\n });\n if (!nodeModulesFolder) {\n throw new Error(`Package ${packageName} not found in ${possiblePaths}`);\n }\n\n const { main } = await import(path.join(nodeModulesFolder, packageName, 'package.json'));\n return import(path.join(nodeModulesFolder, packageName, main));\n}\n"],"names":["resolveBuildCache","resolveBuildCacheProvider","resolvePluginFunction","uploadBuildCache","debug","require","provider","projectRoot","ensureDependenciesAsync","isProjectMutable","installMessage","warningMessage","requiredPackages","pkg","file","dev","plugin","manuallyLoadDependency","default","options","error","CommandError","Log","warn","message","undefined","Error","platform","runOptions","fingerprintHash","calculateFingerprintHashAsync","resolveRemoteBuildCache","buildPath","uploadRemoteBuildCache","calculateFingerprintHash","Fingerprint","importFingerprintForDev","fingerprint","createFingerprintAsync","hash","resolve","paths","code","resolvePluginFilePathForModule","pluginReference","moduleNameIsDirectFileReference","pluginScriptFile","resolveFrom","silent","moduleNameIsPackageReference","pluginFile","SyntaxError","packageName","possiblePaths","path","join","nodeModulesFolder","find","p","packagePath","fs","existsSync","main"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/build-cache-providers/index.ts"],"sourcesContent":["import { ExpoConfig, BuildCacheProviderPlugin, BuildCacheProvider, RunOptions } from '@expo/config';\nimport fs from 'fs';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { moduleNameIsDirectFileReference, moduleNameIsPackageReference } from './helpers';\nimport * as Log from '../../log';\nimport { ensureDependenciesAsync } from '../../start/doctor/dependencies/ensureDependenciesAsync';\nimport { CommandError } from '../errors';\n\nconst debug = require('debug')('expo:run:build-cache-provider') as typeof console.log;\n\nexport const resolveBuildCacheProvider = async (\n provider: Required<ExpoConfig>['buildCacheProvider'] | undefined,\n projectRoot: string\n): Promise<BuildCacheProvider | undefined> => {\n if (!provider) {\n return;\n }\n\n if (provider === 'eas') {\n try {\n await ensureDependenciesAsync(projectRoot, {\n isProjectMutable: true,\n installMessage:\n 'eas-build-cache-provider package is required to use the EAS build cache.\\n',\n warningMessage: 'Unable to to use the EAS remote build cache.',\n requiredPackages: [\n {\n pkg: 'eas-build-cache-provider',\n file: 'eas-build-cache-provider/package.json',\n dev: true,\n },\n ],\n });\n\n // We need to manually load dependencies installed on the fly\n const plugin = await manuallyLoadDependency(projectRoot, 'eas-build-cache-provider');\n\n return {\n plugin: plugin.default ?? plugin,\n options: {},\n };\n } catch (error: any) {\n if (error instanceof CommandError) {\n Log.warn(error.message);\n } else {\n throw error;\n }\n return undefined;\n }\n }\n\n if (typeof provider === 'object' && typeof provider.plugin === 'string') {\n const plugin = resolvePluginFunction(projectRoot, provider.plugin);\n\n return { plugin, options: provider.options };\n }\n\n throw new Error('Invalid build cache provider');\n};\n\nexport async function resolveBuildCache({\n projectRoot,\n platform,\n provider,\n runOptions,\n}: {\n projectRoot: string;\n platform: 'android' | 'ios';\n provider: BuildCacheProvider;\n runOptions: RunOptions;\n}): Promise<string | null> {\n const fingerprintHash = await calculateFingerprintHashAsync({\n projectRoot,\n platform,\n provider,\n runOptions,\n });\n if (!fingerprintHash) {\n return null;\n }\n\n if ('resolveRemoteBuildCache' in provider.plugin) {\n Log.warn('The resolveRemoteBuildCache function is deprecated. Use resolveBuildCache instead.');\n return await provider.plugin.resolveRemoteBuildCache(\n { fingerprintHash, platform, runOptions, projectRoot },\n provider.options\n );\n }\n return await provider.plugin.resolveBuildCache(\n { fingerprintHash, platform, runOptions, projectRoot },\n provider.options\n );\n}\n\nexport async function uploadBuildCache({\n projectRoot,\n platform,\n provider,\n buildPath,\n runOptions,\n}: {\n projectRoot: string;\n platform: 'android' | 'ios';\n provider: BuildCacheProvider;\n buildPath: string;\n runOptions: RunOptions;\n}): Promise<void> {\n const fingerprintHash = await calculateFingerprintHashAsync({\n projectRoot,\n platform,\n provider,\n runOptions,\n });\n if (!fingerprintHash) {\n debug('No fingerprint hash found, skipping upload');\n return;\n }\n\n if ('uploadRemoteBuildCache' in provider.plugin) {\n Log.warn('The uploadRemoteBuildCache function is deprecated. Use uploadBuildCache instead.');\n await provider.plugin.uploadRemoteBuildCache(\n {\n projectRoot,\n platform,\n fingerprintHash,\n buildPath,\n runOptions,\n },\n provider.options\n );\n } else {\n await provider.plugin.uploadBuildCache(\n {\n projectRoot,\n platform,\n fingerprintHash,\n buildPath,\n runOptions,\n },\n provider.options\n );\n }\n}\n\nasync function calculateFingerprintHashAsync({\n projectRoot,\n platform,\n provider,\n runOptions,\n}: {\n projectRoot: string;\n platform: 'android' | 'ios';\n provider: BuildCacheProvider;\n runOptions: RunOptions;\n}): Promise<string | null> {\n if (provider.plugin.calculateFingerprintHash) {\n return await provider.plugin.calculateFingerprintHash(\n { projectRoot, platform, runOptions },\n provider.options\n );\n }\n\n const Fingerprint = importFingerprintForDev(projectRoot);\n if (!Fingerprint) {\n Log.warn('@expo/fingerprint is not installed in the project, skipping build cache.');\n return null;\n }\n const fingerprint = await Fingerprint.createFingerprintAsync(projectRoot);\n\n return fingerprint.hash;\n}\n\nfunction importFingerprintForDev(projectRoot: string): null | typeof import('@expo/fingerprint') {\n try {\n return require(require.resolve('@expo/fingerprint', { paths: [projectRoot] }));\n } catch (error: any) {\n if ('code' in error && error.code === 'MODULE_NOT_FOUND') {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Resolve the provider plugin from a node module or package.\n * If the module or package does not include a provider plugin, this function throws.\n * The resolution is done in following order:\n * 1. Is the reference a relative file path or an import specifier with file path? e.g. `./file.js`, `pkg/file.js` or `@org/pkg/file.js`?\n * - Resolve the provider plugin as-is\n * 2. Does the module have a valid provider plugin in the `main` field?\n * - Resolve the `main` entry point as provider plugin\n */\nfunction resolvePluginFilePathForModule(projectRoot: string, pluginReference: string) {\n if (moduleNameIsDirectFileReference(pluginReference)) {\n // Only resolve `./file.js`, `package/file.js`, `@org/package/file.js`\n const pluginScriptFile = resolveFrom.silent(projectRoot, pluginReference);\n if (pluginScriptFile) {\n return pluginScriptFile;\n }\n } else if (moduleNameIsPackageReference(pluginReference)) {\n // Try to resole the `main` entry as config plugin\n return resolveFrom(projectRoot, pluginReference);\n }\n\n throw new Error(\n `Failed to resolve provider plugin for module \"${pluginReference}\" relative to \"${projectRoot}\". Do you have node modules installed?`\n );\n}\n\n// Resolve the module function and assert type\nexport function resolvePluginFunction(\n projectRoot: string,\n pluginReference: string\n): BuildCacheProviderPlugin {\n const pluginFile = resolvePluginFilePathForModule(projectRoot, pluginReference);\n\n try {\n let plugin = require(pluginFile);\n if (plugin?.default != null) {\n plugin = plugin.default;\n }\n\n if (\n typeof plugin !== 'object' ||\n (typeof plugin.resolveRemoteBuildCache !== 'function' &&\n typeof plugin.resolveBuildCache !== 'function') ||\n (typeof plugin.uploadRemoteBuildCache !== 'function' &&\n typeof plugin.uploadBuildCache !== 'function')\n ) {\n throw new Error(`\n The provider plugin \"${pluginReference}\" must export an object containing\n the resolveBuildCache and uploadBuildCache functions.\n `);\n }\n return plugin;\n } catch (error) {\n if (error instanceof SyntaxError) {\n // Add error linking to the docs of how create a valid provider plugin\n }\n throw error;\n }\n}\n\nasync function manuallyLoadDependency(projectRoot: string, packageName: string) {\n const possiblePaths = [\n path.join(projectRoot, 'node_modules'),\n ...(require.resolve.paths(packageName) ?? []),\n ];\n const nodeModulesFolder = possiblePaths?.find((p) => {\n const packagePath = path.join(p, packageName);\n return fs.existsSync(packagePath);\n });\n if (!nodeModulesFolder) {\n throw new Error(`Package ${packageName} not found in ${possiblePaths}`);\n }\n\n const { main } = await import(path.join(nodeModulesFolder, packageName, 'package.json'));\n return import(path.join(nodeModulesFolder, packageName, main));\n}\n"],"names":["resolveBuildCache","resolveBuildCacheProvider","resolvePluginFunction","uploadBuildCache","debug","require","provider","projectRoot","ensureDependenciesAsync","isProjectMutable","installMessage","warningMessage","requiredPackages","pkg","file","dev","plugin","manuallyLoadDependency","default","options","error","CommandError","Log","warn","message","undefined","Error","platform","runOptions","fingerprintHash","calculateFingerprintHashAsync","resolveRemoteBuildCache","buildPath","uploadRemoteBuildCache","calculateFingerprintHash","Fingerprint","importFingerprintForDev","fingerprint","createFingerprintAsync","hash","resolve","paths","code","resolvePluginFilePathForModule","pluginReference","moduleNameIsDirectFileReference","pluginScriptFile","resolveFrom","silent","moduleNameIsPackageReference","pluginFile","SyntaxError","packageName","possiblePaths","path","join","nodeModulesFolder","find","p","packagePath","fs","existsSync","main"],"mappings":"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"}
|
package/build/src/utils/env.js
CHANGED
|
@@ -164,6 +164,12 @@ class Env {
|
|
|
164
164
|
*/ get EXPO_METRO_UNSTABLE_ERRORS() {
|
|
165
165
|
return (0, _getenv().boolish)('EXPO_METRO_UNSTABLE_ERRORS', true);
|
|
166
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Override the Metro cache stores directory. When set, this takes precedence over
|
|
169
|
+
* any `cacheStores` configuration in metro.config.js.
|
|
170
|
+
*/ get EXPO_METRO_CACHE_STORES_DIR() {
|
|
171
|
+
return (0, _getenv().string)('EXPO_METRO_CACHE_STORES_DIR', '');
|
|
172
|
+
}
|
|
167
173
|
/** Enable the experimental sticky resolver for Metro (Uses Expo Autolinking results and applies them to Metro's resolution)
|
|
168
174
|
* @deprecated Replaced by `exp.experiments.autolinkingModuleResolution`
|
|
169
175
|
*/ get EXPO_USE_STICKY_RESOLVER() {
|
|
@@ -251,6 +257,28 @@ class Env {
|
|
|
251
257
|
*/ get EXPO_UNSTABLE_BONJOUR() {
|
|
252
258
|
return (0, _getenv().boolish)('EXPO_UNSTABLE_BONJOUR', false);
|
|
253
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* Enable JSONL output mode for machine-readable output
|
|
262
|
+
* If set to a string, it will be used as a path for the JSONL output.
|
|
263
|
+
* If set to a boolish value, it will be used as a flag
|
|
264
|
+
* to enable/disable JSONL output in stdout.
|
|
265
|
+
*/ get EXPO_UNSTABLE_JSONL_OUTPUT() {
|
|
266
|
+
const value = (0, _getenv().string)('EXPO_UNSTABLE_JSONL_OUTPUT', '');
|
|
267
|
+
const valueNormalized = value.toLowerCase();
|
|
268
|
+
if ([
|
|
269
|
+
'0',
|
|
270
|
+
'false',
|
|
271
|
+
''
|
|
272
|
+
].includes(valueNormalized)) {
|
|
273
|
+
return false;
|
|
274
|
+
} else if ([
|
|
275
|
+
'1',
|
|
276
|
+
'true'
|
|
277
|
+
].includes(valueNormalized)) {
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
return value;
|
|
281
|
+
}
|
|
254
282
|
}
|
|
255
283
|
const env = new Env();
|
|
256
284
|
function envIsWebcontainer() {
|