@expo/cli 55.0.0-canary-20260114-d8e19f5 → 55.0.0-canary-20260119-70f7c28

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.
Files changed (28) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/export/embed/exportEmbedAsync.js +1 -2
  3. package/build/src/export/embed/exportEmbedAsync.js.map +1 -1
  4. package/build/src/export/exportStaticAsync.js +8 -7
  5. package/build/src/export/exportStaticAsync.js.map +1 -1
  6. package/build/src/start/server/Bonjour.js +100 -0
  7. package/build/src/start/server/Bonjour.js.map +1 -0
  8. package/build/src/start/server/BundlerDevServer.js +22 -4
  9. package/build/src/start/server/BundlerDevServer.js.map +1 -1
  10. package/build/src/start/server/metro/DevToolsPluginWebsocketEndpoint.js +10 -2
  11. package/build/src/start/server/metro/DevToolsPluginWebsocketEndpoint.js.map +1 -1
  12. package/build/src/start/server/metro/MetroBundlerDevServer.js +32 -26
  13. package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
  14. package/build/src/start/server/metro/createServerRouteMiddleware.js +25 -1
  15. package/build/src/start/server/metro/createServerRouteMiddleware.js.map +1 -1
  16. package/build/src/start/server/metro/debugging/createDebugMiddleware.js +22 -8
  17. package/build/src/start/server/metro/debugging/createDebugMiddleware.js.map +1 -1
  18. package/build/src/start/server/metro/instantiateMetro.js +17 -6
  19. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  20. package/build/src/utils/env.js +14 -0
  21. package/build/src/utils/env.js.map +1 -1
  22. package/build/src/utils/net.js +43 -0
  23. package/build/src/utils/net.js.map +1 -0
  24. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  25. package/build/src/utils/telemetry/utils/context.js +1 -1
  26. package/package.json +19 -18
  27. package/build/src/start/server/middleware/DataLoaderModuleMiddleware.js +0 -75
  28. package/build/src/start/server/middleware/DataLoaderModuleMiddleware.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/server/BundlerDevServer.ts"],"sourcesContent":["import assert from 'assert';\nimport resolveFrom from 'resolve-from';\n\nimport { AsyncNgrok } from './AsyncNgrok';\nimport { AsyncWsTunnel } from './AsyncWsTunnel';\nimport DevToolsPluginManager from './DevToolsPluginManager';\nimport { DevelopmentSession } from './DevelopmentSession';\nimport { CreateURLOptions, UrlCreator } from './UrlCreator';\nimport { PlatformBundlers } from './platformBundlers';\nimport * as Log from '../../log';\nimport { FileNotifier } from '../../utils/FileNotifier';\nimport { resolveWithTimeout } from '../../utils/delay';\nimport { env, envIsWebcontainer } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\nimport { openBrowserAsync } from '../../utils/open';\nimport {\n BaseOpenInCustomProps,\n BaseResolveDeviceProps,\n PlatformManager,\n} from '../platforms/PlatformManager';\n\nconst debug = require('debug')('expo:start:server:devServer') as typeof console.log;\n\nexport type MessageSocket = {\n broadcast: (method: string, params?: Record<string, any> | undefined) => void;\n};\n\nexport type ServerLike = {\n close(callback?: (err?: Error) => void): void;\n addListener?(event: string, listener: (...args: any[]) => void): unknown;\n};\n\nexport type DevServerInstance = {\n /** Bundler dev server instance. */\n server: ServerLike;\n /** Dev server URL location properties. */\n location: {\n url: string;\n port: number;\n protocol: 'http' | 'https';\n host?: string;\n };\n /** Additional middleware that's attached to the `server`. */\n middleware: any;\n /** Message socket for communicating with the runtime. */\n messageSocket: MessageSocket;\n};\n\nexport interface BundlerStartOptions {\n /** Should the dev server use `https` protocol. */\n https?: boolean;\n /** Should start the dev servers in development mode (minify). */\n mode?: 'development' | 'production';\n /** Is dev client enabled. */\n devClient?: boolean;\n /** Should run dev servers with clean caches. */\n resetDevServer?: boolean;\n /** Code signing private key path (defaults to same directory as certificate) */\n privateKeyPath?: string;\n\n /** Max amount of workers (threads) to use with Metro bundler, defaults to undefined for max workers. */\n maxWorkers?: number;\n /** Port to start the dev server on. */\n port?: number;\n\n /** Should start a headless dev server e.g. mock representation to approximate info from a server running in a different process. */\n headless?: boolean;\n /** Should instruct the bundler to create minified bundles. */\n minify?: boolean;\n\n /** Will the bundler be used for exporting. NOTE: This is an odd option to pass to the dev server. */\n isExporting?: boolean;\n\n // Webpack options\n /** Should modify and create PWA icons. */\n isImageEditingEnabled?: boolean;\n\n location: CreateURLOptions;\n}\n\nconst PLATFORM_MANAGERS = {\n simulator: () =>\n require('../platforms/ios/ApplePlatformManager')\n .ApplePlatformManager as typeof import('../platforms/ios/ApplePlatformManager').ApplePlatformManager,\n emulator: () =>\n require('../platforms/android/AndroidPlatformManager')\n .AndroidPlatformManager as typeof import('../platforms/android/AndroidPlatformManager').AndroidPlatformManager,\n};\n\nexport abstract class BundlerDevServer {\n /** Name of the bundler. */\n abstract get name(): string;\n\n /** Tunnel instance for managing tunnel connections. */\n protected tunnel: AsyncNgrok | AsyncWsTunnel | null = null;\n /** Interfaces with the Expo 'Development Session' API. */\n protected devSession: DevelopmentSession | null = null;\n /** Http server and related info. */\n protected instance: DevServerInstance | null = null;\n /** Native platform interfaces for opening projects. */\n private platformManagers: Record<string, PlatformManager<any>> = {};\n /** Manages the creation of dev server URLs. */\n protected urlCreator?: UrlCreator | null = null;\n\n private notifier: FileNotifier | null = null;\n protected readonly devToolsPluginManager: DevToolsPluginManager;\n public isDevClient: boolean;\n\n constructor(\n /** Project root folder. */\n public projectRoot: string,\n /** A mapping of bundlers to platforms. */\n public platformBundlers: PlatformBundlers,\n /** Advanced options */\n options?: {\n /**\n * The instance of DevToolsPluginManager\n * @default new DevToolsPluginManager(projectRoot)\n */\n devToolsPluginManager?: DevToolsPluginManager;\n // TODO: Replace with custom scheme maybe...\n isDevClient?: boolean;\n }\n ) {\n this.devToolsPluginManager =\n options?.devToolsPluginManager ?? new DevToolsPluginManager(projectRoot);\n this.isDevClient = options?.isDevClient ?? false;\n }\n\n protected setInstance(instance: DevServerInstance) {\n this.instance = instance;\n }\n\n /** Get the manifest middleware function. */\n protected async getManifestMiddlewareAsync(\n options: Pick<BundlerStartOptions, 'minify' | 'mode' | 'privateKeyPath'> = {}\n ) {\n const Middleware = require('./middleware/ExpoGoManifestHandlerMiddleware')\n .ExpoGoManifestHandlerMiddleware as typeof import('./middleware/ExpoGoManifestHandlerMiddleware').ExpoGoManifestHandlerMiddleware;\n\n const urlCreator = this.getUrlCreator();\n const middleware = new Middleware(this.projectRoot, {\n constructUrl: urlCreator.constructUrl.bind(urlCreator),\n mode: options.mode,\n minify: options.minify,\n isNativeWebpack: this.name === 'webpack' && this.isTargetingNative(),\n privateKeyPath: options.privateKeyPath,\n });\n return middleware;\n }\n\n /** Start the dev server using settings defined in the start command. */\n public async startAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n await this.stopAsync();\n\n let instance: DevServerInstance;\n if (options.headless) {\n instance = await this.startHeadlessAsync(options);\n } else {\n instance = await this.startImplementationAsync(options);\n }\n\n this.setInstance(instance);\n await this.postStartAsync(options);\n return instance;\n }\n\n protected abstract startImplementationAsync(\n options: BundlerStartOptions\n ): Promise<DevServerInstance>;\n\n public async waitForTypeScriptAsync(): Promise<boolean> {\n return false;\n }\n\n public abstract startTypeScriptServices(): Promise<void>;\n\n public async watchEnvironmentVariables(): Promise<void> {\n // noop -- We've only implemented this functionality in Metro.\n }\n\n /**\n * Creates a mock server representation that can be used to estimate URLs for a server started in another process.\n * This is used for the run commands where you can reuse the server from a previous run.\n */\n private async startHeadlessAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n if (!options.port)\n throw new CommandError('HEADLESS_SERVER', 'headless dev server requires a port option');\n this.urlCreator = this.getUrlCreator(options);\n\n return {\n // Create a mock server\n server: {\n close: (callback: () => void) => {\n this.instance = null;\n callback?.();\n },\n addListener() {},\n },\n location: {\n // The port is the main thing we want to send back.\n port: options.port,\n // localhost isn't always correct.\n host: 'localhost',\n // http is the only supported protocol on native.\n url: `http://localhost:${options.port}`,\n protocol: 'http',\n },\n middleware: {},\n messageSocket: {\n broadcast: () => {\n throw new CommandError('HEADLESS_SERVER', 'Cannot broadcast messages to headless server');\n },\n },\n };\n }\n\n /**\n * Runs after the `startAsync` function, performing any additional common operations.\n * You can assume the dev server is started by the time this function is called.\n */\n protected async postStartAsync(options: BundlerStartOptions) {\n if (\n options.location.hostType === 'tunnel' &&\n !env.EXPO_OFFLINE &&\n // This is a hack to prevent using tunnel on web since we block it upstream for some reason.\n this.isTargetingNative()\n ) {\n await this._startTunnelAsync();\n } else if (envIsWebcontainer()) {\n await this._startTunnelAsync();\n }\n\n if (!options.isExporting) {\n await this.startDevSessionAsync();\n this.watchConfig();\n }\n }\n\n protected abstract getConfigModuleIds(): string[];\n\n protected watchConfig() {\n this.notifier?.stopObserving();\n this.notifier = new FileNotifier(this.projectRoot, this.getConfigModuleIds());\n this.notifier.startObserving();\n }\n\n /** Create ngrok instance and start the tunnel server. Exposed for testing. */\n public async _startTunnelAsync(): Promise<AsyncNgrok | AsyncWsTunnel | null> {\n const port = this.getInstance()?.location.port;\n if (!port) return null;\n debug('[tunnel] connect to port: ' + port);\n this.tunnel = envIsWebcontainer()\n ? new AsyncWsTunnel(this.projectRoot, port)\n : new AsyncNgrok(this.projectRoot, port);\n await this.tunnel.startAsync();\n return this.tunnel;\n }\n\n protected async startDevSessionAsync() {\n // This is used to make Expo Go open the project in either Expo Go, or the web browser.\n // Must come after ngrok (`startTunnelAsync`) setup.\n this.devSession = new DevelopmentSession(\n this.projectRoot,\n // This URL will be used on external devices so the computer IP won't be relevant.\n this.isTargetingNative()\n ? this.getNativeRuntimeUrl()\n : this.getDevServerUrl({ hostType: 'localhost' })\n );\n\n await this.devSession.startAsync({\n runtime: this.isTargetingNative() ? 'native' : 'web',\n });\n }\n\n public isTargetingNative() {\n // Temporary hack while we implement multi-bundler dev server proxy.\n return true;\n }\n\n public isTargetingWeb() {\n return this.platformBundlers.web === this.name;\n }\n\n /**\n * Sends a message over web sockets to any connected device,\n * does nothing when the dev server is not running.\n *\n * @param method name of the command. In RN projects `reload`, and `devMenu` are available. In Expo Go, `sendDevCommand` is available.\n * @param params\n */\n public broadcastMessage(\n method: 'reload' | 'devMenu' | 'sendDevCommand',\n params?: Record<string, any>\n ) {\n this.getInstance()?.messageSocket.broadcast(method, params);\n }\n\n /** Get the running dev server instance. */\n public getInstance() {\n return this.instance;\n }\n\n /** Stop the running dev server instance. */\n async stopAsync() {\n // Stop file watching.\n this.notifier?.stopObserving();\n\n // Stop the dev session timer and tell Expo API to remove dev session.\n await this.devSession?.closeAsync();\n\n // Stop tunnel if running.\n await this.tunnel?.stopAsync().catch((e) => {\n Log.error(`Error stopping tunnel:`);\n Log.exception(e);\n });\n\n return resolveWithTimeout(\n () =>\n new Promise<void>((resolve, reject) => {\n // Close the server.\n debug(`Stopping dev server (bundler: ${this.name})`);\n\n if (this.instance?.server) {\n // Check if server is even running.\n this.instance.server.close((error) => {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n if (error) {\n if ('code' in error && error.code === 'ERR_SERVER_NOT_RUNNING') {\n resolve();\n } else {\n reject(error);\n }\n } else {\n resolve();\n }\n });\n } else {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n resolve();\n }\n }),\n {\n // NOTE(Bacon): Metro dev server doesn't seem to be closing in time.\n timeout: 1000,\n errorMessage: `Timeout waiting for '${this.name}' dev server to close`,\n }\n );\n }\n\n public getUrlCreator(options: Partial<Pick<BundlerStartOptions, 'port' | 'location'>> = {}) {\n if (!this.urlCreator) {\n assert(options?.port, 'Dev server instance not found');\n this.urlCreator = new UrlCreator(options.location, {\n port: options.port,\n getTunnelUrl: this.getTunnelUrl.bind(this),\n });\n }\n return this.urlCreator;\n }\n\n public getNativeRuntimeUrl(opts: Partial<CreateURLOptions> = {}) {\n return this.isDevClient\n ? (this.getUrlCreator().constructDevClientUrl(opts) ?? this.getDevServerUrl())\n : this.getUrlCreator().constructUrl({ ...opts, scheme: 'exp' });\n }\n\n /** Get the URL for the running instance of the dev server. */\n public getDevServerUrl(options: { hostType?: 'localhost' } = {}): string | null {\n const instance = this.getInstance();\n if (!instance?.location) {\n return null;\n }\n\n // If we have an active WS tunnel instance, we always need to return the tunnel location.\n if (this.tunnel && this.tunnel instanceof AsyncWsTunnel) {\n return this.getUrlCreator().constructUrl();\n }\n\n const { location } = instance;\n if (options.hostType === 'localhost') {\n return `${location.protocol}://localhost:${location.port}`;\n }\n\n return location.url ?? null;\n }\n\n public getDevServerUrlOrAssert(options: { hostType?: 'localhost' } = {}): string {\n const instance = this.getDevServerUrl(options);\n if (!instance) {\n throw new CommandError(\n 'DEV_SERVER',\n `Cannot get the dev server URL before the server has started - bundler[${this.name}]`\n );\n }\n\n return instance;\n }\n\n /** Get the base URL for JS inspector */\n public getJsInspectorBaseUrl(): string {\n if (this.name !== 'metro') {\n throw new CommandError(\n 'DEV_SERVER',\n `Cannot get the JS inspector base url - bundler[${this.name}]`\n );\n }\n return this.getUrlCreator().constructUrl({ scheme: 'http' });\n }\n\n /** Get the tunnel URL from the tunnel. */\n public getTunnelUrl(): string | null {\n return this.tunnel?.getActiveUrl() ?? null;\n }\n\n /** Open the dev server in a runtime. */\n public async openPlatformAsync(\n launchTarget: keyof typeof PLATFORM_MANAGERS | 'desktop',\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n if (launchTarget === 'desktop') {\n const serverUrl = this.getDevServerUrl({ hostType: 'localhost' });\n // Allow opening the tunnel URL when using Metro web.\n const url = this.name === 'metro' ? (this.getTunnelUrl() ?? serverUrl) : serverUrl;\n await openBrowserAsync(url!);\n return { url };\n }\n\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime }, resolver);\n }\n\n /** Open the dev server in a runtime. */\n public async openCustomRuntimeAsync<T extends BaseOpenInCustomProps = BaseOpenInCustomProps>(\n launchTarget: keyof typeof PLATFORM_MANAGERS,\n launchProps: Partial<T> = {},\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n if (runtime !== 'custom') {\n throw new CommandError(\n `dev server cannot open custom runtimes either because it does not target native platforms or because it is not targeting dev clients. (target: ${runtime})`\n );\n }\n\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime: 'custom', props: launchProps }, resolver);\n }\n\n /** Get the URL for opening in Expo Go. */\n protected getExpoGoUrl(): string {\n return this.getUrlCreator().constructUrl({ scheme: 'exp' });\n }\n\n /** Should use the interstitial page for selecting which runtime to use. */\n protected isRedirectPageEnabled(): boolean {\n return (\n !env.EXPO_NO_REDIRECT_PAGE &&\n // if user passed --dev-client flag, skip interstitial page\n !this.isDevClient &&\n // Checks if dev client is installed.\n !!resolveFrom.silent(this.projectRoot, 'expo-dev-client')\n );\n }\n\n /** Get the redirect URL when redirecting is enabled. */\n public getRedirectUrl(platform: keyof typeof PLATFORM_MANAGERS | null = null): string | null {\n if (!this.isRedirectPageEnabled()) {\n debug('Redirect page is disabled');\n return null;\n }\n\n return (\n this.getUrlCreator().constructLoadingUrl(\n {},\n platform === 'emulator' ? 'android' : platform === 'simulator' ? 'ios' : null\n ) ?? null\n );\n }\n\n protected async getPlatformManagerAsync(platform: keyof typeof PLATFORM_MANAGERS) {\n if (!this.platformManagers[platform]) {\n const Manager = PLATFORM_MANAGERS[platform]();\n const port = this.getInstance()?.location.port;\n if (!port || !this.urlCreator) {\n throw new CommandError(\n 'DEV_SERVER',\n 'Cannot interact with native platforms until dev server has started'\n );\n }\n debug(`Creating platform manager (platform: ${platform}, port: ${port})`);\n this.platformManagers[platform] = new Manager(this.projectRoot, port, {\n getCustomRuntimeUrl: this.urlCreator.constructDevClientUrl.bind(this.urlCreator),\n getExpoGoUrl: this.getExpoGoUrl.bind(this),\n getRedirectUrl: this.getRedirectUrl.bind(this, platform),\n getDevServerUrl: this.getDevServerUrl.bind(this, { hostType: 'localhost' }),\n });\n }\n return this.platformManagers[platform];\n }\n}\n"],"names":["BundlerDevServer","debug","require","PLATFORM_MANAGERS","simulator","ApplePlatformManager","emulator","AndroidPlatformManager","constructor","projectRoot","platformBundlers","options","tunnel","devSession","instance","platformManagers","urlCreator","notifier","devToolsPluginManager","DevToolsPluginManager","isDevClient","setInstance","getManifestMiddlewareAsync","Middleware","ExpoGoManifestHandlerMiddleware","getUrlCreator","middleware","constructUrl","bind","mode","minify","isNativeWebpack","name","isTargetingNative","privateKeyPath","startAsync","stopAsync","headless","startHeadlessAsync","startImplementationAsync","postStartAsync","waitForTypeScriptAsync","watchEnvironmentVariables","port","CommandError","server","close","callback","addListener","location","host","url","protocol","messageSocket","broadcast","hostType","env","EXPO_OFFLINE","_startTunnelAsync","envIsWebcontainer","isExporting","startDevSessionAsync","watchConfig","stopObserving","FileNotifier","getConfigModuleIds","startObserving","getInstance","AsyncWsTunnel","AsyncNgrok","DevelopmentSession","getNativeRuntimeUrl","getDevServerUrl","runtime","isTargetingWeb","web","broadcastMessage","method","params","closeAsync","catch","e","Log","error","exception","resolveWithTimeout","Promise","resolve","reject","code","timeout","errorMessage","assert","UrlCreator","getTunnelUrl","opts","constructDevClientUrl","scheme","getDevServerUrlOrAssert","getJsInspectorBaseUrl","getActiveUrl","openPlatformAsync","launchTarget","resolver","serverUrl","openBrowserAsync","manager","getPlatformManagerAsync","openAsync","openCustomRuntimeAsync","launchProps","props","getExpoGoUrl","isRedirectPageEnabled","EXPO_NO_REDIRECT_PAGE","resolveFrom","silent","getRedirectUrl","platform","constructLoadingUrl","Manager","getCustomRuntimeUrl"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/start/server/BundlerDevServer.ts"],"sourcesContent":["import assert from 'assert';\nimport resolveFrom from 'resolve-from';\n\nimport { AsyncNgrok } from './AsyncNgrok';\nimport { AsyncWsTunnel } from './AsyncWsTunnel';\nimport { Bonjour } from './Bonjour';\nimport DevToolsPluginManager from './DevToolsPluginManager';\nimport { DevelopmentSession } from './DevelopmentSession';\nimport { CreateURLOptions, UrlCreator } from './UrlCreator';\nimport { PlatformBundlers } from './platformBundlers';\nimport * as Log from '../../log';\nimport { FileNotifier } from '../../utils/FileNotifier';\nimport { resolveWithTimeout } from '../../utils/delay';\nimport { env, envIsWebcontainer } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\nimport { openBrowserAsync } from '../../utils/open';\nimport {\n BaseOpenInCustomProps,\n BaseResolveDeviceProps,\n PlatformManager,\n} from '../platforms/PlatformManager';\n\nconst debug = require('debug')('expo:start:server:devServer') as typeof console.log;\n\nexport type MessageSocket = {\n broadcast: (method: string, params?: Record<string, any> | undefined) => void;\n};\n\nexport type ServerLike = {\n close(callback?: (err?: Error) => void): void;\n addListener?(event: string, listener: (...args: any[]) => void): unknown;\n};\n\nexport type DevServerInstance = {\n /** Bundler dev server instance. */\n server: ServerLike;\n /** Dev server URL location properties. */\n location: {\n url: string;\n port: number;\n protocol: 'http' | 'https';\n host?: string;\n };\n /** Additional middleware that's attached to the `server`. */\n middleware: any;\n /** Message socket for communicating with the runtime. */\n messageSocket: MessageSocket;\n};\n\nexport interface BundlerStartOptions {\n /** Should the dev server use `https` protocol. */\n https?: boolean;\n /** Should start the dev servers in development mode (minify). */\n mode?: 'development' | 'production';\n /** Is dev client enabled. */\n devClient?: boolean;\n /** Should run dev servers with clean caches. */\n resetDevServer?: boolean;\n /** Code signing private key path (defaults to same directory as certificate) */\n privateKeyPath?: string;\n\n /** Max amount of workers (threads) to use with Metro bundler, defaults to undefined for max workers. */\n maxWorkers?: number;\n /** Port to start the dev server on. */\n port?: number;\n\n /** Should start a headless dev server e.g. mock representation to approximate info from a server running in a different process. */\n headless?: boolean;\n /** Should instruct the bundler to create minified bundles. */\n minify?: boolean;\n\n /** Will the bundler be used for exporting. NOTE: This is an odd option to pass to the dev server. */\n isExporting?: boolean;\n\n // Webpack options\n /** Should modify and create PWA icons. */\n isImageEditingEnabled?: boolean;\n\n location: CreateURLOptions;\n}\n\nconst PLATFORM_MANAGERS = {\n simulator: () =>\n require('../platforms/ios/ApplePlatformManager')\n .ApplePlatformManager as typeof import('../platforms/ios/ApplePlatformManager').ApplePlatformManager,\n emulator: () =>\n require('../platforms/android/AndroidPlatformManager')\n .AndroidPlatformManager as typeof import('../platforms/android/AndroidPlatformManager').AndroidPlatformManager,\n};\n\nexport abstract class BundlerDevServer {\n /** Name of the bundler. */\n abstract get name(): string;\n\n /** Tunnel instance for managing tunnel connections. */\n protected tunnel: AsyncNgrok | AsyncWsTunnel | null = null;\n /** Interfaces with the Expo 'Development Session' API. */\n protected devSession: DevelopmentSession | null = null;\n /** Announces dev server via Bonjour */\n protected bonjour: Bonjour | null = null;\n /** Http server and related info. */\n protected instance: DevServerInstance | null = null;\n /** Native platform interfaces for opening projects. */\n private platformManagers: Record<string, PlatformManager<any>> = {};\n /** Manages the creation of dev server URLs. */\n protected urlCreator?: UrlCreator | null = null;\n\n private notifier: FileNotifier | null = null;\n protected readonly devToolsPluginManager: DevToolsPluginManager;\n public isDevClient: boolean;\n\n constructor(\n /** Project root folder. */\n public projectRoot: string,\n /** A mapping of bundlers to platforms. */\n public platformBundlers: PlatformBundlers,\n /** Advanced options */\n options?: {\n /**\n * The instance of DevToolsPluginManager\n * @default new DevToolsPluginManager(projectRoot)\n */\n devToolsPluginManager?: DevToolsPluginManager;\n // TODO: Replace with custom scheme maybe...\n isDevClient?: boolean;\n }\n ) {\n this.devToolsPluginManager =\n options?.devToolsPluginManager ?? new DevToolsPluginManager(projectRoot);\n this.isDevClient = options?.isDevClient ?? false;\n }\n\n protected setInstance(instance: DevServerInstance) {\n this.instance = instance;\n }\n\n /** Get the manifest middleware function. */\n protected async getManifestMiddlewareAsync(\n options: Pick<BundlerStartOptions, 'minify' | 'mode' | 'privateKeyPath'> = {}\n ) {\n const Middleware = require('./middleware/ExpoGoManifestHandlerMiddleware')\n .ExpoGoManifestHandlerMiddleware as typeof import('./middleware/ExpoGoManifestHandlerMiddleware').ExpoGoManifestHandlerMiddleware;\n\n const urlCreator = this.getUrlCreator();\n const middleware = new Middleware(this.projectRoot, {\n constructUrl: urlCreator.constructUrl.bind(urlCreator),\n mode: options.mode,\n minify: options.minify,\n isNativeWebpack: this.name === 'webpack' && this.isTargetingNative(),\n privateKeyPath: options.privateKeyPath,\n });\n return middleware;\n }\n\n /** Start the dev server using settings defined in the start command. */\n public async startAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n await this.stopAsync();\n\n let instance: DevServerInstance;\n if (options.headless) {\n instance = await this.startHeadlessAsync(options);\n } else {\n instance = await this.startImplementationAsync(options);\n }\n\n this.setInstance(instance);\n await this.postStartAsync(options);\n return instance;\n }\n\n protected abstract startImplementationAsync(\n options: BundlerStartOptions\n ): Promise<DevServerInstance>;\n\n public async waitForTypeScriptAsync(): Promise<boolean> {\n return false;\n }\n\n public abstract startTypeScriptServices(): Promise<void>;\n\n public async watchEnvironmentVariables(): Promise<void> {\n // noop -- We've only implemented this functionality in Metro.\n }\n\n /**\n * Creates a mock server representation that can be used to estimate URLs for a server started in another process.\n * This is used for the run commands where you can reuse the server from a previous run.\n */\n private async startHeadlessAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n if (!options.port)\n throw new CommandError('HEADLESS_SERVER', 'headless dev server requires a port option');\n this.urlCreator = this.getUrlCreator(options);\n\n return {\n // Create a mock server\n server: {\n close: (callback: () => void) => {\n this.instance = null;\n callback?.();\n },\n addListener() {},\n },\n location: {\n // The port is the main thing we want to send back.\n port: options.port,\n // localhost isn't always correct.\n host: 'localhost',\n // http is the only supported protocol on native.\n url: `http://localhost:${options.port}`,\n protocol: 'http',\n },\n middleware: {},\n messageSocket: {\n broadcast: () => {\n throw new CommandError('HEADLESS_SERVER', 'Cannot broadcast messages to headless server');\n },\n },\n };\n }\n\n /**\n * Runs after the `startAsync` function, performing any additional common operations.\n * You can assume the dev server is started by the time this function is called.\n */\n protected async postStartAsync(options: BundlerStartOptions) {\n if (\n options.location.hostType === 'tunnel' &&\n !env.EXPO_OFFLINE &&\n // This is a hack to prevent using tunnel on web since we block it upstream for some reason.\n this.isTargetingNative()\n ) {\n await this._startTunnelAsync();\n } else if (envIsWebcontainer()) {\n await this._startTunnelAsync();\n }\n\n if (!options.isExporting) {\n await Promise.all([this.startDevSessionAsync(), this.startBonjourAsync()]);\n this.watchConfig();\n }\n }\n\n protected abstract getConfigModuleIds(): string[];\n\n protected watchConfig() {\n this.notifier?.stopObserving();\n this.notifier = new FileNotifier(this.projectRoot, this.getConfigModuleIds());\n this.notifier.startObserving();\n }\n\n /** Create ngrok instance and start the tunnel server. Exposed for testing. */\n public async _startTunnelAsync(): Promise<AsyncNgrok | AsyncWsTunnel | null> {\n const port = this.getInstance()?.location.port;\n if (!port) return null;\n debug('[tunnel] connect to port: ' + port);\n this.tunnel = envIsWebcontainer()\n ? new AsyncWsTunnel(this.projectRoot, port)\n : new AsyncNgrok(this.projectRoot, port);\n await this.tunnel.startAsync();\n return this.tunnel;\n }\n\n protected async startDevSessionAsync() {\n // This is used to make Expo Go open the project in either Expo Go, or the web browser.\n // Must come after ngrok (`startTunnelAsync`) setup.\n this.devSession = new DevelopmentSession(\n this.projectRoot,\n // This URL will be used on external devices so the computer IP won't be relevant.\n this.isTargetingNative()\n ? this.getNativeRuntimeUrl()\n : this.getDevServerUrl({ hostType: 'localhost' })\n );\n\n await this.devSession.startAsync({\n runtime: this.isTargetingNative() ? 'native' : 'web',\n });\n }\n\n protected async startBonjourAsync() {\n // This is used to make Expo Go open the project in either Expo Go, or the web browser.\n // Must come after ngrok (`startTunnelAsync`) setup.\n if (!this.bonjour) {\n this.bonjour = new Bonjour(this.projectRoot, this.getInstance()?.location.port);\n }\n\n await this.bonjour.announceAsync({});\n }\n\n public isTargetingNative() {\n // Temporary hack while we implement multi-bundler dev server proxy.\n return true;\n }\n\n public isTargetingWeb() {\n return this.platformBundlers.web === this.name;\n }\n\n /**\n * Sends a message over web sockets to any connected device,\n * does nothing when the dev server is not running.\n *\n * @param method name of the command. In RN projects `reload`, and `devMenu` are available. In Expo Go, `sendDevCommand` is available.\n * @param params\n */\n public broadcastMessage(\n method: 'reload' | 'devMenu' | 'sendDevCommand',\n params?: Record<string, any>\n ) {\n this.getInstance()?.messageSocket.broadcast(method, params);\n }\n\n /** Get the running dev server instance. */\n public getInstance() {\n return this.instance;\n }\n\n /** Stop the running dev server instance. */\n async stopAsync() {\n // Stop file watching.\n this.notifier?.stopObserving();\n\n await Promise.all([\n // Stop the bonjour advertiser\n this.bonjour?.closeAsync(),\n // Stop the dev session timer and tell Expo API to remove dev session.\n this.devSession?.closeAsync(),\n ]);\n\n // Stop tunnel if running.\n await this.tunnel?.stopAsync().catch((e) => {\n Log.error(`Error stopping tunnel:`);\n Log.exception(e);\n });\n\n return resolveWithTimeout(\n () =>\n new Promise<void>((resolve, reject) => {\n // Close the server.\n debug(`Stopping dev server (bundler: ${this.name})`);\n\n if (this.instance?.server) {\n // Check if server is even running.\n this.instance.server.close((error) => {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n if (error) {\n if ('code' in error && error.code === 'ERR_SERVER_NOT_RUNNING') {\n resolve();\n } else {\n reject(error);\n }\n } else {\n resolve();\n }\n });\n } else {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n resolve();\n }\n }),\n {\n // NOTE(Bacon): Metro dev server doesn't seem to be closing in time.\n timeout: 1000,\n errorMessage: `Timeout waiting for '${this.name}' dev server to close`,\n }\n );\n }\n\n public getUrlCreator(options: Partial<Pick<BundlerStartOptions, 'port' | 'location'>> = {}) {\n if (!this.urlCreator) {\n assert(options?.port, 'Dev server instance not found');\n this.urlCreator = new UrlCreator(options.location, {\n port: options.port,\n getTunnelUrl: this.getTunnelUrl.bind(this),\n });\n }\n return this.urlCreator;\n }\n\n public getNativeRuntimeUrl(opts: Partial<CreateURLOptions> = {}) {\n return this.isDevClient\n ? (this.getUrlCreator().constructDevClientUrl(opts) ?? this.getDevServerUrl())\n : this.getUrlCreator().constructUrl({ ...opts, scheme: 'exp' });\n }\n\n /** Get the URL for the running instance of the dev server. */\n public getDevServerUrl(options: { hostType?: 'localhost' } = {}): string | null {\n const instance = this.getInstance();\n if (!instance?.location) {\n return null;\n }\n\n // If we have an active WS tunnel instance, we always need to return the tunnel location.\n if (this.tunnel && this.tunnel instanceof AsyncWsTunnel) {\n return this.getUrlCreator().constructUrl();\n }\n\n const { location } = instance;\n if (options.hostType === 'localhost') {\n return `${location.protocol}://localhost:${location.port}`;\n }\n\n return location.url ?? null;\n }\n\n public getDevServerUrlOrAssert(options: { hostType?: 'localhost' } = {}): string {\n const instance = this.getDevServerUrl(options);\n if (!instance) {\n throw new CommandError(\n 'DEV_SERVER',\n `Cannot get the dev server URL before the server has started - bundler[${this.name}]`\n );\n }\n\n return instance;\n }\n\n /** Get the base URL for JS inspector */\n public getJsInspectorBaseUrl(): string {\n if (this.name !== 'metro') {\n throw new CommandError(\n 'DEV_SERVER',\n `Cannot get the JS inspector base url - bundler[${this.name}]`\n );\n }\n return this.getUrlCreator().constructUrl({ scheme: 'http' });\n }\n\n /** Get the tunnel URL from the tunnel. */\n public getTunnelUrl(): string | null {\n return this.tunnel?.getActiveUrl() ?? null;\n }\n\n /** Open the dev server in a runtime. */\n public async openPlatformAsync(\n launchTarget: keyof typeof PLATFORM_MANAGERS | 'desktop',\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n if (launchTarget === 'desktop') {\n const serverUrl = this.getDevServerUrl({ hostType: 'localhost' });\n // Allow opening the tunnel URL when using Metro web.\n const url = this.name === 'metro' ? (this.getTunnelUrl() ?? serverUrl) : serverUrl;\n await openBrowserAsync(url!);\n return { url };\n }\n\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime }, resolver);\n }\n\n /** Open the dev server in a runtime. */\n public async openCustomRuntimeAsync<T extends BaseOpenInCustomProps = BaseOpenInCustomProps>(\n launchTarget: keyof typeof PLATFORM_MANAGERS,\n launchProps: Partial<T> = {},\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n if (runtime !== 'custom') {\n throw new CommandError(\n `dev server cannot open custom runtimes either because it does not target native platforms or because it is not targeting dev clients. (target: ${runtime})`\n );\n }\n\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime: 'custom', props: launchProps }, resolver);\n }\n\n /** Get the URL for opening in Expo Go. */\n protected getExpoGoUrl(): string {\n return this.getUrlCreator().constructUrl({ scheme: 'exp' });\n }\n\n /** Should use the interstitial page for selecting which runtime to use. */\n protected isRedirectPageEnabled(): boolean {\n return (\n !env.EXPO_NO_REDIRECT_PAGE &&\n // if user passed --dev-client flag, skip interstitial page\n !this.isDevClient &&\n // Checks if dev client is installed.\n !!resolveFrom.silent(this.projectRoot, 'expo-dev-client')\n );\n }\n\n /** Get the redirect URL when redirecting is enabled. */\n public getRedirectUrl(platform: keyof typeof PLATFORM_MANAGERS | null = null): string | null {\n if (!this.isRedirectPageEnabled()) {\n debug('Redirect page is disabled');\n return null;\n }\n\n return (\n this.getUrlCreator().constructLoadingUrl(\n {},\n platform === 'emulator' ? 'android' : platform === 'simulator' ? 'ios' : null\n ) ?? null\n );\n }\n\n protected async getPlatformManagerAsync(platform: keyof typeof PLATFORM_MANAGERS) {\n if (!this.platformManagers[platform]) {\n const Manager = PLATFORM_MANAGERS[platform]();\n const port = this.getInstance()?.location.port;\n if (!port || !this.urlCreator) {\n throw new CommandError(\n 'DEV_SERVER',\n 'Cannot interact with native platforms until dev server has started'\n );\n }\n debug(`Creating platform manager (platform: ${platform}, port: ${port})`);\n this.platformManagers[platform] = new Manager(this.projectRoot, port, {\n getCustomRuntimeUrl: this.urlCreator.constructDevClientUrl.bind(this.urlCreator),\n getExpoGoUrl: this.getExpoGoUrl.bind(this),\n getRedirectUrl: this.getRedirectUrl.bind(this, platform),\n getDevServerUrl: this.getDevServerUrl.bind(this, { hostType: 'localhost' }),\n });\n }\n return this.platformManagers[platform];\n }\n}\n"],"names":["BundlerDevServer","debug","require","PLATFORM_MANAGERS","simulator","ApplePlatformManager","emulator","AndroidPlatformManager","constructor","projectRoot","platformBundlers","options","tunnel","devSession","bonjour","instance","platformManagers","urlCreator","notifier","devToolsPluginManager","DevToolsPluginManager","isDevClient","setInstance","getManifestMiddlewareAsync","Middleware","ExpoGoManifestHandlerMiddleware","getUrlCreator","middleware","constructUrl","bind","mode","minify","isNativeWebpack","name","isTargetingNative","privateKeyPath","startAsync","stopAsync","headless","startHeadlessAsync","startImplementationAsync","postStartAsync","waitForTypeScriptAsync","watchEnvironmentVariables","port","CommandError","server","close","callback","addListener","location","host","url","protocol","messageSocket","broadcast","hostType","env","EXPO_OFFLINE","_startTunnelAsync","envIsWebcontainer","isExporting","Promise","all","startDevSessionAsync","startBonjourAsync","watchConfig","stopObserving","FileNotifier","getConfigModuleIds","startObserving","getInstance","AsyncWsTunnel","AsyncNgrok","DevelopmentSession","getNativeRuntimeUrl","getDevServerUrl","runtime","Bonjour","announceAsync","isTargetingWeb","web","broadcastMessage","method","params","closeAsync","catch","e","Log","error","exception","resolveWithTimeout","resolve","reject","code","timeout","errorMessage","assert","UrlCreator","getTunnelUrl","opts","constructDevClientUrl","scheme","getDevServerUrlOrAssert","getJsInspectorBaseUrl","getActiveUrl","openPlatformAsync","launchTarget","resolver","serverUrl","openBrowserAsync","manager","getPlatformManagerAsync","openAsync","openCustomRuntimeAsync","launchProps","props","getExpoGoUrl","isRedirectPageEnabled","EXPO_NO_REDIRECT_PAGE","resolveFrom","silent","getRedirectUrl","platform","constructLoadingUrl","Manager","getCustomRuntimeUrl"],"mappings":"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"}
@@ -15,11 +15,19 @@ function _ws() {
15
15
  };
16
16
  return data;
17
17
  }
