@expo/cli 56.1.14 → 56.1.15

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 CHANGED
@@ -139,7 +139,7 @@ const args = (0, _arg().default)({
139
139
  });
140
140
  if (args['--version']) {
141
141
  // Version is added in the build script.
142
- console.log("56.1.14");
142
+ console.log("56.1.15");
143
143
  process.exit(0);
144
144
  }
145
145
  if (args['--non-interactive']) {
@@ -18,6 +18,9 @@ _export(exports, {
18
18
  get graphql () {
19
19
  return graphql;
20
20
  },
21
+ get mutate () {
22
+ return mutate;
23
+ },
21
24
  get query () {
22
25
  return query;
23
26
  }
@@ -73,7 +76,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
73
76
  function graphql(query) {
74
77
  return query.trim();
75
78
  }
76
- const query = (()=>{
79
+ const { query, mutate } = (()=>{
77
80
  const url = (0, _endpoint.getExpoApiBaseUrl)() + '/graphql';
78
81
  let _fetch1;
79
82
  const wrappedFetch = (...args)=>{
@@ -110,7 +113,8 @@ const query = (()=>{
110
113
  function resetCache() {
111
114
  cache = {};
112
115
  }
113
- return async function query(query, variables, options) {
116
+ async function request(query, variables, options, // Mutations must never be served from (or written to) the in-memory cache.
117
+ useCache) {
114
118
  let isTransient = false;
115
119
  let response;
116
120
  let data;
@@ -123,11 +127,12 @@ const query = (()=>{
123
127
  const headersKey = stringifySorted(headers);
124
128
  if (!cacheKey || cacheKey !== headersKey) {
125
129
  resetCache();
130
+ cacheKey = headersKey;
126
131
  }
127
132
  // Retrieve a cached result, if we have any via a `query => variables => Result` cache key
128
133
  const variablesKey = stringifySorted(variables);
129
134
  const queryCache = cache[query] || (cache[query] = new Map());
130
- if (queryCache.has(variablesKey)) {
135
+ if (useCache && queryCache.has(variablesKey)) {
131
136
  data = queryCache.get(variablesKey);
132
137
  }
133
138
  // Retry the query if it fails due to an unknown or transient error
@@ -179,7 +184,9 @@ const query = (()=>{
179
184
  }
180
185
  // Store the data in the cache, and only return a result if we have any values
181
186
  if (data) {
182
- queryCache.set(variablesKey, data);
187
+ if (useCache) {
188
+ queryCache.set(variablesKey, data);
189
+ }
183
190
  const keys = Object.keys(data);
184
191
  if (keys.length > 0 && keys.some((key)=>data[key] != null)) {
185
192
  return data;
@@ -198,6 +205,14 @@ const query = (()=>{
198
205
  } else {
199
206
  throw new _client.UnexpectedServerData('Unexpected server error: No returned query result');
200
207
  }
208
+ }
209
+ return {
210
+ /** Run a GraphQL query, served from the in-memory cache when possible. */ query (document, variables, options) {
211
+ return request(document, variables, options, /* useCache */ true);
212
+ },
213
+ /** Run a GraphQL mutation, always hitting the network and never touching the cache. */ mutate (document, variables, options) {
214
+ return request(document, variables, options, /* useCache */ false);
215
+ }
201
216
  };
202
217
  })();
203
218
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/api/graphql/client.ts"],"sourcesContent":["import * as Log from '../../log';\nimport { fetch, type Response } from '../../utils/fetch';\nimport { getExpoApiBaseUrl } from '../endpoint';\nimport {\n getResponseDataOrThrow,\n UnexpectedServerData,\n UnexpectedServerError,\n} from '../rest/client';\nimport type { FetchLike } from '../rest/client.types';\nimport { wrapFetchWithOffline } from '../rest/wrapFetchWithOffline';\nimport { wrapFetchWithUserAgent } from '../rest/wrapFetchWithUserAgent';\nimport { getAccessToken, getSession } from '../user/UserSettings';\n\ntype JSONObject = Record<string, unknown>;\ntype EmptyVariables = Record<string, never>;\n\nexport type StaticDocumentNode<Result extends JSONObject, Variables extends JSONObject> = string & {\n readonly __graphql: (vars: Variables) => Result;\n};\n\nexport function graphql<Result extends JSONObject, Variables extends JSONObject = EmptyVariables>(\n query: string\n): StaticDocumentNode<Result, Variables> {\n return query.trim() as StaticDocumentNode<Result, Variables>;\n}\n\nexport { UnexpectedServerError, UnexpectedServerData };\n\nexport interface QueryOptions {\n headers?: Record<string, string>;\n}\n\nexport const query = (() => {\n const url = getExpoApiBaseUrl() + '/graphql';\n\n let _fetch: FetchLike | undefined;\n const wrappedFetch: FetchLike = (...args) => {\n if (!_fetch) {\n _fetch = wrapFetchWithOffline(wrapFetchWithUserAgent(fetch));\n }\n return _fetch(...args);\n };\n\n const randomDelay = (attemptCount: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, Math.min(500 + Math.random() * 1000 * attemptCount, 4_000));\n });\n\n const getFetchHeaders = (): Record<string, string> => {\n const token = getAccessToken();\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n accept: 'application/graphql-response+json, application/graphql+json, application/json',\n };\n let sessionSecret: string | undefined;\n if (token) {\n headers.authorization = `Bearer ${token}`;\n } else if ((sessionSecret = getSession()?.sessionSecret)) {\n headers['expo-session'] = sessionSecret;\n }\n return headers;\n };\n\n // NOTE(@kitten): This only sorted keys one level deep since this is sufficient for most cases\n const stringifySorted = (variables: JSONObject): string =>\n JSON.stringify(\n Object.keys(variables)\n .sort()\n .reduce((acc, key) => {\n acc[key] = variables[key];\n return acc;\n }, {} as JSONObject)\n );\n\n let cache: Record<string, Map<string, unknown>> = {};\n let cacheKey: string | undefined;\n\n function resetCache() {\n cache = {};\n }\n\n return async function query<Result extends JSONObject, Variables extends JSONObject>(\n query: StaticDocumentNode<Result, Variables>,\n variables: Variables,\n options?: QueryOptions\n ): Promise<Result> {\n let isTransient = false;\n let response: Response | undefined;\n let data: Result | null | undefined;\n let error: unknown;\n\n // Pre-instantiate headers and reset the cache if they've changed\n const headers = { ...getFetchHeaders(), ...options?.headers };\n const headersKey = stringifySorted(headers);\n if (!cacheKey || cacheKey !== headersKey) {\n resetCache();\n }\n\n // Retrieve a cached result, if we have any via a `query => variables => Result` cache key\n const variablesKey = stringifySorted(variables);\n const queryCache = cache[query] || (cache[query] = new Map());\n if (queryCache.has(variablesKey)) {\n data = queryCache.get(variablesKey) as Result;\n }\n\n // Retry the query if it fails due to an unknown or transient error\n for (let attemptCount = 0; attemptCount < 3 && !data; attemptCount++) {\n // Add a random delay on each subsequent attempt\n if (attemptCount > 0) {\n await randomDelay(attemptCount);\n }\n\n try {\n response = await wrappedFetch(url, {\n ...options,\n method: 'POST',\n body: JSON.stringify({ query, variables }),\n headers,\n });\n } catch (networkError) {\n error = networkError || error;\n continue;\n }\n\n const json = await response.json();\n if (typeof json === 'object' && json) {\n // If we have a transient error, we retry immediately and discard the data\n // Otherwise, we store the first available error and get the data\n if ('errors' in json && Array.isArray(json.errors)) {\n isTransient = json.errors.some((e: any) => e?.extensions?.isTransient);\n if (isTransient) {\n data = undefined;\n continue;\n } else {\n error = json.errors[0] || error;\n }\n }\n\n try {\n data = getResponseDataOrThrow<Result | null>(json);\n } catch (dataError) {\n // We only use the data error, if we don't have an error already\n if (!error) {\n error = dataError || error;\n }\n continue;\n }\n }\n }\n\n // Store the data in the cache, and only return a result if we have any values\n if (data) {\n queryCache.set(variablesKey, data);\n const keys = Object.keys(data);\n if (keys.length > 0 && keys.some((key) => data[key as keyof typeof data] != null)) {\n return data;\n }\n }\n\n // If we have an error, rethrow it wrapped in our custom errors\n if (error) {\n if (isTransient) {\n Log.error(`We've encountered a transient error, please try again shortly.`);\n }\n const wrappedError = new UnexpectedServerError('' + (error as any).message);\n wrappedError.cause = error;\n throw wrappedError;\n } else if (response && !response.ok) {\n throw new UnexpectedServerError(`Unexpected server error: ${response.statusText}`);\n } else {\n throw new UnexpectedServerData('Unexpected server error: No returned query result');\n }\n };\n})();\n"],"names":["UnexpectedServerData","UnexpectedServerError","graphql","query","trim","url","getExpoApiBaseUrl","_fetch","wrappedFetch","args","wrapFetchWithOffline","wrapFetchWithUserAgent","fetch","randomDelay","attemptCount","Promise","resolve","setTimeout","Math","min","random","getFetchHeaders","getSession","token","getAccessToken","headers","accept","sessionSecret","authorization","stringifySorted","variables","JSON","stringify","Object","keys","sort","reduce","acc","key","cache","cacheKey","resetCache","options","isTransient","response","data","error","headersKey","variablesKey","queryCache","Map","has","get","method","body","networkError","json","Array","isArray","errors","some","e","extensions","undefined","getResponseDataOrThrow","dataError","set","length","Log","wrappedError","message","cause","ok","statusText"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/api/graphql/client.ts"],"sourcesContent":["import * as Log from '../../log';\nimport { fetch, type Response } from '../../utils/fetch';\nimport { getExpoApiBaseUrl } from '../endpoint';\nimport {\n getResponseDataOrThrow,\n UnexpectedServerData,\n UnexpectedServerError,\n} from '../rest/client';\nimport type { FetchLike } from '../rest/client.types';\nimport { wrapFetchWithOffline } from '../rest/wrapFetchWithOffline';\nimport { wrapFetchWithUserAgent } from '../rest/wrapFetchWithUserAgent';\nimport { getAccessToken, getSession } from '../user/UserSettings';\n\ntype JSONObject = Record<string, unknown>;\ntype EmptyVariables = Record<string, never>;\n\nexport type StaticDocumentNode<Result extends JSONObject, Variables extends JSONObject> = string & {\n readonly __graphql: (vars: Variables) => Result;\n};\n\nexport function graphql<Result extends JSONObject, Variables extends JSONObject = EmptyVariables>(\n query: string\n): StaticDocumentNode<Result, Variables> {\n return query.trim() as StaticDocumentNode<Result, Variables>;\n}\n\nexport { UnexpectedServerError, UnexpectedServerData };\n\nexport interface QueryOptions {\n headers?: Record<string, string>;\n}\n\nexport const { query, mutate } = (() => {\n const url = getExpoApiBaseUrl() + '/graphql';\n\n let _fetch: FetchLike | undefined;\n const wrappedFetch: FetchLike = (...args) => {\n if (!_fetch) {\n _fetch = wrapFetchWithOffline(wrapFetchWithUserAgent(fetch));\n }\n return _fetch(...args);\n };\n\n const randomDelay = (attemptCount: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, Math.min(500 + Math.random() * 1000 * attemptCount, 4_000));\n });\n\n const getFetchHeaders = (): Record<string, string> => {\n const token = getAccessToken();\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n accept: 'application/graphql-response+json, application/graphql+json, application/json',\n };\n let sessionSecret: string | undefined;\n if (token) {\n headers.authorization = `Bearer ${token}`;\n } else if ((sessionSecret = getSession()?.sessionSecret)) {\n headers['expo-session'] = sessionSecret;\n }\n return headers;\n };\n\n // NOTE(@kitten): This only sorted keys one level deep since this is sufficient for most cases\n const stringifySorted = (variables: JSONObject): string =>\n JSON.stringify(\n Object.keys(variables)\n .sort()\n .reduce((acc, key) => {\n acc[key] = variables[key];\n return acc;\n }, {} as JSONObject)\n );\n\n let cache: Record<string, Map<string, unknown>> = {};\n let cacheKey: string | undefined;\n\n function resetCache() {\n cache = {};\n }\n\n async function request<Result extends JSONObject, Variables extends JSONObject>(\n query: StaticDocumentNode<Result, Variables>,\n variables: Variables,\n options: QueryOptions | undefined,\n // Mutations must never be served from (or written to) the in-memory cache.\n useCache: boolean\n ): Promise<Result> {\n let isTransient = false;\n let response: Response | undefined;\n let data: Result | null | undefined;\n let error: unknown;\n\n // Pre-instantiate headers and reset the cache if they've changed\n const headers = { ...getFetchHeaders(), ...options?.headers };\n const headersKey = stringifySorted(headers);\n if (!cacheKey || cacheKey !== headersKey) {\n resetCache();\n cacheKey = headersKey;\n }\n\n // Retrieve a cached result, if we have any via a `query => variables => Result` cache key\n const variablesKey = stringifySorted(variables);\n const queryCache = cache[query] || (cache[query] = new Map());\n if (useCache && queryCache.has(variablesKey)) {\n data = queryCache.get(variablesKey) as Result;\n }\n\n // Retry the query if it fails due to an unknown or transient error\n for (let attemptCount = 0; attemptCount < 3 && !data; attemptCount++) {\n // Add a random delay on each subsequent attempt\n if (attemptCount > 0) {\n await randomDelay(attemptCount);\n }\n\n try {\n response = await wrappedFetch(url, {\n ...options,\n method: 'POST',\n body: JSON.stringify({ query, variables }),\n headers,\n });\n } catch (networkError) {\n error = networkError || error;\n continue;\n }\n\n const json = await response.json();\n if (typeof json === 'object' && json) {\n // If we have a transient error, we retry immediately and discard the data\n // Otherwise, we store the first available error and get the data\n if ('errors' in json && Array.isArray(json.errors)) {\n isTransient = json.errors.some((e: any) => e?.extensions?.isTransient);\n if (isTransient) {\n data = undefined;\n continue;\n } else {\n error = json.errors[0] || error;\n }\n }\n\n try {\n data = getResponseDataOrThrow<Result | null>(json);\n } catch (dataError) {\n // We only use the data error, if we don't have an error already\n if (!error) {\n error = dataError || error;\n }\n continue;\n }\n }\n }\n\n // Store the data in the cache, and only return a result if we have any values\n if (data) {\n if (useCache) {\n queryCache.set(variablesKey, data);\n }\n const keys = Object.keys(data);\n if (keys.length > 0 && keys.some((key) => data[key as keyof typeof data] != null)) {\n return data;\n }\n }\n\n // If we have an error, rethrow it wrapped in our custom errors\n if (error) {\n if (isTransient) {\n Log.error(`We've encountered a transient error, please try again shortly.`);\n }\n const wrappedError = new UnexpectedServerError('' + (error as any).message);\n wrappedError.cause = error;\n throw wrappedError;\n } else if (response && !response.ok) {\n throw new UnexpectedServerError(`Unexpected server error: ${response.statusText}`);\n } else {\n throw new UnexpectedServerData('Unexpected server error: No returned query result');\n }\n }\n\n return {\n /** Run a GraphQL query, served from the in-memory cache when possible. */\n query<Result extends JSONObject, Variables extends JSONObject>(\n document: StaticDocumentNode<Result, Variables>,\n variables: Variables,\n options?: QueryOptions\n ): Promise<Result> {\n return request(document, variables, options, /* useCache */ true);\n },\n /** Run a GraphQL mutation, always hitting the network and never touching the cache. */\n mutate<Result extends JSONObject, Variables extends JSONObject>(\n document: StaticDocumentNode<Result, Variables>,\n variables: Variables,\n options?: QueryOptions\n ): Promise<Result> {\n return request(document, variables, options, /* useCache */ false);\n },\n };\n})();\n"],"names":["UnexpectedServerData","UnexpectedServerError","graphql","mutate","query","trim","url","getExpoApiBaseUrl","_fetch","wrappedFetch","args","wrapFetchWithOffline","wrapFetchWithUserAgent","fetch","randomDelay","attemptCount","Promise","resolve","setTimeout","Math","min","random","getFetchHeaders","getSession","token","getAccessToken","headers","accept","sessionSecret","authorization","stringifySorted","variables","JSON","stringify","Object","keys","sort","reduce","acc","key","cache","cacheKey","resetCache","request","options","useCache","isTransient","response","data","error","headersKey","variablesKey","queryCache","Map","has","get","method","body","networkError","json","Array","isArray","errors","some","e","extensions","undefined","getResponseDataOrThrow","dataError","set","length","Log","wrappedError","message","cause","ok","statusText","document"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "TunnelMutation", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return TunnelMutation;
9
+ }
10
+ });
11
+ const _client = require("../client");
12
+ const CreateSignedTunnelUrlDocument = (0, _client.graphql)(`
13
+ mutation CreateSignedTunnelUrl($accountId: ID!) {
14
+ tunnels {
15
+ createSignedTunnelUrl(accountId: $accountId) {
16
+ label
17
+ url
18
+ }
19
+ }
20
+ }
21
+ `);
22
+ const TunnelMutation = {
23
+ async createSignedTunnelUrlAsync (accountId) {
24
+ const data = await (0, _client.mutate)(CreateSignedTunnelUrlDocument, {
25
+ accountId
26
+ });
27
+ return data.tunnels.createSignedTunnelUrl;
28
+ }
29
+ };
30
+
31
+ //# sourceMappingURL=TunnelMutation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/api/graphql/mutations/TunnelMutation.ts"],"sourcesContent":["import { graphql, mutate } from '../client';\n\nexport type SignedTunnelUrl = {\n /** The unique tunnel label, used as the hostname segment of the tunnel URL. */\n label: string;\n /** The signed tunnel URL `@expo/ws-tunnel` connects to. */\n url: string;\n};\n\ntype CreateSignedTunnelUrlData = {\n tunnels: {\n createSignedTunnelUrl: SignedTunnelUrl;\n };\n};\n\ntype CreateSignedTunnelUrlVariables = {\n accountId: string;\n};\n\nconst CreateSignedTunnelUrlDocument = graphql<\n CreateSignedTunnelUrlData,\n CreateSignedTunnelUrlVariables\n>(`\n mutation CreateSignedTunnelUrl($accountId: ID!) {\n tunnels {\n createSignedTunnelUrl(accountId: $accountId) {\n label\n url\n }\n }\n }\n`);\n\nexport const TunnelMutation = {\n async createSignedTunnelUrlAsync(accountId: string): Promise<SignedTunnelUrl> {\n const data = await mutate(CreateSignedTunnelUrlDocument, { accountId });\n return data.tunnels.createSignedTunnelUrl;\n },\n};\n"],"names":["TunnelMutation","CreateSignedTunnelUrlDocument","graphql","createSignedTunnelUrlAsync","accountId","data","mutate","tunnels","createSignedTunnelUrl"],"mappings":";;;;+BAiCaA;;;eAAAA;;;wBAjCmB;AAmBhC,MAAMC,gCAAgCC,IAAAA,eAAO,EAG3C,CAAC;;;;;;;;;AASH,CAAC;AAEM,MAAMF,iBAAiB;IAC5B,MAAMG,4BAA2BC,SAAiB;QAChD,MAAMC,OAAO,MAAMC,IAAAA,cAAM,EAACL,+BAA+B;YAAEG;QAAU;QACrE,OAAOC,KAAKE,OAAO,CAACC,qBAAqB;IAC3C;AACF"}
@@ -76,7 +76,7 @@ function getInitMetadata() {
76
76
  return {
77
77
  format: 'v0-jsonl',
78
78
  // Version is added in the build script.
79
- version: "56.1.14" ?? 'UNVERSIONED'
79
+ version: "56.1.15" ?? 'UNVERSIONED'
80
80
  };
81
81
  }
82
82
  function getWellKnownTemporaryLogFile(projectRoot, command) {
@@ -2,12 +2,27 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "AsyncWsTunnel", {
6
- enumerable: true,
7
- get: function() {
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get AsyncWsTunnel () {
8
13
  return AsyncWsTunnel;
14
+ },
15
+ get getExpoAccountTunnelUrlAsync () {
16
+ return getExpoAccountTunnelUrlAsync;
9
17
  }
10
18
  });
19
+ function _config() {
20
+ const data = require("@expo/config");
21
+ _config = function() {
22
+ return data;
23
+ };
24
+ return data;
25
+ }
11
26
  function _wstunnel() {
12
27
  const data = /*#__PURE__*/ _interop_require_wildcard(require("@expo/ws-tunnel"));
13
28
  _wstunnel = function() {
@@ -43,6 +58,10 @@ function _nodepath() {
43
58
  };
44
59
  return data;
45
60
  }
61
+ const _TunnelMutation = require("../../api/graphql/mutations/TunnelMutation");
62
+ const _AppQuery = require("../../api/graphql/queries/AppQuery");
63
+ const _UserSettings = require("../../api/user/UserSettings");
64
+ const _user = require("../../api/user/user");
46
65
  const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../log"));
47
66
  const _env = require("../../utils/env");
48
67
  const _errors = require("../../utils/errors");
@@ -94,25 +113,44 @@ function _interop_require_wildcard(obj, nodeInterop) {
94
113
  }
95
114
  const debug = require('debug')('expo:start:server:ws-tunnel');
96
115
  class AsyncWsTunnel {
97
- constructor(_projectRoot, port){
98
- /** Info about the currently running instance of tunnel. */ this.serverUrl = null;
99
- if (port !== 8081) {
100
- throw new _errors.CommandError('WS_TUNNEL_PORT', `WS-tunnel only supports tunneling over port 8081, attempted to use port ${port}`);
101
- }
116
+ constructor(projectRoot, port, options = {}){
117
+ this.projectRoot = projectRoot;
118
+ this.port = port;
119
+ this.options = options;
120
+ this.serverUrl = null;
102
121
  }
103
122
  getActiveUrl() {
104
- return this.serverUrl;
123
+ var _this_serverUrl;
124
+ return ((_this_serverUrl = this.serverUrl) == null ? void 0 : _this_serverUrl.href) ?? null;
105
125
  }
106
126
  async startAsync() {
107
127
  this.serverUrl = await _wstunnel().startAsync({
108
- ...getTunnelOptions(),
128
+ ...await this.getTunnelOptionsAsync(),
109
129
  onStatusChange (status) {
110
130
  if (status === 'disconnected') {
111
131
  _log.error(_chalk().default.red('Tunnel connection has been closed. This is often related to intermittent connection problems with the ws proxy servers. Restart the dev server to try connecting again.') + _chalk().default.gray('\nCheck the Expo status page for outages: https://status.expo.dev/'));
112
132
  }
113
133
  }
114
134
  });
115
- debug('Tunnel URL:', this.serverUrl);
135
+ debug('Tunnel URL:', this.serverUrl.href);
136
+ }
137
+ async getTunnelOptionsAsync() {
138
+ if (this.options.useExpoAccount) {
139
+ return this.getExpoAccountTunnelOptionsAsync();
140
+ } else {
141
+ return getLegacyTunnelOptions(this.port);
142
+ }
143
+ }
144
+ async getExpoAccountTunnelOptionsAsync() {
145
+ const apiUrl = await getExpoAccountTunnelUrlAsync(this.projectRoot);
146
+ if (!apiUrl) {
147
+ const cause = (0, _UserSettings.hasCredentials)() ? `Your Expo account may not have access to it, or the tunnel service is unavailable.` : `You're not logged in to your Expo account — run 'npx expo login'.`;
148
+ throw new _errors.CommandError('WS_TUNNEL_SIGNED_URL', `Couldn't create a signed tunnel URL for this project. ${cause} ` + `Unset EXPO_UNSTABLE_TUNNEL_V2 to use an ngrok tunnel instead.`);
149
+ }
150
+ return {
151
+ apiUrl,
152
+ targetUrl: `http://localhost:${this.port}`
153
+ };
116
154
  }
117
155
  async stopAsync() {
118
156
  debug('Stopping Tunnel');
@@ -120,36 +158,83 @@ class AsyncWsTunnel {
120
158
  this.serverUrl = null;
121
159
  }
122
160
  }
123
- // Generate a base-36 string of 5 characters (from 32 bits of randomness)
124
- function randomStr() {
125
- return (Math.random().toString(36) + '00000').slice(2, 7);
126
- }
127
- function getTunnelSession() {
128
- let session = randomStr() + randomStr() + randomStr();
129
- if ((0, _env.envIsWebcontainer)()) {
130
- const leaseId = Buffer.from((0, _nodeos().hostname)()).toString('base64url');
131
- const leaseFile = _nodepath().join((0, _nodeos().tmpdir)(), `_ws_tunnel_lease_${leaseId}`);
132
- try {
133
- session = _nodefs().readFileSync(leaseFile, 'utf8').trim() || session;
134
- } catch {}
135
- try {
136
- _nodefs().writeFileSync(leaseFile, session, 'utf8');
137
- } catch {}
138
- }
139
- return session;
140
- }
141
- function getTunnelOptions() {
161
+ function getLegacyTunnelOptions(port) {
162
+ if (port !== 8081) {
163
+ throw new _errors.CommandError('WS_TUNNEL_PORT', `WS-tunnel only supports tunneling over port 8081, attempted to use port ${port}`);
164
+ }
165
+ function randomSessionId() {
166
+ const randomPart = ()=>(Math.random().toString(36) + '00000').slice(2, 7);
167
+ return randomPart() + randomPart() + randomPart();
168
+ }
169
+ function getWebcontainerSession() {
170
+ let session = randomSessionId();
171
+ if ((0, _env.envIsWebcontainer)()) {
172
+ const leaseId = Buffer.from((0, _nodeos().hostname)()).toString('base64url');
173
+ const leaseFile = _nodepath().join((0, _nodeos().tmpdir)(), `_ws_tunnel_lease_${leaseId}`);
174
+ try {
175
+ session = _nodefs().readFileSync(leaseFile, 'utf8').trim() || session;
176
+ } catch {}
177
+ try {
178
+ _nodefs().writeFileSync(leaseFile, session, 'utf8');
179
+ } catch {}
180
+ }
181
+ return session;
182
+ }
142
183
  const userDefinedSubdomain = _env.env.EXPO_TUNNEL_SUBDOMAIN;
143
184
  if (userDefinedSubdomain && typeof userDefinedSubdomain === 'string') {
144
185
  debug('Session:', userDefinedSubdomain);
145
186
  return {
146
187
  session: userDefinedSubdomain
147
188
  };
148
- } else {
149
- const session = getTunnelSession();
150
- return {
151
- session
152
- };
189
+ }
190
+ return {
191
+ session: getWebcontainerSession()
192
+ };
193
+ }
194
+ async function getExpoAccountTunnelUrlAsync(projectRoot) {
195
+ async function resolveExpoAccountIdAsync(projectRoot) {
196
+ var _exp_extra_eas, _exp_extra, _actor_accounts_;
197
+ const { exp } = (0, _config().getConfig)(projectRoot, {
198
+ skipSDKVersionRequirement: true
199
+ });
200
+ const easProjectId = (_exp_extra = exp.extra) == null ? void 0 : (_exp_extra_eas = _exp_extra.eas) == null ? void 0 : _exp_extra_eas.projectId;
201
+ if (easProjectId) {
202
+ try {
203
+ var _app_ownerAccount;
204
+ const app = await _AppQuery.AppQuery.byIdAsync(easProjectId);
205
+ const appOwnerAccountId = app == null ? void 0 : (_app_ownerAccount = app.ownerAccount) == null ? void 0 : _app_ownerAccount.id;
206
+ if (appOwnerAccountId) {
207
+ return appOwnerAccountId;
208
+ }
209
+ } catch (error) {
210
+ debug('Failed to resolve owning account from EAS project ID:', error);
211
+ }
212
+ }
213
+ const actor = await (0, _user.getUserAsync)();
214
+ if (!actor) {
215
+ return null;
216
+ } else if (actor.__typename === 'User' || actor.__typename === 'SSOUser') {
217
+ var _actor_primaryAccount;
218
+ const actorPrimaryAccountId = (_actor_primaryAccount = actor.primaryAccount) == null ? void 0 : _actor_primaryAccount.id;
219
+ if (actorPrimaryAccountId) {
220
+ return actorPrimaryAccountId;
221
+ }
222
+ }
223
+ // Robots have no primary account; fall back to their first available account.
224
+ return ((_actor_accounts_ = actor.accounts[0]) == null ? void 0 : _actor_accounts_.id) ?? null;
225
+ }
226
+ try {
227
+ const accountId = await resolveExpoAccountIdAsync(projectRoot);
228
+ if (!accountId) {
229
+ debug('No Expo account available to create a signed tunnel URL; user is likely logged out.');
230
+ return null;
231
+ }
232
+ const { url } = await _TunnelMutation.TunnelMutation.createSignedTunnelUrlAsync(accountId);
233
+ debug('Created signed tunnel URL for account:', accountId);
234
+ return url;
235
+ } catch (error) {
236
+ debug('Failed to create a signed tunnel URL:', error);
237
+ return null;
153
238
  }
154
239
  }
155
240
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/server/AsyncWsTunnel.ts"],"sourcesContent":["import * as tunnel from '@expo/ws-tunnel';\nimport chalk from 'chalk';\nimport * as fs from 'node:fs';\nimport { tmpdir, hostname } from 'node:os';\nimport * as path from 'node:path';\n\nimport * as Log from '../../log';\nimport { env, envIsWebcontainer } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\n\nconst debug = require('debug')('expo:start:server:ws-tunnel') as typeof console.log;\n\nexport class AsyncWsTunnel {\n /** Info about the currently running instance of tunnel. */\n private serverUrl: string | null = null;\n\n constructor(_projectRoot: string, port: number) {\n if (port !== 8081) {\n throw new CommandError(\n 'WS_TUNNEL_PORT',\n `WS-tunnel only supports tunneling over port 8081, attempted to use port ${port}`\n );\n }\n }\n\n public getActiveUrl(): string | null {\n return this.serverUrl;\n }\n\n async startAsync(): Promise<void> {\n this.serverUrl = await tunnel.startAsync({\n ...getTunnelOptions(),\n onStatusChange(status) {\n if (status === 'disconnected') {\n Log.error(\n chalk.red(\n 'Tunnel connection has been closed. This is often related to intermittent connection problems with the ws proxy servers. Restart the dev server to try connecting again.'\n ) + chalk.gray('\\nCheck the Expo status page for outages: https://status.expo.dev/')\n );\n }\n },\n });\n\n debug('Tunnel URL:', this.serverUrl);\n }\n\n async stopAsync(): Promise<void> {\n debug('Stopping Tunnel');\n await tunnel.stopAsync();\n this.serverUrl = null;\n }\n}\n\n// Generate a base-36 string of 5 characters (from 32 bits of randomness)\nfunction randomStr() {\n return (Math.random().toString(36) + '00000').slice(2, 7);\n}\n\nfunction getTunnelSession(): string {\n let session = randomStr() + randomStr() + randomStr();\n if (envIsWebcontainer()) {\n const leaseId = Buffer.from(hostname()).toString('base64url');\n const leaseFile = path.join(tmpdir(), `_ws_tunnel_lease_${leaseId}`);\n try {\n session = fs.readFileSync(leaseFile, 'utf8').trim() || session;\n } catch {}\n try {\n fs.writeFileSync(leaseFile, session, 'utf8');\n } catch {}\n }\n return session;\n}\n\nfunction getTunnelOptions() {\n const userDefinedSubdomain = env.EXPO_TUNNEL_SUBDOMAIN;\n if (userDefinedSubdomain && typeof userDefinedSubdomain === 'string') {\n debug('Session:', userDefinedSubdomain);\n return { session: userDefinedSubdomain };\n } else {\n const session = getTunnelSession();\n return { session };\n }\n}\n"],"names":["AsyncWsTunnel","debug","require","_projectRoot","port","serverUrl","CommandError","getActiveUrl","startAsync","tunnel","getTunnelOptions","onStatusChange","status","Log","error","chalk","red","gray","stopAsync","randomStr","Math","random","toString","slice","getTunnelSession","session","envIsWebcontainer","leaseId","Buffer","from","hostname","leaseFile","path","join","tmpdir","fs","readFileSync","trim","writeFileSync","userDefinedSubdomain","env","EXPO_TUNNEL_SUBDOMAIN"],"mappings":";;;;+BAYaA;;;eAAAA;;;;iEAZW;;;;;;;gEACN;;;;;;;iEACE;;;;;;;yBACa;;;;;;;iEACX;;;;;;6DAED;qBACkB;wBACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE7B,MAAMC,QAAQC,QAAQ,SAAS;AAExB,MAAMF;IAIX,YAAYG,YAAoB,EAAEC,IAAY,CAAE;QAHhD,yDAAyD,QACjDC,YAA2B;QAGjC,IAAID,SAAS,MAAM;YACjB,MAAM,IAAIE,oBAAY,CACpB,kBACA,CAAC,wEAAwE,EAAEF,MAAM;QAErF;IACF;IAEOG,eAA8B;QACnC,OAAO,IAAI,CAACF,SAAS;IACvB;IAEA,MAAMG,aAA4B;QAChC,IAAI,CAACH,SAAS,GAAG,MAAMI,YAAOD,UAAU,CAAC;YACvC,GAAGE,kBAAkB;YACrBC,gBAAeC,MAAM;gBACnB,IAAIA,WAAW,gBAAgB;oBAC7BC,KAAIC,KAAK,CACPC,gBAAK,CAACC,GAAG,CACP,6KACED,gBAAK,CAACE,IAAI,CAAC;gBAEnB;YACF;QACF;QAEAhB,MAAM,eAAe,IAAI,CAACI,SAAS;IACrC;IAEA,MAAMa,YAA2B;QAC/BjB,MAAM;QACN,MAAMQ,YAAOS,SAAS;QACtB,IAAI,CAACb,SAAS,GAAG;IACnB;AACF;AAEA,yEAAyE;AACzE,SAASc;IACP,OAAO,AAACC,CAAAA,KAAKC,MAAM,GAAGC,QAAQ,CAAC,MAAM,OAAM,EAAGC,KAAK,CAAC,GAAG;AACzD;AAEA,SAASC;IACP,IAAIC,UAAUN,cAAcA,cAAcA;IAC1C,IAAIO,IAAAA,sBAAiB,KAAI;QACvB,MAAMC,UAAUC,OAAOC,IAAI,CAACC,IAAAA,kBAAQ,KAAIR,QAAQ,CAAC;QACjD,MAAMS,YAAYC,YAAKC,IAAI,CAACC,IAAAA,gBAAM,KAAI,CAAC,iBAAiB,EAAEP,SAAS;QACnE,IAAI;YACFF,UAAUU,UAAGC,YAAY,CAACL,WAAW,QAAQM,IAAI,MAAMZ;QACzD,EAAE,OAAM,CAAC;QACT,IAAI;YACFU,UAAGG,aAAa,CAACP,WAAWN,SAAS;QACvC,EAAE,OAAM,CAAC;IACX;IACA,OAAOA;AACT;AAEA,SAASf;IACP,MAAM6B,uBAAuBC,QAAG,CAACC,qBAAqB;IACtD,IAAIF,wBAAwB,OAAOA,yBAAyB,UAAU;QACpEtC,MAAM,YAAYsC;QAClB,OAAO;YAAEd,SAASc;QAAqB;IACzC,OAAO;QACL,MAAMd,UAAUD;QAChB,OAAO;YAAEC;QAAQ;IACnB;AACF"}
1
+ {"version":3,"sources":["../../../../src/start/server/AsyncWsTunnel.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport * as tunnel from '@expo/ws-tunnel';\nimport chalk from 'chalk';\nimport * as fs from 'node:fs';\nimport { tmpdir, hostname } from 'node:os';\nimport * as path from 'node:path';\n\nimport { TunnelMutation } from '../../api/graphql/mutations/TunnelMutation';\nimport { AppQuery } from '../../api/graphql/queries/AppQuery';\nimport { hasCredentials } from '../../api/user/UserSettings';\nimport { getUserAsync } from '../../api/user/user';\nimport * as Log from '../../log';\nimport { env, envIsWebcontainer } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\n\nconst debug = require('debug')('expo:start:server:ws-tunnel') as typeof console.log;\n\nexport interface AsyncWsTunnelOptions {\n useExpoAccount?: boolean;\n}\n\nexport class AsyncWsTunnel {\n private serverUrl: URL | null = null;\n\n constructor(\n private projectRoot: string,\n private port: number,\n private options: AsyncWsTunnelOptions = {}\n ) {}\n\n public getActiveUrl(): string | null {\n return this.serverUrl?.href ?? null;\n }\n\n async startAsync(): Promise<void> {\n this.serverUrl = await tunnel.startAsync({\n ...(await this.getTunnelOptionsAsync()),\n onStatusChange(status) {\n if (status === 'disconnected') {\n Log.error(\n chalk.red(\n 'Tunnel connection has been closed. This is often related to intermittent connection problems with the ws proxy servers. Restart the dev server to try connecting again.'\n ) + chalk.gray('\\nCheck the Expo status page for outages: https://status.expo.dev/')\n );\n }\n },\n });\n\n debug('Tunnel URL:', this.serverUrl.href);\n }\n\n private async getTunnelOptionsAsync(): Promise<tunnel.WsTunnelOptions> {\n if (this.options.useExpoAccount) {\n return this.getExpoAccountTunnelOptionsAsync();\n } else {\n return getLegacyTunnelOptions(this.port);\n }\n }\n\n private async getExpoAccountTunnelOptionsAsync(): Promise<tunnel.WsTunnelOptions> {\n const apiUrl = await getExpoAccountTunnelUrlAsync(this.projectRoot);\n if (!apiUrl) {\n const cause = hasCredentials()\n ? `Your Expo account may not have access to it, or the tunnel service is unavailable.`\n : `You're not logged in to your Expo account — run 'npx expo login'.`;\n throw new CommandError(\n 'WS_TUNNEL_SIGNED_URL',\n `Couldn't create a signed tunnel URL for this project. ${cause} ` +\n `Unset EXPO_UNSTABLE_TUNNEL_V2 to use an ngrok tunnel instead.`\n );\n }\n return { apiUrl, targetUrl: `http://localhost:${this.port}` };\n }\n\n async stopAsync(): Promise<void> {\n debug('Stopping Tunnel');\n await tunnel.stopAsync();\n this.serverUrl = null;\n }\n}\n\nfunction getLegacyTunnelOptions(port: number): tunnel.WsTunnelOptions {\n if (port !== 8081) {\n throw new CommandError(\n 'WS_TUNNEL_PORT',\n `WS-tunnel only supports tunneling over port 8081, attempted to use port ${port}`\n );\n }\n\n function randomSessionId(): string {\n const randomPart = () => (Math.random().toString(36) + '00000').slice(2, 7);\n return randomPart() + randomPart() + randomPart();\n }\n\n function getWebcontainerSession(): string {\n let session = randomSessionId();\n if (envIsWebcontainer()) {\n const leaseId = Buffer.from(hostname()).toString('base64url');\n const leaseFile = path.join(tmpdir(), `_ws_tunnel_lease_${leaseId}`);\n try {\n session = fs.readFileSync(leaseFile, 'utf8').trim() || session;\n } catch {}\n try {\n fs.writeFileSync(leaseFile, session, 'utf8');\n } catch {}\n }\n return session;\n }\n\n const userDefinedSubdomain = env.EXPO_TUNNEL_SUBDOMAIN;\n if (userDefinedSubdomain && typeof userDefinedSubdomain === 'string') {\n debug('Session:', userDefinedSubdomain);\n return { session: userDefinedSubdomain };\n }\n return { session: getWebcontainerSession() };\n}\n\nexport async function getExpoAccountTunnelUrlAsync(projectRoot: string): Promise<string | null> {\n async function resolveExpoAccountIdAsync(projectRoot: string): Promise<string | null> {\n const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true });\n const easProjectId = exp.extra?.eas?.projectId as string | undefined | null;\n if (easProjectId) {\n try {\n const app = await AppQuery.byIdAsync(easProjectId);\n const appOwnerAccountId = app?.ownerAccount?.id;\n if (appOwnerAccountId) {\n return appOwnerAccountId;\n }\n } catch (error) {\n debug('Failed to resolve owning account from EAS project ID:', error);\n }\n }\n\n const actor = await getUserAsync();\n if (!actor) {\n return null;\n } else if (actor.__typename === 'User' || actor.__typename === 'SSOUser') {\n const actorPrimaryAccountId = actor.primaryAccount?.id;\n if (actorPrimaryAccountId) {\n return actorPrimaryAccountId;\n }\n }\n\n // Robots have no primary account; fall back to their first available account.\n return actor.accounts[0]?.id ?? null;\n }\n\n try {\n const accountId = await resolveExpoAccountIdAsync(projectRoot);\n if (!accountId) {\n debug('No Expo account available to create a signed tunnel URL; user is likely logged out.');\n return null;\n }\n const { url } = await TunnelMutation.createSignedTunnelUrlAsync(accountId);\n debug('Created signed tunnel URL for account:', accountId);\n return url;\n } catch (error) {\n debug('Failed to create a signed tunnel URL:', error);\n return null;\n }\n}\n"],"names":["AsyncWsTunnel","getExpoAccountTunnelUrlAsync","debug","require","projectRoot","port","options","serverUrl","getActiveUrl","href","startAsync","tunnel","getTunnelOptionsAsync","onStatusChange","status","Log","error","chalk","red","gray","useExpoAccount","getExpoAccountTunnelOptionsAsync","getLegacyTunnelOptions","apiUrl","cause","hasCredentials","CommandError","targetUrl","stopAsync","randomSessionId","randomPart","Math","random","toString","slice","getWebcontainerSession","session","envIsWebcontainer","leaseId","Buffer","from","hostname","leaseFile","path","join","tmpdir","fs","readFileSync","trim","writeFileSync","userDefinedSubdomain","env","EXPO_TUNNEL_SUBDOMAIN","resolveExpoAccountIdAsync","exp","actor","getConfig","skipSDKVersionRequirement","easProjectId","extra","eas","projectId","app","AppQuery","byIdAsync","appOwnerAccountId","ownerAccount","id","getUserAsync","__typename","actorPrimaryAccountId","primaryAccount","accounts","accountId","url","TunnelMutation","createSignedTunnelUrlAsync"],"mappings":"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"}
@@ -189,15 +189,25 @@ class BundlerDevServer {
189
189
  this.notifier = new _FileNotifier.FileNotifier(this.projectRoot, this.getConfigModuleIds());
190
190
  this.notifier.startObserving();
191
191
  }
192
- /** Create ngrok instance and start the tunnel server. Exposed for testing. */ async _startTunnelAsync() {
192
+ /** Create the tunnel instance and start the tunnel server. Exposed for testing. */ async _startTunnelAsync() {
193
193
  var _this_getInstance;
194
194
  const port = (_this_getInstance = this.getInstance()) == null ? void 0 : _this_getInstance.location.port;
195
195
  if (!port) return null;
196
196
  debug('[tunnel] connect to port: ' + port);
197
- this.tunnel = (0, _env.envIsWebcontainer)() ? new _AsyncWsTunnel.AsyncWsTunnel(this.projectRoot, port) : new _AsyncNgrok.AsyncNgrok(this.projectRoot, port);
197
+ this.tunnel = this._createTunnel(port);
198
198
  await this.tunnel.startAsync();
199
199
  return this.tunnel;
200
200
  }
201
+ /** Resolve which tunnel implementation to use, without starting it. */ _createTunnel(port) {
202
+ const useV2Tunnel = _env.env.EXPO_UNSTABLE_TUNNEL_V2 || (0, _env.envIsWebcontainer)();
203
+ if (useV2Tunnel) {
204
+ const useExpoAccount = !!_env.env.EXPO_UNSTABLE_TUNNEL_V2;
205
+ return new _AsyncWsTunnel.AsyncWsTunnel(this.projectRoot, port, {
206
+ useExpoAccount
207
+ });
208
+ }
209
+ return new _AsyncNgrok.AsyncNgrok(this.projectRoot, port);
210
+ }
201
211
  async startDevSessionAsync() {
202
212
  // This is used to make Expo Go open the project in either Expo Go, or the web browser.
203
213
  // Must come after ngrok (`startTunnelAsync`) setup.
@@ -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 { Bonjour } from './Bonjour';\nimport DevToolsPluginManager from './DevToolsPluginManager';\nimport { DevelopmentSession } from './DevelopmentSession';\nimport type { CreateURLOptions } from './UrlCreator';\nimport { UrlCreator } from './UrlCreator';\nimport type { 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 { isInteractive } from '../../utils/interactive';\nimport { openBrowserAsync } from '../../utils/open';\nimport type { BaseResolveDeviceProps, PlatformManager } 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\ntype PlatformManagers = {\n [K in keyof typeof PLATFORM_MANAGERS]: InstanceType<ReturnType<(typeof PLATFORM_MANAGERS)[K]>>;\n};\n\ntype PlatformDevice<Platform extends keyof PlatformManagers> =\n PlatformManagers[Platform] extends PlatformManager<infer Device, any> ? Device : never;\n\ntype PlatformLaunchProps<Platform extends keyof PlatformManagers> =\n PlatformManagers[Platform] extends PlatformManager<any, infer LaunchProps> ? LaunchProps : never;\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: { [K in keyof PlatformManagers]?: PlatformManagers[K] | undefined } =\n {};\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 await this.initUrlCreator(options);\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 // Reset url creator\n this.urlCreator = undefined;\n\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 // TODO(@kitten): This should be created top-down rather than bottom up from implementors\n protected async initUrlCreator(\n options: Partial<Pick<BundlerStartOptions, 'port' | 'location'>> = {}\n ) {\n assert(options?.port, 'Dev server instance not found');\n assert(!this.urlCreator, 'Dev server is already initialized');\n const urlCreator = await UrlCreator.init(options.location, {\n port: options.port,\n getTunnelUrl: this.getTunnelUrl.bind(this),\n });\n this.urlCreator = urlCreator;\n return urlCreator;\n }\n\n public getUrlCreator() {\n assert(this.urlCreator, 'Dev server is uninitialized');\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 PlatformManagers | '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 // Only launch the browser automatically if the process is interactive, otherwise we'll assume it's an agent.\n if (isInteractive()) {\n await openBrowserAsync(url!);\n }\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<Platform extends keyof PlatformManagers>(\n launchTarget: Platform,\n launchProps: Partial<PlatformLaunchProps<Platform>> = {},\n resolver: BaseResolveDeviceProps<PlatformDevice<Platform>> = {}\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(\n { runtime: 'custom', props: launchProps },\n resolver as BaseResolveDeviceProps<any>\n );\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 PlatformManagers | 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 extends keyof PlatformManagers>(\n ofPlatform: Platform\n ): Promise<PlatformManagers[Platform]> {\n const platform: keyof PlatformManagers = ofPlatform;\n if (!this.platformManagers[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 const managerParams = {\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 switch (platform) {\n case 'simulator': {\n const Manager = PLATFORM_MANAGERS[platform]();\n this.platformManagers[platform] = new Manager(this.projectRoot, port, managerParams);\n break;\n }\n case 'emulator': {\n const Manager = PLATFORM_MANAGERS[platform]();\n this.platformManagers[platform] = new Manager(this.projectRoot, port, managerParams);\n break;\n }\n }\n }\n return this.platformManagers[platform] as PlatformManagers[Platform];\n }\n}\n"],"names":["BundlerDevServer","debug","require","PLATFORM_MANAGERS","simulator","ApplePlatformManager","emulator","AndroidPlatformManager","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","initUrlCreator","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","undefined","closeAsync","catch","e","Log","error","exception","resolveWithTimeout","resolve","reject","code","timeout","errorMessage","assert","UrlCreator","init","getTunnelUrl","opts","constructDevClientUrl","scheme","getDevServerUrlOrAssert","getJsInspectorBaseUrl","getActiveUrl","openPlatformAsync","launchTarget","resolver","serverUrl","isInteractive","openBrowserAsync","manager","getPlatformManagerAsync","openAsync","openCustomRuntimeAsync","launchProps","props","getExpoGoUrl","isRedirectPageEnabled","EXPO_NO_REDIRECT_PAGE","resolveFrom","silent","getRedirectUrl","platform","constructLoadingUrl","ofPlatform","managerParams","getCustomRuntimeUrl","Manager"],"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 type { CreateURLOptions } from './UrlCreator';\nimport { UrlCreator } from './UrlCreator';\nimport type { 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 { isInteractive } from '../../utils/interactive';\nimport { openBrowserAsync } from '../../utils/open';\nimport type { BaseResolveDeviceProps, PlatformManager } 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\ntype PlatformManagers = {\n [K in keyof typeof PLATFORM_MANAGERS]: InstanceType<ReturnType<(typeof PLATFORM_MANAGERS)[K]>>;\n};\n\ntype PlatformDevice<Platform extends keyof PlatformManagers> =\n PlatformManagers[Platform] extends PlatformManager<infer Device, any> ? Device : never;\n\ntype PlatformLaunchProps<Platform extends keyof PlatformManagers> =\n PlatformManagers[Platform] extends PlatformManager<any, infer LaunchProps> ? LaunchProps : never;\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: { [K in keyof PlatformManagers]?: PlatformManagers[K] | undefined } =\n {};\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 await this.initUrlCreator(options);\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 the tunnel 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 = this._createTunnel(port);\n await this.tunnel.startAsync();\n return this.tunnel;\n }\n\n /** Resolve which tunnel implementation to use, without starting it. */\n private _createTunnel(port: number): AsyncNgrok | AsyncWsTunnel {\n const useV2Tunnel = env.EXPO_UNSTABLE_TUNNEL_V2 || envIsWebcontainer();\n if (useV2Tunnel) {\n const useExpoAccount = !!env.EXPO_UNSTABLE_TUNNEL_V2;\n return new AsyncWsTunnel(this.projectRoot, port, { useExpoAccount });\n }\n\n return new AsyncNgrok(this.projectRoot, port);\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 // Reset url creator\n this.urlCreator = undefined;\n\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 // TODO(@kitten): This should be created top-down rather than bottom up from implementors\n protected async initUrlCreator(\n options: Partial<Pick<BundlerStartOptions, 'port' | 'location'>> = {}\n ) {\n assert(options?.port, 'Dev server instance not found');\n assert(!this.urlCreator, 'Dev server is already initialized');\n const urlCreator = await UrlCreator.init(options.location, {\n port: options.port,\n getTunnelUrl: this.getTunnelUrl.bind(this),\n });\n this.urlCreator = urlCreator;\n return urlCreator;\n }\n\n public getUrlCreator() {\n assert(this.urlCreator, 'Dev server is uninitialized');\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 PlatformManagers | '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 // Only launch the browser automatically if the process is interactive, otherwise we'll assume it's an agent.\n if (isInteractive()) {\n await openBrowserAsync(url!);\n }\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<Platform extends keyof PlatformManagers>(\n launchTarget: Platform,\n launchProps: Partial<PlatformLaunchProps<Platform>> = {},\n resolver: BaseResolveDeviceProps<PlatformDevice<Platform>> = {}\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(\n { runtime: 'custom', props: launchProps },\n resolver as BaseResolveDeviceProps<any>\n );\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 PlatformManagers | 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 extends keyof PlatformManagers>(\n ofPlatform: Platform\n ): Promise<PlatformManagers[Platform]> {\n const platform: keyof PlatformManagers = ofPlatform;\n if (!this.platformManagers[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 const managerParams = {\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 switch (platform) {\n case 'simulator': {\n const Manager = PLATFORM_MANAGERS[platform]();\n this.platformManagers[platform] = new Manager(this.projectRoot, port, managerParams);\n break;\n }\n case 'emulator': {\n const Manager = PLATFORM_MANAGERS[platform]();\n this.platformManagers[platform] = new Manager(this.projectRoot, port, managerParams);\n break;\n }\n }\n }\n return this.platformManagers[platform] as PlatformManagers[Platform];\n }\n}\n"],"names":["BundlerDevServer","debug","require","PLATFORM_MANAGERS","simulator","ApplePlatformManager","emulator","AndroidPlatformManager","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","initUrlCreator","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","_createTunnel","useV2Tunnel","EXPO_UNSTABLE_TUNNEL_V2","useExpoAccount","AsyncWsTunnel","AsyncNgrok","DevelopmentSession","getNativeRuntimeUrl","getDevServerUrl","runtime","Bonjour","announceAsync","isTargetingWeb","web","broadcastMessage","method","params","undefined","closeAsync","catch","e","Log","error","exception","resolveWithTimeout","resolve","reject","code","timeout","errorMessage","assert","UrlCreator","init","getTunnelUrl","opts","constructDevClientUrl","scheme","getDevServerUrlOrAssert","getJsInspectorBaseUrl","getActiveUrl","openPlatformAsync","launchTarget","resolver","serverUrl","isInteractive","openBrowserAsync","manager","getPlatformManagerAsync","openAsync","openCustomRuntimeAsync","launchProps","props","getExpoGoUrl","isRedirectPageEnabled","EXPO_NO_REDIRECT_PAGE","resolveFrom","silent","getRedirectUrl","platform","constructLoadingUrl","ofPlatform","managerParams","getCustomRuntimeUrl","Manager"],"mappings":"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"}
@@ -271,7 +271,8 @@ class MetroTerminalReporter extends _TerminalReporter.TerminalReporter {
271
271
  let hasStack = false;
272
272
  const parsed = data.map((msg)=>{
273
273
  // Quick check to see if an unsymbolicated stack is being logged.
274
- if (typeof msg === 'string' && msg.includes('.bundle//&platform=')) {
274
+ if (typeof msg === 'string' && // Native stack frames use `.bundle//&platform=...`; web stack frames use `.bundle?platform=...`.
275
+ (msg.includes('.bundle//&platform=') || msg.includes('.bundle?platform='))) {
275
276
  const stack = (0, _serverLogLikeMetro.parseErrorStringToObject)(msg);
276
277
  if (stack) {
277
278
  hasStack = true;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/server/metro/MetroTerminalReporter.ts"],"sourcesContent":["import type { Terminal } from '@expo/metro/metro-core';\nimport chalk from 'chalk';\nimport path from 'path';\nimport { format as utilFormat, stripVTControlCharacters } from 'util';\n\nimport { logWarning, TerminalReporter } from './TerminalReporter';\nimport type {\n BuildPhase,\n BundleDetails,\n BundleProgress,\n SnippetError,\n TerminalReportableEvent,\n} from './TerminalReporter.types';\nimport { NODE_STDLIB_MODULES } from './externals';\nimport { env } from '../../../utils/env';\nimport { learnMore } from '../../../utils/link';\nimport {\n logLikeMetro,\n maybeSymbolicateAndFormatJSErrorStackLogAsync,\n parseErrorStringToObject,\n} from '../serverLogLikeMetro';\nimport { attachImportStackToRootMessage, nearestImportStack } from './metroErrorInterface';\nimport { events, shouldReduceLogs } from '../../../events';\nimport { stripAnsi } from '../../../utils/ansi';\nimport { isInteractive } from '../../../utils/interactive';\n\ntype ClientLogLevel =\n | 'trace'\n | 'info'\n | 'error'\n | 'warn'\n | 'log'\n | 'group'\n | 'groupCollapsed'\n | 'groupEnd'\n | 'debug';\n\nconst debug = require('debug')('expo:metro:logger') as typeof console.log;\n\n// prettier-ignore\nexport const event = events('metro', (t) => [\n t.event<'bundling:started', {\n id: string;\n platform: null | string;\n environment: null | string;\n entry: string;\n }>(),\n t.event<'bundling:done', {\n id: string | null;\n ms: number | null;\n total: number;\n }>(),\n t.event<'bundling:failed', {\n id: string | null;\n filename: string | null;\n message: string | null;\n importStack: string | null;\n targetModuleName: string | null;\n originModulePath: string | null;\n }>(),\n t.event<'bundling:progress', {\n id: string | null;\n progress: number;\n current: number;\n total: number;\n }>(),\n t.event<'server_log', {\n level: 'info' | 'warn' | 'error' | null;\n data: string | unknown[] | null;\n }>(),\n t.event<'client_log', {\n level: ClientLogLevel | null;\n data: unknown[] | null;\n }>(),\n t.event<'hmr_client_error', {\n message: string;\n }>(),\n t.event<'cache_write_error', {\n message: string;\n }>(),\n t.event<'cache_read_error', {\n message: string;\n }>(),\n]);\n\nconst MAX_PROGRESS_BAR_CHAR_WIDTH = 16;\nconst DARK_BLOCK_CHAR = '\\u2593';\nconst LIGHT_BLOCK_CHAR = '\\u2591';\n/**\n * Extends the default Metro logger and adds some additional features.\n * Also removes the giant Metro logo from the output.\n */\nexport class MetroTerminalReporter extends TerminalReporter {\n #lastFailedBuildID: string | undefined;\n\n constructor(\n public serverRoot: string,\n terminal: Terminal\n ) {\n super(terminal);\n }\n\n /**\n * Suppress status messages in non-interactive mode.\n * In TTY mode, Terminal overwrites status lines in-place (progress bars).\n * In non-TTY mode, Terminal writes status via a 3500ms throttle, producing\n * permanent output that interleaves with log messages like \"Bundled Xms\".\n */\n _getStatusMessage(): string {\n if (!isInteractive()) {\n return '';\n }\n return super._getStatusMessage();\n }\n\n _log(event: TerminalReportableEvent): void {\n this.#captureLog(event);\n switch (event.type) {\n case 'unstable_server_log':\n if (typeof event.data?.[0] === 'string') {\n const message = event.data[0];\n if (message.match(/JavaScript logs have moved/)) {\n // Hide this very loud message from upstream React Native in favor of the note in the terminal UI:\n // The \"› Press j │ open debugger\"\n\n // logger?.info(\n // '\\u001B[1m\\u001B[7m💡 JavaScript logs have moved!\\u001B[22m They can now be ' +\n // 'viewed in React Native DevTools. Tip: Type \\u001B[1mj\\u001B[22m in ' +\n // 'the terminal to open (requires Google Chrome or Microsoft Edge).' +\n // '\\u001B[27m',\n // );\n return;\n }\n\n if (!env.EXPO_DEBUG) {\n // In the context of developing an iOS app or website, the MetroInspectorProxy \"connection\" logs are very confusing.\n // Here we'll hide them behind EXPO_DEBUG or DEBUG=expo:*. In the future we can reformat them to clearly indicate that the \"Connection\" is regarding the debugger.\n // These logs are also confusing because they can say \"connection established\" even when the debugger is not in a usable state. Really they belong in a UI or behind some sort of debug logging.\n if (message.match(/Connection (closed|established|failed|terminated)/i)) {\n // Skip logging.\n return;\n }\n }\n }\n break;\n case 'client_log': {\n if (this.shouldFilterClientLog(event)) {\n return;\n } else if (event.level != null) {\n return this.#onClientLog(event);\n } else {\n break;\n }\n }\n }\n return super._log(event);\n }\n\n // Used for testing\n _getElapsedTime(startTime: bigint): bigint {\n return process.hrtime.bigint() - startTime;\n }\n /**\n * Extends the bundle progress to include the current platform that we're bundling.\n *\n * @returns `iOS path/to/bundle.js ▓▓▓▓▓░░░░░░░░░░░ 36.6% (4790/7922)`\n */\n _getBundleStatusMessage(progress: BundleProgress, phase: BuildPhase): string {\n const env = getEnvironmentForBuildDetails(progress.bundleDetails);\n const platform = env || getPlatformTagForBuildDetails(progress.bundleDetails);\n const inProgress = phase === 'in_progress';\n\n const localPath =\n typeof progress.bundleDetails?.customTransformOptions?.dom === 'string' &&\n progress.bundleDetails.customTransformOptions.dom.includes(path.sep)\n ? progress.bundleDetails.customTransformOptions.dom.replace(/^(\\.?\\.[\\\\/])+/, '')\n : this.#normalizePath(progress.bundleDetails.entryFile);\n\n if (!inProgress) {\n const status = phase === 'done' ? `Bundled ` : `Bundling failed `;\n const color = phase === 'done' ? chalk.green : chalk.red;\n\n const startTime = this._bundleTimers.get(progress.bundleDetails.buildID!);\n\n let time: string = '';\n let ms: number | null = null;\n\n if (startTime != null) {\n const elapsed: bigint = this._getElapsedTime(startTime);\n const micro = Number(elapsed) / 1000;\n ms = Number(elapsed) / 1e6;\n // If the milliseconds are < 0.5 then it will display as 0, so we display in microseconds.\n if (ms <= 0.5) {\n const tenthFractionOfMicro = ((micro * 10) / 1000).toFixed(0);\n // Format as microseconds to nearest tenth\n time = chalk.cyan.bold(`0.${tenthFractionOfMicro}ms`);\n } else {\n time = chalk.dim(ms.toFixed(0) + 'ms');\n }\n }\n\n if (phase === 'done') {\n event('bundling:done', {\n id: progress.bundleDetails.buildID ?? null,\n total: progress.totalFileCount,\n ms,\n });\n }\n\n // iOS Bundled 150ms\n const plural = progress.totalFileCount === 1 ? '' : 's';\n return (\n color(platform + status) +\n time +\n chalk.reset.dim(` ${localPath} (${progress.totalFileCount} module${plural})`)\n );\n }\n\n event('bundling:progress', {\n id: progress.bundleDetails.buildID ?? null,\n progress: progress.ratio,\n total: progress.totalFileCount,\n current: progress.transformedFileCount,\n });\n if (shouldReduceLogs()) {\n return '';\n }\n\n const filledBar = Math.floor(progress.ratio * MAX_PROGRESS_BAR_CHAR_WIDTH);\n const _progress = inProgress\n ? chalk.green.bgGreen(DARK_BLOCK_CHAR.repeat(filledBar)) +\n chalk.bgWhite.white(LIGHT_BLOCK_CHAR.repeat(MAX_PROGRESS_BAR_CHAR_WIDTH - filledBar)) +\n chalk.bold(` ${(100 * progress.ratio).toFixed(1).padStart(4)}% `) +\n chalk.dim(\n `(${progress.transformedFileCount\n .toString()\n .padStart(progress.totalFileCount.toString().length)}/${progress.totalFileCount})`\n )\n : '';\n return (\n platform +\n chalk.reset.dim(`${path.dirname(localPath)}${path.sep}`) +\n chalk.bold(path.basename(localPath)) +\n ' ' +\n _progress\n );\n }\n\n _logInitializing(port: number, hasReducedPerformance: boolean): void {\n // Don't print a giant logo...\n if (!shouldReduceLogs()) {\n this.terminal.log(chalk.dim('Starting Metro Bundler') + '\\n');\n }\n }\n\n shouldFilterClientLog(event: { type: 'client_log'; data: unknown[] }): boolean {\n return isAppRegistryStartupMessage(event.data);\n }\n\n shouldFilterBundleEvent(event: TerminalReportableEvent): boolean {\n return 'bundleDetails' in event && event.bundleDetails?.bundleType === 'map';\n }\n\n /** Print the cache clear message. */\n transformCacheReset(): void {\n logWarning(\n this.terminal,\n chalk`Bundler cache is empty, rebuilding {dim (this may take a minute)}`\n );\n }\n\n /** One of the first logs that will be printed */\n dependencyGraphLoading(hasReducedPerformance: boolean): void {\n // this.terminal.log('Dependency graph is loading...');\n if (hasReducedPerformance) {\n // Extends https://github.com/facebook/metro/blob/347b1d7ed87995d7951aaa9fd597c04b06013dac/packages/metro/src/lib/TerminalReporter.js#L283-L290\n this.terminal.log(\n chalk.red(\n [\n 'Metro is operating with reduced performance.',\n 'Fix the problem above and restart Metro.',\n ].join('\\n')\n )\n );\n }\n }\n\n /**\n * Workaround to link build ids to bundling errors.\n * This works because `_logBundleBuildFailed` is called before `_logBundlingError` in synchronous manner.\n * https://github.com/facebook/metro/blob/main/packages/metro/src/Server.js#L939-L945\n */\n _logBundleBuildFailed(buildID: string): void {\n this.#lastFailedBuildID = buildID;\n super._logBundleBuildFailed(buildID);\n }\n\n _logBundlingError(error: SnippetError): void {\n const importStack = nearestImportStack(error);\n const moduleResolutionError = formatUsingNodeStandardLibraryError(this.serverRoot, error);\n\n if (moduleResolutionError) {\n const message = maybeAppendCodeFrame(moduleResolutionError, error.message);\n event('bundling:failed', {\n id: this.#lastFailedBuildID ?? null,\n message: stripAnsi(message) ?? null,\n importStack: importStack ?? null,\n filename: error.filename ?? null,\n targetModuleName: this.#normalizePath(error.targetModuleName),\n originModulePath: this.#normalizePath(error.originModulePath),\n });\n\n return this.terminal.log(importStack ? `${message}\\n\\n${importStack}` : message);\n } else {\n event('bundling:failed', {\n id: this.#lastFailedBuildID ?? null,\n message: stripAnsi(error.message) ?? null,\n importStack: importStack ?? null,\n filename: error.filename ?? null,\n targetModuleName: error.targetModuleName ?? null,\n originModulePath: error.originModulePath ?? null,\n });\n\n attachImportStackToRootMessage(error, importStack);\n\n // NOTE(@kitten): Metro drops the stack forcefully when it finds a `SyntaxError`. However,\n // this is really unhelpful, since it prevents debugging Babel plugins or reporting bugs\n // in Babel plugins or a transformer entirely\n if (error.snippet == null && error.stack != null && error instanceof SyntaxError) {\n error.message = error.stack;\n delete error.stack;\n }\n\n return super._logBundlingError(error);\n }\n }\n\n #onClientLog(evt: {\n type: 'client_log';\n level?: ClientLogLevel;\n data: unknown[];\n mode?: string;\n }) {\n const { level = 'log' } = evt;\n // Apply printf-style format substitution (e.g. %s, %d) that browsers handle\n // natively in console methods but Node/Metro terminal logging does not.\n const data = applyConsoleFormatting(evt.data);\n const platformTag = getPlatformTagForClientLog(evt.mode);\n if (level === 'warn' || (level as string) === 'error') {\n let hasStack = false;\n const parsed = data.map((msg) => {\n // Quick check to see if an unsymbolicated stack is being logged.\n if (typeof msg === 'string' && msg.includes('.bundle//&platform=')) {\n const stack = parseErrorStringToObject(msg);\n if (stack) {\n hasStack = true;\n }\n return stack;\n }\n return msg;\n });\n\n if (hasStack) {\n (async () => {\n const symbolicating = parsed.map((p) => {\n if (typeof p === 'string') {\n return p;\n } else if (\n p &&\n typeof p === 'object' &&\n 'message' in p &&\n typeof p.message === 'string'\n ) {\n return maybeSymbolicateAndFormatJSErrorStackLogAsync(\n this.serverRoot,\n level,\n p as any\n );\n } else {\n return null;\n }\n });\n\n let usefulStackCount = 0;\n const fallbackIndices: number[] = [];\n const symbolicated = (await Promise.allSettled(symbolicating)).map((s, index) => {\n if (s.status === 'rejected') {\n debug('Error formatting stack', parsed[index], s.reason);\n return parsed[index];\n } else if (!s.value) {\n return parsed[index];\n } else if (typeof s.value === 'string') {\n return s.value;\n } else {\n if (!s.value.isFallback) {\n usefulStackCount++;\n } else {\n fallbackIndices.push(index);\n }\n return s.value.stack;\n }\n });\n\n // Using EXPO_DEBUG we can print all stack\n const filtered =\n usefulStackCount && !env.EXPO_DEBUG\n ? symbolicated.filter((_, index) => !fallbackIndices.includes(index))\n : symbolicated;\n\n event('client_log', { level, data: symbolicated });\n logLikeMetro(this.terminal.log.bind(this.terminal), level, platformTag, ...filtered);\n })();\n return;\n }\n }\n\n event('client_log', { level, data });\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, platformTag, ...data);\n }\n\n #captureLog(evt: TerminalReportableEvent) {\n switch (evt.type) {\n case 'bundle_build_started': {\n const entry =\n typeof evt.bundleDetails?.customTransformOptions?.dom === 'string' &&\n evt.bundleDetails.customTransformOptions.dom.includes(path.sep)\n ? evt.bundleDetails.customTransformOptions.dom.replace(/^(\\.?\\.[\\\\/])+/, '')\n : this.#normalizePath(evt.bundleDetails.entryFile);\n return event('bundling:started', {\n id: evt.buildID,\n platform: evt.bundleDetails.platform ?? null,\n environment: evt.bundleDetails.customTransformOptions?.environment ?? null,\n entry,\n });\n }\n case 'unstable_server_log':\n return event('server_log', {\n level: evt.level ?? null,\n data: evt.data ?? null,\n });\n case 'client_log':\n // Handled separately: see this.#onClientLog\n return;\n case 'hmr_client_error':\n case 'cache_write_error':\n case 'cache_read_error':\n return event(evt.type, {\n message: evt.error.message,\n });\n }\n }\n\n #normalizePath<T extends string | null>(dest: T | undefined): T | string {\n return dest != null && path.isAbsolute(dest)\n ? path.relative(this.serverRoot, dest)\n : ((dest || null) as T);\n }\n}\n\n/**\n * Formats an error where the user is attempting to import a module from the Node.js standard library.\n * Exposed for testing.\n *\n * @param error\n * @returns error message or null if not a module resolution error\n */\nexport function formatUsingNodeStandardLibraryError(\n serverRoot: string,\n error: SnippetError\n): string | null {\n if (!error.message) {\n return null;\n }\n const { targetModuleName, originModulePath } = error;\n if (!targetModuleName || !originModulePath) {\n return null;\n }\n const relativePath = path.relative(serverRoot, originModulePath);\n\n const DOCS_PAGE_URL =\n 'https://docs.expo.dev/workflow/using-libraries/#using-third-party-libraries';\n\n if (isNodeStdLibraryModule(targetModuleName)) {\n if (originModulePath.includes('node_modules')) {\n return [\n `The package at \"${chalk.bold(\n relativePath\n )}\" attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n } else {\n return [\n `You attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\" from \"${chalk.bold(relativePath)}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n }\n }\n return `Unable to resolve \"${targetModuleName}\" from \"${relativePath}\"`;\n}\n\nexport function isNodeStdLibraryModule(moduleName: string): boolean {\n return /^node:/.test(moduleName) || NODE_STDLIB_MODULES.includes(moduleName);\n}\n\n/** If the code frame can be found then append it to the existing message. */\nfunction maybeAppendCodeFrame(message: string, rawMessage: string): string {\n const codeFrame = extractCodeFrame(stripMetroInfo(rawMessage));\n if (codeFrame) {\n message += '\\n' + codeFrame;\n }\n return message;\n}\n\n/** Extract fist code frame presented in the error message */\nexport function extractCodeFrame(errorMessage: string): string {\n const codeFrameLine = /^(?:\\s*(?:>?\\s*\\d+\\s*\\||\\s*\\|).*\\n?)+/;\n let wasPreviousLineCodeFrame: boolean | null = null;\n return errorMessage\n .split('\\n')\n .filter((line) => {\n if (wasPreviousLineCodeFrame === false) return false;\n const keep = codeFrameLine.test(stripVTControlCharacters(line));\n if (keep && wasPreviousLineCodeFrame === null) wasPreviousLineCodeFrame = true;\n else if (!keep && wasPreviousLineCodeFrame) wasPreviousLineCodeFrame = false;\n return keep;\n })\n .join('\\n');\n}\n\n/**\n * Remove the Metro cache clearing steps if they exist.\n * In future versions we won't need this.\n * Returns the remaining code frame logs.\n */\nexport function stripMetroInfo(errorMessage: string): string {\n // Newer versions of Metro don't include the list.\n if (!errorMessage.includes('4. Remove the cache')) {\n return errorMessage;\n }\n const lines = errorMessage.split('\\n');\n const index = lines.findIndex((line) => line.includes('4. Remove the cache'));\n if (index === -1) {\n return errorMessage;\n }\n return lines.slice(index + 1).join('\\n');\n}\n\n/** @returns if the message matches the initial startup log */\nfunction isAppRegistryStartupMessage(body: any[]): boolean {\n return (\n body.length === 1 &&\n (/^Running application \"main\" with appParams:/.test(body[0]) ||\n /^Running \"main\" with \\{/.test(body[0]))\n );\n}\n\n/** Apply printf-style format substitutions (%s, %d, %i, %f, %o, %O) that browsers handle natively */\nfunction applyConsoleFormatting(data: unknown[]): unknown[] {\n if (data.length <= 1 || typeof data[0] !== 'string' || !/%[sdifoO%]/.test(data[0])) {\n return data;\n }\n return [utilFormat(...(data as [string, ...unknown[]]))];\n}\n\n/** @returns formatted platform name for a client log event, or null if no prefix should be shown */\nfunction getPlatformTagForClientLog(mode?: string): string | null {\n switch (mode) {\n case 'ios':\n return 'iOS';\n case 'android':\n return 'Android';\n case 'web':\n return 'Web';\n case 'dom':\n return 'DOM';\n default:\n return null;\n }\n}\n\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getPlatformTagForBuildDetails(bundleDetails?: BundleDetails | null): string {\n const platform = bundleDetails?.platform ?? null;\n if (platform) {\n let formatted: string;\n switch (platform) {\n case 'ios':\n formatted = 'iOS';\n break;\n case 'android':\n formatted = 'Android';\n break;\n case 'web':\n formatted = 'Web';\n break;\n case 'dom':\n formatted = 'DOM';\n break;\n default:\n formatted = platform;\n }\n return `${chalk.bold(formatted)} `;\n }\n\n return '';\n}\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getEnvironmentForBuildDetails(bundleDetails?: BundleDetails | null): string {\n // Expo CLI will pass `customTransformOptions.environment = 'node'` when bundling for the server.\n const env = bundleDetails?.customTransformOptions?.environment ?? null;\n if (env === 'node') {\n return chalk.bold('λ') + ' ';\n } else if (env === 'react-server') {\n return chalk.bold(`RSC(${getPlatformTagForBuildDetails(bundleDetails).trim()})`) + ' ';\n }\n\n if (\n bundleDetails?.customTransformOptions?.dom &&\n typeof bundleDetails?.customTransformOptions?.dom === 'string'\n ) {\n return chalk.bold(`DOM`) + ' ';\n }\n\n return '';\n}\n"],"names":["MetroTerminalReporter","event","extractCodeFrame","formatUsingNodeStandardLibraryError","isNodeStdLibraryModule","stripMetroInfo","debug","require","events","t","MAX_PROGRESS_BAR_CHAR_WIDTH","DARK_BLOCK_CHAR","LIGHT_BLOCK_CHAR","TerminalReporter","serverRoot","terminal","_getStatusMessage","isInteractive","_log","type","data","message","match","env","EXPO_DEBUG","shouldFilterClientLog","level","_getElapsedTime","startTime","process","hrtime","bigint","_getBundleStatusMessage","progress","phase","getEnvironmentForBuildDetails","bundleDetails","platform","getPlatformTagForBuildDetails","inProgress","localPath","customTransformOptions","dom","includes","path","sep","replace","entryFile","status","color","chalk","green","red","_bundleTimers","get","buildID","time","ms","elapsed","micro","Number","tenthFractionOfMicro","toFixed","cyan","bold","dim","id","total","totalFileCount","plural","reset","ratio","current","transformedFileCount","shouldReduceLogs","filledBar","Math","floor","_progress","bgGreen","repeat","bgWhite","white","padStart","toString","length","dirname","basename","_logInitializing","port","hasReducedPerformance","log","isAppRegistryStartupMessage","shouldFilterBundleEvent","bundleType","transformCacheReset","logWarning","dependencyGraphLoading","join","_logBundleBuildFailed","_logBundlingError","error","importStack","nearestImportStack","moduleResolutionError","maybeAppendCodeFrame","stripAnsi","filename","targetModuleName","originModulePath","attachImportStackToRootMessage","snippet","stack","SyntaxError","evt","applyConsoleFormatting","platformTag","getPlatformTagForClientLog","mode","hasStack","parsed","map","msg","parseErrorStringToObject","symbolicating","p","maybeSymbolicateAndFormatJSErrorStackLogAsync","usefulStackCount","fallbackIndices","symbolicated","Promise","allSettled","s","index","reason","value","isFallback","push","filtered","filter","_","logLikeMetro","bind","entry","environment","dest","isAbsolute","relative","relativePath","DOCS_PAGE_URL","learnMore","moduleName","test","NODE_STDLIB_MODULES","rawMessage","codeFrame","errorMessage","codeFrameLine","wasPreviousLineCodeFrame","split","line","keep","stripVTControlCharacters","lines","findIndex","slice","body","utilFormat","formatted","trim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/server/metro/MetroTerminalReporter.ts"],"sourcesContent":["import type { Terminal } from '@expo/metro/metro-core';\nimport chalk from 'chalk';\nimport path from 'path';\nimport { format as utilFormat, stripVTControlCharacters } from 'util';\n\nimport { logWarning, TerminalReporter } from './TerminalReporter';\nimport type {\n BuildPhase,\n BundleDetails,\n BundleProgress,\n SnippetError,\n TerminalReportableEvent,\n} from './TerminalReporter.types';\nimport { NODE_STDLIB_MODULES } from './externals';\nimport { env } from '../../../utils/env';\nimport { learnMore } from '../../../utils/link';\nimport {\n logLikeMetro,\n maybeSymbolicateAndFormatJSErrorStackLogAsync,\n parseErrorStringToObject,\n} from '../serverLogLikeMetro';\nimport { attachImportStackToRootMessage, nearestImportStack } from './metroErrorInterface';\nimport { events, shouldReduceLogs } from '../../../events';\nimport { stripAnsi } from '../../../utils/ansi';\nimport { isInteractive } from '../../../utils/interactive';\n\ntype ClientLogLevel =\n | 'trace'\n | 'info'\n | 'error'\n | 'warn'\n | 'log'\n | 'group'\n | 'groupCollapsed'\n | 'groupEnd'\n | 'debug';\n\nconst debug = require('debug')('expo:metro:logger') as typeof console.log;\n\n// prettier-ignore\nexport const event = events('metro', (t) => [\n t.event<'bundling:started', {\n id: string;\n platform: null | string;\n environment: null | string;\n entry: string;\n }>(),\n t.event<'bundling:done', {\n id: string | null;\n ms: number | null;\n total: number;\n }>(),\n t.event<'bundling:failed', {\n id: string | null;\n filename: string | null;\n message: string | null;\n importStack: string | null;\n targetModuleName: string | null;\n originModulePath: string | null;\n }>(),\n t.event<'bundling:progress', {\n id: string | null;\n progress: number;\n current: number;\n total: number;\n }>(),\n t.event<'server_log', {\n level: 'info' | 'warn' | 'error' | null;\n data: string | unknown[] | null;\n }>(),\n t.event<'client_log', {\n level: ClientLogLevel | null;\n data: unknown[] | null;\n }>(),\n t.event<'hmr_client_error', {\n message: string;\n }>(),\n t.event<'cache_write_error', {\n message: string;\n }>(),\n t.event<'cache_read_error', {\n message: string;\n }>(),\n]);\n\nconst MAX_PROGRESS_BAR_CHAR_WIDTH = 16;\nconst DARK_BLOCK_CHAR = '\\u2593';\nconst LIGHT_BLOCK_CHAR = '\\u2591';\n/**\n * Extends the default Metro logger and adds some additional features.\n * Also removes the giant Metro logo from the output.\n */\nexport class MetroTerminalReporter extends TerminalReporter {\n #lastFailedBuildID: string | undefined;\n\n constructor(\n public serverRoot: string,\n terminal: Terminal\n ) {\n super(terminal);\n }\n\n /**\n * Suppress status messages in non-interactive mode.\n * In TTY mode, Terminal overwrites status lines in-place (progress bars).\n * In non-TTY mode, Terminal writes status via a 3500ms throttle, producing\n * permanent output that interleaves with log messages like \"Bundled Xms\".\n */\n _getStatusMessage(): string {\n if (!isInteractive()) {\n return '';\n }\n return super._getStatusMessage();\n }\n\n _log(event: TerminalReportableEvent): void {\n this.#captureLog(event);\n switch (event.type) {\n case 'unstable_server_log':\n if (typeof event.data?.[0] === 'string') {\n const message = event.data[0];\n if (message.match(/JavaScript logs have moved/)) {\n // Hide this very loud message from upstream React Native in favor of the note in the terminal UI:\n // The \"› Press j │ open debugger\"\n\n // logger?.info(\n // '\\u001B[1m\\u001B[7m💡 JavaScript logs have moved!\\u001B[22m They can now be ' +\n // 'viewed in React Native DevTools. Tip: Type \\u001B[1mj\\u001B[22m in ' +\n // 'the terminal to open (requires Google Chrome or Microsoft Edge).' +\n // '\\u001B[27m',\n // );\n return;\n }\n\n if (!env.EXPO_DEBUG) {\n // In the context of developing an iOS app or website, the MetroInspectorProxy \"connection\" logs are very confusing.\n // Here we'll hide them behind EXPO_DEBUG or DEBUG=expo:*. In the future we can reformat them to clearly indicate that the \"Connection\" is regarding the debugger.\n // These logs are also confusing because they can say \"connection established\" even when the debugger is not in a usable state. Really they belong in a UI or behind some sort of debug logging.\n if (message.match(/Connection (closed|established|failed|terminated)/i)) {\n // Skip logging.\n return;\n }\n }\n }\n break;\n case 'client_log': {\n if (this.shouldFilterClientLog(event)) {\n return;\n } else if (event.level != null) {\n return this.#onClientLog(event);\n } else {\n break;\n }\n }\n }\n return super._log(event);\n }\n\n // Used for testing\n _getElapsedTime(startTime: bigint): bigint {\n return process.hrtime.bigint() - startTime;\n }\n /**\n * Extends the bundle progress to include the current platform that we're bundling.\n *\n * @returns `iOS path/to/bundle.js ▓▓▓▓▓░░░░░░░░░░░ 36.6% (4790/7922)`\n */\n _getBundleStatusMessage(progress: BundleProgress, phase: BuildPhase): string {\n const env = getEnvironmentForBuildDetails(progress.bundleDetails);\n const platform = env || getPlatformTagForBuildDetails(progress.bundleDetails);\n const inProgress = phase === 'in_progress';\n\n const localPath =\n typeof progress.bundleDetails?.customTransformOptions?.dom === 'string' &&\n progress.bundleDetails.customTransformOptions.dom.includes(path.sep)\n ? progress.bundleDetails.customTransformOptions.dom.replace(/^(\\.?\\.[\\\\/])+/, '')\n : this.#normalizePath(progress.bundleDetails.entryFile);\n\n if (!inProgress) {\n const status = phase === 'done' ? `Bundled ` : `Bundling failed `;\n const color = phase === 'done' ? chalk.green : chalk.red;\n\n const startTime = this._bundleTimers.get(progress.bundleDetails.buildID!);\n\n let time: string = '';\n let ms: number | null = null;\n\n if (startTime != null) {\n const elapsed: bigint = this._getElapsedTime(startTime);\n const micro = Number(elapsed) / 1000;\n ms = Number(elapsed) / 1e6;\n // If the milliseconds are < 0.5 then it will display as 0, so we display in microseconds.\n if (ms <= 0.5) {\n const tenthFractionOfMicro = ((micro * 10) / 1000).toFixed(0);\n // Format as microseconds to nearest tenth\n time = chalk.cyan.bold(`0.${tenthFractionOfMicro}ms`);\n } else {\n time = chalk.dim(ms.toFixed(0) + 'ms');\n }\n }\n\n if (phase === 'done') {\n event('bundling:done', {\n id: progress.bundleDetails.buildID ?? null,\n total: progress.totalFileCount,\n ms,\n });\n }\n\n // iOS Bundled 150ms\n const plural = progress.totalFileCount === 1 ? '' : 's';\n return (\n color(platform + status) +\n time +\n chalk.reset.dim(` ${localPath} (${progress.totalFileCount} module${plural})`)\n );\n }\n\n event('bundling:progress', {\n id: progress.bundleDetails.buildID ?? null,\n progress: progress.ratio,\n total: progress.totalFileCount,\n current: progress.transformedFileCount,\n });\n if (shouldReduceLogs()) {\n return '';\n }\n\n const filledBar = Math.floor(progress.ratio * MAX_PROGRESS_BAR_CHAR_WIDTH);\n const _progress = inProgress\n ? chalk.green.bgGreen(DARK_BLOCK_CHAR.repeat(filledBar)) +\n chalk.bgWhite.white(LIGHT_BLOCK_CHAR.repeat(MAX_PROGRESS_BAR_CHAR_WIDTH - filledBar)) +\n chalk.bold(` ${(100 * progress.ratio).toFixed(1).padStart(4)}% `) +\n chalk.dim(\n `(${progress.transformedFileCount\n .toString()\n .padStart(progress.totalFileCount.toString().length)}/${progress.totalFileCount})`\n )\n : '';\n return (\n platform +\n chalk.reset.dim(`${path.dirname(localPath)}${path.sep}`) +\n chalk.bold(path.basename(localPath)) +\n ' ' +\n _progress\n );\n }\n\n _logInitializing(port: number, hasReducedPerformance: boolean): void {\n // Don't print a giant logo...\n if (!shouldReduceLogs()) {\n this.terminal.log(chalk.dim('Starting Metro Bundler') + '\\n');\n }\n }\n\n shouldFilterClientLog(event: { type: 'client_log'; data: unknown[] }): boolean {\n return isAppRegistryStartupMessage(event.data);\n }\n\n shouldFilterBundleEvent(event: TerminalReportableEvent): boolean {\n return 'bundleDetails' in event && event.bundleDetails?.bundleType === 'map';\n }\n\n /** Print the cache clear message. */\n transformCacheReset(): void {\n logWarning(\n this.terminal,\n chalk`Bundler cache is empty, rebuilding {dim (this may take a minute)}`\n );\n }\n\n /** One of the first logs that will be printed */\n dependencyGraphLoading(hasReducedPerformance: boolean): void {\n // this.terminal.log('Dependency graph is loading...');\n if (hasReducedPerformance) {\n // Extends https://github.com/facebook/metro/blob/347b1d7ed87995d7951aaa9fd597c04b06013dac/packages/metro/src/lib/TerminalReporter.js#L283-L290\n this.terminal.log(\n chalk.red(\n [\n 'Metro is operating with reduced performance.',\n 'Fix the problem above and restart Metro.',\n ].join('\\n')\n )\n );\n }\n }\n\n /**\n * Workaround to link build ids to bundling errors.\n * This works because `_logBundleBuildFailed` is called before `_logBundlingError` in synchronous manner.\n * https://github.com/facebook/metro/blob/main/packages/metro/src/Server.js#L939-L945\n */\n _logBundleBuildFailed(buildID: string): void {\n this.#lastFailedBuildID = buildID;\n super._logBundleBuildFailed(buildID);\n }\n\n _logBundlingError(error: SnippetError): void {\n const importStack = nearestImportStack(error);\n const moduleResolutionError = formatUsingNodeStandardLibraryError(this.serverRoot, error);\n\n if (moduleResolutionError) {\n const message = maybeAppendCodeFrame(moduleResolutionError, error.message);\n event('bundling:failed', {\n id: this.#lastFailedBuildID ?? null,\n message: stripAnsi(message) ?? null,\n importStack: importStack ?? null,\n filename: error.filename ?? null,\n targetModuleName: this.#normalizePath(error.targetModuleName),\n originModulePath: this.#normalizePath(error.originModulePath),\n });\n\n return this.terminal.log(importStack ? `${message}\\n\\n${importStack}` : message);\n } else {\n event('bundling:failed', {\n id: this.#lastFailedBuildID ?? null,\n message: stripAnsi(error.message) ?? null,\n importStack: importStack ?? null,\n filename: error.filename ?? null,\n targetModuleName: error.targetModuleName ?? null,\n originModulePath: error.originModulePath ?? null,\n });\n\n attachImportStackToRootMessage(error, importStack);\n\n // NOTE(@kitten): Metro drops the stack forcefully when it finds a `SyntaxError`. However,\n // this is really unhelpful, since it prevents debugging Babel plugins or reporting bugs\n // in Babel plugins or a transformer entirely\n if (error.snippet == null && error.stack != null && error instanceof SyntaxError) {\n error.message = error.stack;\n delete error.stack;\n }\n\n return super._logBundlingError(error);\n }\n }\n\n #onClientLog(evt: {\n type: 'client_log';\n level?: ClientLogLevel;\n data: unknown[];\n mode?: string;\n }) {\n const { level = 'log' } = evt;\n // Apply printf-style format substitution (e.g. %s, %d) that browsers handle\n // natively in console methods but Node/Metro terminal logging does not.\n const data = applyConsoleFormatting(evt.data);\n const platformTag = getPlatformTagForClientLog(evt.mode);\n if (level === 'warn' || (level as string) === 'error') {\n let hasStack = false;\n const parsed = data.map((msg) => {\n // Quick check to see if an unsymbolicated stack is being logged.\n if (\n typeof msg === 'string' &&\n // Native stack frames use `.bundle//&platform=...`; web stack frames use `.bundle?platform=...`.\n (msg.includes('.bundle//&platform=') || msg.includes('.bundle?platform='))\n ) {\n const stack = parseErrorStringToObject(msg);\n if (stack) {\n hasStack = true;\n }\n return stack;\n }\n return msg;\n });\n\n if (hasStack) {\n (async () => {\n const symbolicating = parsed.map((p) => {\n if (typeof p === 'string') {\n return p;\n } else if (\n p &&\n typeof p === 'object' &&\n 'message' in p &&\n typeof p.message === 'string'\n ) {\n return maybeSymbolicateAndFormatJSErrorStackLogAsync(\n this.serverRoot,\n level,\n p as any\n );\n } else {\n return null;\n }\n });\n\n let usefulStackCount = 0;\n const fallbackIndices: number[] = [];\n const symbolicated = (await Promise.allSettled(symbolicating)).map((s, index) => {\n if (s.status === 'rejected') {\n debug('Error formatting stack', parsed[index], s.reason);\n return parsed[index];\n } else if (!s.value) {\n return parsed[index];\n } else if (typeof s.value === 'string') {\n return s.value;\n } else {\n if (!s.value.isFallback) {\n usefulStackCount++;\n } else {\n fallbackIndices.push(index);\n }\n return s.value.stack;\n }\n });\n\n // Using EXPO_DEBUG we can print all stack\n const filtered =\n usefulStackCount && !env.EXPO_DEBUG\n ? symbolicated.filter((_, index) => !fallbackIndices.includes(index))\n : symbolicated;\n\n event('client_log', { level, data: symbolicated });\n logLikeMetro(this.terminal.log.bind(this.terminal), level, platformTag, ...filtered);\n })();\n return;\n }\n }\n\n event('client_log', { level, data });\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, platformTag, ...data);\n }\n\n #captureLog(evt: TerminalReportableEvent) {\n switch (evt.type) {\n case 'bundle_build_started': {\n const entry =\n typeof evt.bundleDetails?.customTransformOptions?.dom === 'string' &&\n evt.bundleDetails.customTransformOptions.dom.includes(path.sep)\n ? evt.bundleDetails.customTransformOptions.dom.replace(/^(\\.?\\.[\\\\/])+/, '')\n : this.#normalizePath(evt.bundleDetails.entryFile);\n return event('bundling:started', {\n id: evt.buildID,\n platform: evt.bundleDetails.platform ?? null,\n environment: evt.bundleDetails.customTransformOptions?.environment ?? null,\n entry,\n });\n }\n case 'unstable_server_log':\n return event('server_log', {\n level: evt.level ?? null,\n data: evt.data ?? null,\n });\n case 'client_log':\n // Handled separately: see this.#onClientLog\n return;\n case 'hmr_client_error':\n case 'cache_write_error':\n case 'cache_read_error':\n return event(evt.type, {\n message: evt.error.message,\n });\n }\n }\n\n #normalizePath<T extends string | null>(dest: T | undefined): T | string {\n return dest != null && path.isAbsolute(dest)\n ? path.relative(this.serverRoot, dest)\n : ((dest || null) as T);\n }\n}\n\n/**\n * Formats an error where the user is attempting to import a module from the Node.js standard library.\n * Exposed for testing.\n *\n * @param error\n * @returns error message or null if not a module resolution error\n */\nexport function formatUsingNodeStandardLibraryError(\n serverRoot: string,\n error: SnippetError\n): string | null {\n if (!error.message) {\n return null;\n }\n const { targetModuleName, originModulePath } = error;\n if (!targetModuleName || !originModulePath) {\n return null;\n }\n const relativePath = path.relative(serverRoot, originModulePath);\n\n const DOCS_PAGE_URL =\n 'https://docs.expo.dev/workflow/using-libraries/#using-third-party-libraries';\n\n if (isNodeStdLibraryModule(targetModuleName)) {\n if (originModulePath.includes('node_modules')) {\n return [\n `The package at \"${chalk.bold(\n relativePath\n )}\" attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n } else {\n return [\n `You attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\" from \"${chalk.bold(relativePath)}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n }\n }\n return `Unable to resolve \"${targetModuleName}\" from \"${relativePath}\"`;\n}\n\nexport function isNodeStdLibraryModule(moduleName: string): boolean {\n return /^node:/.test(moduleName) || NODE_STDLIB_MODULES.includes(moduleName);\n}\n\n/** If the code frame can be found then append it to the existing message. */\nfunction maybeAppendCodeFrame(message: string, rawMessage: string): string {\n const codeFrame = extractCodeFrame(stripMetroInfo(rawMessage));\n if (codeFrame) {\n message += '\\n' + codeFrame;\n }\n return message;\n}\n\n/** Extract fist code frame presented in the error message */\nexport function extractCodeFrame(errorMessage: string): string {\n const codeFrameLine = /^(?:\\s*(?:>?\\s*\\d+\\s*\\||\\s*\\|).*\\n?)+/;\n let wasPreviousLineCodeFrame: boolean | null = null;\n return errorMessage\n .split('\\n')\n .filter((line) => {\n if (wasPreviousLineCodeFrame === false) return false;\n const keep = codeFrameLine.test(stripVTControlCharacters(line));\n if (keep && wasPreviousLineCodeFrame === null) wasPreviousLineCodeFrame = true;\n else if (!keep && wasPreviousLineCodeFrame) wasPreviousLineCodeFrame = false;\n return keep;\n })\n .join('\\n');\n}\n\n/**\n * Remove the Metro cache clearing steps if they exist.\n * In future versions we won't need this.\n * Returns the remaining code frame logs.\n */\nexport function stripMetroInfo(errorMessage: string): string {\n // Newer versions of Metro don't include the list.\n if (!errorMessage.includes('4. Remove the cache')) {\n return errorMessage;\n }\n const lines = errorMessage.split('\\n');\n const index = lines.findIndex((line) => line.includes('4. Remove the cache'));\n if (index === -1) {\n return errorMessage;\n }\n return lines.slice(index + 1).join('\\n');\n}\n\n/** @returns if the message matches the initial startup log */\nfunction isAppRegistryStartupMessage(body: any[]): boolean {\n return (\n body.length === 1 &&\n (/^Running application \"main\" with appParams:/.test(body[0]) ||\n /^Running \"main\" with \\{/.test(body[0]))\n );\n}\n\n/** Apply printf-style format substitutions (%s, %d, %i, %f, %o, %O) that browsers handle natively */\nfunction applyConsoleFormatting(data: unknown[]): unknown[] {\n if (data.length <= 1 || typeof data[0] !== 'string' || !/%[sdifoO%]/.test(data[0])) {\n return data;\n }\n return [utilFormat(...(data as [string, ...unknown[]]))];\n}\n\n/** @returns formatted platform name for a client log event, or null if no prefix should be shown */\nfunction getPlatformTagForClientLog(mode?: string): string | null {\n switch (mode) {\n case 'ios':\n return 'iOS';\n case 'android':\n return 'Android';\n case 'web':\n return 'Web';\n case 'dom':\n return 'DOM';\n default:\n return null;\n }\n}\n\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getPlatformTagForBuildDetails(bundleDetails?: BundleDetails | null): string {\n const platform = bundleDetails?.platform ?? null;\n if (platform) {\n let formatted: string;\n switch (platform) {\n case 'ios':\n formatted = 'iOS';\n break;\n case 'android':\n formatted = 'Android';\n break;\n case 'web':\n formatted = 'Web';\n break;\n case 'dom':\n formatted = 'DOM';\n break;\n default:\n formatted = platform;\n }\n return `${chalk.bold(formatted)} `;\n }\n\n return '';\n}\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getEnvironmentForBuildDetails(bundleDetails?: BundleDetails | null): string {\n // Expo CLI will pass `customTransformOptions.environment = 'node'` when bundling for the server.\n const env = bundleDetails?.customTransformOptions?.environment ?? null;\n if (env === 'node') {\n return chalk.bold('λ') + ' ';\n } else if (env === 'react-server') {\n return chalk.bold(`RSC(${getPlatformTagForBuildDetails(bundleDetails).trim()})`) + ' ';\n }\n\n if (\n bundleDetails?.customTransformOptions?.dom &&\n typeof bundleDetails?.customTransformOptions?.dom === 'string'\n ) {\n return chalk.bold(`DOM`) + ' ';\n }\n\n return '';\n}\n"],"names":["MetroTerminalReporter","event","extractCodeFrame","formatUsingNodeStandardLibraryError","isNodeStdLibraryModule","stripMetroInfo","debug","require","events","t","MAX_PROGRESS_BAR_CHAR_WIDTH","DARK_BLOCK_CHAR","LIGHT_BLOCK_CHAR","TerminalReporter","serverRoot","terminal","_getStatusMessage","isInteractive","_log","type","data","message","match","env","EXPO_DEBUG","shouldFilterClientLog","level","_getElapsedTime","startTime","process","hrtime","bigint","_getBundleStatusMessage","progress","phase","getEnvironmentForBuildDetails","bundleDetails","platform","getPlatformTagForBuildDetails","inProgress","localPath","customTransformOptions","dom","includes","path","sep","replace","entryFile","status","color","chalk","green","red","_bundleTimers","get","buildID","time","ms","elapsed","micro","Number","tenthFractionOfMicro","toFixed","cyan","bold","dim","id","total","totalFileCount","plural","reset","ratio","current","transformedFileCount","shouldReduceLogs","filledBar","Math","floor","_progress","bgGreen","repeat","bgWhite","white","padStart","toString","length","dirname","basename","_logInitializing","port","hasReducedPerformance","log","isAppRegistryStartupMessage","shouldFilterBundleEvent","bundleType","transformCacheReset","logWarning","dependencyGraphLoading","join","_logBundleBuildFailed","_logBundlingError","error","importStack","nearestImportStack","moduleResolutionError","maybeAppendCodeFrame","stripAnsi","filename","targetModuleName","originModulePath","attachImportStackToRootMessage","snippet","stack","SyntaxError","evt","applyConsoleFormatting","platformTag","getPlatformTagForClientLog","mode","hasStack","parsed","map","msg","parseErrorStringToObject","symbolicating","p","maybeSymbolicateAndFormatJSErrorStackLogAsync","usefulStackCount","fallbackIndices","symbolicated","Promise","allSettled","s","index","reason","value","isFallback","push","filtered","filter","_","logLikeMetro","bind","entry","environment","dest","isAbsolute","relative","relativePath","DOCS_PAGE_URL","learnMore","moduleName","test","NODE_STDLIB_MODULES","rawMessage","codeFrame","errorMessage","codeFrameLine","wasPreviousLineCodeFrame","split","line","keep","stripVTControlCharacters","lines","findIndex","slice","body","utilFormat","formatted","trim"],"mappings":"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"}
@@ -73,9 +73,18 @@ function htmlFromSerialAssets(assets, { isExporting, template, baseUrl, bundleUr
73
73
  if ((route == null ? void 0 : route.entryPoints) && Array.isArray(route.entryPoints)) {
74
74
  const syncAssets = orderedJsAssets.filter((a)=>!a.metadata.isAsync);
75
75
  const sortedAsync = sortMatchedAssetsByEntryPoints(orderedJsAssets.filter((a)=>a.metadata.isAsync), route.entryPoints);
76
+ const runtimeAssets = syncAssets.filter((a)=>{
77
+ var _a_metadata_requires;
78
+ return !((_a_metadata_requires = a.metadata.requires) == null ? void 0 : _a_metadata_requires.length);
79
+ });
80
+ const entryAssets = syncAssets.filter((a)=>{
81
+ var _a_metadata_requires;
82
+ return !!((_a_metadata_requires = a.metadata.requires) == null ? void 0 : _a_metadata_requires.length);
83
+ });
76
84
  orderedJsAssets = [
77
- ...syncAssets,
78
- ...sortedAsync
85
+ ...runtimeAssets,
86
+ ...sortedAsync,
87
+ ...entryAssets
79
88
  ];
80
89
  }
81
90
  const scripts = bundleUrl ? `<script src="${bundleUrl}" defer></script>` : orderedJsAssets.map(({ filename, metadata })=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/server/metro/serializeHtml.ts"],"sourcesContent":["import type { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport {\n createInjectedCssAsString,\n createInjectedScriptsAsString,\n getHydrationFlagScriptAsString,\n} from '@expo/router-server/build/utils/html';\nimport type { RouteNode } from 'expo-router/build/Route';\n\nconst debug = require('debug')('expo:metro:html') as typeof console.log;\n\nexport function serializeHtmlWithAssets({\n resources,\n template,\n devBundleUrl,\n baseUrl,\n route,\n isExporting,\n hydrate,\n}: {\n resources: SerialAsset[];\n template: string;\n /** asset prefix used for deploying to non-standard origins like GitHub pages. */\n baseUrl: string;\n devBundleUrl?: string;\n route?: RouteNode;\n isExporting: boolean;\n hydrate?: boolean;\n}): string {\n if (!resources) {\n return '';\n }\n return htmlFromSerialAssets(resources, {\n isExporting,\n template,\n baseUrl,\n bundleUrl: isExporting ? undefined : devBundleUrl,\n route,\n hydrate,\n });\n}\n\n/**\n * Combine the path segments of a URL.\n * This filters out empty segments and avoids duplicate slashes when joining.\n * If base url is empty, it will be treated as a root path, adding `/` to the beginning.\n */\nfunction combineUrlPath(baseUrl: string, ...segments: string[]) {\n return [baseUrl || '/', ...segments]\n .filter(Boolean)\n .map((segment, index) => {\n const segmentIsBaseUrl = index === 0;\n // Do not remove leading slashes from baseUrl\n return segment.replace(segmentIsBaseUrl ? /\\/+$/g : /^\\/+|\\/+$/g, '');\n })\n .join('/');\n}\n\nfunction htmlFromSerialAssets(\n assets: SerialAsset[],\n {\n isExporting,\n template,\n baseUrl,\n bundleUrl,\n route,\n hydrate,\n }: {\n isExporting: boolean;\n template: string;\n baseUrl: string;\n /** This is dev-only. */\n bundleUrl?: string;\n route?: RouteNode;\n hydrate?: boolean;\n }\n) {\n // Combine the CSS modules into tags that have hot refresh data attributes.\n const styleString = assets\n .filter((asset) => asset.type.startsWith('css'))\n .map(({ type, metadata, filename, source }) => {\n if (type === 'css') {\n if (isExporting) {\n return createInjectedCssAsString([combineUrlPath(baseUrl, filename)]);\n } else {\n return `<style data-expo-css-hmr=\"${metadata.hmrId}\">` + source + '\\n</style>';\n }\n }\n // External link tags will be passed through as-is.\n return source;\n })\n .join('');\n\n let orderedJsAssets = assetsRequiresSort(assets.filter((asset) => asset.type === 'js'));\n\n if (route?.entryPoints && Array.isArray(route.entryPoints)) {\n const syncAssets = orderedJsAssets.filter((a) => !a.metadata.isAsync);\n const sortedAsync = sortMatchedAssetsByEntryPoints(\n orderedJsAssets.filter((a) => a.metadata.isAsync),\n route.entryPoints\n );\n orderedJsAssets = [...syncAssets, ...sortedAsync];\n }\n\n const scripts = bundleUrl\n ? `<script src=\"${bundleUrl}\" defer></script>`\n : orderedJsAssets\n .map(({ filename, metadata }) => {\n // TODO: Mark dependencies of the HTML and include them to prevent waterfalls.\n if (metadata.isAsync) {\n // We have the data required to match async chunks to the route's HTML file.\n if (\n route?.entryPoints &&\n metadata.modulePaths &&\n Array.isArray(route.entryPoints) &&\n Array.isArray(metadata.modulePaths)\n ) {\n // TODO: Handle module IDs like `expo-router/build/views/Unmatched.js`\n const doesAsyncChunkContainRouteEntryPoint = route.entryPoints.some((entryPoint) =>\n (metadata.modulePaths as string[]).includes(entryPoint)\n );\n if (!doesAsyncChunkContainRouteEntryPoint) {\n return '';\n }\n debug('Linking async chunk %s to HTML for route %s', filename, route.contextKey);\n // Pass through to the next condition.\n } else {\n return '';\n }\n // Mark async chunks as defer so they don't block the page load.\n // return `<script src=\"${combineUrlPath(baseUrl, filename)\" defer></script>`;\n }\n\n return createInjectedScriptsAsString([combineUrlPath(baseUrl, filename)]);\n })\n .join('');\n\n if (hydrate) {\n template = template.replace('</head>', `${getHydrationFlagScriptAsString()}</head>`);\n }\n\n return template\n .replace('</head>', `${styleString}</head>`)\n .replace('</body>', `${scripts}\\n</body>`);\n}\n\n/**\n * Sorts matched async assets by their matching `entryPoint` in the route's `entryPoints` array.\n * This ensures layout chunks come before page chunks.\n */\nexport function sortMatchedAssetsByEntryPoints(\n matchedAssets: SerialAsset[],\n entryPoints: string[]\n): SerialAsset[] {\n const getEntryPointIndex = (modulePaths?: string[]) =>\n modulePaths ? entryPoints.findIndex((ep) => modulePaths.includes(ep)) : -1;\n\n return matchedAssets.sort(\n (a, b) =>\n getEntryPointIndex(a.metadata.modulePaths) - getEntryPointIndex(b.metadata.modulePaths)\n );\n}\n\n/**\n * Sorts assets based on the requires tree. DFS order.\n */\nexport function assetsRequiresSort(assets: SerialAsset[]): SerialAsset[] {\n const lookup = new Map<string, SerialAsset>();\n const visited = new Set();\n const visiting = new Set();\n const result: SerialAsset[] = [];\n\n assets.forEach((a) => {\n lookup.set(a.filename, a);\n });\n\n function visit(name: string) {\n if (visited.has(name)) return;\n if (visiting.has(name))\n throw new Error(\n `Circular dependencies in assets are not allowed. Found cycle: ${[...visiting, name].join(' -> ')}`\n );\n\n visiting.add(name);\n\n const module = lookup.get(name);\n if (!module) throw new Error(`Asset not found: ${name}`);\n\n module.metadata.requires?.forEach((dependency) => {\n visit(dependency);\n });\n\n visiting.delete(name);\n visited.add(name);\n result.push(module);\n }\n\n assets.forEach((a) => {\n if (!visited.has(a.filename)) {\n visit(a.filename);\n }\n });\n\n return result;\n}\n"],"names":["assetsRequiresSort","serializeHtmlWithAssets","sortMatchedAssetsByEntryPoints","debug","require","resources","template","devBundleUrl","baseUrl","route","isExporting","hydrate","htmlFromSerialAssets","bundleUrl","undefined","combineUrlPath","segments","filter","Boolean","map","segment","index","segmentIsBaseUrl","replace","join","assets","styleString","asset","type","startsWith","metadata","filename","source","createInjectedCssAsString","hmrId","orderedJsAssets","entryPoints","Array","isArray","syncAssets","a","isAsync","sortedAsync","scripts","modulePaths","doesAsyncChunkContainRouteEntryPoint","some","entryPoint","includes","contextKey","createInjectedScriptsAsString","getHydrationFlagScriptAsString","matchedAssets","getEntryPointIndex","findIndex","ep","sort","b","lookup","Map","visited","Set","visiting","result","forEach","set","visit","name","module","has","Error","add","get","requires","dependency","delete","push"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/server/metro/serializeHtml.ts"],"sourcesContent":["import type { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport {\n createInjectedCssAsString,\n createInjectedScriptsAsString,\n getHydrationFlagScriptAsString,\n} from '@expo/router-server/build/utils/html';\nimport type { RouteNode } from 'expo-router/build/Route';\n\nconst debug = require('debug')('expo:metro:html') as typeof console.log;\n\nexport function serializeHtmlWithAssets({\n resources,\n template,\n devBundleUrl,\n baseUrl,\n route,\n isExporting,\n hydrate,\n}: {\n resources: SerialAsset[];\n template: string;\n /** asset prefix used for deploying to non-standard origins like GitHub pages. */\n baseUrl: string;\n devBundleUrl?: string;\n route?: RouteNode;\n isExporting: boolean;\n hydrate?: boolean;\n}): string {\n if (!resources) {\n return '';\n }\n return htmlFromSerialAssets(resources, {\n isExporting,\n template,\n baseUrl,\n bundleUrl: isExporting ? undefined : devBundleUrl,\n route,\n hydrate,\n });\n}\n\n/**\n * Combine the path segments of a URL.\n * This filters out empty segments and avoids duplicate slashes when joining.\n * If base url is empty, it will be treated as a root path, adding `/` to the beginning.\n */\nfunction combineUrlPath(baseUrl: string, ...segments: string[]) {\n return [baseUrl || '/', ...segments]\n .filter(Boolean)\n .map((segment, index) => {\n const segmentIsBaseUrl = index === 0;\n // Do not remove leading slashes from baseUrl\n return segment.replace(segmentIsBaseUrl ? /\\/+$/g : /^\\/+|\\/+$/g, '');\n })\n .join('/');\n}\n\nfunction htmlFromSerialAssets(\n assets: SerialAsset[],\n {\n isExporting,\n template,\n baseUrl,\n bundleUrl,\n route,\n hydrate,\n }: {\n isExporting: boolean;\n template: string;\n baseUrl: string;\n /** This is dev-only. */\n bundleUrl?: string;\n route?: RouteNode;\n hydrate?: boolean;\n }\n) {\n // Combine the CSS modules into tags that have hot refresh data attributes.\n const styleString = assets\n .filter((asset) => asset.type.startsWith('css'))\n .map(({ type, metadata, filename, source }) => {\n if (type === 'css') {\n if (isExporting) {\n return createInjectedCssAsString([combineUrlPath(baseUrl, filename)]);\n } else {\n return `<style data-expo-css-hmr=\"${metadata.hmrId}\">` + source + '\\n</style>';\n }\n }\n // External link tags will be passed through as-is.\n return source;\n })\n .join('');\n\n let orderedJsAssets = assetsRequiresSort(assets.filter((asset) => asset.type === 'js'));\n\n if (route?.entryPoints && Array.isArray(route.entryPoints)) {\n const syncAssets = orderedJsAssets.filter((a) => !a.metadata.isAsync);\n const sortedAsync = sortMatchedAssetsByEntryPoints(\n orderedJsAssets.filter((a) => a.metadata.isAsync),\n route.entryPoints\n );\n const runtimeAssets = syncAssets.filter((a) => !a.metadata.requires?.length);\n const entryAssets = syncAssets.filter((a) => !!a.metadata.requires?.length);\n orderedJsAssets = [...runtimeAssets, ...sortedAsync, ...entryAssets];\n }\n\n const scripts = bundleUrl\n ? `<script src=\"${bundleUrl}\" defer></script>`\n : orderedJsAssets\n .map(({ filename, metadata }) => {\n // TODO: Mark dependencies of the HTML and include them to prevent waterfalls.\n if (metadata.isAsync) {\n // We have the data required to match async chunks to the route's HTML file.\n if (\n route?.entryPoints &&\n metadata.modulePaths &&\n Array.isArray(route.entryPoints) &&\n Array.isArray(metadata.modulePaths)\n ) {\n // TODO: Handle module IDs like `expo-router/build/views/Unmatched.js`\n const doesAsyncChunkContainRouteEntryPoint = route.entryPoints.some((entryPoint) =>\n (metadata.modulePaths as string[]).includes(entryPoint)\n );\n if (!doesAsyncChunkContainRouteEntryPoint) {\n return '';\n }\n debug('Linking async chunk %s to HTML for route %s', filename, route.contextKey);\n // Pass through to the next condition.\n } else {\n return '';\n }\n // Mark async chunks as defer so they don't block the page load.\n // return `<script src=\"${combineUrlPath(baseUrl, filename)\" defer></script>`;\n }\n\n return createInjectedScriptsAsString([combineUrlPath(baseUrl, filename)]);\n })\n .join('');\n\n if (hydrate) {\n template = template.replace('</head>', `${getHydrationFlagScriptAsString()}</head>`);\n }\n\n return template\n .replace('</head>', `${styleString}</head>`)\n .replace('</body>', `${scripts}\\n</body>`);\n}\n\n/**\n * Sorts matched async assets by their matching `entryPoint` in the route's `entryPoints` array.\n * This ensures layout chunks come before page chunks.\n */\nexport function sortMatchedAssetsByEntryPoints(\n matchedAssets: SerialAsset[],\n entryPoints: string[]\n): SerialAsset[] {\n const getEntryPointIndex = (modulePaths?: string[]) =>\n modulePaths ? entryPoints.findIndex((ep) => modulePaths.includes(ep)) : -1;\n\n return matchedAssets.sort(\n (a, b) =>\n getEntryPointIndex(a.metadata.modulePaths) - getEntryPointIndex(b.metadata.modulePaths)\n );\n}\n\n/**\n * Sorts assets based on the requires tree. DFS order.\n */\nexport function assetsRequiresSort(assets: SerialAsset[]): SerialAsset[] {\n const lookup = new Map<string, SerialAsset>();\n const visited = new Set();\n const visiting = new Set();\n const result: SerialAsset[] = [];\n\n assets.forEach((a) => {\n lookup.set(a.filename, a);\n });\n\n function visit(name: string) {\n if (visited.has(name)) return;\n if (visiting.has(name))\n throw new Error(\n `Circular dependencies in assets are not allowed. Found cycle: ${[...visiting, name].join(' -> ')}`\n );\n\n visiting.add(name);\n\n const module = lookup.get(name);\n if (!module) throw new Error(`Asset not found: ${name}`);\n\n module.metadata.requires?.forEach((dependency) => {\n visit(dependency);\n });\n\n visiting.delete(name);\n visited.add(name);\n result.push(module);\n }\n\n assets.forEach((a) => {\n if (!visited.has(a.filename)) {\n visit(a.filename);\n }\n });\n\n return result;\n}\n"],"names":["assetsRequiresSort","serializeHtmlWithAssets","sortMatchedAssetsByEntryPoints","debug","require","resources","template","devBundleUrl","baseUrl","route","isExporting","hydrate","htmlFromSerialAssets","bundleUrl","undefined","combineUrlPath","segments","filter","Boolean","map","segment","index","segmentIsBaseUrl","replace","join","assets","styleString","asset","type","startsWith","metadata","filename","source","createInjectedCssAsString","hmrId","orderedJsAssets","entryPoints","Array","isArray","syncAssets","a","isAsync","sortedAsync","runtimeAssets","requires","length","entryAssets","scripts","modulePaths","doesAsyncChunkContainRouteEntryPoint","some","entryPoint","includes","contextKey","createInjectedScriptsAsString","getHydrationFlagScriptAsString","matchedAssets","getEntryPointIndex","findIndex","ep","sort","b","lookup","Map","visited","Set","visiting","result","forEach","set","visit","name","module","has","Error","add","get","dependency","delete","push"],"mappings":"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"}
@@ -123,6 +123,9 @@ class Env {
123
123
  // Read from the pre-dotenv env — overrides dev server URL served to clients.
124
124
  return (0, _env().getOriginalEnvValue)('EXPO_PACKAGER_PROXY_URL') || '';
125
125
  }
126
+ get EXPO_UNSTABLE_TUNNEL_V2() {
127
+ return (0, _getenv().boolish)('EXPO_UNSTABLE_TUNNEL_V2', false);
128
+ }
126
129
  /**
127
130
  * **Experimental** - Disable using `exp.direct` as the hostname for
128
131
  * `--tunnel` connections. This enables **https://** forwarding which
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/env.ts"],"sourcesContent":["import { getOriginalEnvValue } from '@expo/env';\nimport { boolish, int, string } from 'getenv';\nimport process from 'node:process';\n\n// @expo/webpack-config -> expo-pwa -> @expo/image-utils: EXPO_IMAGE_UTILS_NO_SHARP\n\n// TODO: EXPO_CLI_USERNAME, EXPO_CLI_PASSWORD\n\nclass Env {\n /** Enable profiling metrics */\n get EXPO_PROFILE() {\n return boolish('EXPO_PROFILE', false);\n }\n\n /** Enable debug logging */\n get EXPO_DEBUG() {\n return boolish('EXPO_DEBUG', false);\n }\n\n /** Disable all network requests */\n get EXPO_OFFLINE() {\n return boolish('EXPO_OFFLINE', false);\n }\n\n /** Enable the beta version of Expo (TODO: Should this just be in the beta version of expo releases?) */\n get EXPO_BETA() {\n return boolish('EXPO_BETA', false);\n }\n\n /** Enable staging API environment */\n get EXPO_STAGING() {\n return boolish('EXPO_STAGING', false);\n }\n\n /** Enable local API environment */\n get EXPO_LOCAL() {\n return boolish('EXPO_LOCAL', false);\n }\n\n /** Is running in non-interactive CI mode */\n get CI() {\n return boolish('CI', false);\n }\n\n /** Disable telemetry (analytics) */\n get EXPO_NO_TELEMETRY() {\n return boolish('EXPO_NO_TELEMETRY', false);\n }\n\n /** Disable detaching telemetry to separate process */\n get EXPO_NO_TELEMETRY_DETACH() {\n return boolish('EXPO_NO_TELEMETRY_DETACH', false);\n }\n\n /** local directory to the universe repo for testing locally */\n get EXPO_UNIVERSE_DIR() {\n // Read from the pre-dotenv env — this is a filesystem path used by internal\n // tooling; a project `.env` overriding it could redirect file access.\n return getOriginalEnvValue('EXPO_UNIVERSE_DIR') || '';\n }\n\n /** @deprecated Default Webpack host string */\n get WEB_HOST() {\n return string('WEB_HOST', '0.0.0.0');\n }\n\n /** Skip warning users about a dirty git status */\n get EXPO_NO_GIT_STATUS() {\n return boolish('EXPO_NO_GIT_STATUS', true);\n }\n /** Disable auto web setup */\n get EXPO_NO_WEB_SETUP() {\n return boolish('EXPO_NO_WEB_SETUP', envIsHeadless());\n }\n /** Disable auto TypeScript setup */\n get EXPO_NO_TYPESCRIPT_SETUP() {\n return boolish('EXPO_NO_TYPESCRIPT_SETUP', false);\n }\n /** Disable all API caches. Does not disable bundler caches. */\n get EXPO_NO_CACHE() {\n return boolish('EXPO_NO_CACHE', false);\n }\n /** Disable the app select redirect page. */\n get EXPO_NO_REDIRECT_PAGE() {\n return boolish('EXPO_NO_REDIRECT_PAGE', false);\n }\n /** Disable printing the QR code in the interactive Terminal UI. */\n get EXPO_NO_QR_CODE(): boolean {\n return boolish('EXPO_NO_QR_CODE', false);\n }\n /** Resolve application IDs from Expo app config before native files in `expo start`. */\n get EXPO_RUN_PREFER_APP_CONFIG_ID(): boolean {\n return boolish('EXPO_RUN_PREFER_APP_CONFIG_ID', false);\n }\n /** The React Metro port that's baked into react-native scripts and tools. */\n get RCT_METRO_PORT() {\n return int('RCT_METRO_PORT', 0);\n }\n /** Skip validating the manifest during `export`. */\n get EXPO_SKIP_MANIFEST_VALIDATION_TOKEN(): boolean {\n return !!string('EXPO_SKIP_MANIFEST_VALIDATION_TOKEN', '');\n }\n\n /** Public folder path relative to the project root. Default to `public` */\n get EXPO_PUBLIC_FOLDER(): string {\n return string('EXPO_PUBLIC_FOLDER', 'public');\n }\n\n /** Higher priority `$EDIOTR` variable for indicating which editor to use when pressing `o` in the Terminal UI. */\n get EXPO_EDITOR(): string {\n return string('EXPO_EDITOR', '');\n }\n\n /**\n * Overwrite the dev server URL, disregarding the `--port`, `--host`, `--tunnel`, `--lan`, `--localhost` arguments.\n * This is useful for browser editors that require custom proxy URLs.\n */\n get EXPO_PACKAGER_PROXY_URL(): string {\n // Read from the pre-dotenv env — overrides dev server URL served to clients.\n return getOriginalEnvValue('EXPO_PACKAGER_PROXY_URL') || '';\n }\n\n /**\n * **Experimental** - Disable using `exp.direct` as the hostname for\n * `--tunnel` connections. This enables **https://** forwarding which\n * can be used to test universal links on iOS.\n *\n * This may cause issues with `expo-linking` and Expo Go.\n *\n * Select the exact subdomain by passing a string value that is not one of: `true`, `false`, `1`, `0`.\n */\n get EXPO_TUNNEL_SUBDOMAIN(): string | boolean {\n const subdomain = string('EXPO_TUNNEL_SUBDOMAIN', '');\n if (['0', 'false', ''].includes(subdomain)) {\n return false;\n } else if (['1', 'true'].includes(subdomain)) {\n return true;\n }\n return subdomain;\n }\n\n /**\n * Force Expo CLI to use the [`resolver.resolverMainFields`](https://facebook.github.io/metro/docs/configuration/#resolvermainfields) from the project `metro.config.js` for all platforms.\n *\n * By default, Expo CLI will use `['browser', 'module', 'main']` (default for Webpack) for web and the user-defined main fields for other platforms.\n */\n get EXPO_METRO_NO_MAIN_FIELD_OVERRIDE(): boolean {\n return boolish('EXPO_METRO_NO_MAIN_FIELD_OVERRIDE', false);\n }\n\n /**\n * HTTP/HTTPS proxy to connect to for network requests. Configures [https-proxy-agent](https://www.npmjs.com/package/https-proxy-agent).\n */\n get HTTP_PROXY(): string {\n return process.env.HTTP_PROXY || process.env.http_proxy || '';\n }\n\n /**\n * Instructs a different Metro config to be loaded.\n * The path, according to metro-config, should be a path relative to the current working directory.\n * This flag is internal and was added for external tools.\n * @internal\n */\n get EXPO_OVERRIDE_METRO_CONFIG(): string | undefined {\n // Read from the pre-dotenv env — this path is `require()`d as Metro config,\n // so a project `.env` overriding it would execute attacker code in-process.\n return getOriginalEnvValue('EXPO_OVERRIDE_METRO_CONFIG')?.trim() || undefined;\n }\n\n /**\n * Use the network inspector by overriding the metro inspector proxy with a custom version.\n * @deprecated This has been replaced by `@react-native/dev-middleware` and is now unused.\n */\n get EXPO_NO_INSPECTOR_PROXY(): boolean {\n return boolish('EXPO_NO_INSPECTOR_PROXY', false);\n }\n\n /** Disable lazy bundling in Metro bundler. */\n get EXPO_NO_METRO_LAZY() {\n return boolish('EXPO_NO_METRO_LAZY', false);\n }\n\n /**\n * Enable the unstable inverse dependency stack trace for Metro bundling errors.\n * @deprecated This will be removed in the future.\n */\n get EXPO_METRO_UNSTABLE_ERRORS() {\n return boolish('EXPO_METRO_UNSTABLE_ERRORS', true);\n }\n\n /** Disable Environment Variable injection in client bundles. */\n get EXPO_NO_CLIENT_ENV_VARS(): boolean {\n return boolish('EXPO_NO_CLIENT_ENV_VARS', false);\n }\n\n /** Set the default `user` that should be passed to `--user` with ADB commands. Used for installing APKs on Android devices with multiple profiles. Defaults to `0`. */\n get EXPO_ADB_USER(): string {\n return string('EXPO_ADB_USER', '0');\n }\n\n /** Used internally to enable E2E utilities. This behavior is not stable to external users. */\n get __EXPO_E2E_TEST(): boolean {\n return boolish('__EXPO_E2E_TEST', false);\n }\n\n /** Unstable: Force single-bundle exports in production. */\n get EXPO_NO_BUNDLE_SPLITTING(): boolean {\n return boolish('EXPO_NO_BUNDLE_SPLITTING', false);\n }\n\n /**\n * Enable Atlas to gather bundle information during development or export.\n * Note, because this used to be an experimental feature, both `EXPO_ATLAS` and `EXPO_UNSTABLE_ATLAS` are supported.\n */\n get EXPO_ATLAS() {\n return boolish('EXPO_ATLAS', boolish('EXPO_UNSTABLE_ATLAS', false));\n }\n\n /** Unstable: Enable tree shaking for Metro. */\n get EXPO_UNSTABLE_TREE_SHAKING() {\n return boolish('EXPO_UNSTABLE_TREE_SHAKING', false);\n }\n\n /** Unstable: Enable eager bundling where transformation runs uncached after the entire bundle has been created. This is required for production tree shaking and less optimized for development bundling. */\n get EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH() {\n return boolish('EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH', false);\n }\n\n /** Enable the use of Expo's custom metro require implementation. The custom require supports better debugging, tree shaking, and React Server Components. */\n get EXPO_USE_METRO_REQUIRE() {\n return boolish('EXPO_USE_METRO_REQUIRE', false);\n }\n\n /** Internal key used to pass eager bundle data from the CLI to the native run scripts during `npx expo run` commands. */\n get __EXPO_EAGER_BUNDLE_OPTIONS() {\n return getOriginalEnvValue('__EXPO_EAGER_BUNDLE_OPTIONS') || '';\n }\n\n /** Disable server deployment during production builds (during `expo export:embed`). This is useful for testing API routes and server components against a local server. */\n get EXPO_NO_DEPLOY(): boolean {\n return boolish('EXPO_NO_DEPLOY', false);\n }\n\n /** Enable hydration during development when rendering Expo Web */\n get EXPO_WEB_DEV_HYDRATE(): boolean {\n return boolish('EXPO_WEB_DEV_HYDRATE', false);\n }\n\n /** Enable experimental React Server Functions support. */\n get EXPO_UNSTABLE_SERVER_FUNCTIONS(): boolean {\n return boolish('EXPO_UNSTABLE_SERVER_FUNCTIONS', false);\n }\n\n /** Enable unstable/experimental support for deploying the native server in `npx expo run` commands. */\n get EXPO_UNSTABLE_DEPLOY_SERVER(): boolean {\n return boolish('EXPO_UNSTABLE_DEPLOY_SERVER', false);\n }\n\n /** Is running in EAS Build. This is set by EAS: https://docs.expo.dev/eas/environment-variables/ */\n get EAS_BUILD(): boolean {\n return boolish('EAS_BUILD', false);\n }\n\n /** Disable the React Native Directory compatibility check for new architecture when installing packages */\n get EXPO_NO_NEW_ARCH_COMPAT_CHECK(): boolean {\n return boolish('EXPO_NO_NEW_ARCH_COMPAT_CHECK', envIsHeadless());\n }\n\n /** Disable the dependency validation when installing other dependencies and starting the project */\n get EXPO_NO_DEPENDENCY_VALIDATION(): boolean {\n return boolish('EXPO_NO_DEPENDENCY_VALIDATION', envIsHeadless());\n }\n\n /** Force Expo CLI to run in webcontainer mode, this has impact on which URL Expo is using by default */\n get EXPO_FORCE_WEBCONTAINER_ENV(): boolean {\n return boolish('EXPO_FORCE_WEBCONTAINER_ENV', false);\n }\n\n /** Force Expo CLI to run in webcontainer mode, this has impact on which URL Expo is using by default */\n get EXPO_UNSTABLE_WEB_MODAL(): boolean {\n return boolish('EXPO_UNSTABLE_WEB_MODAL', false);\n }\n\n /** Disable @react-navigation checks for expo-router projects */\n get EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK(): boolean {\n return boolish('EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK', false);\n }\n\n /**\n * Disable Material Symbols (`md`) icon support in expo-router's NativeTabs on Android.\n * When enabled, the Metro resolver swaps the Android-specific md icon converter for a no-op\n * stub, so the `expo-symbols` dependency is tree-shaken out of the Android bundle.\n */\n get EXPO_ROUTER_DISABLE_NATIVE_TABS_MD(): boolean {\n return boolish('EXPO_ROUTER_DISABLE_NATIVE_TABS_MD', false);\n }\n\n /** Disable by falsy value live binding in experimental import export support. Enabled by default. */\n get EXPO_UNSTABLE_LIVE_BINDINGS(): boolean {\n return boolish('EXPO_UNSTABLE_LIVE_BINDINGS', true);\n }\n\n /**\n * Enable the experimental MCP integration or further specify the MCP server URL.\n */\n get EXPO_UNSTABLE_MCP_SERVER(): string {\n const value = string('EXPO_UNSTABLE_MCP_SERVER', '');\n if (value === '1' || value.toLowerCase() === 'true') {\n return this.EXPO_STAGING ? 'staging-mcp.expo.dev' : 'mcp.expo.dev';\n }\n // Re-read from the pre-dotenv env — overrides dev server URL served to clients.\n return getOriginalEnvValue('EXPO_UNSTABLE_MCP_SERVER') || '';\n }\n\n /** Enable Expo Log Box for iOS and Android (Web is enabled by default) */\n get EXPO_UNSTABLE_LOG_BOX(): boolean {\n return boolish('EXPO_UNSTABLE_LOG_BOX', false);\n }\n\n /**\n * Enable Bonjour advertising of the Expo CLI on local networks\n */\n get EXPO_UNSTABLE_BONJOUR(): boolean {\n return boolish('EXPO_UNSTABLE_BONJOUR', !envIsHeadless());\n }\n\n /** @internal Configure other environment variables for headless operations */\n get EXPO_UNSTABLE_HEADLESS() {\n return boolish('EXPO_UNSTABLE_HEADLESS', envIsWebcontainer());\n }\n}\n\nexport const env = new Env();\n\nexport function envIsWebcontainer() {\n // See: https://github.com/unjs/std-env/blob/4b1e03c4efce58249858efc2cc5f5eac727d0adb/src/providers.ts#L134-L143\n return (\n env.EXPO_FORCE_WEBCONTAINER_ENV ||\n (process.env.SHELL === '/bin/jsh' && !!process.versions.webcontainer)\n );\n}\n\nexport function envIsHeadless() {\n return env.EXPO_UNSTABLE_HEADLESS;\n}\n"],"names":["env","envIsHeadless","envIsWebcontainer","Env","EXPO_PROFILE","boolish","EXPO_DEBUG","EXPO_OFFLINE","EXPO_BETA","EXPO_STAGING","EXPO_LOCAL","CI","EXPO_NO_TELEMETRY","EXPO_NO_TELEMETRY_DETACH","EXPO_UNIVERSE_DIR","getOriginalEnvValue","WEB_HOST","string","EXPO_NO_GIT_STATUS","EXPO_NO_WEB_SETUP","EXPO_NO_TYPESCRIPT_SETUP","EXPO_NO_CACHE","EXPO_NO_REDIRECT_PAGE","EXPO_NO_QR_CODE","EXPO_RUN_PREFER_APP_CONFIG_ID","RCT_METRO_PORT","int","EXPO_SKIP_MANIFEST_VALIDATION_TOKEN","EXPO_PUBLIC_FOLDER","EXPO_EDITOR","EXPO_PACKAGER_PROXY_URL","EXPO_TUNNEL_SUBDOMAIN","subdomain","includes","EXPO_METRO_NO_MAIN_FIELD_OVERRIDE","HTTP_PROXY","process","http_proxy","EXPO_OVERRIDE_METRO_CONFIG","trim","undefined","EXPO_NO_INSPECTOR_PROXY","EXPO_NO_METRO_LAZY","EXPO_METRO_UNSTABLE_ERRORS","EXPO_NO_CLIENT_ENV_VARS","EXPO_ADB_USER","__EXPO_E2E_TEST","EXPO_NO_BUNDLE_SPLITTING","EXPO_ATLAS","EXPO_UNSTABLE_TREE_SHAKING","EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH","EXPO_USE_METRO_REQUIRE","__EXPO_EAGER_BUNDLE_OPTIONS","EXPO_NO_DEPLOY","EXPO_WEB_DEV_HYDRATE","EXPO_UNSTABLE_SERVER_FUNCTIONS","EXPO_UNSTABLE_DEPLOY_SERVER","EAS_BUILD","EXPO_NO_NEW_ARCH_COMPAT_CHECK","EXPO_NO_DEPENDENCY_VALIDATION","EXPO_FORCE_WEBCONTAINER_ENV","EXPO_UNSTABLE_WEB_MODAL","EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK","EXPO_ROUTER_DISABLE_NATIVE_TABS_MD","EXPO_UNSTABLE_LIVE_BINDINGS","EXPO_UNSTABLE_MCP_SERVER","value","toLowerCase","EXPO_UNSTABLE_LOG_BOX","EXPO_UNSTABLE_BONJOUR","EXPO_UNSTABLE_HEADLESS","SHELL","versions","webcontainer"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/utils/env.ts"],"sourcesContent":["import { getOriginalEnvValue } from '@expo/env';\nimport { boolish, int, string } from 'getenv';\nimport process from 'node:process';\n\n// @expo/webpack-config -> expo-pwa -> @expo/image-utils: EXPO_IMAGE_UTILS_NO_SHARP\n\n// TODO: EXPO_CLI_USERNAME, EXPO_CLI_PASSWORD\n\nclass Env {\n /** Enable profiling metrics */\n get EXPO_PROFILE() {\n return boolish('EXPO_PROFILE', false);\n }\n\n /** Enable debug logging */\n get EXPO_DEBUG() {\n return boolish('EXPO_DEBUG', false);\n }\n\n /** Disable all network requests */\n get EXPO_OFFLINE() {\n return boolish('EXPO_OFFLINE', false);\n }\n\n /** Enable the beta version of Expo (TODO: Should this just be in the beta version of expo releases?) */\n get EXPO_BETA() {\n return boolish('EXPO_BETA', false);\n }\n\n /** Enable staging API environment */\n get EXPO_STAGING() {\n return boolish('EXPO_STAGING', false);\n }\n\n /** Enable local API environment */\n get EXPO_LOCAL() {\n return boolish('EXPO_LOCAL', false);\n }\n\n /** Is running in non-interactive CI mode */\n get CI() {\n return boolish('CI', false);\n }\n\n /** Disable telemetry (analytics) */\n get EXPO_NO_TELEMETRY() {\n return boolish('EXPO_NO_TELEMETRY', false);\n }\n\n /** Disable detaching telemetry to separate process */\n get EXPO_NO_TELEMETRY_DETACH() {\n return boolish('EXPO_NO_TELEMETRY_DETACH', false);\n }\n\n /** local directory to the universe repo for testing locally */\n get EXPO_UNIVERSE_DIR() {\n // Read from the pre-dotenv env — this is a filesystem path used by internal\n // tooling; a project `.env` overriding it could redirect file access.\n return getOriginalEnvValue('EXPO_UNIVERSE_DIR') || '';\n }\n\n /** @deprecated Default Webpack host string */\n get WEB_HOST() {\n return string('WEB_HOST', '0.0.0.0');\n }\n\n /** Skip warning users about a dirty git status */\n get EXPO_NO_GIT_STATUS() {\n return boolish('EXPO_NO_GIT_STATUS', true);\n }\n /** Disable auto web setup */\n get EXPO_NO_WEB_SETUP() {\n return boolish('EXPO_NO_WEB_SETUP', envIsHeadless());\n }\n /** Disable auto TypeScript setup */\n get EXPO_NO_TYPESCRIPT_SETUP() {\n return boolish('EXPO_NO_TYPESCRIPT_SETUP', false);\n }\n /** Disable all API caches. Does not disable bundler caches. */\n get EXPO_NO_CACHE() {\n return boolish('EXPO_NO_CACHE', false);\n }\n /** Disable the app select redirect page. */\n get EXPO_NO_REDIRECT_PAGE() {\n return boolish('EXPO_NO_REDIRECT_PAGE', false);\n }\n /** Disable printing the QR code in the interactive Terminal UI. */\n get EXPO_NO_QR_CODE(): boolean {\n return boolish('EXPO_NO_QR_CODE', false);\n }\n /** Resolve application IDs from Expo app config before native files in `expo start`. */\n get EXPO_RUN_PREFER_APP_CONFIG_ID(): boolean {\n return boolish('EXPO_RUN_PREFER_APP_CONFIG_ID', false);\n }\n /** The React Metro port that's baked into react-native scripts and tools. */\n get RCT_METRO_PORT() {\n return int('RCT_METRO_PORT', 0);\n }\n /** Skip validating the manifest during `export`. */\n get EXPO_SKIP_MANIFEST_VALIDATION_TOKEN(): boolean {\n return !!string('EXPO_SKIP_MANIFEST_VALIDATION_TOKEN', '');\n }\n\n /** Public folder path relative to the project root. Default to `public` */\n get EXPO_PUBLIC_FOLDER(): string {\n return string('EXPO_PUBLIC_FOLDER', 'public');\n }\n\n /** Higher priority `$EDIOTR` variable for indicating which editor to use when pressing `o` in the Terminal UI. */\n get EXPO_EDITOR(): string {\n return string('EXPO_EDITOR', '');\n }\n\n /**\n * Overwrite the dev server URL, disregarding the `--port`, `--host`, `--tunnel`, `--lan`, `--localhost` arguments.\n * This is useful for browser editors that require custom proxy URLs.\n */\n get EXPO_PACKAGER_PROXY_URL(): string {\n // Read from the pre-dotenv env — overrides dev server URL served to clients.\n return getOriginalEnvValue('EXPO_PACKAGER_PROXY_URL') || '';\n }\n\n get EXPO_UNSTABLE_TUNNEL_V2(): boolean {\n return boolish('EXPO_UNSTABLE_TUNNEL_V2', false);\n }\n\n /**\n * **Experimental** - Disable using `exp.direct` as the hostname for\n * `--tunnel` connections. This enables **https://** forwarding which\n * can be used to test universal links on iOS.\n *\n * This may cause issues with `expo-linking` and Expo Go.\n *\n * Select the exact subdomain by passing a string value that is not one of: `true`, `false`, `1`, `0`.\n */\n get EXPO_TUNNEL_SUBDOMAIN(): string | boolean {\n const subdomain = string('EXPO_TUNNEL_SUBDOMAIN', '');\n if (['0', 'false', ''].includes(subdomain)) {\n return false;\n } else if (['1', 'true'].includes(subdomain)) {\n return true;\n }\n return subdomain;\n }\n\n /**\n * Force Expo CLI to use the [`resolver.resolverMainFields`](https://facebook.github.io/metro/docs/configuration/#resolvermainfields) from the project `metro.config.js` for all platforms.\n *\n * By default, Expo CLI will use `['browser', 'module', 'main']` (default for Webpack) for web and the user-defined main fields for other platforms.\n */\n get EXPO_METRO_NO_MAIN_FIELD_OVERRIDE(): boolean {\n return boolish('EXPO_METRO_NO_MAIN_FIELD_OVERRIDE', false);\n }\n\n /**\n * HTTP/HTTPS proxy to connect to for network requests. Configures [https-proxy-agent](https://www.npmjs.com/package/https-proxy-agent).\n */\n get HTTP_PROXY(): string {\n return process.env.HTTP_PROXY || process.env.http_proxy || '';\n }\n\n /**\n * Instructs a different Metro config to be loaded.\n * The path, according to metro-config, should be a path relative to the current working directory.\n * This flag is internal and was added for external tools.\n * @internal\n */\n get EXPO_OVERRIDE_METRO_CONFIG(): string | undefined {\n // Read from the pre-dotenv env — this path is `require()`d as Metro config,\n // so a project `.env` overriding it would execute attacker code in-process.\n return getOriginalEnvValue('EXPO_OVERRIDE_METRO_CONFIG')?.trim() || undefined;\n }\n\n /**\n * Use the network inspector by overriding the metro inspector proxy with a custom version.\n * @deprecated This has been replaced by `@react-native/dev-middleware` and is now unused.\n */\n get EXPO_NO_INSPECTOR_PROXY(): boolean {\n return boolish('EXPO_NO_INSPECTOR_PROXY', false);\n }\n\n /** Disable lazy bundling in Metro bundler. */\n get EXPO_NO_METRO_LAZY() {\n return boolish('EXPO_NO_METRO_LAZY', false);\n }\n\n /**\n * Enable the unstable inverse dependency stack trace for Metro bundling errors.\n * @deprecated This will be removed in the future.\n */\n get EXPO_METRO_UNSTABLE_ERRORS() {\n return boolish('EXPO_METRO_UNSTABLE_ERRORS', true);\n }\n\n /** Disable Environment Variable injection in client bundles. */\n get EXPO_NO_CLIENT_ENV_VARS(): boolean {\n return boolish('EXPO_NO_CLIENT_ENV_VARS', false);\n }\n\n /** Set the default `user` that should be passed to `--user` with ADB commands. Used for installing APKs on Android devices with multiple profiles. Defaults to `0`. */\n get EXPO_ADB_USER(): string {\n return string('EXPO_ADB_USER', '0');\n }\n\n /** Used internally to enable E2E utilities. This behavior is not stable to external users. */\n get __EXPO_E2E_TEST(): boolean {\n return boolish('__EXPO_E2E_TEST', false);\n }\n\n /** Unstable: Force single-bundle exports in production. */\n get EXPO_NO_BUNDLE_SPLITTING(): boolean {\n return boolish('EXPO_NO_BUNDLE_SPLITTING', false);\n }\n\n /**\n * Enable Atlas to gather bundle information during development or export.\n * Note, because this used to be an experimental feature, both `EXPO_ATLAS` and `EXPO_UNSTABLE_ATLAS` are supported.\n */\n get EXPO_ATLAS() {\n return boolish('EXPO_ATLAS', boolish('EXPO_UNSTABLE_ATLAS', false));\n }\n\n /** Unstable: Enable tree shaking for Metro. */\n get EXPO_UNSTABLE_TREE_SHAKING() {\n return boolish('EXPO_UNSTABLE_TREE_SHAKING', false);\n }\n\n /** Unstable: Enable eager bundling where transformation runs uncached after the entire bundle has been created. This is required for production tree shaking and less optimized for development bundling. */\n get EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH() {\n return boolish('EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH', false);\n }\n\n /** Enable the use of Expo's custom metro require implementation. The custom require supports better debugging, tree shaking, and React Server Components. */\n get EXPO_USE_METRO_REQUIRE() {\n return boolish('EXPO_USE_METRO_REQUIRE', false);\n }\n\n /** Internal key used to pass eager bundle data from the CLI to the native run scripts during `npx expo run` commands. */\n get __EXPO_EAGER_BUNDLE_OPTIONS() {\n return getOriginalEnvValue('__EXPO_EAGER_BUNDLE_OPTIONS') || '';\n }\n\n /** Disable server deployment during production builds (during `expo export:embed`). This is useful for testing API routes and server components against a local server. */\n get EXPO_NO_DEPLOY(): boolean {\n return boolish('EXPO_NO_DEPLOY', false);\n }\n\n /** Enable hydration during development when rendering Expo Web */\n get EXPO_WEB_DEV_HYDRATE(): boolean {\n return boolish('EXPO_WEB_DEV_HYDRATE', false);\n }\n\n /** Enable experimental React Server Functions support. */\n get EXPO_UNSTABLE_SERVER_FUNCTIONS(): boolean {\n return boolish('EXPO_UNSTABLE_SERVER_FUNCTIONS', false);\n }\n\n /** Enable unstable/experimental support for deploying the native server in `npx expo run` commands. */\n get EXPO_UNSTABLE_DEPLOY_SERVER(): boolean {\n return boolish('EXPO_UNSTABLE_DEPLOY_SERVER', false);\n }\n\n /** Is running in EAS Build. This is set by EAS: https://docs.expo.dev/eas/environment-variables/ */\n get EAS_BUILD(): boolean {\n return boolish('EAS_BUILD', false);\n }\n\n /** Disable the React Native Directory compatibility check for new architecture when installing packages */\n get EXPO_NO_NEW_ARCH_COMPAT_CHECK(): boolean {\n return boolish('EXPO_NO_NEW_ARCH_COMPAT_CHECK', envIsHeadless());\n }\n\n /** Disable the dependency validation when installing other dependencies and starting the project */\n get EXPO_NO_DEPENDENCY_VALIDATION(): boolean {\n return boolish('EXPO_NO_DEPENDENCY_VALIDATION', envIsHeadless());\n }\n\n /** Force Expo CLI to run in webcontainer mode, this has impact on which URL Expo is using by default */\n get EXPO_FORCE_WEBCONTAINER_ENV(): boolean {\n return boolish('EXPO_FORCE_WEBCONTAINER_ENV', false);\n }\n\n /** Force Expo CLI to run in webcontainer mode, this has impact on which URL Expo is using by default */\n get EXPO_UNSTABLE_WEB_MODAL(): boolean {\n return boolish('EXPO_UNSTABLE_WEB_MODAL', false);\n }\n\n /** Disable @react-navigation checks for expo-router projects */\n get EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK(): boolean {\n return boolish('EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK', false);\n }\n\n /**\n * Disable Material Symbols (`md`) icon support in expo-router's NativeTabs on Android.\n * When enabled, the Metro resolver swaps the Android-specific md icon converter for a no-op\n * stub, so the `expo-symbols` dependency is tree-shaken out of the Android bundle.\n */\n get EXPO_ROUTER_DISABLE_NATIVE_TABS_MD(): boolean {\n return boolish('EXPO_ROUTER_DISABLE_NATIVE_TABS_MD', false);\n }\n\n /** Disable by falsy value live binding in experimental import export support. Enabled by default. */\n get EXPO_UNSTABLE_LIVE_BINDINGS(): boolean {\n return boolish('EXPO_UNSTABLE_LIVE_BINDINGS', true);\n }\n\n /**\n * Enable the experimental MCP integration or further specify the MCP server URL.\n */\n get EXPO_UNSTABLE_MCP_SERVER(): string {\n const value = string('EXPO_UNSTABLE_MCP_SERVER', '');\n if (value === '1' || value.toLowerCase() === 'true') {\n return this.EXPO_STAGING ? 'staging-mcp.expo.dev' : 'mcp.expo.dev';\n }\n // Re-read from the pre-dotenv env — overrides dev server URL served to clients.\n return getOriginalEnvValue('EXPO_UNSTABLE_MCP_SERVER') || '';\n }\n\n /** Enable Expo Log Box for iOS and Android (Web is enabled by default) */\n get EXPO_UNSTABLE_LOG_BOX(): boolean {\n return boolish('EXPO_UNSTABLE_LOG_BOX', false);\n }\n\n /**\n * Enable Bonjour advertising of the Expo CLI on local networks\n */\n get EXPO_UNSTABLE_BONJOUR(): boolean {\n return boolish('EXPO_UNSTABLE_BONJOUR', !envIsHeadless());\n }\n\n /** @internal Configure other environment variables for headless operations */\n get EXPO_UNSTABLE_HEADLESS() {\n return boolish('EXPO_UNSTABLE_HEADLESS', envIsWebcontainer());\n }\n}\n\nexport const env = new Env();\n\nexport function envIsWebcontainer() {\n // See: https://github.com/unjs/std-env/blob/4b1e03c4efce58249858efc2cc5f5eac727d0adb/src/providers.ts#L134-L143\n return (\n env.EXPO_FORCE_WEBCONTAINER_ENV ||\n (process.env.SHELL === '/bin/jsh' && !!process.versions.webcontainer)\n );\n}\n\nexport function envIsHeadless() {\n return env.EXPO_UNSTABLE_HEADLESS;\n}\n"],"names":["env","envIsHeadless","envIsWebcontainer","Env","EXPO_PROFILE","boolish","EXPO_DEBUG","EXPO_OFFLINE","EXPO_BETA","EXPO_STAGING","EXPO_LOCAL","CI","EXPO_NO_TELEMETRY","EXPO_NO_TELEMETRY_DETACH","EXPO_UNIVERSE_DIR","getOriginalEnvValue","WEB_HOST","string","EXPO_NO_GIT_STATUS","EXPO_NO_WEB_SETUP","EXPO_NO_TYPESCRIPT_SETUP","EXPO_NO_CACHE","EXPO_NO_REDIRECT_PAGE","EXPO_NO_QR_CODE","EXPO_RUN_PREFER_APP_CONFIG_ID","RCT_METRO_PORT","int","EXPO_SKIP_MANIFEST_VALIDATION_TOKEN","EXPO_PUBLIC_FOLDER","EXPO_EDITOR","EXPO_PACKAGER_PROXY_URL","EXPO_UNSTABLE_TUNNEL_V2","EXPO_TUNNEL_SUBDOMAIN","subdomain","includes","EXPO_METRO_NO_MAIN_FIELD_OVERRIDE","HTTP_PROXY","process","http_proxy","EXPO_OVERRIDE_METRO_CONFIG","trim","undefined","EXPO_NO_INSPECTOR_PROXY","EXPO_NO_METRO_LAZY","EXPO_METRO_UNSTABLE_ERRORS","EXPO_NO_CLIENT_ENV_VARS","EXPO_ADB_USER","__EXPO_E2E_TEST","EXPO_NO_BUNDLE_SPLITTING","EXPO_ATLAS","EXPO_UNSTABLE_TREE_SHAKING","EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH","EXPO_USE_METRO_REQUIRE","__EXPO_EAGER_BUNDLE_OPTIONS","EXPO_NO_DEPLOY","EXPO_WEB_DEV_HYDRATE","EXPO_UNSTABLE_SERVER_FUNCTIONS","EXPO_UNSTABLE_DEPLOY_SERVER","EAS_BUILD","EXPO_NO_NEW_ARCH_COMPAT_CHECK","EXPO_NO_DEPENDENCY_VALIDATION","EXPO_FORCE_WEBCONTAINER_ENV","EXPO_UNSTABLE_WEB_MODAL","EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK","EXPO_ROUTER_DISABLE_NATIVE_TABS_MD","EXPO_UNSTABLE_LIVE_BINDINGS","EXPO_UNSTABLE_MCP_SERVER","value","toLowerCase","EXPO_UNSTABLE_LOG_BOX","EXPO_UNSTABLE_BONJOUR","EXPO_UNSTABLE_HEADLESS","SHELL","versions","webcontainer"],"mappings":"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"}
@@ -26,7 +26,7 @@ class FetchClient {
26
26
  this.headers = {
27
27
  accept: 'application/json',
28
28
  'content-type': 'application/json',
29
- 'user-agent': `expo-cli/${"56.1.14"}`,
29
+ 'user-agent': `expo-cli/${"56.1.15"}`,
30
30
  authorization: 'Basic ' + _nodebuffer().Buffer.from(`${target}:`).toString('base64')
31
31
  };
32
32
  }
@@ -83,7 +83,7 @@ function createContext() {
83
83
  cpu: summarizeCpuInfo(),
84
84
  app: {
85
85
  name: 'expo/cli',
86
- version: "56.1.14"
86
+ version: "56.1.15"
87
87
  },
88
88
  ci: _ciinfo().isCI ? {
89
89
  name: _ciinfo().name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/cli",
3
- "version": "56.1.14",
3
+ "version": "56.1.15",
4
4
  "description": "The Expo CLI",
5
5
  "main": "main.js",
6
6
  "bin": {
@@ -46,9 +46,9 @@
46
46
  "@expo/image-utils": "^0.10.1",
47
47
  "@expo/inline-modules": "^0.0.11",
48
48
  "@expo/json-file": "^10.2.0",
49
- "@expo/log-box": "^56.0.12",
49
+ "@expo/log-box": "^56.0.13",
50
50
  "@expo/metro": "~56.0.0",
51
- "@expo/metro-config": "~56.0.13",
51
+ "@expo/metro-config": "~56.0.14",
52
52
  "@expo/metro-file-map": "^56.0.3",
53
53
  "@expo/osascript": "^2.6.0",
54
54
  "@expo/package-manager": "^1.12.1",
@@ -58,7 +58,7 @@
58
58
  "@expo/router-server": "^56.0.13",
59
59
  "@expo/schema-utils": "^56.0.0",
60
60
  "@expo/spawn-async": "^1.8.0",
61
- "@expo/ws-tunnel": "^1.0.1",
61
+ "@expo/ws-tunnel": "^2.0.0",
62
62
  "@expo/xcpretty": "^4.4.4",
63
63
  "@react-native/dev-middleware": "0.85.3",
64
64
  "accepts": "^1.3.8",
@@ -157,12 +157,12 @@
157
157
  "taskr": "^1.1.0",
158
158
  "tree-kill": "^1.2.2",
159
159
  "@expo/fingerprint": "0.19.4",
160
- "expo-router": "56.2.9",
161
- "expo": "56.0.9",
160
+ "expo": "56.0.10",
162
161
  "expo-module-scripts": "56.0.3",
163
- "expo-modules-autolinking": "56.0.15"
162
+ "expo-modules-autolinking": "56.0.15",
163
+ "expo-router": "56.2.10"
164
164
  },
165
- "gitHead": "175f1e78e3444ca99ddea473faea6777a0656668",
165
+ "gitHead": "b1e94a5c1c5b19472a42ca25752a3533699bc46a",
166
166
  "scripts": {
167
167
  "build": "taskr",
168
168
  "clean": "expo-module clean",