@expo/cli 55.0.31 → 55.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/api/rest/client.js +27 -12
  3. package/build/src/api/rest/client.js.map +1 -1
  4. package/build/src/api/user/UserSettings.js +4 -2
  5. package/build/src/api/user/UserSettings.js.map +1 -1
  6. package/build/src/events/index.js +1 -1
  7. package/build/src/export/embed/exportEmbedAsync.js +2 -2
  8. package/build/src/export/embed/exportEmbedAsync.js.map +1 -1
  9. package/build/src/prebuild/resolveTemplate.js +10 -5
  10. package/build/src/prebuild/resolveTemplate.js.map +1 -1
  11. package/build/src/start/platforms/android/adb.js +16 -15
  12. package/build/src/start/platforms/android/adb.js.map +1 -1
  13. package/build/src/start/server/getStaticRenderFunctions.js +2 -1
  14. package/build/src/start/server/getStaticRenderFunctions.js.map +1 -1
  15. package/build/src/start/server/metro/debugging/createDebugMiddleware.js +6 -5
  16. package/build/src/start/server/metro/debugging/createDebugMiddleware.js.map +1 -1
  17. package/build/src/start/server/metro/debugging/messageHandlers/NetworkResponse.js +17 -1
  18. package/build/src/start/server/metro/debugging/messageHandlers/NetworkResponse.js.map +1 -1
  19. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js +7 -1
  20. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js.map +1 -1
  21. package/build/src/start/server/metro/instantiateMetro.js +3 -1
  22. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  23. package/build/src/start/server/metro/metroErrorInterface.js +5 -2
  24. package/build/src/start/server/metro/metroErrorInterface.js.map +1 -1
  25. package/build/src/start/server/middleware/InterstitialPageMiddleware.js +7 -4
  26. package/build/src/start/server/middleware/InterstitialPageMiddleware.js.map +1 -1
  27. package/build/src/start/server/middleware/inspector/createJsInspectorMiddleware.js +14 -24
  28. package/build/src/start/server/middleware/inspector/createJsInspectorMiddleware.js.map +1 -1
  29. package/build/src/utils/codesigning.js +6 -0
  30. package/build/src/utils/codesigning.js.map +1 -1
  31. package/build/src/utils/net.js +13 -0
  32. package/build/src/utils/net.js.map +1 -1
  33. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  34. package/build/src/utils/telemetry/utils/context.js +1 -1
  35. package/build/src/utils/url.js +0 -12
  36. package/build/src/utils/url.js.map +1 -1
  37. package/package.json +9 -9
  38. package/static/loading-page/index.html +10 -2
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("55.0.31");
142
+ console.log("55.0.32");
143
143
  process.exit(0);
144
144
  }
145
145
  if (args['--non-interactive']) {
@@ -84,20 +84,23 @@ function getResponseDataOrThrow(json) {
84
84
  }
85
85
  throw new UnexpectedServerData(!!json && typeof json === 'object' ? JSON.stringify(json) : 'Unknown data received from server.');
86
86
  }