18
- function createDevToolsPluginWebsocketEndpoint() {
18
+ const _net = require("../../../utils/net");
19
+ function createDevToolsPluginWebsocketEndpoint({ serverBaseUrl }) {
19
20
  const wss = new (_ws()).WebSocketServer({
20
21
  noServer: true
21
22
  });
22
- wss.on('connection', (ws)=>{
23
+ wss.on('connection', (ws, request)=>{
24
+ // Explicitly limit devtools websocket to loopback requests
25
+ if (!(0, _net.isLocalSocket)(request.socket) || !(0, _net.isMatchingOrigin)(request, serverBaseUrl)) {
26
+ // NOTE: `socket.close` nicely closes the websocket, which will still allow incoming messages
27
+ // `socket.terminate` instead forcefully closes down the socket
28
+ ws.terminate();
29
+ return;
30
+ }
23
31
  ws.on('message', (message, isBinary)=>{
24
32
  // Broadcast the received message to all other connected clients
25
33
  wss.clients.forEach((client)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/server/metro/DevToolsPluginWebsocketEndpoint.ts"],"sourcesContent":["import { WebSocket, WebSocketServer } from 'ws';\n\nexport function createDevToolsPluginWebsocketEndpoint(): Record<string, WebSocketServer> {\n const wss = new WebSocketServer({ noServer: true });\n\n wss.on('connection', (ws: WebSocket) => {\n ws.on('message', (message, isBinary) => {\n // Broadcast the received message to all other connected clients\n wss.clients.forEach((client) => {\n if (client !== ws && client.readyState === WebSocket.OPEN) {\n client.send(message, { binary: isBinary });\n }\n });\n });\n });\n\n return { '/expo-dev-plugins/broadcast': wss };\n}\n"],"names":["createDevToolsPluginWebsocketEndpoint","wss","WebSocketServer","noServer","on","ws","message","isBinary","clients","forEach","client","readyState","WebSocket","OPEN","send","binary"],"mappings":";;;;+BAEgBA;;;eAAAA;;;;yBAF2B;;;;;;AAEpC,SAASA;IACd,MAAMC,MAAM,IAAIC,CAAAA,KAAc,iBAAC,CAAC;QAAEC,UAAU;IAAK;IAEjDF,IAAIG,EAAE,CAAC,cAAc,CAACC;QACpBA,GAAGD,EAAE,CAAC,WAAW,CAACE,SAASC;YACzB,gEAAgE;YAChEN,IAAIO,OAAO,CAACC,OAAO,CAAC,CAACC;gBACnB,IAAIA,WAAWL,MAAMK,OAAOC,UAAU,KAAKC,eAAS,CAACC,IAAI,EAAE;oBACzDH,OAAOI,IAAI,CAACR,SAAS;wBAAES,QAAQR;oBAAS;gBAC1C;YACF;QACF;IACF;IAEA,OAAO;QAAE,+BAA+BN;IAAI;AAC9C"}
1
+ {"version":3,"sources":["../../../../../src/start/server/metro/DevToolsPluginWebsocketEndpoint.ts"],"sourcesContent":["import { WebSocket, WebSocketServer } from 'ws';\n\nimport { isLocalSocket, isMatchingOrigin } from '../../../utils/net';\n\ninterface DevToolsPluginWebsocketEndpointParams {\n serverBaseUrl: string;\n}\n\nexport function createDevToolsPluginWebsocketEndpoint({\n serverBaseUrl,\n}: DevToolsPluginWebsocketEndpointParams): Record<string, WebSocketServer> {\n const wss = new WebSocketServer({ noServer: true });\n\n wss.on('connection', (ws, request) => {\n // Explicitly limit devtools websocket to loopback requests\n if (!isLocalSocket(request.socket) || !isMatchingOrigin(request, serverBaseUrl)) {\n // NOTE: `socket.close` nicely closes the websocket, which will still allow incoming messages\n // `socket.terminate` instead forcefully closes down the socket\n ws.terminate();\n return;\n }\n\n ws.on('message', (message, isBinary) => {\n // Broadcast the received message to all other connected clients\n wss.clients.forEach((client) => {\n if (client !== ws && client.readyState === WebSocket.OPEN) {\n client.send(message, { binary: isBinary });\n }\n });\n });\n });\n\n return { '/expo-dev-plugins/broadcast': wss };\n}\n"],"names":["createDevToolsPluginWebsocketEndpoint","serverBaseUrl","wss","WebSocketServer","noServer","on","ws","request","isLocalSocket","socket","isMatchingOrigin","terminate","message","isBinary","clients","forEach","client","readyState","WebSocket","OPEN","send","binary"],"mappings":";;;;+BAQgBA;;;eAAAA;;;;yBAR2B;;;;;;qBAEK;AAMzC,SAASA,sCAAsC,EACpDC,aAAa,EACyB;IACtC,MAAMC,MAAM,IAAIC,CAAAA,KAAc,iBAAC,CAAC;QAAEC,UAAU;IAAK;IAEjDF,IAAIG,EAAE,CAAC,cAAc,CAACC,IAAIC;QACxB,2DAA2D;QAC3D,IAAI,CAACC,IAAAA,kBAAa,EAACD,QAAQE,MAAM,KAAK,CAACC,IAAAA,qBAAgB,EAACH,SAASN,gBAAgB;YAC/E,6FAA6F;YAC7F,+DAA+D;YAC/DK,GAAGK,SAAS;YACZ;QACF;QAEAL,GAAGD,EAAE,CAAC,WAAW,CAACO,SAASC;YACzB,gEAAgE;YAChEX,IAAIY,OAAO,CAACC,OAAO,CAAC,CAACC;gBACnB,IAAIA,WAAWV,MAAMU,OAAOC,UAAU,KAAKC,eAAS,CAACC,IAAI,EAAE;oBACzDH,OAAOI,IAAI,CAACR,SAAS;wBAAES,QAAQR;oBAAS;gBAC1C;YACF;QACF;IACF;IAEA,OAAO;QAAE,+BAA+BX;IAAI;AAC9C"}
@@ -102,7 +102,6 @@ const _getStaticRenderFunctions = require("../getStaticRenderFunctions");
102
102
  const _resolveLoader = require("./resolveLoader");
103
103
  const _ContextModuleSourceMapsMiddleware = require("../middleware/ContextModuleSourceMapsMiddleware");
104
104
  const _CreateFileMiddleware = require("../middleware/CreateFileMiddleware");
105
- const _DataLoaderModuleMiddleware = require("../middleware/DataLoaderModuleMiddleware");
106
105
  const _DevToolsPluginMiddleware = require("../middleware/DevToolsPluginMiddleware");
107
106
  const _DomComponentsMiddleware = require("../middleware/DomComponentsMiddleware");
108
107
  const _FaviconMiddleware = require("../middleware/FaviconMiddleware");
@@ -403,7 +402,7 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
403
402
  if (!resolvedLoaderRoute) {
404
403
  return undefined;
405
404
  }
406
- return await this.executeServerDataLoaderAsync(location, resolvedLoaderRoute);
405
+ return this.executeServerDataLoaderAsync(location, resolvedLoaderRoute);
407
406
  }
408
407
  };
409
408
  }
@@ -433,7 +432,7 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
433
432
  }
434
433
  /**
435
434
  * This function is invoked when running in development via `expo start`
436
- */ async getStaticPageAsync(pathname, route) {
435
+ */ async getStaticPageAsync(pathname, route, request) {
437
436
  const { exp } = (0, _config().getConfig)(this.projectRoot);
438
437
  const { mode, isExporting, clientBoundaries, baseUrl, reactCompiler, routerRoot, asyncRoutes } = this.instanceMetroOptions;
439
438
  (0, _assert().default)(mode != null && isExporting != null && baseUrl != null && reactCompiler != null && routerRoot != null && asyncRoutes != null, 'The server must be started before calling getStaticPageAsync.');
@@ -474,10 +473,13 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
474
473
  if (!resolvedLoaderRoute) {
475
474
  return await getStaticContent(location);
476
475
  }
477
- const data = await this.executeServerDataLoaderAsync(location, resolvedLoaderRoute);
476
+ const loaderResult = await this.executeServerDataLoaderAsync(location, resolvedLoaderRoute, request);
477
+ if (!loaderResult) {
478
+ return await getStaticContent(location);
479
+ }
478
480
  return await getStaticContent(location, {
479
481
  loader: {
480
- data
482
+ data: loaderResult.data
481
483
  }
482
484
  });
483
485
  };
@@ -905,18 +907,6 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
905
907
  });
906
908
  // Append support for redirecting unhandled requests to the index.html page on web.
907
909
  if (this.isTargetingWeb()) {
908
- var _exp_extra_router1, _exp_extra2;
909
- if ((_exp_extra2 = exp.extra) == null ? void 0 : (_exp_extra_router1 = _exp_extra2.router) == null ? void 0 : _exp_extra_router1.unstable_useServerDataLoaders) {
910
- const loaderModuleMiddleware = new _DataLoaderModuleMiddleware.DataLoaderModuleMiddleware(this.projectRoot, appDir, async (location, route)=>{
911
- const resolvedLoaderRoute = (0, _resolveLoader.fromServerManifestRoute)(location.pathname, route);
912
- if (!resolvedLoaderRoute) {
913
- return;
914
- }
915
- return this.executeServerDataLoaderAsync(location, resolvedLoaderRoute);
916
- }, ()=>this.getDevServerUrlOrAssert());
917
- // This MUST be before ServeStaticMiddleware so it doesn't treat the loader files as static assets
918
- middleware.use(loaderModuleMiddleware.getHandler());
919
- }
920
910
  // This MUST be after the manifest middleware so it doesn't have a chance to serve the template `public/index.html`.
921
911
  middleware.use(new _ServeStaticMiddleware.ServeStaticMiddleware(this.projectRoot).getHandler());
922
912
  // This should come after the static middleware so it doesn't serve the favicon from `public/favicon.ico`.
@@ -988,7 +978,19 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
988
978
  bundleApiRoute: (functionFilePath)=>this.ssrImportApiRoute(functionFilePath, {
989
979
  platform: 'web'
990
980
  }),
991
- getStaticPageAsync: async (pathname, route)=>{
981
+ executeLoaderAsync: async (route, request)=>{
982
+ var _exp_web, _exp_extra_router, _exp_extra;
983
+ const url = new URL(request.url);
984
+ const resolvedLoaderRoute = (0, _resolveLoader.fromServerManifestRoute)(url.pathname, route);
985
+ if (!resolvedLoaderRoute) {
986
+ return undefined;
987
+ }
988
+ // Only pass the request in SSR mode (server output with SSR enabled).
989
+ // In static mode, loaders should not receive request data.
990
+ const isSSREnabled = ((_exp_web = exp.web) == null ? void 0 : _exp_web.output) === 'server' && ((_exp_extra = exp.extra) == null ? void 0 : (_exp_extra_router = _exp_extra.router) == null ? void 0 : _exp_extra_router.unstable_useServerRendering) === true;
991
+ return this.executeServerDataLoaderAsync(url, resolvedLoaderRoute, isSSREnabled ? request : undefined);
992
+ },
993
+ getStaticPageAsync: async (pathname, route, request)=>{
992
994
  // TODO: Add server rendering when RSC is enabled.
993
995
  if (isReactServerComponentsEnabled) {
994
996
  // NOTE: This is a temporary hack to return the SPA/template index.html in development when RSC is enabled.
@@ -999,7 +1001,7 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
999
1001
  };
1000
1002
  }
1001
1003
  // Non-RSC apps will bundle the static HTML for a given pathname and respond with it.
1002
- return this.getStaticPageAsync(pathname, route);
1004
+ return this.getStaticPageAsync(pathname, route, request);
1003
1005
  }
1004
1006
  }));
1005
1007
  }
@@ -1238,7 +1240,8 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
1238
1240
  * matched route.
1239
1241
  *
1240
1242
  * @experimental
1241
- */ async executeServerDataLoaderAsync(location, route) {
1243
+ */ async executeServerDataLoaderAsync(location, route, // The `request` object is only available when using SSR
1244
+ request) {
1242
1245
  var _exp_extra;
1243
1246
  const { exp } = (0, _config().getConfig)(this.projectRoot);
1244
1247
  const { unstable_useServerDataLoaders } = (_exp_extra = exp.extra) == null ? void 0 : _exp_extra.router;
@@ -1247,7 +1250,6 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
1247
1250
  }
1248
1251
  const { routerRoot } = this.instanceMetroOptions;
1249
1252
  (0, _assert().default)(routerRoot != null, 'The server must be started before calling executeRouteLoaderAsync.');
1250
- let loaderData;
1251
1253
  try {
1252
1254
  debug(`Matched ${location.pathname} to file: ${route.file}`);
1253
1255
  const appDir = _path().default.join(this.projectRoot, routerRoot);
@@ -1262,17 +1264,21 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
1262
1264
  if (routeModule.loader) {
1263
1265
  // Register this module for loader HMR
1264
1266
  this.setupLoaderHmr(modulePath);
1265
- loaderData = await routeModule.loader({
1267
+ const data = await routeModule.loader({
1266
1268
  params: route.params,
1267
- // NOTE(@hassankhan): The `request` object is only available when using SSR
1268
- request: null
1269
+ request
1269
1270
  });
1271
+ const normalizedData = data === undefined ? {} : data;
1272
+ debug('Loader data:', normalizedData, ' for location:', location.pathname);
1273
+ return {
1274
+ data: normalizedData
1275
+ };
1270
1276
  }
1277
+ debug('No loader found for location:', location.pathname);
1278
+ return undefined;
1271
1279
  } catch (error) {
1272
1280
  throw new _errors.CommandError('LOADER_EXECUTION_FAILED', `Failed to execute loader for route "${location.pathname}": ${error.message}`);
1273
1281
  }
1274
- debug('Loader data:', loaderData, ' for location:', location.pathname);
1275
- return loaderData;
1276
1282
  }
1277
1283
  /**
1278
1284
  * Bundle a loader module with Metro and return the string contents.