87
- function wrapFetchWithCredentials(fetchFunction) {
87
+ function wrapFetchWithCredentials(fetchFunction, expoApiBaseUrl) {
88
+ const expoApiOrigin = new URL(expoApiBaseUrl).origin;
88
89
  return async function fetchWithCredentials(url, options = {}) {
89
90
  if (Array.isArray(options.headers)) {
90
91
  throw new Error('request headers must be in object form');
91
92
  }
92
93
  const resolvedHeaders = options.headers ?? {};
93
- const token = (0, _UserSettings.getAccessToken)();
94
- if (token) {
95
- resolvedHeaders.authorization = `Bearer ${token}`;
96
- } else {
97
- var _getSession;
98
- const sessionSecret = (_getSession = (0, _UserSettings.getSession)()) == null ? void 0 : _getSession.sessionSecret;
99
- if (sessionSecret) {
100
- resolvedHeaders['expo-session'] = sessionSecret;
94
+ if (isExpoApiUrl(url, expoApiBaseUrl, expoApiOrigin)) {
95
+ const token = (0, _UserSettings.getAccessToken)();
96
+ if (token) {
97
+ resolvedHeaders.authorization = `Bearer ${token}`;
98
+ } else {
99
+ var _getSession;
100
+ const sessionSecret = (_getSession = (0, _UserSettings.getSession)()) == null ? void 0 : _getSession.sessionSecret;
101
+ if (sessionSecret) {
102
+ resolvedHeaders['expo-session'] = sessionSecret;
103
+ }
101
104
  }
102
105
  }
103
106
  try {
@@ -133,6 +136,17 @@ function wrapFetchWithCredentials(fetchFunction) {
133
136
  }
134
137
  };
135
138
  }
139
+ function isExpoApiUrl(url, expoApiBaseUrl, expoApiOrigin) {
140
+ if (typeof url !== 'string') {
141
+ return false;
142
+ }
143
+ try {
144
+ // Relative URLs resolve against the Expo API base, so they always match the Expo origin.
145
+ return new URL(url, expoApiBaseUrl).origin === expoApiOrigin;
146
+ } catch {
147
+ return false;
148
+ }
149
+ }
136
150
  /**
137
151
  * Determine if the provided error is related to a network issue.
138
152
  * When this returns true, offline mode should be enabled.
@@ -150,8 +164,9 @@ function wrapFetchWithCredentials(fetchFunction) {
150
164
  ].includes(error.code);
151
165
  }
152
166
  const fetchWithOffline = (0, _wrapFetchWithOffline.wrapFetchWithOffline)((0, _wrapFetchWithUserAgent.wrapFetchWithUserAgent)(_fetch.fetch));
153
- const fetchWithBaseUrl = (0, _wrapFetchWithBaseUrl.wrapFetchWithBaseUrl)(fetchWithOffline, (0, _endpoint.getExpoApiBaseUrl)() + '/v2/');
154
- const fetchWithCredentials = (0, _wrapFetchWithProgress.wrapFetchWithProgress)(wrapFetchWithCredentials(fetchWithBaseUrl));
167
+ const expoApiBaseUrl = (0, _endpoint.getExpoApiBaseUrl)() + '/v2/';
168
+ const fetchWithBaseUrl = (0, _wrapFetchWithBaseUrl.wrapFetchWithBaseUrl)(fetchWithOffline, expoApiBaseUrl);
169
+ const fetchWithCredentials = (0, _wrapFetchWithProgress.wrapFetchWithProgress)(wrapFetchWithCredentials(fetchWithBaseUrl, expoApiBaseUrl));
155
170
  function createCachedFetch({ fetch = fetchWithCredentials, cacheDirectory, ttl, skipCache }) {
156
171
  // Disable all caching in EXPO_BETA.
157
172
  if (skipCache || _env.env.EXPO_BETA || _env.env.EXPO_NO_CACHE) {
@@ -163,6 +178,6 @@ function createCachedFetch({ fetch = fetchWithCredentials, cacheDirectory, ttl,
163
178
  ttl
164
179
  }));
165
180
  }
166
- const fetchAsync = (0, _wrapFetchWithProgress.wrapFetchWithProgress)(wrapFetchWithCredentials(fetchWithBaseUrl));
181
+ const fetchAsync = (0, _wrapFetchWithProgress.wrapFetchWithProgress)(wrapFetchWithCredentials(fetchWithBaseUrl, expoApiBaseUrl));
167
182
 
168
183
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/api/rest/client.ts"],"sourcesContent":["import type { JSONValue } from '@expo/json-file';\nimport path from 'path';\n\nimport { wrapFetchWithCache } from './cache/wrapFetchWithCache';\nimport type { FetchLike } from './client.types';\nimport { wrapFetchWithBaseUrl } from './wrapFetchWithBaseUrl';\nimport { wrapFetchWithOffline } from './wrapFetchWithOffline';\nimport { wrapFetchWithProgress } from './wrapFetchWithProgress';\nimport { wrapFetchWithUserAgent } from './wrapFetchWithUserAgent';\nimport { env } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\nimport { fetch } from '../../utils/fetch';\nimport { getExpoApiBaseUrl } from '../endpoint';\nimport { disableNetwork } from '../settings';\nimport { getAccessToken, getExpoHomeDirectory, getSession } from '../user/UserSettings';\n\nexport class ApiV2Error extends Error {\n readonly name = 'ApiV2Error';\n readonly code: string;\n readonly expoApiV2ErrorCode: string;\n readonly expoApiV2ErrorDetails?: JSONValue;\n readonly expoApiV2ErrorServerStack?: string;\n readonly expoApiV2ErrorMetadata?: object;\n readonly expoApiV2RequestId?: string;\n\n constructor(response: {\n message: string;\n code: string;\n stack?: string;\n details?: JSONValue;\n metadata?: object;\n requestId: string;\n }) {\n super(response.message);\n this.code = response.code;\n this.expoApiV2ErrorCode = response.code;\n this.expoApiV2ErrorDetails = response.details;\n this.expoApiV2ErrorServerStack = response.stack;\n this.expoApiV2ErrorMetadata = response.metadata;\n this.expoApiV2RequestId = response.requestId;\n }\n\n toString() {\n return `${super.toString()}${env.EXPO_DEBUG && this.expoApiV2RequestId ? ` (Request Id: ${this.expoApiV2RequestId})` : ''}`;\n }\n}\n\n/**\n * An Expo server error that didn't return the expected error JSON information.\n * The only 'expected' place for this is in testing, all other cases are bugs with the server.\n */\nexport class UnexpectedServerError extends Error {\n readonly name = 'UnexpectedServerError';\n}\n\n/**\n * An error defining that the server didn't return the expected error JSON information.\n * The only 'expected' place for this is in testing, all other cases are bugs with the client.\n */\nexport class UnexpectedServerData extends Error {\n readonly name = 'UnexpectedServerData';\n}\n\n/** Validate the response json contains `.data` property, or throw an unexpected server data error */\nexport function getResponseDataOrThrow<T = any>(json: unknown): T {\n if (!!json && typeof json === 'object' && 'data' in json) {\n return json.data as T;\n }\n\n throw new UnexpectedServerData(\n !!json && typeof json === 'object' ? JSON.stringify(json) : 'Unknown data received from server.'\n );\n}\n\n/**\n * @returns a `fetch` function that will inject user authentication information and handle errors from the Expo API.\n */\nexport function wrapFetchWithCredentials(fetchFunction: FetchLike): FetchLike {\n return async function fetchWithCredentials(url, options = {}) {\n if (Array.isArray(options.headers)) {\n throw new Error('request headers must be in object form');\n }\n\n const resolvedHeaders = options.headers ?? ({} as any);\n\n const token = getAccessToken();\n if (token) {\n resolvedHeaders.authorization = `Bearer ${token}`;\n } else {\n const sessionSecret = getSession()?.sessionSecret;\n if (sessionSecret) {\n resolvedHeaders['expo-session'] = sessionSecret;\n }\n }\n\n try {\n const response = await fetchFunction(url, {\n ...options,\n headers: resolvedHeaders,\n });\n\n // Handle expected API errors (4xx)\n if (response.status >= 400 && response.status < 500) {\n const body = await response.text();\n try {\n const data = JSON.parse(body);\n if (data?.errors?.length) {\n throw new ApiV2Error(data.errors[0]);\n }\n } catch (error: any) {\n // Server returned non-json response.\n if (error.message.includes('in JSON at position')) {\n throw new UnexpectedServerError(body);\n }\n throw error;\n }\n }\n\n return response;\n } catch (error: any) {\n // When running `expo start`, but wifi or internet has issues\n if (isNetworkError(error) || ('cause' in error && isNetworkError(error.cause))) {\n disableNetwork();\n\n throw new CommandError(\n 'OFFLINE',\n 'Network connection is unreliable. Try again with the environment variable `EXPO_OFFLINE=1` to skip network requests.'\n );\n }\n\n throw error;\n }\n };\n}\n\n/**\n * Determine if the provided error is related to a network issue.\n * When this returns true, offline mode should be enabled.\n * - `ENOTFOUND` is thrown when the DNS lookup failed\n * - `EAI_AGAIN` is thrown when DNS lookup failed due to a server-side error\n * - `UND_ERR_CONNECT_TIMEOUT` is thrown after DNS is resolved, but server can't be reached\n *\n * @see https://nodejs.org/api/errors.html\n * @see https://github.com/nodejs/undici#network-address-family-autoselection\n */\nfunction isNetworkError(error: Error & { code?: string }) {\n return (\n 'code' in error &&\n error.code &&\n ['ENOTFOUND', 'EAI_AGAIN', 'UND_ERR_CONNECT_TIMEOUT'].includes(error.code)\n );\n}\n\nconst fetchWithOffline = wrapFetchWithOffline(wrapFetchWithUserAgent(fetch));\n\nconst fetchWithBaseUrl = wrapFetchWithBaseUrl(fetchWithOffline, getExpoApiBaseUrl() + '/v2/');\n\nconst fetchWithCredentials = wrapFetchWithProgress(wrapFetchWithCredentials(fetchWithBaseUrl));\n\n/**\n * Create an instance of the fully qualified fetch command (auto authentication and api) but with caching in the '~/.expo' directory.\n * Caching is disabled automatically if the EXPO_NO_CACHE or EXPO_BETA environment variables are enabled.\n */\nexport function createCachedFetch({\n fetch = fetchWithCredentials,\n cacheDirectory,\n ttl,\n skipCache,\n}: {\n fetch?: FetchLike;\n cacheDirectory: string;\n ttl?: number;\n skipCache?: boolean;\n}): FetchLike {\n // Disable all caching in EXPO_BETA.\n if (skipCache || env.EXPO_BETA || env.EXPO_NO_CACHE) {\n return fetch;\n }\n\n const { FileSystemResponseCache } =\n require('./cache/FileSystemResponseCache') as typeof import('./cache/FileSystemResponseCache');\n\n return wrapFetchWithCache(\n fetch,\n new FileSystemResponseCache({\n cacheDirectory: path.join(getExpoHomeDirectory(), cacheDirectory),\n ttl,\n })\n );\n}\n\n/** Instance of fetch with automatic base URL pointing to the Expo API, user credential injection, and API error handling. Caching not included. */\nexport const fetchAsync = wrapFetchWithProgress(wrapFetchWithCredentials(fetchWithBaseUrl));\n"],"names":["ApiV2Error","UnexpectedServerData","UnexpectedServerError","createCachedFetch","fetchAsync","getResponseDataOrThrow","wrapFetchWithCredentials","Error","constructor","response","message","name","code","expoApiV2ErrorCode","expoApiV2ErrorDetails","details","expoApiV2ErrorServerStack","stack","expoApiV2ErrorMetadata","metadata","expoApiV2RequestId","requestId","toString","env","EXPO_DEBUG","json","data","JSON","stringify","fetchFunction","fetchWithCredentials","url","options","Array","isArray","headers","resolvedHeaders","token","getAccessToken","authorization","getSession","sessionSecret","status","body","text","parse","errors","length","error","includes","isNetworkError","cause","disableNetwork","CommandError","fetchWithOffline","wrapFetchWithOffline","wrapFetchWithUserAgent","fetch","fetchWithBaseUrl","wrapFetchWithBaseUrl","getExpoApiBaseUrl","wrapFetchWithProgress","cacheDirectory","ttl","skipCache","EXPO_BETA","EXPO_NO_CACHE","FileSystemResponseCache","require","wrapFetchWithCache","path","join","getExpoHomeDirectory"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/api/rest/client.ts"],"sourcesContent":["import type { JSONValue } from '@expo/json-file';\nimport path from 'path';\n\nimport { wrapFetchWithCache } from './cache/wrapFetchWithCache';\nimport type { FetchLike } from './client.types';\nimport { wrapFetchWithBaseUrl } from './wrapFetchWithBaseUrl';\nimport { wrapFetchWithOffline } from './wrapFetchWithOffline';\nimport { wrapFetchWithProgress } from './wrapFetchWithProgress';\nimport { wrapFetchWithUserAgent } from './wrapFetchWithUserAgent';\nimport { env } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\nimport { fetch } from '../../utils/fetch';\nimport { getExpoApiBaseUrl } from '../endpoint';\nimport { disableNetwork } from '../settings';\nimport { getAccessToken, getExpoHomeDirectory, getSession } from '../user/UserSettings';\n\nexport class ApiV2Error extends Error {\n readonly name = 'ApiV2Error';\n readonly code: string;\n readonly expoApiV2ErrorCode: string;\n readonly expoApiV2ErrorDetails?: JSONValue;\n readonly expoApiV2ErrorServerStack?: string;\n readonly expoApiV2ErrorMetadata?: object;\n readonly expoApiV2RequestId?: string;\n\n constructor(response: {\n message: string;\n code: string;\n stack?: string;\n details?: JSONValue;\n metadata?: object;\n requestId: string;\n }) {\n super(response.message);\n this.code = response.code;\n this.expoApiV2ErrorCode = response.code;\n this.expoApiV2ErrorDetails = response.details;\n this.expoApiV2ErrorServerStack = response.stack;\n this.expoApiV2ErrorMetadata = response.metadata;\n this.expoApiV2RequestId = response.requestId;\n }\n\n toString() {\n return `${super.toString()}${env.EXPO_DEBUG && this.expoApiV2RequestId ? ` (Request Id: ${this.expoApiV2RequestId})` : ''}`;\n }\n}\n\n/**\n * An Expo server error that didn't return the expected error JSON information.\n * The only 'expected' place for this is in testing, all other cases are bugs with the server.\n */\nexport class UnexpectedServerError extends Error {\n readonly name = 'UnexpectedServerError';\n}\n\n/**\n * An error defining that the server didn't return the expected error JSON information.\n * The only 'expected' place for this is in testing, all other cases are bugs with the client.\n */\nexport class UnexpectedServerData extends Error {\n readonly name = 'UnexpectedServerData';\n}\n\n/** Validate the response json contains `.data` property, or throw an unexpected server data error */\nexport function getResponseDataOrThrow<T = any>(json: unknown): T {\n if (!!json && typeof json === 'object' && 'data' in json) {\n return json.data as T;\n }\n\n throw new UnexpectedServerData(\n !!json && typeof json === 'object' ? JSON.stringify(json) : 'Unknown data received from server.'\n );\n}\n\n/**\n * @returns a `fetch` function that will inject user authentication information and handle errors from the Expo API.\n *\n * Credentials are only attached to requests targeting `expoApiBaseUrl`'s origin (including relative\n * URLs, which the downstream base-URL wrapper resolves against the Expo API). Absolute URLs to any\n * other host pass through without Expo credentials.\n */\nexport function wrapFetchWithCredentials(\n fetchFunction: FetchLike,\n expoApiBaseUrl: string\n): FetchLike {\n const expoApiOrigin = new URL(expoApiBaseUrl).origin;\n\n return async function fetchWithCredentials(url, options = {}) {\n if (Array.isArray(options.headers)) {\n throw new Error('request headers must be in object form');\n }\n\n const resolvedHeaders = options.headers ?? ({} as any);\n\n if (isExpoApiUrl(url, expoApiBaseUrl, expoApiOrigin)) {\n const token = getAccessToken();\n if (token) {\n resolvedHeaders.authorization = `Bearer ${token}`;\n } else {\n const sessionSecret = getSession()?.sessionSecret;\n if (sessionSecret) {\n resolvedHeaders['expo-session'] = sessionSecret;\n }\n }\n }\n\n try {\n const response = await fetchFunction(url, {\n ...options,\n headers: resolvedHeaders,\n });\n\n // Handle expected API errors (4xx)\n if (response.status >= 400 && response.status < 500) {\n const body = await response.text();\n try {\n const data = JSON.parse(body);\n if (data?.errors?.length) {\n throw new ApiV2Error(data.errors[0]);\n }\n } catch (error: any) {\n // Server returned non-json response.\n if (error.message.includes('in JSON at position')) {\n throw new UnexpectedServerError(body);\n }\n throw error;\n }\n }\n\n return response;\n } catch (error: any) {\n // When running `expo start`, but wifi or internet has issues\n if (isNetworkError(error) || ('cause' in error && isNetworkError(error.cause))) {\n disableNetwork();\n\n throw new CommandError(\n 'OFFLINE',\n 'Network connection is unreliable. Try again with the environment variable `EXPO_OFFLINE=1` to skip network requests.'\n );\n }\n\n throw error;\n }\n };\n}\n\nfunction isExpoApiUrl(url: unknown, expoApiBaseUrl: string, expoApiOrigin: string): boolean {\n if (typeof url !== 'string') {\n return false;\n }\n try {\n // Relative URLs resolve against the Expo API base, so they always match the Expo origin.\n return new URL(url, expoApiBaseUrl).origin === expoApiOrigin;\n } catch {\n return false;\n }\n}\n\n/**\n * Determine if the provided error is related to a network issue.\n * When this returns true, offline mode should be enabled.\n * - `ENOTFOUND` is thrown when the DNS lookup failed\n * - `EAI_AGAIN` is thrown when DNS lookup failed due to a server-side error\n * - `UND_ERR_CONNECT_TIMEOUT` is thrown after DNS is resolved, but server can't be reached\n *\n * @see https://nodejs.org/api/errors.html\n * @see https://github.com/nodejs/undici#network-address-family-autoselection\n */\nfunction isNetworkError(error: Error & { code?: string }) {\n return (\n 'code' in error &&\n error.code &&\n ['ENOTFOUND', 'EAI_AGAIN', 'UND_ERR_CONNECT_TIMEOUT'].includes(error.code)\n );\n}\n\nconst fetchWithOffline = wrapFetchWithOffline(wrapFetchWithUserAgent(fetch));\n\nconst expoApiBaseUrl = getExpoApiBaseUrl() + '/v2/';\n\nconst fetchWithBaseUrl = wrapFetchWithBaseUrl(fetchWithOffline, expoApiBaseUrl);\n\nconst fetchWithCredentials = wrapFetchWithProgress(\n wrapFetchWithCredentials(fetchWithBaseUrl, expoApiBaseUrl)\n);\n\n/**\n * Create an instance of the fully qualified fetch command (auto authentication and api) but with caching in the '~/.expo' directory.\n * Caching is disabled automatically if the EXPO_NO_CACHE or EXPO_BETA environment variables are enabled.\n */\nexport function createCachedFetch({\n fetch = fetchWithCredentials,\n cacheDirectory,\n ttl,\n skipCache,\n}: {\n fetch?: FetchLike;\n cacheDirectory: string;\n ttl?: number;\n skipCache?: boolean;\n}): FetchLike {\n // Disable all caching in EXPO_BETA.\n if (skipCache || env.EXPO_BETA || env.EXPO_NO_CACHE) {\n return fetch;\n }\n\n const { FileSystemResponseCache } =\n require('./cache/FileSystemResponseCache') as typeof import('./cache/FileSystemResponseCache');\n\n return wrapFetchWithCache(\n fetch,\n new FileSystemResponseCache({\n cacheDirectory: path.join(getExpoHomeDirectory(), cacheDirectory),\n ttl,\n })\n );\n}\n\n/** Instance of fetch with automatic base URL pointing to the Expo API, user credential injection, and API error handling. Caching not included. */\nexport const fetchAsync = wrapFetchWithProgress(\n wrapFetchWithCredentials(fetchWithBaseUrl, expoApiBaseUrl)\n);\n"],"names":["ApiV2Error","UnexpectedServerData","UnexpectedServerError","createCachedFetch","fetchAsync","getResponseDataOrThrow","wrapFetchWithCredentials","Error","constructor","response","message","name","code","expoApiV2ErrorCode","expoApiV2ErrorDetails","details","expoApiV2ErrorServerStack","stack","expoApiV2ErrorMetadata","metadata","expoApiV2RequestId","requestId","toString","env","EXPO_DEBUG","json","data","JSON","stringify","fetchFunction","expoApiBaseUrl","expoApiOrigin","URL","origin","fetchWithCredentials","url","options","Array","isArray","headers","resolvedHeaders","isExpoApiUrl","token","getAccessToken","authorization","getSession","sessionSecret","status","body","text","parse","errors","length","error","includes","isNetworkError","cause","disableNetwork","CommandError","fetchWithOffline","wrapFetchWithOffline","wrapFetchWithUserAgent","fetch","getExpoApiBaseUrl","fetchWithBaseUrl","wrapFetchWithBaseUrl","wrapFetchWithProgress","cacheDirectory","ttl","skipCache","EXPO_BETA","EXPO_NO_CACHE","FileSystemResponseCache","require","wrapFetchWithCache","path","join","getExpoHomeDirectory"],"mappings":";;;;;;;;;;;IAgBaA,UAAU;eAAVA;;IA2CAC,oBAAoB;eAApBA;;IARAC,qBAAqB;eAArBA;;IA2IGC,iBAAiB;eAAjBA;;IA6BHC,UAAU;eAAVA;;IA3JGC,sBAAsB;eAAtBA;;IAiBAC,wBAAwB;eAAxBA;;;;gEAhFC;;;;;;oCAEkB;sCAEE;sCACA;uCACC;wCACC;qBACnB;wBACS;uBACP;0BACY;0BACH;8BACkC;;;;;;AAE1D,MAAMN,mBAAmBO;IAS9BC,YAAYC,QAOX,CAAE;QACD,KAAK,CAACA,SAASC,OAAO,QAhBfC,OAAO;QAiBd,IAAI,CAACC,IAAI,GAAGH,SAASG,IAAI;QACzB,IAAI,CAACC,kBAAkB,GAAGJ,SAASG,IAAI;QACvC,IAAI,CAACE,qBAAqB,GAAGL,SAASM,OAAO;QAC7C,IAAI,CAACC,yBAAyB,GAAGP,SAASQ,KAAK;QAC/C,IAAI,CAACC,sBAAsB,GAAGT,SAASU,QAAQ;QAC/C,IAAI,CAACC,kBAAkB,GAAGX,SAASY,SAAS;IAC9C;IAEAC,WAAW;QACT,OAAO,GAAG,KAAK,CAACA,aAAaC,QAAG,CAACC,UAAU,IAAI,IAAI,CAACJ,kBAAkB,GAAG,CAAC,cAAc,EAAE,IAAI,CAACA,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI;IAC7H;AACF;AAMO,MAAMlB,8BAA8BK;;QAApC,qBACII,OAAO;;AAClB;AAMO,MAAMV,6BAA6BM;;QAAnC,qBACII,OAAO;;AAClB;AAGO,SAASN,uBAAgCoB,IAAa;IAC3D,IAAI,CAAC,CAACA,QAAQ,OAAOA,SAAS,YAAY,UAAUA,MAAM;QACxD,OAAOA,KAAKC,IAAI;IAClB;IAEA,MAAM,IAAIzB,qBACR,CAAC,CAACwB,QAAQ,OAAOA,SAAS,WAAWE,KAAKC,SAAS,CAACH,QAAQ;AAEhE;AASO,SAASnB,yBACduB,aAAwB,EACxBC,cAAsB;IAEtB,MAAMC,gBAAgB,IAAIC,IAAIF,gBAAgBG,MAAM;IAEpD,OAAO,eAAeC,qBAAqBC,GAAG,EAAEC,UAAU,CAAC,CAAC;QAC1D,IAAIC,MAAMC,OAAO,CAACF,QAAQG,OAAO,GAAG;YAClC,MAAM,IAAIhC,MAAM;QAClB;QAEA,MAAMiC,kBAAkBJ,QAAQG,OAAO,IAAK,CAAC;QAE7C,IAAIE,aAAaN,KAAKL,gBAAgBC,gBAAgB;YACpD,MAAMW,QAAQC,IAAAA,4BAAc;YAC5B,IAAID,OAAO;gBACTF,gBAAgBI,aAAa,GAAG,CAAC,OAAO,EAAEF,OAAO;YACnD,OAAO;oBACiBG;gBAAtB,MAAMC,iBAAgBD,cAAAA,IAAAA,wBAAU,wBAAVA,YAAcC,aAAa;gBACjD,IAAIA,eAAe;oBACjBN,eAAe,CAAC,eAAe,GAAGM;gBACpC;YACF;QACF;QAEA,IAAI;YACF,MAAMrC,WAAW,MAAMoB,cAAcM,KAAK;gBACxC,GAAGC,OAAO;gBACVG,SAASC;YACX;YAEA,mCAAmC;YACnC,IAAI/B,SAASsC,MAAM,IAAI,OAAOtC,SAASsC,MAAM,GAAG,KAAK;gBACnD,MAAMC,OAAO,MAAMvC,SAASwC,IAAI;gBAChC,IAAI;wBAEEvB;oBADJ,MAAMA,OAAOC,KAAKuB,KAAK,CAACF;oBACxB,IAAItB,yBAAAA,eAAAA,KAAMyB,MAAM,qBAAZzB,aAAc0B,MAAM,EAAE;wBACxB,MAAM,IAAIpD,WAAW0B,KAAKyB,MAAM,CAAC,EAAE;oBACrC;gBACF,EAAE,OAAOE,OAAY;oBACnB,qCAAqC;oBACrC,IAAIA,MAAM3C,OAAO,CAAC4C,QAAQ,CAAC,wBAAwB;wBACjD,MAAM,IAAIpD,sBAAsB8C;oBAClC;oBACA,MAAMK;gBACR;YACF;YAEA,OAAO5C;QACT,EAAE,OAAO4C,OAAY;YACnB,6DAA6D;YAC7D,IAAIE,eAAeF,UAAW,WAAWA,SAASE,eAAeF,MAAMG,KAAK,GAAI;gBAC9EC,IAAAA,wBAAc;gBAEd,MAAM,IAAIC,oBAAY,CACpB,WACA;YAEJ;YAEA,MAAML;QACR;IACF;AACF;AAEA,SAASZ,aAAaN,GAAY,EAAEL,cAAsB,EAAEC,aAAqB;IAC/E,IAAI,OAAOI,QAAQ,UAAU;QAC3B,OAAO;IACT;IACA,IAAI;QACF,yFAAyF;QACzF,OAAO,IAAIH,IAAIG,KAAKL,gBAAgBG,MAAM,KAAKF;IACjD,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA;;;;;;;;;CASC,GACD,SAASwB,eAAeF,KAAgC;IACtD,OACE,UAAUA,SACVA,MAAMzC,IAAI,IACV;QAAC;QAAa;QAAa;KAA0B,CAAC0C,QAAQ,CAACD,MAAMzC,IAAI;AAE7E;AAEA,MAAM+C,mBAAmBC,IAAAA,0CAAoB,EAACC,IAAAA,8CAAsB,EAACC,YAAK;AAE1E,MAAMhC,iBAAiBiC,IAAAA,2BAAiB,MAAK;AAE7C,MAAMC,mBAAmBC,IAAAA,0CAAoB,EAACN,kBAAkB7B;AAEhE,MAAMI,uBAAuBgC,IAAAA,4CAAqB,EAChD5D,yBAAyB0D,kBAAkBlC;AAOtC,SAAS3B,kBAAkB,EAChC2D,QAAQ5B,oBAAoB,EAC5BiC,cAAc,EACdC,GAAG,EACHC,SAAS,EAMV;IACC,oCAAoC;IACpC,IAAIA,aAAa9C,QAAG,CAAC+C,SAAS,IAAI/C,QAAG,CAACgD,aAAa,EAAE;QACnD,OAAOT;IACT;IAEA,MAAM,EAAEU,uBAAuB,EAAE,GAC/BC,QAAQ;IAEV,OAAOC,IAAAA,sCAAkB,EACvBZ,OACA,IAAIU,wBAAwB;QAC1BL,gBAAgBQ,eAAI,CAACC,IAAI,CAACC,IAAAA,kCAAoB,KAAIV;QAClDC;IACF;AAEJ;AAGO,MAAMhE,aAAa8D,IAAAA,4CAAqB,EAC7C5D,yBAAyB0D,kBAAkBlC"}
@@ -138,9 +138,12 @@ function getSettingsDirectory() {
138
138
  function getSettingsFilePath() {
139
139
  return _path().join(getExpoHomeDirectory(), 'state.json');
140
140
  }
141
+ // state.json holds the auth session secret, so restrict it to the owner only.
142
+ const SETTINGS_FILE_MODE = 384;
141
143
  function getSettings() {
142
144
  return new (_jsonfile()).default(getSettingsFilePath(), {
143
145
  ensureDir: true,
146
+ mode: SETTINGS_FILE_MODE,
144
147
  jsonParseErrorDefault: {},
145
148
  // This will ensure that an error isn't thrown if the file doesn't exist.
146
149
  cantReadFileDefault: {}
@@ -154,8 +157,7 @@ function getSession() {
154
157
  }
155
158
  async function setSessionAsync(sessionData) {
156
159
  await getSettings().setAsync('auth', sessionData, {
157
- default: {},
158
- ensureDir: true
160
+ default: {}
159
161
  });
160
162
  }
161
163
  function hasCredentials() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/api/user/UserSettings.ts"],"sourcesContent":["import JsonFile from '@expo/json-file';\nimport crypto from 'crypto';\nimport { boolish } from 'getenv';\nimport { homedir } from 'os';\nimport * as path from 'path';\n\ntype SessionData = {\n sessionSecret?: string;\n userId?: string;\n username?: string;\n currentConnection?: 'Username-Password-Authentication' | 'Browser-Flow-Authentication';\n};\n\nexport type UserSettingsData = {\n auth?: SessionData | null;\n ignoreBundledBinaries?: string[];\n PATH?: string;\n /** Last development code signing ID used for `npx expo run:ios`. */\n developmentCodeSigningId?: string;\n /** Unique user ID which is generated anonymously and can be cleared locally. */\n uuid?: string;\n};\n\n// The ~/.expo directory is used to store authentication sessions,\n// which are shared between EAS CLI and Expo CLI.\nexport function getExpoHomeDirectory() {\n const home = homedir();\n\n if (process.env.__UNSAFE_EXPO_HOME_DIRECTORY) {\n return process.env.__UNSAFE_EXPO_HOME_DIRECTORY;\n } else if (boolish('EXPO_STAGING', false)) {\n return path.join(home, '.expo-staging');\n } else if (boolish('EXPO_LOCAL', false)) {\n return path.join(home, '.expo-local');\n }\n return path.join(home, '.expo');\n}\n\n/** Return the user cache directory. */\nexport function getSettingsDirectory() {\n return getExpoHomeDirectory();\n}\n\n/** Return the file path of the settings file */\nexport function getSettingsFilePath(): string {\n return path.join(getExpoHomeDirectory(), 'state.json');\n}\n\n/** Get a new JsonFile instance pointed towards the settings file */\nexport function getSettings(): JsonFile<UserSettingsData> {\n return new JsonFile<UserSettingsData>(getSettingsFilePath(), {\n ensureDir: true,\n jsonParseErrorDefault: {},\n // This will ensure that an error isn't thrown if the file doesn't exist.\n cantReadFileDefault: {},\n });\n}\n\nexport function getAccessToken(): string | null {\n return process.env.EXPO_TOKEN ?? null;\n}\n\nexport function getSession() {\n return getSettings().get('auth', null);\n}\n\nexport async function setSessionAsync(sessionData?: SessionData) {\n await getSettings().setAsync('auth', sessionData, {\n default: {},\n ensureDir: true,\n });\n}\n\n/**\n * Check if there are credentials available, without fetching the user information.\n * This can be used as a faster check to see if users are authenticated.\n * Note, this isn't checking the validity of the credentials.\n */\nexport function hasCredentials() {\n return !!getAccessToken() || !!getSession();\n}\n\n/**\n * Get an anonymous and randomly generated identifier.\n * This is used to group telemetry event by unknown actor,\n * and cannot be used to identify a single user.\n */\nexport async function getAnonymousIdAsync(): Promise<string> {\n const settings = getSettings();\n let id = await settings.getAsync('uuid', null);\n\n if (!id) {\n id = crypto.randomUUID();\n await settings.setAsync('uuid', id);\n }\n\n return id;\n}\n\n/**\n * Get an anonymous and randomly generated identifier.\n * This is used to group telemetry event by unknown actor,\n * and cannot be used to identify a single user.\n */\nexport function getAnonymousId(): string {\n const settings = getSettings();\n let id = settings.get('uuid', null);\n\n if (!id) {\n id = crypto.randomUUID();\n settings.set('uuid', id);\n }\n\n return id;\n}\n"],"names":["getAccessToken","getAnonymousId","getAnonymousIdAsync","getExpoHomeDirectory","getSession","getSettings","getSettingsDirectory","getSettingsFilePath","hasCredentials","setSessionAsync","home","homedir","process","env","__UNSAFE_EXPO_HOME_DIRECTORY","boolish","path","join","JsonFile","ensureDir","jsonParseErrorDefault","cantReadFileDefault","EXPO_TOKEN","get","sessionData","setAsync","default","settings","id","getAsync","crypto","randomUUID","set"],"mappings":";;;;;;;;;;;IA0DgBA,cAAc;eAAdA;;IA8CAC,cAAc;eAAdA;;IAjBMC,mBAAmB;eAAnBA;;IA9DNC,oBAAoB;eAApBA;;IAqCAC,UAAU;eAAVA;;IAbAC,WAAW;eAAXA;;IAVAC,oBAAoB;eAApBA;;IAKAC,mBAAmB;eAAnBA;;IAkCAC,cAAc;eAAdA;;IAZMC,eAAe;eAAfA;;;;gEAlED;;;;;;;gEACF;;;;;;;yBACK;;;;;;;yBACA;;;;;;;iEACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBf,SAASN;IACd,MAAMO,OAAOC,IAAAA,aAAO;IAEpB,IAAIC,QAAQC,GAAG,CAACC,4BAA4B,EAAE;QAC5C,OAAOF,QAAQC,GAAG,CAACC,4BAA4B;IACjD,OAAO,IAAIC,IAAAA,iBAAO,EAAC,gBAAgB,QAAQ;QACzC,OAAOC,QAAKC,IAAI,CAACP,MAAM;IACzB,OAAO,IAAIK,IAAAA,iBAAO,EAAC,cAAc,QAAQ;QACvC,OAAOC,QAAKC,IAAI,CAACP,MAAM;IACzB;IACA,OAAOM,QAAKC,IAAI,CAACP,MAAM;AACzB;AAGO,SAASJ;IACd,OAAOH;AACT;AAGO,SAASI;IACd,OAAOS,QAAKC,IAAI,CAACd,wBAAwB;AAC3C;AAGO,SAASE;IACd,OAAO,IAAIa,CAAAA,WAAO,SAAC,CAAmBX,uBAAuB;QAC3DY,WAAW;QACXC,uBAAuB,CAAC;QACxB,yEAAyE;QACzEC,qBAAqB,CAAC;IACxB;AACF;AAEO,SAASrB;IACd,OAAOY,QAAQC,GAAG,CAACS,UAAU,IAAI;AACnC;AAEO,SAASlB;IACd,OAAOC,cAAckB,GAAG,CAAC,QAAQ;AACnC;AAEO,eAAed,gBAAgBe,WAAyB;IAC7D,MAAMnB,cAAcoB,QAAQ,CAAC,QAAQD,aAAa;QAChDE,SAAS,CAAC;QACVP,WAAW;IACb;AACF;AAOO,SAASX;IACd,OAAO,CAAC,CAACR,oBAAoB,CAAC,CAACI;AACjC;AAOO,eAAeF;IACpB,MAAMyB,WAAWtB;IACjB,IAAIuB,KAAK,MAAMD,SAASE,QAAQ,CAAC,QAAQ;IAEzC,IAAI,CAACD,IAAI;QACPA,KAAKE,iBAAM,CAACC,UAAU;QACtB,MAAMJ,SAASF,QAAQ,CAAC,QAAQG;IAClC;IAEA,OAAOA;AACT;AAOO,SAAS3B;IACd,MAAM0B,WAAWtB;IACjB,IAAIuB,KAAKD,SAASJ,GAAG,CAAC,QAAQ;IAE9B,IAAI,CAACK,IAAI;QACPA,KAAKE,iBAAM,CAACC,UAAU;QACtBJ,SAASK,GAAG,CAAC,QAAQJ;IACvB;IAEA,OAAOA;AACT"}
1
+ {"version":3,"sources":["../../../../src/api/user/UserSettings.ts"],"sourcesContent":["import JsonFile from '@expo/json-file';\nimport crypto from 'crypto';\nimport { boolish } from 'getenv';\nimport { homedir } from 'os';\nimport * as path from 'path';\n\ntype SessionData = {\n sessionSecret?: string;\n userId?: string;\n username?: string;\n currentConnection?: 'Username-Password-Authentication' | 'Browser-Flow-Authentication';\n};\n\nexport type UserSettingsData = {\n auth?: SessionData | null;\n ignoreBundledBinaries?: string[];\n PATH?: string;\n /** Last development code signing ID used for `npx expo run:ios`. */\n developmentCodeSigningId?: string;\n /** Unique user ID which is generated anonymously and can be cleared locally. */\n uuid?: string;\n};\n\n// The ~/.expo directory is used to store authentication sessions,\n// which are shared between EAS CLI and Expo CLI.\nexport function getExpoHomeDirectory() {\n const home = homedir();\n\n if (process.env.__UNSAFE_EXPO_HOME_DIRECTORY) {\n return process.env.__UNSAFE_EXPO_HOME_DIRECTORY;\n } else if (boolish('EXPO_STAGING', false)) {\n return path.join(home, '.expo-staging');\n } else if (boolish('EXPO_LOCAL', false)) {\n return path.join(home, '.expo-local');\n }\n return path.join(home, '.expo');\n}\n\n/** Return the user cache directory. */\nexport function getSettingsDirectory() {\n return getExpoHomeDirectory();\n}\n\n/** Return the file path of the settings file */\nexport function getSettingsFilePath(): string {\n return path.join(getExpoHomeDirectory(), 'state.json');\n}\n\n// state.json holds the auth session secret, so restrict it to the owner only.\nconst SETTINGS_FILE_MODE = 0o600;\n\n/** Get a new JsonFile instance pointed towards the settings file */\nexport function getSettings(): JsonFile<UserSettingsData> {\n return new JsonFile<UserSettingsData>(getSettingsFilePath(), {\n ensureDir: true,\n mode: SETTINGS_FILE_MODE,\n jsonParseErrorDefault: {},\n // This will ensure that an error isn't thrown if the file doesn't exist.\n cantReadFileDefault: {},\n });\n}\n\nexport function getAccessToken(): string | null {\n return process.env.EXPO_TOKEN ?? null;\n}\n\nexport function getSession() {\n return getSettings().get('auth', null);\n}\n\nexport async function setSessionAsync(sessionData?: SessionData) {\n await getSettings().setAsync('auth', sessionData, { default: {} });\n}\n\n/**\n * Check if there are credentials available, without fetching the user information.\n * This can be used as a faster check to see if users are authenticated.\n * Note, this isn't checking the validity of the credentials.\n */\nexport function hasCredentials() {\n return !!getAccessToken() || !!getSession();\n}\n\n/**\n * Get an anonymous and randomly generated identifier.\n * This is used to group telemetry event by unknown actor,\n * and cannot be used to identify a single user.\n */\nexport async function getAnonymousIdAsync(): Promise<string> {\n const settings = getSettings();\n let id = await settings.getAsync('uuid', null);\n\n if (!id) {\n id = crypto.randomUUID();\n await settings.setAsync('uuid', id);\n }\n\n return id;\n}\n\n/**\n * Get an anonymous and randomly generated identifier.\n * This is used to group telemetry event by unknown actor,\n * and cannot be used to identify a single user.\n */\nexport function getAnonymousId(): string {\n const settings = getSettings();\n let id = settings.get('uuid', null);\n\n if (!id) {\n id = crypto.randomUUID();\n settings.set('uuid', id);\n }\n\n return id;\n}\n"],"names":["getAccessToken","getAnonymousId","getAnonymousIdAsync","getExpoHomeDirectory","getSession","getSettings","getSettingsDirectory","getSettingsFilePath","hasCredentials","setSessionAsync","home","homedir","process","env","__UNSAFE_EXPO_HOME_DIRECTORY","boolish","path","join","SETTINGS_FILE_MODE","JsonFile","ensureDir","mode","jsonParseErrorDefault","cantReadFileDefault","EXPO_TOKEN","get","sessionData","setAsync","default","settings","id","getAsync","crypto","randomUUID","set"],"mappings":";;;;;;;;;;;IA8DgBA,cAAc;eAAdA;;IA2CAC,cAAc;eAAdA;;IAjBMC,mBAAmB;eAAnBA;;IA/DNC,oBAAoB;eAApBA;;IAyCAC,UAAU;eAAVA;;IAdAC,WAAW;eAAXA;;IAbAC,oBAAoB;eAApBA;;IAKAC,mBAAmB;eAAnBA;;IAmCAC,cAAc;eAAdA;;IATMC,eAAe;eAAfA;;;;gEAtED;;;;;;;gEACF;;;;;;;yBACK;;;;;;;yBACA;;;;;;;iEACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBf,SAASN;IACd,MAAMO,OAAOC,IAAAA,aAAO;IAEpB,IAAIC,QAAQC,GAAG,CAACC,4BAA4B,EAAE;QAC5C,OAAOF,QAAQC,GAAG,CAACC,4BAA4B;IACjD,OAAO,IAAIC,IAAAA,iBAAO,EAAC,gBAAgB,QAAQ;QACzC,OAAOC,QAAKC,IAAI,CAACP,MAAM;IACzB,OAAO,IAAIK,IAAAA,iBAAO,EAAC,cAAc,QAAQ;QACvC,OAAOC,QAAKC,IAAI,CAACP,MAAM;IACzB;IACA,OAAOM,QAAKC,IAAI,CAACP,MAAM;AACzB;AAGO,SAASJ;IACd,OAAOH;AACT;AAGO,SAASI;IACd,OAAOS,QAAKC,IAAI,CAACd,wBAAwB;AAC3C;AAEA,8EAA8E;AAC9E,MAAMe,qBAAqB;AAGpB,SAASb;IACd,OAAO,IAAIc,CAAAA,WAAO,SAAC,CAAmBZ,uBAAuB;QAC3Da,WAAW;QACXC,MAAMH;QACNI,uBAAuB,CAAC;QACxB,yEAAyE;QACzEC,qBAAqB,CAAC;IACxB;AACF;AAEO,SAASvB;IACd,OAAOY,QAAQC,GAAG,CAACW,UAAU,IAAI;AACnC;AAEO,SAASpB;IACd,OAAOC,cAAcoB,GAAG,CAAC,QAAQ;AACnC;AAEO,eAAehB,gBAAgBiB,WAAyB;IAC7D,MAAMrB,cAAcsB,QAAQ,CAAC,QAAQD,aAAa;QAAEE,SAAS,CAAC;IAAE;AAClE;AAOO,SAASpB;IACd,OAAO,CAAC,CAACR,oBAAoB,CAAC,CAACI;AACjC;AAOO,eAAeF;IACpB,MAAM2B,WAAWxB;IACjB,IAAIyB,KAAK,MAAMD,SAASE,QAAQ,CAAC,QAAQ;IAEzC,IAAI,CAACD,IAAI;QACPA,KAAKE,iBAAM,CAACC,UAAU;QACtB,MAAMJ,SAASF,QAAQ,CAAC,QAAQG;IAClC;IAEA,OAAOA;AACT;AAOO,SAAS7B;IACd,MAAM4B,WAAWxB;IACjB,IAAIyB,KAAKD,SAASJ,GAAG,CAAC,QAAQ;IAE9B,IAAI,CAACK,IAAI;QACPA,KAAKE,iBAAM,CAACC,UAAU;QACtBJ,SAASK,GAAG,CAAC,QAAQJ;IACvB;IAEA,OAAOA;AACT"}
@@ -70,7 +70,7 @@ function getInitMetadata() {
70
70
  return {
71
71
  format: 'v0-jsonl',
72
72
  // Version is added in the build script.
73
- version: "55.0.31" ?? 'UNVERSIONED'
73
+ version: "55.0.32" ?? 'UNVERSIONED'
74
74
  };
75
75
  }
76
76
  function installEventLogger(env = process.env.LOG_EVENTS) {
@@ -204,9 +204,9 @@ async function exportEmbedAsync(projectRoot, options) {
204
204
  if (eagerBundleOptions.key === inputKey) {
205
205
  // Copy the eager bundleOutput and assets to the new locations.
206
206
  await (0, _dir.removeAsync)(options.bundleOutput);
207
- (0, _dir.copyAsync)(eagerBundleOptions.options.bundleOutput, options.bundleOutput);
207
+ await (0, _dir.copyAsync)(eagerBundleOptions.options.bundleOutput, options.bundleOutput);
208
208
  if (eagerBundleOptions.options.assetsDest && options.assetsDest) {
209
- (0, _dir.copyAsync)(eagerBundleOptions.options.assetsDest, options.assetsDest);
209
+ await (0, _dir.copyAsync)(eagerBundleOptions.options.assetsDest, options.assetsDest);
210
210
  }
211
211
  console.log('info: Copied output to binary:', options.bundleOutput);
212
212
  return;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/export/embed/exportEmbedAsync.ts"],"sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport { getConfig } from '@expo/config';\nimport { convertEntryPointToRelative } from '@expo/config/paths';\nimport Server from '@expo/metro/metro/Server';\nimport splitBundleOptions from '@expo/metro/metro/lib/splitBundleOptions';\nimport * as output from '@expo/metro/metro/shared/output/bundle';\nimport type { BundleOptions } from '@expo/metro/metro/shared/types';\nimport getMetroAssets from '@expo/metro-config/build/transform-worker/getAssets';\nimport assert from 'assert';\nimport fs from 'fs';\nimport { sync as globSync } from 'glob';\nimport path from 'path';\n\nimport { deserializeEagerKey, getExportEmbedOptionsKey, Options } from './resolveOptions';\nimport { isExecutingFromXcodebuild, logMetroErrorInXcode } from './xcodeCompilerLogger';\nimport { Log } from '../../log';\nimport { DevServerManager } from '../../start/server/DevServerManager';\nimport { MetroBundlerDevServer } from '../../start/server/metro/MetroBundlerDevServer';\nimport { loadMetroConfigAsync } from '../../start/server/metro/instantiateMetro';\nimport { DOM_COMPONENTS_BUNDLE_DIR } from '../../start/server/middleware/DomComponentsMiddleware';\nimport { getMetroDirectBundleOptionsForExpoConfig } from '../../start/server/middleware/metroOptions';\nimport { stripAnsi } from '../../utils/ansi';\nimport { copyAsync, removeAsync } from '../../utils/dir';\nimport { env } from '../../utils/env';\nimport { setNodeEnv, loadEnvFiles } from '../../utils/nodeEnv';\nimport { exportDomComponentAsync } from '../exportDomComponents';\nimport { isEnableHermesManaged } from '../exportHermes';\nimport { persistMetroAssetsAsync } from '../persistMetroAssets';\nimport { copyPublicFolderAsync, getPublicFolderPath } from '../publicFolder';\nimport type { BundleAssetWithFileHashes, ExportAssetMap } from '../saveAssets';\nimport { persistMetroFilesAsync } from '../saveAssets';\nimport { exportStandaloneServerAsync } from './exportServer';\nimport { ensureProcessExitsAfterDelay } from '../../utils/exit';\n\nconst debug = require('debug')('expo:export:embed');\n\nfunction guessCopiedAppleBundlePath(bundleOutput: string) {\n // Ensure the path is familiar before guessing.\n if (\n !bundleOutput.match(/\\/Xcode\\/DerivedData\\/.*\\/Build\\/Products\\//) &&\n !bundleOutput.match(/\\/CoreSimulator\\/Devices\\/.*\\/data\\/Containers\\/Bundle\\/Application\\//)\n ) {\n debug('Bundling to non-standard location:', bundleOutput);\n return false;\n }\n const bundleName = path.basename(bundleOutput);\n const bundleParent = path.dirname(bundleOutput);\n const possiblePath = globSync(`*.app/${bundleName}`, {\n cwd: bundleParent,\n absolute: true,\n // bundle identifiers can start with dots.\n dot: true,\n })[0];\n debug('Possible path for previous bundle:', possiblePath);\n return possiblePath;\n}\n\nexport async function exportEmbedAsync(projectRoot: string, options: Options) {\n // The React Native build scripts always enable the cache reset but we shouldn't need this in CI environments.\n // By disabling it, we can eagerly bundle code before the build and reuse the cached artifacts in subsequent builds.\n if (env.CI && options.resetCache) {\n debug('CI environment detected, disabling automatic cache reset');\n options.resetCache = false;\n }\n\n setNodeEnv(options.dev ? 'development' : 'production');\n loadEnvFiles(projectRoot);\n\n // This is an optimized codepath that can occur during `npx expo run` and does not occur during builds from Xcode or Android Studio.\n // Here we reconcile a bundle pass that was run before the native build process. This order can fail faster and is show better errors since the logs won't be obscured by Xcode and Android Studio.\n // This path is also used for automatically deploying server bundles to a remote host.\n const eagerBundleOptions = env.__EXPO_EAGER_BUNDLE_OPTIONS\n ? deserializeEagerKey(env.__EXPO_EAGER_BUNDLE_OPTIONS)\n : null;\n if (eagerBundleOptions) {\n // Get the cache key for the current process to compare against the eager key.\n const inputKey = getExportEmbedOptionsKey(options);\n\n // If the app was bundled previously in the same process, then we should reuse the Metro cache.\n options.resetCache = false;\n\n if (eagerBundleOptions.key === inputKey) {\n // Copy the eager bundleOutput and assets to the new locations.\n await removeAsync(options.bundleOutput);\n\n copyAsync(eagerBundleOptions.options.bundleOutput, options.bundleOutput);\n\n if (eagerBundleOptions.options.assetsDest && options.assetsDest) {\n copyAsync(eagerBundleOptions.options.assetsDest, options.assetsDest);\n }\n\n console.log('info: Copied output to binary:', options.bundleOutput);\n return;\n }\n // TODO: sourcemapOutput is set on Android but not during eager. This is tolerable since it doesn't invalidate the Metro cache.\n console.log(' Eager key:', eagerBundleOptions.key);\n console.log('Request key:', inputKey);\n\n // TODO: We may want an analytic event here in the future to understand when this happens.\n console.warn('warning: Eager bundle does not match new options, bundling again.');\n }\n\n await exportEmbedInternalAsync(projectRoot, options);\n\n // Ensure the process closes after bundling\n ensureProcessExitsAfterDelay();\n}\n\nexport async function exportEmbedInternalAsync(projectRoot: string, options: Options) {\n // Ensure we delete the old bundle to trigger a failure if the bundle cannot be created.\n await removeAsync(options.bundleOutput);\n\n // The iOS bundle is copied in to the Xcode project, so we need to remove the old one\n // to prevent Xcode from loading the old one after a build failure.\n if (options.platform === 'ios') {\n const previousPath = guessCopiedAppleBundlePath(options.bundleOutput);\n if (previousPath && fs.existsSync(previousPath)) {\n debug('Removing previous iOS bundle:', previousPath);\n await removeAsync(previousPath);\n }\n }\n\n const { bundle, assets, files } = await exportEmbedBundleAndAssetsAsync(projectRoot, options);\n\n fs.mkdirSync(path.dirname(options.bundleOutput), { recursive: true, mode: 0o755 });\n\n // On Android, dom components proxy files should write to the assets directory instead of the res directory.\n // We use the bundleOutput directory to get the assets directory.\n const domComponentProxyOutputDir =\n options.platform === 'android' ? path.dirname(options.bundleOutput) : options.assetsDest;\n const hasDomComponents = domComponentProxyOutputDir && files.size > 0;\n\n // Persist bundle and source maps.\n await Promise.all([\n output.save(bundle, options, Log.log),\n\n // Write dom components proxy files.\n hasDomComponents ? persistMetroFilesAsync(files, domComponentProxyOutputDir) : null,\n // Copy public folder for dom components only if\n hasDomComponents\n ? copyPublicFolderAsync(\n getPublicFolderPath(projectRoot),\n path.join(domComponentProxyOutputDir, DOM_COMPONENTS_BUNDLE_DIR)\n )\n : null,\n\n // NOTE(EvanBacon): This may need to be adjusted in the future if want to support baseUrl on native\n // platforms when doing production embeds (unlikely).\n options.assetsDest\n ? persistMetroAssetsAsync(projectRoot, assets, {\n platform: options.platform,\n outputDirectory: options.assetsDest,\n iosAssetCatalogDirectory: options.assetCatalogDest,\n })\n : null,\n ]);\n}\n\nexport async function exportEmbedBundleAndAssetsAsync(\n projectRoot: string,\n options: Options\n): Promise<{\n bundle: Awaited<ReturnType<Server['build']>>;\n assets: readonly BundleAssetWithFileHashes[];\n files: ExportAssetMap;\n}> {\n const devServerManager = await DevServerManager.startMetroAsync(projectRoot, {\n minify: options.minify,\n mode: options.dev ? 'development' : 'production',\n port: 8081,\n isExporting: true,\n location: {},\n resetDevServer: options.resetCache,\n maxWorkers: options.maxWorkers,\n });\n\n const devServer = devServerManager.getDefaultDevServer();\n assert(devServer instanceof MetroBundlerDevServer);\n\n const { exp, pkg } = getConfig(projectRoot, { skipSDKVersionRequirement: true });\n const isHermes = isEnableHermesManaged(exp, options.platform);\n\n let sourceMapUrl = options.sourcemapOutput;\n if (sourceMapUrl && !options.sourcemapUseAbsolutePath) {\n sourceMapUrl = path.basename(sourceMapUrl);\n }\n\n const files: ExportAssetMap = new Map();\n\n try {\n const bundles = await devServer.nativeExportBundleAsync(\n exp,\n {\n // TODO: Re-enable when we get bytecode chunk splitting working again.\n splitChunks: false, //devServer.isReactServerComponentsEnabled,\n mainModuleName: convertEntryPointToRelative(projectRoot, options.entryFile),\n platform: options.platform,\n minify: options.minify,\n mode: options.dev ? 'development' : 'production',\n engine: isHermes ? 'hermes' : undefined,\n serializerIncludeMaps: !!sourceMapUrl,\n bytecode: options.bytecode ?? false,\n // source map inline\n reactCompiler: !!exp.experiments?.reactCompiler,\n },\n files,\n {\n sourceMapUrl,\n unstable_transformProfile: (options.unstableTransformProfile ||\n (isHermes ? 'hermes-stable' : 'default')) as BundleOptions['unstable_transformProfile'],\n }\n );\n\n // We optimistically build the server-side API routes code here, to ensure they're\n // valid or to enable parallel deployment in the future (TBD). This is disabled using\n // the explicit `--skip-server` flag.\n const apiRoutesEnabled =\n devServer.isReactServerComponentsEnabled || exp.web?.output === 'server';\n if (!options.skipServer && apiRoutesEnabled) {\n await exportStandaloneServerAsync(projectRoot, devServer, {\n exp,\n pkg,\n files,\n options,\n });\n }\n\n const expoDomComponentReferences = [\n ...new Set(\n bundles.artifacts\n .map((artifact) =>\n Array.isArray(artifact.metadata.expoDomComponentReferences)\n ? artifact.metadata.expoDomComponentReferences\n : []\n )\n .flat()\n ),\n ];\n if (expoDomComponentReferences.length > 0) {\n await Promise.all(\n // TODO: Make a version of this which uses `this.metro.getBundler().buildGraphForEntries([])` to bundle all the DOM components at once.\n expoDomComponentReferences.map(async (filePath) => {\n const { bundle } = await exportDomComponentAsync({\n filePath,\n projectRoot,\n dev: options.dev,\n devServer,\n isHermes,\n includeSourceMaps: !!sourceMapUrl,\n exp,\n files,\n });\n\n if (options.assetsDest) {\n // Save assets like a typical bundler, preserving the file paths on web.\n // This is saving web-style inside of a native app's binary.\n await persistMetroAssetsAsync(\n projectRoot,\n bundle.assets.map((asset) => ({\n ...asset,\n httpServerLocation: path.join(DOM_COMPONENTS_BUNDLE_DIR, asset.httpServerLocation),\n })),\n {\n files,\n platform: 'web',\n outputDirectory: options.assetsDest,\n }\n );\n }\n })\n );\n }\n\n return {\n files,\n bundle: {\n code: bundles.artifacts.filter((a: any) => a.type === 'js')[0].source,\n // Can be optional when source maps aren't enabled.\n map: bundles.artifacts.filter((a: any) => a.type === 'map')[0]?.source.toString(),\n },\n assets: bundles.assets,\n };\n } catch (error: any) {\n if (isError(error)) {\n // Log using Xcode error format so the errors are picked up by xcodebuild.\n // https://developer.apple.com/documentation/xcode/running-custom-scripts-during-a-build#Log-errors-and-warnings-from-your-script\n if (options.platform === 'ios') {\n // If the error is about to be presented in Xcode, strip the ansi characters from the message.\n if ('message' in error && isExecutingFromXcodebuild()) {\n error.message = stripAnsi(error.message) as string;\n }\n logMetroErrorInXcode(projectRoot, error);\n }\n }\n throw error;\n } finally {\n devServerManager.stopAsync();\n }\n}\n\n// Exports for expo-updates\nexport async function createMetroServerAndBundleRequestAsync(\n projectRoot: string,\n options: Pick<\n Options,\n | 'maxWorkers'\n | 'config'\n | 'platform'\n | 'sourcemapOutput'\n | 'sourcemapUseAbsolutePath'\n | 'entryFile'\n | 'minify'\n | 'dev'\n | 'resetCache'\n | 'unstableTransformProfile'\n >\n): Promise<{ server: Server; bundleRequest: BundleOptions }> {\n const exp = getConfig(projectRoot, { skipSDKVersionRequirement: true }).exp;\n\n // TODO: This is slow ~40ms\n const { config } = await loadMetroConfigAsync(\n projectRoot,\n {\n // TODO: This is always enabled in the native script and there's no way to disable it.\n resetCache: options.resetCache,\n maxWorkers: options.maxWorkers,\n },\n {\n exp,\n isExporting: true,\n getMetroBundler() {\n return server.getBundler().getBundler();\n },\n }\n );\n\n const isHermes = isEnableHermesManaged(exp, options.platform);\n\n let sourceMapUrl = options.sourcemapOutput;\n if (sourceMapUrl && !options.sourcemapUseAbsolutePath) {\n sourceMapUrl = path.basename(sourceMapUrl);\n }\n\n const directBundleOptions = getMetroDirectBundleOptionsForExpoConfig(projectRoot, exp, {\n splitChunks: false,\n // TODO(@kitten): This currently has to match a filename exactly\n mainModuleName: convertEntryPointToRelative(projectRoot, options.entryFile, null),\n platform: options.platform,\n minify: options.minify,\n mode: options.dev ? 'development' : 'production',\n engine: isHermes ? 'hermes' : undefined,\n isExporting: true,\n // Never output bytecode in the exported bundle since that is hardcoded in the native run script.\n bytecode: false,\n hosted: false,\n });\n\n // TODO(cedric): check if we can use the proper `bundleType=bundle` and `entryPoint=mainModuleName` properties\n const bundleRequest: BundleOptions = {\n ...Server.DEFAULT_BUNDLE_OPTIONS,\n ...directBundleOptions,\n\n // NOTE(@kitten): Cast non-optional defaults\n lazy: directBundleOptions.lazy ?? Server.DEFAULT_BUNDLE_OPTIONS.lazy,\n modulesOnly: directBundleOptions.modulesOnly ?? Server.DEFAULT_BUNDLE_OPTIONS.modulesOnly,\n runModule: directBundleOptions.runModule ?? Server.DEFAULT_BUNDLE_OPTIONS.runModule,\n\n sourceMapUrl,\n unstable_transformProfile: (options.unstableTransformProfile ||\n (isHermes ? 'hermes-stable' : 'default')) as BundleOptions['unstable_transformProfile'],\n };\n\n const server = new Server(config, {\n watch: false,\n });\n\n return { server, bundleRequest };\n}\n\nexport async function exportEmbedAssetsAsync(\n server: Server,\n bundleRequest: BundleOptions,\n projectRoot: string,\n options: Pick<Options, 'platform'>\n) {\n try {\n const { entryFile, onProgress, resolverOptions, transformOptions } = splitBundleOptions({\n ...bundleRequest,\n // @ts-ignore-error TODO(@kitten): Very unclear why this is here. Remove?\n bundleType: 'todo',\n });\n\n const dependencies = await server._bundler.getDependencies(\n // NOTE(@kitten): This isn't an `entryFile`, but instead a `mainModuleName`, that's been renamed\n // in `getMetroDirectBundleOptions`, where we've passed the already converted name\n [entryFile],\n transformOptions,\n resolverOptions,\n { onProgress, shallow: false, lazy: false }\n );\n\n const config = server._config;\n\n return getMetroAssets(dependencies, {\n processModuleFilter: config.serializer.processModuleFilter,\n assetPlugins: config.transformer.assetPlugins,\n platform: transformOptions.platform!,\n // Forked out of Metro because the `this._getServerRootDir()` doesn't match the development\n // behavior.\n projectRoot: config.projectRoot, // this._getServerRootDir(),\n publicPath: config.transformer.publicPath,\n isHosted: false,\n });\n } catch (error: any) {\n if (isError(error)) {\n // Log using Xcode error format so the errors are picked up by xcodebuild.\n // https://developer.apple.com/documentation/xcode/running-custom-scripts-during-a-build#Log-errors-and-warnings-from-your-script\n if (options.platform === 'ios') {\n // If the error is about to be presented in Xcode, strip the ansi characters from the message.\n if ('message' in error && isExecutingFromXcodebuild()) {\n error.message = stripAnsi(error.message) as string;\n }\n logMetroErrorInXcode(projectRoot, error);\n }\n }\n throw error;\n }\n}\n\nfunction isError(error: any): error is Error {\n return error instanceof Error;\n}\n"],"names":["createMetroServerAndBundleRequestAsync","exportEmbedAssetsAsync","exportEmbedAsync","exportEmbedBundleAndAssetsAsync","exportEmbedInternalAsync","debug","require","guessCopiedAppleBundlePath","bundleOutput","match","bundleName","path","basename","bundleParent","dirname","possiblePath","globSync","cwd","absolute","dot","projectRoot","options","env","CI","resetCache","setNodeEnv","dev","loadEnvFiles","eagerBundleOptions","__EXPO_EAGER_BUNDLE_OPTIONS","deserializeEagerKey","inputKey","getExportEmbedOptionsKey","key","removeAsync","copyAsync","assetsDest","console","log","warn","ensureProcessExitsAfterDelay","platform","previousPath","fs","existsSync","bundle","assets","files","mkdirSync","recursive","mode","domComponentProxyOutputDir","hasDomComponents","size","Promise","all","output","save","Log","persistMetroFilesAsync","copyPublicFolderAsync","getPublicFolderPath","join","DOM_COMPONENTS_BUNDLE_DIR","persistMetroAssetsAsync","outputDirectory","iosAssetCatalogDirectory","assetCatalogDest","devServerManager","DevServerManager","startMetroAsync","minify","port","isExporting","location","resetDevServer","maxWorkers","devServer","getDefaultDevServer","assert","MetroBundlerDevServer","exp","pkg","getConfig","skipSDKVersionRequirement","isHermes","isEnableHermesManaged","sourceMapUrl","sourcemapOutput","sourcemapUseAbsolutePath","Map","bundles","nativeExportBundleAsync","splitChunks","mainModuleName","convertEntryPointToRelative","entryFile","engine","undefined","serializerIncludeMaps","bytecode","reactCompiler","experiments","unstable_transformProfile","unstableTransformProfile","apiRoutesEnabled","isReactServerComponentsEnabled","web","skipServer","exportStandaloneServerAsync","expoDomComponentReferences","Set","artifacts","map","artifact","Array","isArray","metadata","flat","length","filePath","exportDomComponentAsync","includeSourceMaps","asset","httpServerLocation","code","filter","a","type","source","toString","error","isError","isExecutingFromXcodebuild","message","stripAnsi","logMetroErrorInXcode","stopAsync","config","loadMetroConfigAsync","getMetroBundler","server","getBundler","directBundleOptions","getMetroDirectBundleOptionsForExpoConfig","hosted","bundleRequest","Server","DEFAULT_BUNDLE_OPTIONS","lazy","modulesOnly","runModule","watch","onProgress","resolverOptions","transformOptions","splitBundleOptions","bundleType","dependencies","_bundler","getDependencies","shallow","_config","getMetroAssets","processModuleFilter","serializer","assetPlugins","transformer","publicPath","isHosted","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/export/embed/exportEmbedAsync.ts"],"sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport { getConfig } from '@expo/config';\nimport { convertEntryPointToRelative } from '@expo/config/paths';\nimport Server from '@expo/metro/metro/Server';\nimport splitBundleOptions from '@expo/metro/metro/lib/splitBundleOptions';\nimport * as output from '@expo/metro/metro/shared/output/bundle';\nimport type { BundleOptions } from '@expo/metro/metro/shared/types';\nimport getMetroAssets from '@expo/metro-config/build/transform-worker/getAssets';\nimport assert from 'assert';\nimport fs from 'fs';\nimport { sync as globSync } from 'glob';\nimport path from 'path';\n\nimport { deserializeEagerKey, getExportEmbedOptionsKey, Options } from './resolveOptions';\nimport { isExecutingFromXcodebuild, logMetroErrorInXcode } from './xcodeCompilerLogger';\nimport { Log } from '../../log';\nimport { DevServerManager } from '../../start/server/DevServerManager';\nimport { MetroBundlerDevServer } from '../../start/server/metro/MetroBundlerDevServer';\nimport { loadMetroConfigAsync } from '../../start/server/metro/instantiateMetro';\nimport { DOM_COMPONENTS_BUNDLE_DIR } from '../../start/server/middleware/DomComponentsMiddleware';\nimport { getMetroDirectBundleOptionsForExpoConfig } from '../../start/server/middleware/metroOptions';\nimport { stripAnsi } from '../../utils/ansi';\nimport { copyAsync, removeAsync } from '../../utils/dir';\nimport { env } from '../../utils/env';\nimport { setNodeEnv, loadEnvFiles } from '../../utils/nodeEnv';\nimport { exportDomComponentAsync } from '../exportDomComponents';\nimport { isEnableHermesManaged } from '../exportHermes';\nimport { persistMetroAssetsAsync } from '../persistMetroAssets';\nimport { copyPublicFolderAsync, getPublicFolderPath } from '../publicFolder';\nimport type { BundleAssetWithFileHashes, ExportAssetMap } from '../saveAssets';\nimport { persistMetroFilesAsync } from '../saveAssets';\nimport { exportStandaloneServerAsync } from './exportServer';\nimport { ensureProcessExitsAfterDelay } from '../../utils/exit';\n\nconst debug = require('debug')('expo:export:embed');\n\nfunction guessCopiedAppleBundlePath(bundleOutput: string) {\n // Ensure the path is familiar before guessing.\n if (\n !bundleOutput.match(/\\/Xcode\\/DerivedData\\/.*\\/Build\\/Products\\//) &&\n !bundleOutput.match(/\\/CoreSimulator\\/Devices\\/.*\\/data\\/Containers\\/Bundle\\/Application\\//)\n ) {\n debug('Bundling to non-standard location:', bundleOutput);\n return false;\n }\n const bundleName = path.basename(bundleOutput);\n const bundleParent = path.dirname(bundleOutput);\n const possiblePath = globSync(`*.app/${bundleName}`, {\n cwd: bundleParent,\n absolute: true,\n // bundle identifiers can start with dots.\n dot: true,\n })[0];\n debug('Possible path for previous bundle:', possiblePath);\n return possiblePath;\n}\n\nexport async function exportEmbedAsync(projectRoot: string, options: Options) {\n // The React Native build scripts always enable the cache reset but we shouldn't need this in CI environments.\n // By disabling it, we can eagerly bundle code before the build and reuse the cached artifacts in subsequent builds.\n if (env.CI && options.resetCache) {\n debug('CI environment detected, disabling automatic cache reset');\n options.resetCache = false;\n }\n\n setNodeEnv(options.dev ? 'development' : 'production');\n loadEnvFiles(projectRoot);\n\n // This is an optimized codepath that can occur during `npx expo run` and does not occur during builds from Xcode or Android Studio.\n // Here we reconcile a bundle pass that was run before the native build process. This order can fail faster and is show better errors since the logs won't be obscured by Xcode and Android Studio.\n // This path is also used for automatically deploying server bundles to a remote host.\n const eagerBundleOptions = env.__EXPO_EAGER_BUNDLE_OPTIONS\n ? deserializeEagerKey(env.__EXPO_EAGER_BUNDLE_OPTIONS)\n : null;\n if (eagerBundleOptions) {\n // Get the cache key for the current process to compare against the eager key.\n const inputKey = getExportEmbedOptionsKey(options);\n\n // If the app was bundled previously in the same process, then we should reuse the Metro cache.\n options.resetCache = false;\n\n if (eagerBundleOptions.key === inputKey) {\n // Copy the eager bundleOutput and assets to the new locations.\n await removeAsync(options.bundleOutput);\n\n await copyAsync(eagerBundleOptions.options.bundleOutput, options.bundleOutput);\n\n if (eagerBundleOptions.options.assetsDest && options.assetsDest) {\n await copyAsync(eagerBundleOptions.options.assetsDest, options.assetsDest);\n }\n\n console.log('info: Copied output to binary:', options.bundleOutput);\n return;\n }\n // TODO: sourcemapOutput is set on Android but not during eager. This is tolerable since it doesn't invalidate the Metro cache.\n console.log(' Eager key:', eagerBundleOptions.key);\n console.log('Request key:', inputKey);\n\n // TODO: We may want an analytic event here in the future to understand when this happens.\n console.warn('warning: Eager bundle does not match new options, bundling again.');\n }\n\n await exportEmbedInternalAsync(projectRoot, options);\n\n // Ensure the process closes after bundling\n ensureProcessExitsAfterDelay();\n}\n\nexport async function exportEmbedInternalAsync(projectRoot: string, options: Options) {\n // Ensure we delete the old bundle to trigger a failure if the bundle cannot be created.\n await removeAsync(options.bundleOutput);\n\n // The iOS bundle is copied in to the Xcode project, so we need to remove the old one\n // to prevent Xcode from loading the old one after a build failure.\n if (options.platform === 'ios') {\n const previousPath = guessCopiedAppleBundlePath(options.bundleOutput);\n if (previousPath && fs.existsSync(previousPath)) {\n debug('Removing previous iOS bundle:', previousPath);\n await removeAsync(previousPath);\n }\n }\n\n const { bundle, assets, files } = await exportEmbedBundleAndAssetsAsync(projectRoot, options);\n\n fs.mkdirSync(path.dirname(options.bundleOutput), { recursive: true, mode: 0o755 });\n\n // On Android, dom components proxy files should write to the assets directory instead of the res directory.\n // We use the bundleOutput directory to get the assets directory.\n const domComponentProxyOutputDir =\n options.platform === 'android' ? path.dirname(options.bundleOutput) : options.assetsDest;\n const hasDomComponents = domComponentProxyOutputDir && files.size > 0;\n\n // Persist bundle and source maps.\n await Promise.all([\n output.save(bundle, options, Log.log),\n\n // Write dom components proxy files.\n hasDomComponents ? persistMetroFilesAsync(files, domComponentProxyOutputDir) : null,\n // Copy public folder for dom components only if\n hasDomComponents\n ? copyPublicFolderAsync(\n getPublicFolderPath(projectRoot),\n path.join(domComponentProxyOutputDir, DOM_COMPONENTS_BUNDLE_DIR)\n )\n : null,\n\n // NOTE(EvanBacon): This may need to be adjusted in the future if want to support baseUrl on native\n // platforms when doing production embeds (unlikely).\n options.assetsDest\n ? persistMetroAssetsAsync(projectRoot, assets, {\n platform: options.platform,\n outputDirectory: options.assetsDest,\n iosAssetCatalogDirectory: options.assetCatalogDest,\n })\n : null,\n ]);\n}\n\nexport async function exportEmbedBundleAndAssetsAsync(\n projectRoot: string,\n options: Options\n): Promise<{\n bundle: Awaited<ReturnType<Server['build']>>;\n assets: readonly BundleAssetWithFileHashes[];\n files: ExportAssetMap;\n}> {\n const devServerManager = await DevServerManager.startMetroAsync(projectRoot, {\n minify: options.minify,\n mode: options.dev ? 'development' : 'production',\n port: 8081,\n isExporting: true,\n location: {},\n resetDevServer: options.resetCache,\n maxWorkers: options.maxWorkers,\n });\n\n const devServer = devServerManager.getDefaultDevServer();\n assert(devServer instanceof MetroBundlerDevServer);\n\n const { exp, pkg } = getConfig(projectRoot, { skipSDKVersionRequirement: true });\n const isHermes = isEnableHermesManaged(exp, options.platform);\n\n let sourceMapUrl = options.sourcemapOutput;\n if (sourceMapUrl && !options.sourcemapUseAbsolutePath) {\n sourceMapUrl = path.basename(sourceMapUrl);\n }\n\n const files: ExportAssetMap = new Map();\n\n try {\n const bundles = await devServer.nativeExportBundleAsync(\n exp,\n {\n // TODO: Re-enable when we get bytecode chunk splitting working again.\n splitChunks: false, //devServer.isReactServerComponentsEnabled,\n mainModuleName: convertEntryPointToRelative(projectRoot, options.entryFile),\n platform: options.platform,\n minify: options.minify,\n mode: options.dev ? 'development' : 'production',\n engine: isHermes ? 'hermes' : undefined,\n serializerIncludeMaps: !!sourceMapUrl,\n bytecode: options.bytecode ?? false,\n // source map inline\n reactCompiler: !!exp.experiments?.reactCompiler,\n },\n files,\n {\n sourceMapUrl,\n unstable_transformProfile: (options.unstableTransformProfile ||\n (isHermes ? 'hermes-stable' : 'default')) as BundleOptions['unstable_transformProfile'],\n }\n );\n\n // We optimistically build the server-side API routes code here, to ensure they're\n // valid or to enable parallel deployment in the future (TBD). This is disabled using\n // the explicit `--skip-server` flag.\n const apiRoutesEnabled =\n devServer.isReactServerComponentsEnabled || exp.web?.output === 'server';\n if (!options.skipServer && apiRoutesEnabled) {\n await exportStandaloneServerAsync(projectRoot, devServer, {\n exp,\n pkg,\n files,\n options,\n });\n }\n\n const expoDomComponentReferences = [\n ...new Set(\n bundles.artifacts\n .map((artifact) =>\n Array.isArray(artifact.metadata.expoDomComponentReferences)\n ? artifact.metadata.expoDomComponentReferences\n : []\n )\n .flat()\n ),\n ];\n if (expoDomComponentReferences.length > 0) {\n await Promise.all(\n // TODO: Make a version of this which uses `this.metro.getBundler().buildGraphForEntries([])` to bundle all the DOM components at once.\n expoDomComponentReferences.map(async (filePath) => {\n const { bundle } = await exportDomComponentAsync({\n filePath,\n projectRoot,\n dev: options.dev,\n devServer,\n isHermes,\n includeSourceMaps: !!sourceMapUrl,\n exp,\n files,\n });\n\n if (options.assetsDest) {\n // Save assets like a typical bundler, preserving the file paths on web.\n // This is saving web-style inside of a native app's binary.\n await persistMetroAssetsAsync(\n projectRoot,\n bundle.assets.map((asset) => ({\n ...asset,\n httpServerLocation: path.join(DOM_COMPONENTS_BUNDLE_DIR, asset.httpServerLocation),\n })),\n {\n files,\n platform: 'web',\n outputDirectory: options.assetsDest,\n }\n );\n }\n })\n );\n }\n\n return {\n files,\n bundle: {\n code: bundles.artifacts.filter((a: any) => a.type === 'js')[0].source,\n // Can be optional when source maps aren't enabled.\n map: bundles.artifacts.filter((a: any) => a.type === 'map')[0]?.source.toString(),\n },\n assets: bundles.assets,\n };\n } catch (error: any) {\n if (isError(error)) {\n // Log using Xcode error format so the errors are picked up by xcodebuild.\n // https://developer.apple.com/documentation/xcode/running-custom-scripts-during-a-build#Log-errors-and-warnings-from-your-script\n if (options.platform === 'ios') {\n // If the error is about to be presented in Xcode, strip the ansi characters from the message.\n if ('message' in error && isExecutingFromXcodebuild()) {\n error.message = stripAnsi(error.message) as string;\n }\n logMetroErrorInXcode(projectRoot, error);\n }\n }\n throw error;\n } finally {\n devServerManager.stopAsync();\n }\n}\n\n// Exports for expo-updates\nexport async function createMetroServerAndBundleRequestAsync(\n projectRoot: string,\n options: Pick<\n Options,\n | 'maxWorkers'\n | 'config'\n | 'platform'\n | 'sourcemapOutput'\n | 'sourcemapUseAbsolutePath'\n | 'entryFile'\n | 'minify'\n | 'dev'\n | 'resetCache'\n | 'unstableTransformProfile'\n >\n): Promise<{ server: Server; bundleRequest: BundleOptions }> {\n const exp = getConfig(projectRoot, { skipSDKVersionRequirement: true }).exp;\n\n // TODO: This is slow ~40ms\n const { config } = await loadMetroConfigAsync(\n projectRoot,\n {\n // TODO: This is always enabled in the native script and there's no way to disable it.\n resetCache: options.resetCache,\n maxWorkers: options.maxWorkers,\n },\n {\n exp,\n isExporting: true,\n getMetroBundler() {\n return server.getBundler().getBundler();\n },\n }\n );\n\n const isHermes = isEnableHermesManaged(exp, options.platform);\n\n let sourceMapUrl = options.sourcemapOutput;\n if (sourceMapUrl && !options.sourcemapUseAbsolutePath) {\n sourceMapUrl = path.basename(sourceMapUrl);\n }\n\n const directBundleOptions = getMetroDirectBundleOptionsForExpoConfig(projectRoot, exp, {\n splitChunks: false,\n // TODO(@kitten): This currently has to match a filename exactly\n mainModuleName: convertEntryPointToRelative(projectRoot, options.entryFile, null),\n platform: options.platform,\n minify: options.minify,\n mode: options.dev ? 'development' : 'production',\n engine: isHermes ? 'hermes' : undefined,\n isExporting: true,\n // Never output bytecode in the exported bundle since that is hardcoded in the native run script.\n bytecode: false,\n hosted: false,\n });\n\n // TODO(cedric): check if we can use the proper `bundleType=bundle` and `entryPoint=mainModuleName` properties\n const bundleRequest: BundleOptions = {\n ...Server.DEFAULT_BUNDLE_OPTIONS,\n ...directBundleOptions,\n\n // NOTE(@kitten): Cast non-optional defaults\n lazy: directBundleOptions.lazy ?? Server.DEFAULT_BUNDLE_OPTIONS.lazy,\n modulesOnly: directBundleOptions.modulesOnly ?? Server.DEFAULT_BUNDLE_OPTIONS.modulesOnly,\n runModule: directBundleOptions.runModule ?? Server.DEFAULT_BUNDLE_OPTIONS.runModule,\n\n sourceMapUrl,\n unstable_transformProfile: (options.unstableTransformProfile ||\n (isHermes ? 'hermes-stable' : 'default')) as BundleOptions['unstable_transformProfile'],\n };\n\n const server = new Server(config, {\n watch: false,\n });\n\n return { server, bundleRequest };\n}\n\nexport async function exportEmbedAssetsAsync(\n server: Server,\n bundleRequest: BundleOptions,\n projectRoot: string,\n options: Pick<Options, 'platform'>\n) {\n try {\n const { entryFile, onProgress, resolverOptions, transformOptions } = splitBundleOptions({\n ...bundleRequest,\n // @ts-ignore-error TODO(@kitten): Very unclear why this is here. Remove?\n bundleType: 'todo',\n });\n\n const dependencies = await server._bundler.getDependencies(\n // NOTE(@kitten): This isn't an `entryFile`, but instead a `mainModuleName`, that's been renamed\n // in `getMetroDirectBundleOptions`, where we've passed the already converted name\n [entryFile],\n transformOptions,\n resolverOptions,\n { onProgress, shallow: false, lazy: false }\n );\n\n const config = server._config;\n\n return getMetroAssets(dependencies, {\n processModuleFilter: config.serializer.processModuleFilter,\n assetPlugins: config.transformer.assetPlugins,\n platform: transformOptions.platform!,\n // Forked out of Metro because the `this._getServerRootDir()` doesn't match the development\n // behavior.\n projectRoot: config.projectRoot, // this._getServerRootDir(),\n publicPath: config.transformer.publicPath,\n isHosted: false,\n });\n } catch (error: any) {\n if (isError(error)) {\n // Log using Xcode error format so the errors are picked up by xcodebuild.\n // https://developer.apple.com/documentation/xcode/running-custom-scripts-during-a-build#Log-errors-and-warnings-from-your-script\n if (options.platform === 'ios') {\n // If the error is about to be presented in Xcode, strip the ansi characters from the message.\n if ('message' in error && isExecutingFromXcodebuild()) {\n error.message = stripAnsi(error.message) as string;\n }\n logMetroErrorInXcode(projectRoot, error);\n }\n }\n throw error;\n }\n}\n\nfunction isError(error: any): error is Error {\n return error instanceof Error;\n}\n"],"names":["createMetroServerAndBundleRequestAsync","exportEmbedAssetsAsync","exportEmbedAsync","exportEmbedBundleAndAssetsAsync","exportEmbedInternalAsync","debug","require","guessCopiedAppleBundlePath","bundleOutput","match","bundleName","path","basename","bundleParent","dirname","possiblePath","globSync","cwd","absolute","dot","projectRoot","options","env","CI","resetCache","setNodeEnv","dev","loadEnvFiles","eagerBundleOptions","__EXPO_EAGER_BUNDLE_OPTIONS","deserializeEagerKey","inputKey","getExportEmbedOptionsKey","key","removeAsync","copyAsync","assetsDest","console","log","warn","ensureProcessExitsAfterDelay","platform","previousPath","fs","existsSync","bundle","assets","files","mkdirSync","recursive","mode","domComponentProxyOutputDir","hasDomComponents","size","Promise","all","output","save","Log","persistMetroFilesAsync","copyPublicFolderAsync","getPublicFolderPath","join","DOM_COMPONENTS_BUNDLE_DIR","persistMetroAssetsAsync","outputDirectory","iosAssetCatalogDirectory","assetCatalogDest","devServerManager","DevServerManager","startMetroAsync","minify","port","isExporting","location","resetDevServer","maxWorkers","devServer","getDefaultDevServer","assert","MetroBundlerDevServer","exp","pkg","getConfig","skipSDKVersionRequirement","isHermes","isEnableHermesManaged","sourceMapUrl","sourcemapOutput","sourcemapUseAbsolutePath","Map","bundles","nativeExportBundleAsync","splitChunks","mainModuleName","convertEntryPointToRelative","entryFile","engine","undefined","serializerIncludeMaps","bytecode","reactCompiler","experiments","unstable_transformProfile","unstableTransformProfile","apiRoutesEnabled","isReactServerComponentsEnabled","web","skipServer","exportStandaloneServerAsync","expoDomComponentReferences","Set","artifacts","map","artifact","Array","isArray","metadata","flat","length","filePath","exportDomComponentAsync","includeSourceMaps","asset","httpServerLocation","code","filter","a","type","source","toString","error","isError","isExecutingFromXcodebuild","message","stripAnsi","logMetroErrorInXcode","stopAsync","config","loadMetroConfigAsync","getMetroBundler","server","getBundler","directBundleOptions","getMetroDirectBundleOptionsForExpoConfig","hosted","bundleRequest","Server","DEFAULT_BUNDLE_OPTIONS","lazy","modulesOnly","runModule","watch","onProgress","resolverOptions","transformOptions","splitBundleOptions","bundleType","dependencies","_bundler","getDependencies","shallow","_config","getMetroAssets","processModuleFilter","serializer","assetPlugins","transformer","publicPath","isHosted","Error"],"mappings":"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"}
@@ -22,13 +22,12 @@ function _semver() {
22
22
  };
23
23
  return data;
24
24
  }
25
- const _client = require("../api/rest/client");
26
25
  const _log = /*#__PURE__*/ _interop_require_wildcard(require("../log"));
27
26
  const _resolveLocalTemplate = require("./resolveLocalTemplate");
28
27
  const _createFileTransform = require("../utils/createFileTransform");
29
28
  const _errors = require("../utils/errors");
29
+ const _fetch = require("../utils/fetch");
30
30
  const _npm = require("../utils/npm");
31
- const _url = require("../utils/url");
32
31
  function _interop_require_default(obj) {
33
32
  return obj && obj.__esModule ? obj : {
34
33
  default: obj
@@ -122,8 +121,9 @@ async function getRepoInfo(url, examplePath) {
122
121
  const filePath = examplePath ? examplePath.replace(/^\//, '') : file.join('/');
123
122
  // Support repos whose entire purpose is to be an example, e.g.
124
123
  // https://github.com/:username/:my-cool-example-repo-name.
124
+ // Use the plain unauthenticated `fetch` so Expo credentials aren't forwarded to GitHub.
125
125
  if (t === undefined) {
126
- const infoResponse = await (0, _client.fetchAsync)(`https://api.github.com/repos/${username}/${name}`);
126
+ const infoResponse = await (0, _fetch.fetch)(`https://api.github.com/repos/${username}/${name}`);
127
127
  if (infoResponse.status !== 200) {
128
128
  return;
129
129
  }
@@ -147,10 +147,15 @@ async function getRepoInfo(url, examplePath) {
147
147
  }
148
148
  return undefined;
149
149
  }
150
- function hasRepo({ username, name, branch, filePath }) {
150
+ async function hasRepo({ username, name, branch, filePath }) {
151
151
  const contentsUrl = `https://api.github.com/repos/${username}/${name}/contents`;
152
152
  const packagePath = `${filePath ? `/${filePath}` : ''}/package.json`;
153
- return (0, _url.isUrlOk)(contentsUrl + packagePath + `?ref=${branch}`);
153
+ try {
154
+ const response = await (0, _fetch.fetch)(contentsUrl + packagePath + `?ref=${branch}`);
155
+ return response.ok;
156
+ } catch {
157
+ return false;
158
+ }
154
159
  }
155
160
  async function downloadAndExtractRepoAsync({ username, name, branch, filePath }, output, props) {
156
161
  const url = `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/prebuild/resolveTemplate.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport { Ora } from 'ora';\nimport semver from 'semver';\n\nimport { type ResolvedTemplateOption } from './resolveOptions';\nimport { fetchAsync } from '../api/rest/client';\nimport * as Log from '../log';\nimport { resolveLocalTemplateAsync } from './resolveLocalTemplate';\nimport { createGlobFilter } from '../utils/createFileTransform';\nimport { AbortCommandError } from '../utils/errors';\nimport {\n downloadAndExtractNpmModuleAsync,\n extractLocalNpmTarballAsync,\n extractNpmTarballFromUrlAsync,\n} from '../utils/npm';\nimport { isUrlOk } from '../utils/url';\n\nconst debug = require('debug')('expo:prebuild:resolveTemplate') as typeof console.log;\n\ntype RepoInfo = {\n username: string;\n name: string;\n branch: string;\n filePath: string;\n};\n\nexport async function cloneTemplateAsync({\n templateDirectory,\n projectRoot,\n template,\n exp,\n ora,\n}: {\n templateDirectory: string;\n projectRoot: string;\n template?: ResolvedTemplateOption;\n exp: Pick<ExpoConfig, 'name' | 'sdkVersion'>;\n ora: Ora;\n}): Promise<string> {\n if (template) {\n const expName = exp.name;\n const { type, uri } = template;\n if (type === 'file') {\n return await extractLocalNpmTarballAsync(uri, templateDirectory, {\n expName,\n });\n } else if (type === 'npm') {\n return await downloadAndExtractNpmModuleAsync(uri, templateDirectory, {\n expName,\n });\n } else if (type === 'repository') {\n return await resolveAndDownloadRepoTemplateAsync(templateDirectory, ora, expName, uri);\n } else {\n throw new Error(`Unknown template type: ${type}`);\n }\n } else {\n try {\n return await resolveLocalTemplateAsync({ templateDirectory, projectRoot, exp });\n } catch (error: any) {\n const templatePackageName = getTemplateNpmPackageNameFromSdkVersion(exp.sdkVersion);\n debug('Fallback to SDK template:', templatePackageName);\n return await downloadAndExtractNpmModuleAsync(templatePackageName, templateDirectory, {\n expName: exp.name,\n });\n }\n }\n}\n\n/** Given an `sdkVersion` like `44.0.0` return a fully qualified NPM package name like: `expo-template-bare-minimum@sdk-44` */\nfunction getTemplateNpmPackageNameFromSdkVersion(sdkVersion?: string): string {\n // When undefined or UNVERSIONED, we use the latest version.\n if (!sdkVersion || sdkVersion === 'UNVERSIONED') {\n Log.log('Using an unspecified Expo SDK version. The latest template will be used.');\n return `expo-template-bare-minimum@latest`;\n }\n return `expo-template-bare-minimum@sdk-${semver.major(sdkVersion)}`;\n}\n\nasync function getRepoInfo(url: any, examplePath?: string): Promise<RepoInfo | undefined> {\n const [, username, name, t, _branch, ...file] = url.pathname.split('/');\n const filePath = examplePath ? examplePath.replace(/^\\//, '') : file.join('/');\n\n // Support repos whose entire purpose is to be an example, e.g.\n // https://github.com/:username/:my-cool-example-repo-name.\n if (t === undefined) {\n const infoResponse = await fetchAsync(`https://api.github.com/repos/${username}/${name}`);\n if (infoResponse.status !== 200) {\n return;\n }\n const info: any = await infoResponse.json();\n return { username, name, branch: info['default_branch'], filePath };\n }\n\n // If examplePath is available, the branch name takes the entire path\n const branch = examplePath\n ? `${_branch}/${file.join('/')}`.replace(new RegExp(`/${filePath}|/$`), '')\n : _branch;\n\n if (username && name && branch && t === 'tree') {\n return { username, name, branch, filePath };\n }\n return undefined;\n}\n\nfunction hasRepo({ username, name, branch, filePath }: RepoInfo) {\n const contentsUrl = `https://api.github.com/repos/${username}/${name}/contents`;\n const packagePath = `${filePath ? `/${filePath}` : ''}/package.json`;\n\n return isUrlOk(contentsUrl + packagePath + `?ref=${branch}`);\n}\n\nasync function downloadAndExtractRepoAsync(\n { username, name, branch, filePath }: RepoInfo,\n output: string,\n props: { expName?: string }\n): Promise<string> {\n const url = `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`;\n\n debug('Downloading tarball from:', url);\n\n // Extract the (sub)directory into non-empty path segments\n const directory = filePath.replace(/^\\//, '').split('/').filter(Boolean);\n // Remove the (sub)directory paths, and the root folder added by GitHub\n const strip = directory.length + 1;\n // Only extract the relevant (sub)directories, ignoring irrelevant files\n // The filder auto-ignores dotfiles, unless explicitly included\n const filter = createGlobFilter(\n !directory.length\n ? ['*/**', '*/ios/.xcode.env']\n : [`*/${directory.join('/')}/**`, `*/${directory.join('/')}/ios/.xcode.env`],\n {\n // Always ignore the `.xcworkspace` folder\n ignore: ['**/ios/*.xcworkspace/**'],\n }\n );\n\n return await extractNpmTarballFromUrlAsync(url, output, {\n ...props,\n strip,\n filter,\n });\n}\n\nasync function resolveAndDownloadRepoTemplateAsync(\n templateDirectory: string,\n oraInstance: Ora,\n expName: string,\n template: string,\n templatePath?: string\n) {\n let repoUrl: URL | undefined;\n\n try {\n repoUrl = new URL(template);\n } catch (error: any) {\n if (error.code !== 'ERR_INVALID_URL') {\n oraInstance.fail(error);\n throw error;\n }\n }\n if (!repoUrl) {\n oraInstance.fail(`Invalid URL: ${chalk.red(`\"${template}\"`)}. Try again with a valid URL.`);\n throw new AbortCommandError();\n }\n\n if (repoUrl.origin !== 'https://github.com') {\n oraInstance.fail(\n `Invalid URL: ${chalk.red(\n `\"${template}\"`\n )}. Only GitHub repositories are supported. Try again with a valid GitHub URL.`\n );\n throw new AbortCommandError();\n }\n\n const repoInfo = await getRepoInfo(repoUrl, templatePath);\n\n if (!repoInfo) {\n oraInstance.fail(\n `Found invalid GitHub URL: ${chalk.red(`\"${template}\"`)}. Fix the URL and try again.`\n );\n throw new AbortCommandError();\n }\n\n const found = await hasRepo(repoInfo);\n\n if (!found) {\n oraInstance.fail(\n `Could not locate the repository for ${chalk.red(\n `\"${template}\"`\n )}. Check that the repository exists and try again.`\n );\n throw new AbortCommandError();\n }\n\n oraInstance.text = chalk.bold(\n `Downloading files from repo ${chalk.cyan(template)}. This might take a moment.`\n );\n\n return await downloadAndExtractRepoAsync(repoInfo, templateDirectory, { expName });\n}\n"],"names":["cloneTemplateAsync","debug","require","templateDirectory","projectRoot","template","exp","ora","expName","name","type","uri","extractLocalNpmTarballAsync","downloadAndExtractNpmModuleAsync","resolveAndDownloadRepoTemplateAsync","Error","resolveLocalTemplateAsync","error","templatePackageName","getTemplateNpmPackageNameFromSdkVersion","sdkVersion","Log","log","semver","major","getRepoInfo","url","examplePath","username","t","_branch","file","pathname","split","filePath","replace","join","undefined","infoResponse","fetchAsync","status","info","json","branch","RegExp","hasRepo","contentsUrl","packagePath","isUrlOk","downloadAndExtractRepoAsync","output","props","directory","filter","Boolean","strip","length","createGlobFilter","ignore","extractNpmTarballFromUrlAsync","oraInstance","templatePath","repoUrl","URL","code","fail","chalk","red","AbortCommandError","origin","repoInfo","found","text","bold","cyan"],"mappings":";;;;+BA2BsBA;;;eAAAA;;;;gEA1BJ;;;;;;;gEAEC;;;;;;wBAGQ;6DACN;sCACqB;qCACT;wBACC;qBAK3B;qBACiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAExB,MAAMC,QAAQC,QAAQ,SAAS;AASxB,eAAeF,mBAAmB,EACvCG,iBAAiB,EACjBC,WAAW,EACXC,QAAQ,EACRC,GAAG,EACHC,GAAG,EAOJ;IACC,IAAIF,UAAU;QACZ,MAAMG,UAAUF,IAAIG,IAAI;QACxB,MAAM,EAAEC,IAAI,EAAEC,GAAG,EAAE,GAAGN;QACtB,IAAIK,SAAS,QAAQ;YACnB,OAAO,MAAME,IAAAA,gCAA2B,EAACD,KAAKR,mBAAmB;gBAC/DK;YACF;QACF,OAAO,IAAIE,SAAS,OAAO;YACzB,OAAO,MAAMG,IAAAA,qCAAgC,EAACF,KAAKR,mBAAmB;gBACpEK;YACF;QACF,OAAO,IAAIE,SAAS,cAAc;YAChC,OAAO,MAAMI,oCAAoCX,mBAAmBI,KAAKC,SAASG;QACpF,OAAO;YACL,MAAM,IAAII,MAAM,CAAC,uBAAuB,EAAEL,MAAM;QAClD;IACF,OAAO;QACL,IAAI;YACF,OAAO,MAAMM,IAAAA,+CAAyB,EAAC;gBAAEb;gBAAmBC;gBAAaE;YAAI;QAC/E,EAAE,OAAOW,OAAY;YACnB,MAAMC,sBAAsBC,wCAAwCb,IAAIc,UAAU;YAClFnB,MAAM,6BAA6BiB;YACnC,OAAO,MAAML,IAAAA,qCAAgC,EAACK,qBAAqBf,mBAAmB;gBACpFK,SAASF,IAAIG,IAAI;YACnB;QACF;IACF;AACF;AAEA,4HAA4H,GAC5H,SAASU,wCAAwCC,UAAmB;IAClE,4DAA4D;IAC5D,IAAI,CAACA,cAAcA,eAAe,eAAe;QAC/CC,KAAIC,GAAG,CAAC;QACR,OAAO,CAAC,iCAAiC,CAAC;IAC5C;IACA,OAAO,CAAC,+BAA+B,EAAEC,iBAAM,CAACC,KAAK,CAACJ,aAAa;AACrE;AAEA,eAAeK,YAAYC,GAAQ,EAAEC,WAAoB;IACvD,MAAM,GAAGC,UAAUnB,MAAMoB,GAAGC,SAAS,GAAGC,KAAK,GAAGL,IAAIM,QAAQ,CAACC,KAAK,CAAC;IACnE,MAAMC,WAAWP,cAAcA,YAAYQ,OAAO,CAAC,OAAO,MAAMJ,KAAKK,IAAI,CAAC;IAE1E,+DAA+D;IAC/D,2DAA2D;IAC3D,IAAIP,MAAMQ,WAAW;QACnB,MAAMC,eAAe,MAAMC,IAAAA,kBAAU,EAAC,CAAC,6BAA6B,EAAEX,SAAS,CAAC,EAAEnB,MAAM;QACxF,IAAI6B,aAAaE,MAAM,KAAK,KAAK;YAC/B;QACF;QACA,MAAMC,OAAY,MAAMH,aAAaI,IAAI;QACzC,OAAO;YAAEd;YAAUnB;YAAMkC,QAAQF,IAAI,CAAC,iBAAiB;YAAEP;QAAS;IACpE;IAEA,qEAAqE;IACrE,MAAMS,SAAShB,cACX,GAAGG,QAAQ,CAAC,EAAEC,KAAKK,IAAI,CAAC,MAAM,CAACD,OAAO,CAAC,IAAIS,OAAO,CAAC,CAAC,EAAEV,SAAS,GAAG,CAAC,GAAG,MACtEJ;IAEJ,IAAIF,YAAYnB,QAAQkC,UAAUd,MAAM,QAAQ;QAC9C,OAAO;YAAED;YAAUnB;YAAMkC;YAAQT;QAAS;IAC5C;IACA,OAAOG;AACT;AAEA,SAASQ,QAAQ,EAAEjB,QAAQ,EAAEnB,IAAI,EAAEkC,MAAM,EAAET,QAAQ,EAAY;IAC7D,MAAMY,cAAc,CAAC,6BAA6B,EAAElB,SAAS,CAAC,EAAEnB,KAAK,SAAS,CAAC;IAC/E,MAAMsC,cAAc,GAAGb,WAAW,CAAC,CAAC,EAAEA,UAAU,GAAG,GAAG,aAAa,CAAC;IAEpE,OAAOc,IAAAA,YAAO,EAACF,cAAcC,cAAc,CAAC,KAAK,EAAEJ,QAAQ;AAC7D;AAEA,eAAeM,4BACb,EAAErB,QAAQ,EAAEnB,IAAI,EAAEkC,MAAM,EAAET,QAAQ,EAAY,EAC9CgB,MAAc,EACdC,KAA2B;IAE3B,MAAMzB,MAAM,CAAC,4BAA4B,EAAEE,SAAS,CAAC,EAAEnB,KAAK,QAAQ,EAAEkC,QAAQ;IAE9E1C,MAAM,6BAA6ByB;IAEnC,0DAA0D;IAC1D,MAAM0B,YAAYlB,SAASC,OAAO,CAAC,OAAO,IAAIF,KAAK,CAAC,KAAKoB,MAAM,CAACC;IAChE,uEAAuE;IACvE,MAAMC,QAAQH,UAAUI,MAAM,GAAG;IACjC,wEAAwE;IACxE,+DAA+D;IAC/D,MAAMH,SAASI,IAAAA,qCAAgB,EAC7B,CAACL,UAAUI,MAAM,GACb;QAAC;QAAQ;KAAmB,GAC5B;QAAC,CAAC,EAAE,EAAEJ,UAAUhB,IAAI,CAAC,KAAK,GAAG,CAAC;QAAE,CAAC,EAAE,EAAEgB,UAAUhB,IAAI,CAAC,KAAK,eAAe,CAAC;KAAC,EAC9E;QACE,0CAA0C;QAC1CsB,QAAQ;YAAC;SAA0B;IACrC;IAGF,OAAO,MAAMC,IAAAA,kCAA6B,EAACjC,KAAKwB,QAAQ;QACtD,GAAGC,KAAK;QACRI;QACAF;IACF;AACF;AAEA,eAAevC,oCACbX,iBAAyB,EACzByD,WAAgB,EAChBpD,OAAe,EACfH,QAAgB,EAChBwD,YAAqB;IAErB,IAAIC;IAEJ,IAAI;QACFA,UAAU,IAAIC,IAAI1D;IACpB,EAAE,OAAOY,OAAY;QACnB,IAAIA,MAAM+C,IAAI,KAAK,mBAAmB;YACpCJ,YAAYK,IAAI,CAAChD;YACjB,MAAMA;QACR;IACF;IACA,IAAI,CAAC6C,SAAS;QACZF,YAAYK,IAAI,CAAC,CAAC,aAAa,EAAEC,gBAAK,CAACC,GAAG,CAAC,CAAC,CAAC,EAAE9D,SAAS,CAAC,CAAC,EAAE,6BAA6B,CAAC;QAC1F,MAAM,IAAI+D,yBAAiB;IAC7B;IAEA,IAAIN,QAAQO,MAAM,KAAK,sBAAsB;QAC3CT,YAAYK,IAAI,CACd,CAAC,aAAa,EAAEC,gBAAK,CAACC,GAAG,CACvB,CAAC,CAAC,EAAE9D,SAAS,CAAC,CAAC,EACf,4EAA4E,CAAC;QAEjF,MAAM,IAAI+D,yBAAiB;IAC7B;IAEA,MAAME,WAAW,MAAM7C,YAAYqC,SAASD;IAE5C,IAAI,CAACS,UAAU;QACbV,YAAYK,IAAI,CACd,CAAC,0BAA0B,EAAEC,gBAAK,CAACC,GAAG,CAAC,CAAC,CAAC,EAAE9D,SAAS,CAAC,CAAC,EAAE,4BAA4B,CAAC;QAEvF,MAAM,IAAI+D,yBAAiB;IAC7B;IAEA,MAAMG,QAAQ,MAAM1B,QAAQyB;IAE5B,IAAI,CAACC,OAAO;QACVX,YAAYK,IAAI,CACd,CAAC,oCAAoC,EAAEC,gBAAK,CAACC,GAAG,CAC9C,CAAC,CAAC,EAAE9D,SAAS,CAAC,CAAC,EACf,iDAAiD,CAAC;QAEtD,MAAM,IAAI+D,yBAAiB;IAC7B;IAEAR,YAAYY,IAAI,GAAGN,gBAAK,CAACO,IAAI,CAC3B,CAAC,4BAA4B,EAAEP,gBAAK,CAACQ,IAAI,CAACrE,UAAU,2BAA2B,CAAC;IAGlF,OAAO,MAAM4C,4BAA4BqB,UAAUnE,mBAAmB;QAAEK;IAAQ;AAClF"}
1
+ {"version":3,"sources":["../../../src/prebuild/resolveTemplate.ts"],"sourcesContent":["import type { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport type { Ora } from 'ora';\nimport semver from 'semver';\n\nimport type { ResolvedTemplateOption } from './resolveOptions';\nimport * as Log from '../log';\nimport { resolveLocalTemplateAsync } from './resolveLocalTemplate';\nimport { createGlobFilter } from '../utils/createFileTransform';\nimport { AbortCommandError } from '../utils/errors';\nimport { fetch } from '../utils/fetch';\nimport {\n downloadAndExtractNpmModuleAsync,\n extractLocalNpmTarballAsync,\n extractNpmTarballFromUrlAsync,\n} from '../utils/npm';\n\nconst debug = require('debug')('expo:prebuild:resolveTemplate') as typeof console.log;\n\ntype RepoInfo = {\n username: string;\n name: string;\n branch: string;\n filePath: string;\n};\n\nexport async function cloneTemplateAsync({\n templateDirectory,\n projectRoot,\n template,\n exp,\n ora,\n}: {\n templateDirectory: string;\n projectRoot: string;\n template?: ResolvedTemplateOption;\n exp: Pick<ExpoConfig, 'name' | 'sdkVersion'>;\n ora: Ora;\n}): Promise<string> {\n if (template) {\n const expName = exp.name;\n const { type, uri } = template;\n if (type === 'file') {\n return await extractLocalNpmTarballAsync(uri, templateDirectory, {\n expName,\n });\n } else if (type === 'npm') {\n return await downloadAndExtractNpmModuleAsync(uri, templateDirectory, {\n expName,\n });\n } else if (type === 'repository') {\n return await resolveAndDownloadRepoTemplateAsync(templateDirectory, ora, expName, uri);\n } else {\n throw new Error(`Unknown template type: ${type}`);\n }\n } else {\n try {\n return await resolveLocalTemplateAsync({ templateDirectory, projectRoot, exp });\n } catch (error: any) {\n const templatePackageName = getTemplateNpmPackageNameFromSdkVersion(exp.sdkVersion);\n debug('Fallback to SDK template:', templatePackageName);\n return await downloadAndExtractNpmModuleAsync(templatePackageName, templateDirectory, {\n expName: exp.name,\n });\n }\n }\n}\n\n/** Given an `sdkVersion` like `44.0.0` return a fully qualified NPM package name like: `expo-template-bare-minimum@sdk-44` */\nfunction getTemplateNpmPackageNameFromSdkVersion(sdkVersion?: string): string {\n // When undefined or UNVERSIONED, we use the latest version.\n if (!sdkVersion || sdkVersion === 'UNVERSIONED') {\n Log.log('Using an unspecified Expo SDK version. The latest template will be used.');\n return `expo-template-bare-minimum@latest`;\n }\n return `expo-template-bare-minimum@sdk-${semver.major(sdkVersion)}`;\n}\n\nasync function getRepoInfo(url: any, examplePath?: string): Promise<RepoInfo | undefined> {\n const [, username, name, t, _branch, ...file] = url.pathname.split('/');\n const filePath = examplePath ? examplePath.replace(/^\\//, '') : file.join('/');\n\n // Support repos whose entire purpose is to be an example, e.g.\n // https://github.com/:username/:my-cool-example-repo-name.\n // Use the plain unauthenticated `fetch` so Expo credentials aren't forwarded to GitHub.\n if (t === undefined) {\n const infoResponse = await fetch(`https://api.github.com/repos/${username}/${name}`);\n if (infoResponse.status !== 200) {\n return;\n }\n const info: any = await infoResponse.json();\n return { username, name, branch: info['default_branch'], filePath };\n }\n\n // If examplePath is available, the branch name takes the entire path\n const branch = examplePath\n ? `${_branch}/${file.join('/')}`.replace(new RegExp(`/${filePath}|/$`), '')\n : _branch;\n\n if (username && name && branch && t === 'tree') {\n return { username, name, branch, filePath };\n }\n return undefined;\n}\n\nasync function hasRepo({ username, name, branch, filePath }: RepoInfo): Promise<boolean> {\n const contentsUrl = `https://api.github.com/repos/${username}/${name}/contents`;\n const packagePath = `${filePath ? `/${filePath}` : ''}/package.json`;\n\n try {\n const response = await fetch(contentsUrl + packagePath + `?ref=${branch}`);\n return response.ok;\n } catch {\n return false;\n }\n}\n\nasync function downloadAndExtractRepoAsync(\n { username, name, branch, filePath }: RepoInfo,\n output: string,\n props: { expName?: string }\n): Promise<string> {\n const url = `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`;\n\n debug('Downloading tarball from:', url);\n\n // Extract the (sub)directory into non-empty path segments\n const directory = filePath.replace(/^\\//, '').split('/').filter(Boolean);\n // Remove the (sub)directory paths, and the root folder added by GitHub\n const strip = directory.length + 1;\n // Only extract the relevant (sub)directories, ignoring irrelevant files\n // The filder auto-ignores dotfiles, unless explicitly included\n const filter = createGlobFilter(\n !directory.length\n ? ['*/**', '*/ios/.xcode.env']\n : [`*/${directory.join('/')}/**`, `*/${directory.join('/')}/ios/.xcode.env`],\n {\n // Always ignore the `.xcworkspace` folder\n ignore: ['**/ios/*.xcworkspace/**'],\n }\n );\n\n return await extractNpmTarballFromUrlAsync(url, output, {\n ...props,\n strip,\n filter,\n });\n}\n\nasync function resolveAndDownloadRepoTemplateAsync(\n templateDirectory: string,\n oraInstance: Ora,\n expName: string,\n template: string,\n templatePath?: string\n) {\n let repoUrl: URL | undefined;\n\n try {\n repoUrl = new URL(template);\n } catch (error: any) {\n if (error.code !== 'ERR_INVALID_URL') {\n oraInstance.fail(error);\n throw error;\n }\n }\n if (!repoUrl) {\n oraInstance.fail(`Invalid URL: ${chalk.red(`\"${template}\"`)}. Try again with a valid URL.`);\n throw new AbortCommandError();\n }\n\n if (repoUrl.origin !== 'https://github.com') {\n oraInstance.fail(\n `Invalid URL: ${chalk.red(\n `\"${template}\"`\n )}. Only GitHub repositories are supported. Try again with a valid GitHub URL.`\n );\n throw new AbortCommandError();\n }\n\n const repoInfo = await getRepoInfo(repoUrl, templatePath);\n\n if (!repoInfo) {\n oraInstance.fail(\n `Found invalid GitHub URL: ${chalk.red(`\"${template}\"`)}. Fix the URL and try again.`\n );\n throw new AbortCommandError();\n }\n\n const found = await hasRepo(repoInfo);\n\n if (!found) {\n oraInstance.fail(\n `Could not locate the repository for ${chalk.red(\n `\"${template}\"`\n )}. Check that the repository exists and try again.`\n );\n throw new AbortCommandError();\n }\n\n oraInstance.text = chalk.bold(\n `Downloading files from repo ${chalk.cyan(template)}. This might take a moment.`\n );\n\n return await downloadAndExtractRepoAsync(repoInfo, templateDirectory, { expName });\n}\n"],"names":["cloneTemplateAsync","debug","require","templateDirectory","projectRoot","template","exp","ora","expName","name","type","uri","extractLocalNpmTarballAsync","downloadAndExtractNpmModuleAsync","resolveAndDownloadRepoTemplateAsync","Error","resolveLocalTemplateAsync","error","templatePackageName","getTemplateNpmPackageNameFromSdkVersion","sdkVersion","Log","log","semver","major","getRepoInfo","url","examplePath","username","t","_branch","file","pathname","split","filePath","replace","join","undefined","infoResponse","fetch","status","info","json","branch","RegExp","hasRepo","contentsUrl","packagePath","response","ok","downloadAndExtractRepoAsync","output","props","directory","filter","Boolean","strip","length","createGlobFilter","ignore","extractNpmTarballFromUrlAsync","oraInstance","templatePath","repoUrl","URL","code","fail","chalk","red","AbortCommandError","origin","repoInfo","found","text","bold","cyan"],"mappings":";;;;+BA0BsBA;;;eAAAA;;;;gEAzBJ;;;;;;;gEAEC;;;;;;6DAGE;sCACqB;qCACT;wBACC;uBACZ;qBAKf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEP,MAAMC,QAAQC,QAAQ,SAAS;AASxB,eAAeF,mBAAmB,EACvCG,iBAAiB,EACjBC,WAAW,EACXC,QAAQ,EACRC,GAAG,EACHC,GAAG,EAOJ;IACC,IAAIF,UAAU;QACZ,MAAMG,UAAUF,IAAIG,IAAI;QACxB,MAAM,EAAEC,IAAI,EAAEC,GAAG,EAAE,GAAGN;QACtB,IAAIK,SAAS,QAAQ;YACnB,OAAO,MAAME,IAAAA,gCAA2B,EAACD,KAAKR,mBAAmB;gBAC/DK;YACF;QACF,OAAO,IAAIE,SAAS,OAAO;YACzB,OAAO,MAAMG,IAAAA,qCAAgC,EAACF,KAAKR,mBAAmB;gBACpEK;YACF;QACF,OAAO,IAAIE,SAAS,cAAc;YAChC,OAAO,MAAMI,oCAAoCX,mBAAmBI,KAAKC,SAASG;QACpF,OAAO;YACL,MAAM,IAAII,MAAM,CAAC,uBAAuB,EAAEL,MAAM;QAClD;IACF,OAAO;QACL,IAAI;YACF,OAAO,MAAMM,IAAAA,+CAAyB,EAAC;gBAAEb;gBAAmBC;gBAAaE;YAAI;QAC/E,EAAE,OAAOW,OAAY;YACnB,MAAMC,sBAAsBC,wCAAwCb,IAAIc,UAAU;YAClFnB,MAAM,6BAA6BiB;YACnC,OAAO,MAAML,IAAAA,qCAAgC,EAACK,qBAAqBf,mBAAmB;gBACpFK,SAASF,IAAIG,IAAI;YACnB;QACF;IACF;AACF;AAEA,4HAA4H,GAC5H,SAASU,wCAAwCC,UAAmB;IAClE,4DAA4D;IAC5D,IAAI,CAACA,cAAcA,eAAe,eAAe;QAC/CC,KAAIC,GAAG,CAAC;QACR,OAAO,CAAC,iCAAiC,CAAC;IAC5C;IACA,OAAO,CAAC,+BAA+B,EAAEC,iBAAM,CAACC,KAAK,CAACJ,aAAa;AACrE;AAEA,eAAeK,YAAYC,GAAQ,EAAEC,WAAoB;IACvD,MAAM,GAAGC,UAAUnB,MAAMoB,GAAGC,SAAS,GAAGC,KAAK,GAAGL,IAAIM,QAAQ,CAACC,KAAK,CAAC;IACnE,MAAMC,WAAWP,cAAcA,YAAYQ,OAAO,CAAC,OAAO,MAAMJ,KAAKK,IAAI,CAAC;IAE1E,+DAA+D;IAC/D,2DAA2D;IAC3D,wFAAwF;IACxF,IAAIP,MAAMQ,WAAW;QACnB,MAAMC,eAAe,MAAMC,IAAAA,YAAK,EAAC,CAAC,6BAA6B,EAAEX,SAAS,CAAC,EAAEnB,MAAM;QACnF,IAAI6B,aAAaE,MAAM,KAAK,KAAK;YAC/B;QACF;QACA,MAAMC,OAAY,MAAMH,aAAaI,IAAI;QACzC,OAAO;YAAEd;YAAUnB;YAAMkC,QAAQF,IAAI,CAAC,iBAAiB;YAAEP;QAAS;IACpE;IAEA,qEAAqE;IACrE,MAAMS,SAAShB,cACX,GAAGG,QAAQ,CAAC,EAAEC,KAAKK,IAAI,CAAC,MAAM,CAACD,OAAO,CAAC,IAAIS,OAAO,CAAC,CAAC,EAAEV,SAAS,GAAG,CAAC,GAAG,MACtEJ;IAEJ,IAAIF,YAAYnB,QAAQkC,UAAUd,MAAM,QAAQ;QAC9C,OAAO;YAAED;YAAUnB;YAAMkC;YAAQT;QAAS;IAC5C;IACA,OAAOG;AACT;AAEA,eAAeQ,QAAQ,EAAEjB,QAAQ,EAAEnB,IAAI,EAAEkC,MAAM,EAAET,QAAQ,EAAY;IACnE,MAAMY,cAAc,CAAC,6BAA6B,EAAElB,SAAS,CAAC,EAAEnB,KAAK,SAAS,CAAC;IAC/E,MAAMsC,cAAc,GAAGb,WAAW,CAAC,CAAC,EAAEA,UAAU,GAAG,GAAG,aAAa,CAAC;IAEpE,IAAI;QACF,MAAMc,WAAW,MAAMT,IAAAA,YAAK,EAACO,cAAcC,cAAc,CAAC,KAAK,EAAEJ,QAAQ;QACzE,OAAOK,SAASC,EAAE;IACpB,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA,eAAeC,4BACb,EAAEtB,QAAQ,EAAEnB,IAAI,EAAEkC,MAAM,EAAET,QAAQ,EAAY,EAC9CiB,MAAc,EACdC,KAA2B;IAE3B,MAAM1B,MAAM,CAAC,4BAA4B,EAAEE,SAAS,CAAC,EAAEnB,KAAK,QAAQ,EAAEkC,QAAQ;IAE9E1C,MAAM,6BAA6ByB;IAEnC,0DAA0D;IAC1D,MAAM2B,YAAYnB,SAASC,OAAO,CAAC,OAAO,IAAIF,KAAK,CAAC,KAAKqB,MAAM,CAACC;IAChE,uEAAuE;IACvE,MAAMC,QAAQH,UAAUI,MAAM,GAAG;IACjC,wEAAwE;IACxE,+DAA+D;IAC/D,MAAMH,SAASI,IAAAA,qCAAgB,EAC7B,CAACL,UAAUI,MAAM,GACb;QAAC;QAAQ;KAAmB,GAC5B;QAAC,CAAC,EAAE,EAAEJ,UAAUjB,IAAI,CAAC,KAAK,GAAG,CAAC;QAAE,CAAC,EAAE,EAAEiB,UAAUjB,IAAI,CAAC,KAAK,eAAe,CAAC;KAAC,EAC9E;QACE,0CAA0C;QAC1CuB,QAAQ;YAAC;SAA0B;IACrC;IAGF,OAAO,MAAMC,IAAAA,kCAA6B,EAAClC,KAAKyB,QAAQ;QACtD,GAAGC,KAAK;QACRI;QACAF;IACF;AACF;AAEA,eAAexC,oCACbX,iBAAyB,EACzB0D,WAAgB,EAChBrD,OAAe,EACfH,QAAgB,EAChByD,YAAqB;IAErB,IAAIC;IAEJ,IAAI;QACFA,UAAU,IAAIC,IAAI3D;IACpB,EAAE,OAAOY,OAAY;QACnB,IAAIA,MAAMgD,IAAI,KAAK,mBAAmB;YACpCJ,YAAYK,IAAI,CAACjD;YACjB,MAAMA;QACR;IACF;IACA,IAAI,CAAC8C,SAAS;QACZF,YAAYK,IAAI,CAAC,CAAC,aAAa,EAAEC,gBAAK,CAACC,GAAG,CAAC,CAAC,CAAC,EAAE/D,SAAS,CAAC,CAAC,EAAE,6BAA6B,CAAC;QAC1F,MAAM,IAAIgE,yBAAiB;IAC7B;IAEA,IAAIN,QAAQO,MAAM,KAAK,sBAAsB;QAC3CT,YAAYK,IAAI,CACd,CAAC,aAAa,EAAEC,gBAAK,CAACC,GAAG,CACvB,CAAC,CAAC,EAAE/D,SAAS,CAAC,CAAC,EACf,4EAA4E,CAAC;QAEjF,MAAM,IAAIgE,yBAAiB;IAC7B;IAEA,MAAME,WAAW,MAAM9C,YAAYsC,SAASD;IAE5C,IAAI,CAACS,UAAU;QACbV,YAAYK,IAAI,CACd,CAAC,0BAA0B,EAAEC,gBAAK,CAACC,GAAG,CAAC,CAAC,CAAC,EAAE/D,SAAS,CAAC,CAAC,EAAE,4BAA4B,CAAC;QAEvF,MAAM,IAAIgE,yBAAiB;IAC7B;IAEA,MAAMG,QAAQ,MAAM3B,QAAQ0B;IAE5B,IAAI,CAACC,OAAO;QACVX,YAAYK,IAAI,CACd,CAAC,oCAAoC,EAAEC,gBAAK,CAACC,GAAG,CAC9C,CAAC,CAAC,EAAE/D,SAAS,CAAC,CAAC,EACf,iDAAiD,CAAC;QAEtD,MAAM,IAAIgE,yBAAiB;IAC7B;IAEAR,YAAYY,IAAI,GAAGN,gBAAK,CAACO,IAAI,CAC3B,CAAC,4BAA4B,EAAEP,gBAAK,CAACQ,IAAI,CAACtE,UAAU,2BAA2B,CAAC;IAGlF,OAAO,MAAM6C,4BAA4BqB,UAAUpE,mBAAmB;QAAEK;IAAQ;AAClF"}
@@ -15,6 +15,9 @@ _export(exports, {
15
15
  adbArgs: function() {
16
16
  return adbArgs;
17
17
  },
18
+ adbShellArgs: function() {
19
+ return adbShellArgs;
20
+ },
18
21
  getAdbNameForDeviceIdAsync: function() {
19
22
  return getAdbNameForDeviceIdAsync;
20
23
  },
@@ -159,7 +162,7 @@ function logUnauthorized(device) {
159
162
  _log.warn(`\nThis computer is not authorized for developing on ${_chalk().default.bold(device.name)}. ${_chalk().default.dim((0, _link.learnMore)('https://expo.fyi/authorize-android-device'))}`);
160
163
  }
161
164
  async function isPackageInstalledAsync(device, androidPackage) {
162
- const packages = await getServer().runAsync(adbArgs(device.pid, 'shell', 'pm', 'list', 'packages', '--user', _env.env.EXPO_ADB_USER, androidPackage));
165
+ const packages = await getServer().runAsync(adbShellArgs(device.pid, 'pm', 'list', 'packages', '--user', _env.env.EXPO_ADB_USER, androidPackage));
163
166
  const lines = packages.split(/\r?\n/);
164
167
  for(let i = 0; i < lines.length; i++){
165
168
  const line = lines[i].trim();
@@ -170,8 +173,7 @@ async function isPackageInstalledAsync(device, androidPackage) {
170
173
  return false;
171
174
  }
172
175
  async function launchActivityAsync(device, { launchActivity, url }) {
173
- const args = [
174
- 'shell',
176
+ const command = [
175
177
  'am',
176
178
  'start',
177
179
  // FLAG_ACTIVITY_SINGLE_TOP -- If set, the activity will not be launched if it is already running at the top of the history stack.
@@ -182,13 +184,12 @@ async function launchActivityAsync(device, { launchActivity, url }) {
182
184
  launchActivity
183
185
  ];
184
186
  if (url) {
185
- args.push('-d', url);
187
+ command.push('-d', url);
186
188
  }
187
- return openAsync(adbArgs(device.pid, ...args));
189
+ return openAsync(adbShellArgs(device.pid, ...command));
188
190
  }
189
191
  async function openUrlAsync(device, { url }) {
190
- return openAsync(adbArgs(device.pid, 'shell', 'am', 'start', '-a', 'android.intent.action.VIEW', '-d', // ADB requires ampersands to be escaped.
191
- url.replace(/&/g, String.raw`\&`)));
192
+ return openAsync(adbShellArgs(device.pid, 'am', 'start', '-a', 'android.intent.action.VIEW', '-d', url));
192
193
  }
193
194
  /** Runs a generic command watches for common errors in order to throw with an expected code. */ async function openAsync(args) {
194
195
  const results = await getServer().runAsync(args);
@@ -201,7 +202,7 @@ async function uninstallAsync(device, { appId }) {
201
202
  return await getServer().runAsync(adbArgs(device.pid, 'uninstall', '--user', _env.env.EXPO_ADB_USER, appId));
202
203
  }
203
204
  async function getPackageInfoAsync(device, { appId }) {
204
- return await getServer().runAsync(adbArgs(device.pid, 'shell', 'dumpsys', 'package', appId));
205
+ return await getServer().runAsync(adbShellArgs(device.pid, 'dumpsys', 'package', appId));
205
206
  }
206
207
  async function installAsync(device, { filePath }) {
207
208
  // TODO: Handle the `INSTALL_FAILED_INSUFFICIENT_STORAGE` error.
@@ -214,6 +215,12 @@ function adbArgs(pid, ...options) {
214
215
  }
215
216
  return args.concat(options);
216
217
  }
218
+ function adbShellArgs(pid, ...command) {
219
+ return adbArgs(pid, 'shell', ...command.map(shellQuote));
220
+ }
221
+ function shellQuote(value) {
222
+ return `'${value.replace(/'/g, `'\\''`)}'`;
223
+ }
217
224
  async function getAttachedDevicesAsync() {
218
225
  const output = await getServer().runAsync([
219
226
  'devices',
@@ -325,13 +332,7 @@ async function getDeviceABIsAsync(device) {
325
332
  ];
326
333
  }
327
334
  async function getPropertyDataForDeviceAsync(device, prop) {
328
- // @ts-ignore
329
- const propCommand = adbArgs(...[
330
- device.pid,
331
- 'shell',
332
- 'getprop',
333
- prop
334
- ].filter(Boolean));
335
+ const propCommand = prop ? adbShellArgs(device.pid, 'getprop', prop) : adbShellArgs(device.pid, 'getprop');
335
336
  try {
336
337
  // Prevent reading as UTF8.
337
338
  const results = await getServer().getFileOutputAsync(propCommand);