@expo/cli 54.1.0-canary-20251023-4c86f95 → 55.0.0-canary-20251118-8f7ee64

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 (52) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/api/rest/cache/ResponseCache.js +3 -1
  3. package/build/src/api/rest/cache/ResponseCache.js.map +1 -1
  4. package/build/src/export/exportStaticAsync.js +30 -2
  5. package/build/src/export/exportStaticAsync.js.map +1 -1
  6. package/build/src/export/saveAssets.js +10 -0
  7. package/build/src/export/saveAssets.js.map +1 -1
  8. package/build/src/start/interface/commandsTable.js.map +1 -1
  9. package/build/src/start/interface/startInterface.js +3 -0
  10. package/build/src/start/interface/startInterface.js.map +1 -1
  11. package/build/src/start/platforms/android/AndroidDeviceManager.js +2 -7
  12. package/build/src/start/platforms/android/AndroidDeviceManager.js.map +1 -1
  13. package/build/src/start/platforms/android/adb.js +0 -6
  14. package/build/src/start/platforms/android/adb.js.map +1 -1
  15. package/build/src/start/server/MCP.js +15 -4
  16. package/build/src/start/server/MCP.js.map +1 -1
  17. package/build/src/start/server/metro/MetroBundlerDevServer.js +41 -36
  18. package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
  19. package/build/src/start/server/metro/createServerComponentsMiddleware.js +16 -16
  20. package/build/src/start/server/metro/createServerComponentsMiddleware.js.map +1 -1
  21. package/build/src/start/server/metro/createServerRouteMiddleware.js +7 -29
  22. package/build/src/start/server/metro/createServerRouteMiddleware.js.map +1 -1
  23. package/build/src/start/server/metro/debugging/createDebugMiddleware.js +3 -1
  24. package/build/src/start/server/metro/debugging/createDebugMiddleware.js.map +1 -1
  25. package/build/src/start/server/metro/errors/FailedToResolveNativeOnlyModuleError.js +17 -0
  26. package/build/src/start/server/metro/errors/FailedToResolveNativeOnlyModuleError.js.map +1 -0
  27. package/build/src/start/server/metro/fetchRouterManifest.js.map +1 -1
  28. package/build/src/start/server/metro/instantiateMetro.js +14 -10
  29. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  30. package/build/src/start/server/metro/resolveLoader.js +65 -0
  31. package/build/src/start/server/metro/resolveLoader.js.map +1 -0
  32. package/build/src/start/server/metro/withMetroMultiPlatform.js +25 -26
  33. package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
  34. package/build/src/start/server/middleware/DataLoaderModuleMiddleware.js.map +1 -1
  35. package/build/src/start/server/middleware/inspector/CdpClient.js +2 -0
  36. package/build/src/start/server/middleware/inspector/CdpClient.js.map +1 -1
  37. package/build/src/start/server/type-generation/routes.js +3 -1
  38. package/build/src/start/server/type-generation/routes.js.map +1 -1
  39. package/build/src/start/startAsync.js +11 -8
  40. package/build/src/start/startAsync.js.map +1 -1
  41. package/build/src/utils/env.js +0 -3
  42. package/build/src/utils/env.js.map +1 -1
  43. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  44. package/build/src/utils/telemetry/utils/context.js +1 -1
  45. package/package.json +21 -23
  46. package/static/template/[...rsc]+api.ts +1 -1
  47. package/build/src/start/server/metro/createExpoMetroResolver.js +0 -265
  48. package/build/src/start/server/metro/createExpoMetroResolver.js.map +0 -1
  49. package/build/src/start/server/metro/createJResolver.js +0 -201
  50. package/build/src/start/server/metro/createJResolver.js.map +0 -1
  51. package/build/src/start/server/metro/formatFileCandidates.js +0 -84
  52. package/build/src/start/server/metro/formatFileCandidates.js.map +0 -1
package/build/bin/cli CHANGED
@@ -123,7 +123,7 @@ const args = (0, _arg().default)({
123
123
  });
124
124
  if (args['--version']) {
125
125
  // Version is added in the build script.
126
- console.log("54.1.0-canary-20251023-4c86f95");
126
+ console.log("55.0.0-canary-20251118-8f7ee64");
127
127
  process.exit(0);
128
128
  }
129
129
  if (args['--non-interactive']) {
@@ -43,11 +43,13 @@ function _interop_require_default(obj) {
43
43
  }
44
44
  const GLOBAL_CACHE_VERSION = 4;
45
45
  function getResponseInfo(response) {
46
+ const headers = Object.fromEntries(response.headers.entries());
47
+ delete headers['set-cookie'];
46
48
  return {
47
49
  url: response.url,
48
50
  status: response.status,
49
51
  statusText: response.statusText,
50
- headers: Object.fromEntries(response.headers.entries())
52
+ headers
51
53
  };
52
54
  }
53
55
  function getRequestCacheKey(info, init) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/api/rest/cache/ResponseCache.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { ReadStream } from 'fs';\nimport type { Response, RequestInfo, RequestInit } from 'undici';\n\nconst GLOBAL_CACHE_VERSION = 4;\n\nexport type ResponseCacheEntry = {\n body: import('stream/web').ReadableStream;\n info: ReturnType<typeof getResponseInfo>;\n};\n\nexport interface ResponseCache {\n /** Load the response info from cache, if any */\n get(cacheKey: string): Promise<ResponseCacheEntry | undefined>;\n /** Store the response info to cache, and return the cached info */\n set(cacheKey: string, response: ResponseCacheEntry): Promise<ResponseCacheEntry | undefined>;\n /** Remove a response entry from the cache */\n remove(cacheKey: string): Promise<void>;\n}\n\nexport function getResponseInfo(response: Response) {\n return {\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n };\n}\n\nexport function getRequestCacheKey(info: RequestInfo, init?: RequestInit) {\n const infoKeyData = getRequestInfoCacheData(info);\n const initKeyData = { body: init?.body ? getRequestBodyCacheData(init.body) : undefined };\n\n return crypto\n .createHash('md5')\n .update(JSON.stringify([infoKeyData, initKeyData, GLOBAL_CACHE_VERSION]))\n .digest('hex');\n}\n\n/** @internal Exposed for testing */\nexport function getRequestInfoCacheData(info: RequestInfo) {\n if (typeof info === 'string') {\n return { url: info };\n }\n\n if (info instanceof URL) {\n return { url: info.toString() };\n }\n\n if (info instanceof Request) {\n return {\n // cache: req.cache,\n credentials: info.credentials.toString(),\n destination: info.destination.toString(),\n headers: Object.fromEntries(info.headers.entries()),\n integrity: info.integrity,\n method: info.method,\n redirect: info.redirect,\n referrer: info.referrer,\n referrerPolicy: info.referrerPolicy,\n url: info.url.toString(),\n // body: // TODO\n };\n }\n\n throw new Error('Unsupported request info type for caching: ' + typeof info);\n}\n\n/** @internal Exposed for testing */\nexport function getRequestBodyCacheData(body: RequestInit['body']) {\n if (!body) {\n return body;\n }\n\n if (typeof body === 'string') {\n return body;\n }\n\n if (body instanceof URLSearchParams) {\n return body.toString();\n }\n\n // Supported for legacy purposes because node-fetch uses fs.readStream\n if (body instanceof ReadStream) {\n return body.path;\n }\n\n if (body.toString && body.toString() === '[object FormData]') {\n return new URLSearchParams(body as any).toString();\n }\n\n if (body instanceof Buffer) {\n return body.toString();\n }\n\n throw new Error(`Unsupported request body type for caching: ${typeof body}`);\n}\n"],"names":["getRequestBodyCacheData","getRequestCacheKey","getRequestInfoCacheData","getResponseInfo","GLOBAL_CACHE_VERSION","response","url","status","statusText","headers","Object","fromEntries","entries","info","init","infoKeyData","initKeyData","body","undefined","crypto","createHash","update","JSON","stringify","digest","URL","toString","Request","credentials","destination","integrity","method","redirect","referrer","referrerPolicy","Error","URLSearchParams","ReadStream","path","Buffer"],"mappings":";;;;;;;;;;;IAqEgBA,uBAAuB;eAAvBA;;IAxCAC,kBAAkB;eAAlBA;;IAWAC,uBAAuB;eAAvBA;;IApBAC,eAAe;eAAfA;;;;gEApBG;;;;;;;yBACQ;;;;;;;;;;;AAG3B,MAAMC,uBAAuB;AAgBtB,SAASD,gBAAgBE,QAAkB;IAChD,OAAO;QACLC,KAAKD,SAASC,GAAG;QACjBC,QAAQF,SAASE,MAAM;QACvBC,YAAYH,SAASG,UAAU;QAC/BC,SAASC,OAAOC,WAAW,CAACN,SAASI,OAAO,CAACG,OAAO;IACtD;AACF;AAEO,SAASX,mBAAmBY,IAAiB,EAAEC,IAAkB;IACtE,MAAMC,cAAcb,wBAAwBW;IAC5C,MAAMG,cAAc;QAAEC,MAAMH,CAAAA,wBAAAA,KAAMG,IAAI,IAAGjB,wBAAwBc,KAAKG,IAAI,IAAIC;IAAU;IAExF,OAAOC,iBAAM,CACVC,UAAU,CAAC,OACXC,MAAM,CAACC,KAAKC,SAAS,CAAC;QAACR;QAAaC;QAAaZ;KAAqB,GACtEoB,MAAM,CAAC;AACZ;AAGO,SAAStB,wBAAwBW,IAAiB;IACvD,IAAI,OAAOA,SAAS,UAAU;QAC5B,OAAO;YAAEP,KAAKO;QAAK;IACrB;IAEA,IAAIA,gBAAgBY,KAAK;QACvB,OAAO;YAAEnB,KAAKO,KAAKa,QAAQ;QAAG;IAChC;IAEA,IAAIb,gBAAgBc,SAAS;QAC3B,OAAO;YACL,oBAAoB;YACpBC,aAAaf,KAAKe,WAAW,CAACF,QAAQ;YACtCG,aAAahB,KAAKgB,WAAW,CAACH,QAAQ;YACtCjB,SAASC,OAAOC,WAAW,CAACE,KAAKJ,OAAO,CAACG,OAAO;YAChDkB,WAAWjB,KAAKiB,SAAS;YACzBC,QAAQlB,KAAKkB,MAAM;YACnBC,UAAUnB,KAAKmB,QAAQ;YACvBC,UAAUpB,KAAKoB,QAAQ;YACvBC,gBAAgBrB,KAAKqB,cAAc;YACnC5B,KAAKO,KAAKP,GAAG,CAACoB,QAAQ;QAExB;IACF;IAEA,MAAM,IAAIS,MAAM,gDAAgD,OAAOtB;AACzE;AAGO,SAASb,wBAAwBiB,IAAyB;IAC/D,IAAI,CAACA,MAAM;QACT,OAAOA;IACT;IAEA,IAAI,OAAOA,SAAS,UAAU;QAC5B,OAAOA;IACT;IAEA,IAAIA,gBAAgBmB,iBAAiB;QACnC,OAAOnB,KAAKS,QAAQ;IACtB;IAEA,sEAAsE;IACtE,IAAIT,gBAAgBoB,gBAAU,EAAE;QAC9B,OAAOpB,KAAKqB,IAAI;IAClB;IAEA,IAAIrB,KAAKS,QAAQ,IAAIT,KAAKS,QAAQ,OAAO,qBAAqB;QAC5D,OAAO,IAAIU,gBAAgBnB,MAAaS,QAAQ;IAClD;IAEA,IAAIT,gBAAgBsB,QAAQ;QAC1B,OAAOtB,KAAKS,QAAQ;IACtB;IAEA,MAAM,IAAIS,MAAM,CAAC,2CAA2C,EAAE,OAAOlB,MAAM;AAC7E"}
1
+ {"version":3,"sources":["../../../../../src/api/rest/cache/ResponseCache.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { ReadStream } from 'fs';\nimport type { Response, RequestInfo, RequestInit } from 'undici';\n\nconst GLOBAL_CACHE_VERSION = 4;\n\nexport type ResponseCacheEntry = {\n body: import('stream/web').ReadableStream;\n info: ReturnType<typeof getResponseInfo>;\n};\n\nexport interface ResponseCache {\n /** Load the response info from cache, if any */\n get(cacheKey: string): Promise<ResponseCacheEntry | undefined>;\n /** Store the response info to cache, and return the cached info */\n set(cacheKey: string, response: ResponseCacheEntry): Promise<ResponseCacheEntry | undefined>;\n /** Remove a response entry from the cache */\n remove(cacheKey: string): Promise<void>;\n}\n\nexport function getResponseInfo(response: Response) {\n const headers = Object.fromEntries(response.headers.entries());\n delete headers['set-cookie'];\n return {\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n headers,\n };\n}\n\nexport function getRequestCacheKey(info: RequestInfo, init?: RequestInit) {\n const infoKeyData = getRequestInfoCacheData(info);\n const initKeyData = { body: init?.body ? getRequestBodyCacheData(init.body) : undefined };\n\n return crypto\n .createHash('md5')\n .update(JSON.stringify([infoKeyData, initKeyData, GLOBAL_CACHE_VERSION]))\n .digest('hex');\n}\n\n/** @internal Exposed for testing */\nexport function getRequestInfoCacheData(info: RequestInfo) {\n if (typeof info === 'string') {\n return { url: info };\n }\n\n if (info instanceof URL) {\n return { url: info.toString() };\n }\n\n if (info instanceof Request) {\n return {\n // cache: req.cache,\n credentials: info.credentials.toString(),\n destination: info.destination.toString(),\n headers: Object.fromEntries(info.headers.entries()),\n integrity: info.integrity,\n method: info.method,\n redirect: info.redirect,\n referrer: info.referrer,\n referrerPolicy: info.referrerPolicy,\n url: info.url.toString(),\n // body: // TODO\n };\n }\n\n throw new Error('Unsupported request info type for caching: ' + typeof info);\n}\n\n/** @internal Exposed for testing */\nexport function getRequestBodyCacheData(body: RequestInit['body']) {\n if (!body) {\n return body;\n }\n\n if (typeof body === 'string') {\n return body;\n }\n\n if (body instanceof URLSearchParams) {\n return body.toString();\n }\n\n // Supported for legacy purposes because node-fetch uses fs.readStream\n if (body instanceof ReadStream) {\n return body.path;\n }\n\n if (body.toString && body.toString() === '[object FormData]') {\n return new URLSearchParams(body as any).toString();\n }\n\n if (body instanceof Buffer) {\n return body.toString();\n }\n\n throw new Error(`Unsupported request body type for caching: ${typeof body}`);\n}\n"],"names":["getRequestBodyCacheData","getRequestCacheKey","getRequestInfoCacheData","getResponseInfo","GLOBAL_CACHE_VERSION","response","headers","Object","fromEntries","entries","url","status","statusText","info","init","infoKeyData","initKeyData","body","undefined","crypto","createHash","update","JSON","stringify","digest","URL","toString","Request","credentials","destination","integrity","method","redirect","referrer","referrerPolicy","Error","URLSearchParams","ReadStream","path","Buffer"],"mappings":";;;;;;;;;;;IAuEgBA,uBAAuB;eAAvBA;;IAxCAC,kBAAkB;eAAlBA;;IAWAC,uBAAuB;eAAvBA;;IAtBAC,eAAe;eAAfA;;;;gEApBG;;;;;;;yBACQ;;;;;;;;;;;AAG3B,MAAMC,uBAAuB;AAgBtB,SAASD,gBAAgBE,QAAkB;IAChD,MAAMC,UAAUC,OAAOC,WAAW,CAACH,SAASC,OAAO,CAACG,OAAO;IAC3D,OAAOH,OAAO,CAAC,aAAa;IAC5B,OAAO;QACLI,KAAKL,SAASK,GAAG;QACjBC,QAAQN,SAASM,MAAM;QACvBC,YAAYP,SAASO,UAAU;QAC/BN;IACF;AACF;AAEO,SAASL,mBAAmBY,IAAiB,EAAEC,IAAkB;IACtE,MAAMC,cAAcb,wBAAwBW;IAC5C,MAAMG,cAAc;QAAEC,MAAMH,CAAAA,wBAAAA,KAAMG,IAAI,IAAGjB,wBAAwBc,KAAKG,IAAI,IAAIC;IAAU;IAExF,OAAOC,iBAAM,CACVC,UAAU,CAAC,OACXC,MAAM,CAACC,KAAKC,SAAS,CAAC;QAACR;QAAaC;QAAaZ;KAAqB,GACtEoB,MAAM,CAAC;AACZ;AAGO,SAAStB,wBAAwBW,IAAiB;IACvD,IAAI,OAAOA,SAAS,UAAU;QAC5B,OAAO;YAAEH,KAAKG;QAAK;IACrB;IAEA,IAAIA,gBAAgBY,KAAK;QACvB,OAAO;YAAEf,KAAKG,KAAKa,QAAQ;QAAG;IAChC;IAEA,IAAIb,gBAAgBc,SAAS;QAC3B,OAAO;YACL,oBAAoB;YACpBC,aAAaf,KAAKe,WAAW,CAACF,QAAQ;YACtCG,aAAahB,KAAKgB,WAAW,CAACH,QAAQ;YACtCpB,SAASC,OAAOC,WAAW,CAACK,KAAKP,OAAO,CAACG,OAAO;YAChDqB,WAAWjB,KAAKiB,SAAS;YACzBC,QAAQlB,KAAKkB,MAAM;YACnBC,UAAUnB,KAAKmB,QAAQ;YACvBC,UAAUpB,KAAKoB,QAAQ;YACvBC,gBAAgBrB,KAAKqB,cAAc;YACnCxB,KAAKG,KAAKH,GAAG,CAACgB,QAAQ;QAExB;IACF;IAEA,MAAM,IAAIS,MAAM,gDAAgD,OAAOtB;AACzE;AAGO,SAASb,wBAAwBiB,IAAyB;IAC/D,IAAI,CAACA,MAAM;QACT,OAAOA;IACT;IAEA,IAAI,OAAOA,SAAS,UAAU;QAC5B,OAAOA;IACT;IAEA,IAAIA,gBAAgBmB,iBAAiB;QACnC,OAAOnB,KAAKS,QAAQ;IACtB;IAEA,sEAAsE;IACtE,IAAIT,gBAAgBoB,gBAAU,EAAE;QAC9B,OAAOpB,KAAKqB,IAAI;IAClB;IAEA,IAAIrB,KAAKS,QAAQ,IAAIT,KAAKS,QAAQ,OAAO,qBAAqB;QAC5D,OAAO,IAAIU,gBAAgBnB,MAAaS,QAAQ;IAClD;IAEA,IAAIT,gBAAgBsB,QAAQ;QAC1B,OAAOtB,KAAKS,QAAQ;IACtB;IAEA,MAAM,IAAIS,MAAM,CAAC,2CAA2C,EAAE,OAAOlB,MAAM;AAC7E"}
@@ -40,6 +40,13 @@ function _chalk() {
40
40
  };
41
41
  return data;
42
42
  }
43
+ function _utils() {
44
+ const data = require("expo-router/build/loaders/utils");
45
+ _utils = function() {
46
+ return data;
47
+ };
48
+ return data;
49
+ }
43
50
  function _matchers() {
44
51
  const data = require("expo-router/build/matchers");
45
52
  _matchers = function() {
@@ -190,7 +197,7 @@ async function exportFromServerAsync(projectRoot, devServer, { outputDir, baseUr
190
197
  files,
191
198
  exp
192
199
  });
193
- const [resources, { manifest, serverManifest, renderAsync }] = await Promise.all([
200
+ const [resources, { manifest, serverManifest, renderAsync, executeLoaderAsync }] = await Promise.all([
194
201
  devServer.getStaticResourcesAsync({
195
202
  includeSourceMaps
196
203
  }),
@@ -207,7 +214,28 @@ async function exportFromServerAsync(projectRoot, devServer, { outputDir, baseUr
207
214
  serverManifest,
208
215
  exportServer,
209
216
  async renderAsync ({ pathname, route }) {
210
- const template = await renderAsync(pathname);
217
+ var _exp_extra_router, _exp_extra;
218
+ const normalizedPathname = pathname === '' ? '/' : pathname.startsWith('/') ? pathname : `/${pathname}`;
219
+ const useServerLoaders = exp == null ? void 0 : (_exp_extra = exp.extra) == null ? void 0 : (_exp_extra_router = _exp_extra.router) == null ? void 0 : _exp_extra_router.unstable_useServerDataLoaders;
220
+ let renderOpts;
221
+ if (useServerLoaders) {
222
+ const loaderData = await executeLoaderAsync(normalizedPathname, route);
223
+ if (loaderData != null) {
224
+ const loaderPath = (0, _utils().getLoaderModulePath)(normalizedPathname);
225
+ const fileSystemPath = loaderPath.startsWith('/') ? loaderPath.slice(1) : loaderPath;
226
+ files.set(fileSystemPath, {
227
+ contents: JSON.stringify(loaderData, null, 2),
228
+ targetDomain: 'client',
229
+ loaderId: normalizedPathname
230
+ });
231
+ renderOpts = {
232
+ loader: {
233
+ data: loaderData
234
+ }
235
+ };
236
+ }
237
+ }
238
+ const template = await renderAsync(normalizedPathname, route, renderOpts);
211
239
  let html = await (0, _serializeHtml.serializeHtmlWithAssets)({
212
240
  isExporting,
213
241
  resources: resources.artifacts,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/export/exportStaticAsync.ts"],"sourcesContent":["/**\n * Copyright © 2022 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport { RouteNode } from 'expo-router/build/Route';\nimport { stripGroupSegmentsFromPath } from 'expo-router/build/matchers';\nimport { shouldLinkExternally } from 'expo-router/build/utils/url';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\nimport { inspect } from 'util';\n\nimport { getVirtualFaviconAssetsAsync } from './favicon';\nimport { persistMetroAssetsAsync } from './persistMetroAssets';\nimport { ExportAssetMap, getFilesFromSerialAssets } from './saveAssets';\nimport { Log } from '../log';\nimport {\n ExpoRouterRuntimeManifest,\n MetroBundlerDevServer,\n} from '../start/server/metro/MetroBundlerDevServer';\nimport { ExpoRouterServerManifestV1 } from '../start/server/metro/fetchRouterManifest';\nimport { logMetroErrorAsync } from '../start/server/metro/metroErrorInterface';\nimport { getApiRoutesForDirectory, getMiddlewareForDirectory } from '../start/server/metro/router';\nimport { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';\nimport { learnMore } from '../utils/link';\n\nconst debug = require('debug')('expo:export:generateStaticRoutes') as typeof console.log;\n\ntype ExtraScriptTag = {\n platform: string;\n src: string;\n};\n\ntype Options = {\n mode: 'production' | 'development';\n files?: ExportAssetMap;\n outputDir: string;\n minify: boolean;\n exportServer: boolean;\n baseUrl: string;\n includeSourceMaps: boolean;\n entryPoint?: string;\n clear: boolean;\n routerRoot: string;\n reactCompiler: boolean;\n maxWorkers?: number;\n isExporting: boolean;\n exp?: ExpoConfig;\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n scriptTags?: ExtraScriptTag[];\n};\n\ntype HtmlRequestLocation = {\n /** The output file path name to use relative to the static folder. */\n filePath: string;\n /** The pathname to make requests to in order to fetch the HTML. */\n pathname: string;\n /** The runtime route node object, used to associate async modules with the static HTML. */\n route: RouteNode;\n};\n\nexport function injectScriptTags(html: string, scriptTags: ExtraScriptTag[]): string {\n const scriptTagsHtml = scriptTags\n .map((tag) =>\n tag.platform === 'web'\n ? `<script src=\"${tag.src}\"></script>`\n : `<script type=\"type/expo\" src=\"${tag.src}\" data-platform=\"${tag.platform}\"></script>`\n )\n .join('\\n');\n html = html.replace('</head>', `${scriptTagsHtml}\\n</head>`);\n return html;\n}\n\n/** Match `(page)` -> `page` */\nfunction matchGroupName(name: string): string | undefined {\n return name.match(/^\\(([^/]+?)\\)$/)?.[1];\n}\n\nexport async function getFilesToExportFromServerAsync(\n projectRoot: string,\n {\n manifest,\n serverManifest,\n renderAsync,\n // Servers can handle group routes automatically and therefore\n // don't require the build-time generation of every possible group\n // variation.\n exportServer,\n // name : contents\n files = new Map(),\n }: {\n manifest: ExpoRouterRuntimeManifest;\n serverManifest: ExpoRouterServerManifestV1;\n renderAsync: (requestLocation: HtmlRequestLocation) => Promise<string>;\n exportServer?: boolean;\n files?: ExportAssetMap;\n }\n): Promise<ExportAssetMap> {\n if (!exportServer && serverManifest) {\n // When we're not exporting a `server` output, we provide a `_expo/.routes.json` for\n // EAS Hosting to recognize the `headers` and `redirects` configs\n const subsetServerManifest = {\n headers: serverManifest.headers,\n redirects: serverManifest.redirects,\n };\n files.set('_expo/.routes.json', {\n contents: JSON.stringify(subsetServerManifest, null, 2),\n targetDomain: 'client',\n });\n }\n\n await Promise.all(\n getHtmlFiles({ manifest, includeGroupVariations: !exportServer }).map(\n async ({ route, filePath, pathname }) => {\n // Rewrite routes should not be statically generated\n if (route.type === 'rewrite') {\n return;\n }\n\n try {\n const targetDomain = exportServer ? 'server' : 'client';\n files.set(filePath, { contents: '', targetDomain });\n const data = await renderAsync({ route, filePath, pathname });\n files.set(filePath, {\n contents: data,\n routeId: pathname,\n targetDomain,\n });\n } catch (e: any) {\n await logMetroErrorAsync({ error: e, projectRoot });\n throw new Error('Failed to statically export route: ' + pathname);\n }\n }\n )\n );\n\n return files;\n}\n\nfunction modifyRouteNodeInRuntimeManifest(\n manifest: ExpoRouterRuntimeManifest,\n callback: (route: RouteNode) => any\n) {\n const iterateScreens = (screens: ExpoRouterRuntimeManifest['screens']) => {\n Object.values(screens).map((value) => {\n if (typeof value !== 'string') {\n if (value._route) callback(value._route);\n iterateScreens(value.screens);\n }\n });\n };\n\n iterateScreens(manifest.screens);\n}\n\n// TODO: Do this earlier in the process.\nfunction makeRuntimeEntryPointsAbsolute(manifest: ExpoRouterRuntimeManifest, appDir: string) {\n modifyRouteNodeInRuntimeManifest(manifest, (route) => {\n if (Array.isArray(route.entryPoints)) {\n route.entryPoints = route.entryPoints.map((entryPoint) => {\n // TODO(@hassankhan): ENG-16577\n if (shouldLinkExternally(entryPoint)) {\n return entryPoint;\n }\n\n if (entryPoint.startsWith('.')) {\n return path.resolve(appDir, entryPoint);\n } else if (!path.isAbsolute(entryPoint)) {\n return resolveFrom(appDir, entryPoint);\n }\n return entryPoint;\n });\n }\n });\n}\n\n/** Perform all fs commits */\nexport async function exportFromServerAsync(\n projectRoot: string,\n devServer: MetroBundlerDevServer,\n {\n outputDir,\n baseUrl,\n exportServer,\n includeSourceMaps,\n routerRoot,\n files = new Map(),\n exp,\n scriptTags,\n }: Options\n): Promise<ExportAssetMap> {\n Log.log(\n `Static rendering is enabled. ` +\n learnMore('https://docs.expo.dev/router/reference/static-rendering/')\n );\n\n const platform = 'web';\n const isExporting = true;\n const appDir = path.join(projectRoot, routerRoot);\n const injectFaviconTag = await getVirtualFaviconAssetsAsync(projectRoot, {\n outputDir,\n baseUrl,\n files,\n exp,\n });\n\n const [resources, { manifest, serverManifest, renderAsync }] = await Promise.all([\n devServer.getStaticResourcesAsync({\n includeSourceMaps,\n }),\n devServer.getStaticRenderFunctionAsync(),\n ]);\n\n makeRuntimeEntryPointsAbsolute(manifest, appDir);\n\n debug('Routes:\\n', inspect(manifest, { colors: true, depth: null }));\n\n await getFilesToExportFromServerAsync(projectRoot, {\n files,\n manifest,\n serverManifest,\n exportServer,\n async renderAsync({ pathname, route }) {\n const template = await renderAsync(pathname);\n let html = await serializeHtmlWithAssets({\n isExporting,\n resources: resources.artifacts,\n template,\n baseUrl,\n route,\n hydrate: true,\n });\n\n if (injectFaviconTag) {\n html = injectFaviconTag(html);\n }\n\n if (scriptTags) {\n // Inject script tags into the HTML.\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n html = injectScriptTags(html, scriptTags);\n }\n\n return html;\n },\n });\n\n getFilesFromSerialAssets(resources.artifacts, {\n platform,\n includeSourceMaps,\n files,\n isServerHosted: true,\n });\n\n if (resources.assets) {\n // TODO: Collect files without writing to disk.\n // NOTE(kitten): Re. above, this is now using `files` except for iOS catalog output, which isn't used here\n await persistMetroAssetsAsync(projectRoot, resources.assets, {\n files,\n platform,\n outputDirectory: outputDir,\n baseUrl,\n });\n }\n\n if (exportServer) {\n const apiRoutes = await exportApiRoutesAsync({\n platform: 'web',\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n } else {\n warnPossibleInvalidExportType(appDir);\n }\n\n return files;\n}\n\nexport function getHtmlFiles({\n manifest,\n includeGroupVariations,\n}: {\n manifest: ExpoRouterRuntimeManifest;\n includeGroupVariations?: boolean;\n}): HtmlRequestLocation[] {\n const htmlFiles = new Set<Omit<HtmlRequestLocation, 'pathname'>>();\n\n function traverseScreens(\n screens: ExpoRouterRuntimeManifest['screens'],\n route: RouteNode | null,\n baseUrl = ''\n ) {\n for (const [key, value] of Object.entries(screens)) {\n let leaf: string | null = null;\n if (typeof value === 'string') {\n leaf = value;\n } else if (value.screens && Object.keys(value.screens).length === 0) {\n // Ensure the trailing index is accounted for.\n if (key === value.path + '/index') {\n leaf = key;\n } else {\n leaf = value.path;\n }\n\n route = value._route ?? null;\n }\n\n if (leaf != null) {\n let filePath = baseUrl + leaf;\n\n if (leaf === '') {\n filePath =\n baseUrl === ''\n ? 'index'\n : baseUrl.endsWith('/')\n ? baseUrl + 'index'\n : baseUrl.slice(0, -1);\n } else if (\n // If the path is a collection of group segments leading to an index route, append `/index`.\n stripGroupSegmentsFromPath(filePath) === ''\n ) {\n filePath += '/index';\n }\n\n // This should never happen, the type of `string | object` originally comes from React Navigation.\n if (!route) {\n throw new Error(\n `Internal error: Route not found for \"${filePath}\" while collecting static export paths.`\n );\n }\n\n if (includeGroupVariations) {\n // TODO: Dedupe requests for alias routes.\n addOptionalGroups(filePath, route);\n } else {\n htmlFiles.add({\n filePath,\n route,\n });\n }\n } else if (typeof value === 'object' && value?.screens) {\n // The __root slot has no path.\n const newPath = value.path ? baseUrl + value.path + '/' : baseUrl;\n traverseScreens(value.screens, value._route ?? null, newPath);\n }\n }\n }\n\n function addOptionalGroups(path: string, route: RouteNode) {\n const variations = getPathVariations(path);\n for (const variation of variations) {\n htmlFiles.add({ filePath: variation, route });\n }\n }\n\n traverseScreens(manifest.screens, null);\n\n return uniqueBy(Array.from(htmlFiles), (value) => value.filePath).map((value) => {\n const parts = value.filePath.split('/');\n // Replace `:foo` with `[foo]` and `*foo` with `[...foo]`\n const partsWithGroups = parts.map((part) => {\n if (part === '*not-found') {\n return `+not-found`;\n } else if (part.startsWith(':')) {\n return `[${part.slice(1)}]`;\n } else if (part.startsWith('*')) {\n return `[...${part.slice(1)}]`;\n }\n return part;\n });\n const filePathLocation = partsWithGroups.join('/');\n const filePath = filePathLocation + '.html';\n return {\n ...value,\n filePath,\n pathname: filePathLocation.replace(/(\\/?index)?$/, ''),\n };\n });\n}\n\nfunction uniqueBy<T>(array: T[], key: (value: T) => string): T[] {\n const seen = new Set<string>();\n const result: T[] = [];\n for (const value of array) {\n const id = key(value);\n if (!seen.has(id)) {\n seen.add(id);\n result.push(value);\n }\n }\n return result;\n}\n\n// Given a route like `(foo)/bar/(baz)`, return all possible variations of the route.\n// e.g. `(foo)/bar/(baz)`, `(foo)/bar/baz`, `foo/bar/(baz)`, `foo/bar/baz`,\nexport function getPathVariations(routePath: string): string[] {\n const variations = new Set<string>();\n const segments = routePath.split('/');\n\n function generateVariations(segments: string[], current = ''): void {\n if (segments.length === 0) {\n if (current) variations.add(current);\n return;\n }\n\n const [head, ...rest] = segments;\n\n if (matchGroupName(head)) {\n const groups = head.slice(1, -1).split(',');\n\n if (groups.length > 1) {\n for (const group of groups) {\n // If there are multiple groups, recurse on each group.\n generateVariations([`(${group.trim()})`, ...rest], current);\n }\n return;\n } else {\n // Start a fork where this group is included\n generateVariations(rest, current ? `${current}/(${groups[0]})` : `(${groups[0]})`);\n // This code will continue and add paths without this group included`\n }\n } else if (current) {\n current = `${current}/${head}`;\n } else {\n current = head;\n }\n\n generateVariations(rest, current);\n }\n\n generateVariations(segments);\n\n return Array.from(variations);\n}\n\nexport async function exportApiRoutesStandaloneAsync(\n devServer: MetroBundlerDevServer,\n {\n files = new Map(),\n platform,\n apiRoutesOnly,\n templateHtml,\n }: {\n files?: ExportAssetMap;\n platform: string;\n apiRoutesOnly: boolean;\n templateHtml?: string;\n }\n) {\n const { serverManifest, htmlManifest } = await devServer.getServerManifestAsync();\n\n const apiRoutes = await exportApiRoutesAsync({\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n platform,\n apiRoutesOnly,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n\n if (templateHtml && devServer.isReactServerComponentsEnabled) {\n // TODO: Export an HTML entry for each file. This is a temporary solution until we have SSR/SSG for RSC.\n await getFilesToExportFromServerAsync(devServer.projectRoot, {\n manifest: htmlManifest,\n serverManifest,\n exportServer: true,\n files,\n renderAsync: async ({ pathname, filePath }) => {\n files.set(filePath, {\n contents: templateHtml!,\n routeId: pathname,\n targetDomain: 'server',\n });\n return templateHtml!;\n },\n });\n }\n\n return files;\n}\n\nasync function exportApiRoutesAsync({\n includeSourceMaps,\n server,\n platform,\n apiRoutesOnly,\n ...props\n}: Pick<Options, 'includeSourceMaps'> & {\n server: MetroBundlerDevServer;\n manifest: ExpoRouterServerManifestV1;\n platform: string;\n apiRoutesOnly?: boolean;\n}): Promise<ExportAssetMap> {\n const { manifest, files } = await server.exportExpoRouterApiRoutesAsync({\n outputDir: '_expo/functions',\n prerenderManifest: props.manifest,\n includeSourceMaps,\n platform,\n });\n\n // HACK: Clear out the HTML and 404 routes if we're only exporting API routes. This is used for native apps that are using API routes but haven't implemented web support yet.\n if (apiRoutesOnly) {\n manifest.htmlRoutes = [];\n manifest.notFoundRoutes = [];\n }\n\n files.set('_expo/routes.json', {\n contents: JSON.stringify(manifest, null, 2),\n targetDomain: 'server',\n });\n\n return files;\n}\n\nfunction warnPossibleInvalidExportType(appDir: string) {\n const apiRoutes = getApiRoutesForDirectory(appDir);\n if (apiRoutes.length) {\n // TODO: Allow API Routes for native-only.\n Log.warn(\n chalk.yellow`Skipping export for API routes because \\`web.output\\` is not \"server\". You may want to remove the routes: ${apiRoutes\n .map((v) => path.relative(appDir, v))\n .join(', ')}`\n );\n }\n\n const middlewareFile = getMiddlewareForDirectory(appDir);\n if (middlewareFile) {\n Log.warn(\n chalk.yellow`Skipping export for middleware because \\`web.output\\` is not \"server\". You may want to remove ${path.relative(appDir, middlewareFile)}`\n );\n }\n}\n"],"names":["exportApiRoutesStandaloneAsync","exportFromServerAsync","getFilesToExportFromServerAsync","getHtmlFiles","getPathVariations","injectScriptTags","debug","require","html","scriptTags","scriptTagsHtml","map","tag","platform","src","join","replace","matchGroupName","name","match","projectRoot","manifest","serverManifest","renderAsync","exportServer","files","Map","subsetServerManifest","headers","redirects","set","contents","JSON","stringify","targetDomain","Promise","all","includeGroupVariations","route","filePath","pathname","type","data","routeId","e","logMetroErrorAsync","error","Error","modifyRouteNodeInRuntimeManifest","callback","iterateScreens","screens","Object","values","value","_route","makeRuntimeEntryPointsAbsolute","appDir","Array","isArray","entryPoints","entryPoint","shouldLinkExternally","startsWith","path","resolve","isAbsolute","resolveFrom","devServer","outputDir","baseUrl","includeSourceMaps","routerRoot","exp","Log","log","learnMore","isExporting","injectFaviconTag","getVirtualFaviconAssetsAsync","resources","getStaticResourcesAsync","getStaticRenderFunctionAsync","inspect","colors","depth","template","serializeHtmlWithAssets","artifacts","hydrate","getFilesFromSerialAssets","isServerHosted","assets","persistMetroAssetsAsync","outputDirectory","apiRoutes","exportApiRoutesAsync","server","warnPossibleInvalidExportType","htmlFiles","Set","traverseScreens","key","entries","leaf","keys","length","endsWith","slice","stripGroupSegmentsFromPath","addOptionalGroups","add","newPath","variations","variation","uniqueBy","from","parts","split","partsWithGroups","part","filePathLocation","array","seen","result","id","has","push","routePath","segments","generateVariations","current","head","rest","groups","group","trim","apiRoutesOnly","templateHtml","htmlManifest","getServerManifestAsync","isReactServerComponentsEnabled","props","exportExpoRouterApiRoutesAsync","prerenderManifest","htmlRoutes","notFoundRoutes","getApiRoutesForDirectory","warn","chalk","yellow","v","relative","middlewareFile","getMiddlewareForDirectory"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/export/exportStaticAsync.ts"],"sourcesContent":["/**\n * Copyright © 2022 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport { RouteNode } from 'expo-router/build/Route';\nimport { getLoaderModulePath } from 'expo-router/build/loaders/utils';\nimport { stripGroupSegmentsFromPath } from 'expo-router/build/matchers';\nimport { shouldLinkExternally } from 'expo-router/build/utils/url';\nimport { type RoutesManifest } from 'expo-server/private';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\nimport { inspect } from 'util';\n\nimport { getVirtualFaviconAssetsAsync } from './favicon';\nimport { persistMetroAssetsAsync } from './persistMetroAssets';\nimport { ExportAssetMap, getFilesFromSerialAssets } from './saveAssets';\nimport { Log } from '../log';\nimport {\n ExpoRouterRuntimeManifest,\n MetroBundlerDevServer,\n} from '../start/server/metro/MetroBundlerDevServer';\nimport { logMetroErrorAsync } from '../start/server/metro/metroErrorInterface';\nimport { getApiRoutesForDirectory, getMiddlewareForDirectory } from '../start/server/metro/router';\nimport { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';\nimport { learnMore } from '../utils/link';\n\nconst debug = require('debug')('expo:export:generateStaticRoutes') as typeof console.log;\n\ntype ExtraScriptTag = {\n platform: string;\n src: string;\n};\n\ntype Options = {\n mode: 'production' | 'development';\n files?: ExportAssetMap;\n outputDir: string;\n minify: boolean;\n exportServer: boolean;\n baseUrl: string;\n includeSourceMaps: boolean;\n entryPoint?: string;\n clear: boolean;\n routerRoot: string;\n reactCompiler: boolean;\n maxWorkers?: number;\n isExporting: boolean;\n exp?: ExpoConfig;\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n scriptTags?: ExtraScriptTag[];\n};\n\ntype HtmlRequestLocation = {\n /** The output file path name to use relative to the static folder. */\n filePath: string;\n /** The pathname to make requests to in order to fetch the HTML. */\n pathname: string;\n /** The runtime route node object, used to associate async modules with the static HTML. */\n route: RouteNode;\n};\n\nexport function injectScriptTags(html: string, scriptTags: ExtraScriptTag[]): string {\n const scriptTagsHtml = scriptTags\n .map((tag) =>\n tag.platform === 'web'\n ? `<script src=\"${tag.src}\"></script>`\n : `<script type=\"type/expo\" src=\"${tag.src}\" data-platform=\"${tag.platform}\"></script>`\n )\n .join('\\n');\n html = html.replace('</head>', `${scriptTagsHtml}\\n</head>`);\n return html;\n}\n\n/** Match `(page)` -> `page` */\nfunction matchGroupName(name: string): string | undefined {\n return name.match(/^\\(([^/]+?)\\)$/)?.[1];\n}\n\nexport async function getFilesToExportFromServerAsync(\n projectRoot: string,\n {\n manifest,\n serverManifest,\n renderAsync,\n // Servers can handle group routes automatically and therefore\n // don't require the build-time generation of every possible group\n // variation.\n exportServer,\n // name : contents\n files = new Map(),\n }: {\n manifest: ExpoRouterRuntimeManifest;\n serverManifest: RoutesManifest;\n renderAsync: (requestLocation: HtmlRequestLocation) => Promise<string>;\n exportServer?: boolean;\n files?: ExportAssetMap;\n }\n): Promise<ExportAssetMap> {\n if (!exportServer && serverManifest) {\n // When we're not exporting a `server` output, we provide a `_expo/.routes.json` for\n // EAS Hosting to recognize the `headers` and `redirects` configs\n const subsetServerManifest = {\n headers: serverManifest.headers,\n redirects: serverManifest.redirects,\n };\n files.set('_expo/.routes.json', {\n contents: JSON.stringify(subsetServerManifest, null, 2),\n targetDomain: 'client',\n });\n }\n\n await Promise.all(\n getHtmlFiles({ manifest, includeGroupVariations: !exportServer }).map(\n async ({ route, filePath, pathname }) => {\n // Rewrite routes should not be statically generated\n if (route.type === 'rewrite') {\n return;\n }\n\n try {\n const targetDomain = exportServer ? 'server' : 'client';\n files.set(filePath, { contents: '', targetDomain });\n const data = await renderAsync({ route, filePath, pathname });\n files.set(filePath, {\n contents: data,\n routeId: pathname,\n targetDomain,\n });\n } catch (e: any) {\n await logMetroErrorAsync({ error: e, projectRoot });\n throw new Error('Failed to statically export route: ' + pathname);\n }\n }\n )\n );\n\n return files;\n}\n\nfunction modifyRouteNodeInRuntimeManifest(\n manifest: ExpoRouterRuntimeManifest,\n callback: (route: RouteNode) => any\n) {\n const iterateScreens = (screens: ExpoRouterRuntimeManifest['screens']) => {\n Object.values(screens).map((value) => {\n if (typeof value !== 'string') {\n if (value._route) callback(value._route);\n iterateScreens(value.screens);\n }\n });\n };\n\n iterateScreens(manifest.screens);\n}\n\n// TODO: Do this earlier in the process.\nfunction makeRuntimeEntryPointsAbsolute(manifest: ExpoRouterRuntimeManifest, appDir: string) {\n modifyRouteNodeInRuntimeManifest(manifest, (route) => {\n if (Array.isArray(route.entryPoints)) {\n route.entryPoints = route.entryPoints.map((entryPoint) => {\n // TODO(@hassankhan): ENG-16577\n if (shouldLinkExternally(entryPoint)) {\n return entryPoint;\n }\n\n if (entryPoint.startsWith('.')) {\n return path.resolve(appDir, entryPoint);\n } else if (!path.isAbsolute(entryPoint)) {\n return resolveFrom(appDir, entryPoint);\n }\n return entryPoint;\n });\n }\n });\n}\n\n/** Perform all fs commits */\nexport async function exportFromServerAsync(\n projectRoot: string,\n devServer: MetroBundlerDevServer,\n {\n outputDir,\n baseUrl,\n exportServer,\n includeSourceMaps,\n routerRoot,\n files = new Map(),\n exp,\n scriptTags,\n }: Options\n): Promise<ExportAssetMap> {\n Log.log(\n `Static rendering is enabled. ` +\n learnMore('https://docs.expo.dev/router/reference/static-rendering/')\n );\n\n const platform = 'web';\n const isExporting = true;\n const appDir = path.join(projectRoot, routerRoot);\n const injectFaviconTag = await getVirtualFaviconAssetsAsync(projectRoot, {\n outputDir,\n baseUrl,\n files,\n exp,\n });\n\n const [resources, { manifest, serverManifest, renderAsync, executeLoaderAsync }] =\n await Promise.all([\n devServer.getStaticResourcesAsync({\n includeSourceMaps,\n }),\n devServer.getStaticRenderFunctionAsync(),\n ]);\n\n makeRuntimeEntryPointsAbsolute(manifest, appDir);\n\n debug('Routes:\\n', inspect(manifest, { colors: true, depth: null }));\n\n await getFilesToExportFromServerAsync(projectRoot, {\n files,\n manifest,\n serverManifest,\n exportServer,\n async renderAsync({ pathname, route }) {\n const normalizedPathname =\n pathname === '' ? '/' : pathname.startsWith('/') ? pathname : `/${pathname}`;\n\n const useServerLoaders = exp?.extra?.router?.unstable_useServerDataLoaders;\n let renderOpts;\n\n if (useServerLoaders) {\n const loaderData = await executeLoaderAsync(normalizedPathname, route);\n\n if (loaderData != null) {\n const loaderPath = getLoaderModulePath(normalizedPathname);\n const fileSystemPath = loaderPath.startsWith('/') ? loaderPath.slice(1) : loaderPath;\n files.set(fileSystemPath, {\n contents: JSON.stringify(loaderData, null, 2),\n targetDomain: 'client',\n loaderId: normalizedPathname,\n });\n\n renderOpts = { loader: { data: loaderData } };\n }\n }\n\n const template = await renderAsync(normalizedPathname, route, renderOpts);\n let html = await serializeHtmlWithAssets({\n isExporting,\n resources: resources.artifacts,\n template,\n baseUrl,\n route,\n hydrate: true,\n });\n\n if (injectFaviconTag) {\n html = injectFaviconTag(html);\n }\n\n if (scriptTags) {\n // Inject script tags into the HTML.\n // <script type=\"type/expo\" data-platform=\"ios\" src=\"...\" />\n html = injectScriptTags(html, scriptTags);\n }\n\n return html;\n },\n });\n\n getFilesFromSerialAssets(resources.artifacts, {\n platform,\n includeSourceMaps,\n files,\n isServerHosted: true,\n });\n\n if (resources.assets) {\n // TODO: Collect files without writing to disk.\n // NOTE(kitten): Re. above, this is now using `files` except for iOS catalog output, which isn't used here\n await persistMetroAssetsAsync(projectRoot, resources.assets, {\n files,\n platform,\n outputDirectory: outputDir,\n baseUrl,\n });\n }\n\n if (exportServer) {\n const apiRoutes = await exportApiRoutesAsync({\n platform: 'web',\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n } else {\n warnPossibleInvalidExportType(appDir);\n }\n\n return files;\n}\n\nexport function getHtmlFiles({\n manifest,\n includeGroupVariations,\n}: {\n manifest: ExpoRouterRuntimeManifest;\n includeGroupVariations?: boolean;\n}): HtmlRequestLocation[] {\n const htmlFiles = new Set<Omit<HtmlRequestLocation, 'pathname'>>();\n\n function traverseScreens(\n screens: ExpoRouterRuntimeManifest['screens'],\n route: RouteNode | null,\n baseUrl = ''\n ) {\n for (const [key, value] of Object.entries(screens)) {\n let leaf: string | null = null;\n if (typeof value === 'string') {\n leaf = value;\n } else if (value.screens && Object.keys(value.screens).length === 0) {\n // Ensure the trailing index is accounted for.\n if (key === value.path + '/index') {\n leaf = key;\n } else {\n leaf = value.path;\n }\n\n route = value._route ?? null;\n }\n\n if (leaf != null) {\n let filePath = baseUrl + leaf;\n\n if (leaf === '') {\n filePath =\n baseUrl === ''\n ? 'index'\n : baseUrl.endsWith('/')\n ? baseUrl + 'index'\n : baseUrl.slice(0, -1);\n } else if (\n // If the path is a collection of group segments leading to an index route, append `/index`.\n stripGroupSegmentsFromPath(filePath) === ''\n ) {\n filePath += '/index';\n }\n\n // This should never happen, the type of `string | object` originally comes from React Navigation.\n if (!route) {\n throw new Error(\n `Internal error: Route not found for \"${filePath}\" while collecting static export paths.`\n );\n }\n\n if (includeGroupVariations) {\n // TODO: Dedupe requests for alias routes.\n addOptionalGroups(filePath, route);\n } else {\n htmlFiles.add({\n filePath,\n route,\n });\n }\n } else if (typeof value === 'object' && value?.screens) {\n // The __root slot has no path.\n const newPath = value.path ? baseUrl + value.path + '/' : baseUrl;\n traverseScreens(value.screens, value._route ?? null, newPath);\n }\n }\n }\n\n function addOptionalGroups(path: string, route: RouteNode) {\n const variations = getPathVariations(path);\n for (const variation of variations) {\n htmlFiles.add({ filePath: variation, route });\n }\n }\n\n traverseScreens(manifest.screens, null);\n\n return uniqueBy(Array.from(htmlFiles), (value) => value.filePath).map((value) => {\n const parts = value.filePath.split('/');\n // Replace `:foo` with `[foo]` and `*foo` with `[...foo]`\n const partsWithGroups = parts.map((part) => {\n if (part === '*not-found') {\n return `+not-found`;\n } else if (part.startsWith(':')) {\n return `[${part.slice(1)}]`;\n } else if (part.startsWith('*')) {\n return `[...${part.slice(1)}]`;\n }\n return part;\n });\n const filePathLocation = partsWithGroups.join('/');\n const filePath = filePathLocation + '.html';\n return {\n ...value,\n filePath,\n pathname: filePathLocation.replace(/(\\/?index)?$/, ''),\n };\n });\n}\n\nfunction uniqueBy<T>(array: T[], key: (value: T) => string): T[] {\n const seen = new Set<string>();\n const result: T[] = [];\n for (const value of array) {\n const id = key(value);\n if (!seen.has(id)) {\n seen.add(id);\n result.push(value);\n }\n }\n return result;\n}\n\n// Given a route like `(foo)/bar/(baz)`, return all possible variations of the route.\n// e.g. `(foo)/bar/(baz)`, `(foo)/bar/baz`, `foo/bar/(baz)`, `foo/bar/baz`,\nexport function getPathVariations(routePath: string): string[] {\n const variations = new Set<string>();\n const segments = routePath.split('/');\n\n function generateVariations(segments: string[], current = ''): void {\n if (segments.length === 0) {\n if (current) variations.add(current);\n return;\n }\n\n const [head, ...rest] = segments;\n\n if (matchGroupName(head)) {\n const groups = head.slice(1, -1).split(',');\n\n if (groups.length > 1) {\n for (const group of groups) {\n // If there are multiple groups, recurse on each group.\n generateVariations([`(${group.trim()})`, ...rest], current);\n }\n return;\n } else {\n // Start a fork where this group is included\n generateVariations(rest, current ? `${current}/(${groups[0]})` : `(${groups[0]})`);\n // This code will continue and add paths without this group included`\n }\n } else if (current) {\n current = `${current}/${head}`;\n } else {\n current = head;\n }\n\n generateVariations(rest, current);\n }\n\n generateVariations(segments);\n\n return Array.from(variations);\n}\n\nexport async function exportApiRoutesStandaloneAsync(\n devServer: MetroBundlerDevServer,\n {\n files = new Map(),\n platform,\n apiRoutesOnly,\n templateHtml,\n }: {\n files?: ExportAssetMap;\n platform: string;\n apiRoutesOnly: boolean;\n templateHtml?: string;\n }\n) {\n const { serverManifest, htmlManifest } = await devServer.getServerManifestAsync();\n\n const apiRoutes = await exportApiRoutesAsync({\n server: devServer,\n manifest: serverManifest,\n // NOTE(kitten): For now, we always output source maps for API route exports\n includeSourceMaps: true,\n platform,\n apiRoutesOnly,\n });\n\n // Add the api routes to the files to export.\n for (const [route, contents] of apiRoutes) {\n files.set(route, contents);\n }\n\n if (templateHtml && devServer.isReactServerComponentsEnabled) {\n // TODO: Export an HTML entry for each file. This is a temporary solution until we have SSR/SSG for RSC.\n await getFilesToExportFromServerAsync(devServer.projectRoot, {\n manifest: htmlManifest,\n serverManifest,\n exportServer: true,\n files,\n renderAsync: async ({ pathname, filePath }) => {\n files.set(filePath, {\n contents: templateHtml!,\n routeId: pathname,\n targetDomain: 'server',\n });\n return templateHtml!;\n },\n });\n }\n\n return files;\n}\n\nasync function exportApiRoutesAsync({\n includeSourceMaps,\n server,\n platform,\n apiRoutesOnly,\n ...props\n}: Pick<Options, 'includeSourceMaps'> & {\n server: MetroBundlerDevServer;\n manifest: RoutesManifest<string>;\n platform: string;\n apiRoutesOnly?: boolean;\n}): Promise<ExportAssetMap> {\n const { manifest, files } = await server.exportExpoRouterApiRoutesAsync({\n outputDir: '_expo/functions',\n prerenderManifest: props.manifest,\n includeSourceMaps,\n platform,\n });\n\n // HACK: Clear out the HTML and 404 routes if we're only exporting API routes. This is used for native apps that are using API routes but haven't implemented web support yet.\n if (apiRoutesOnly) {\n manifest.htmlRoutes = [];\n manifest.notFoundRoutes = [];\n }\n\n files.set('_expo/routes.json', {\n contents: JSON.stringify(manifest, null, 2),\n targetDomain: 'server',\n });\n\n return files;\n}\n\nfunction warnPossibleInvalidExportType(appDir: string) {\n const apiRoutes = getApiRoutesForDirectory(appDir);\n if (apiRoutes.length) {\n // TODO: Allow API Routes for native-only.\n Log.warn(\n chalk.yellow`Skipping export for API routes because \\`web.output\\` is not \"server\". You may want to remove the routes: ${apiRoutes\n .map((v) => path.relative(appDir, v))\n .join(', ')}`\n );\n }\n\n const middlewareFile = getMiddlewareForDirectory(appDir);\n if (middlewareFile) {\n Log.warn(\n chalk.yellow`Skipping export for middleware because \\`web.output\\` is not \"server\". You may want to remove ${path.relative(appDir, middlewareFile)}`\n );\n }\n}\n"],"names":["exportApiRoutesStandaloneAsync","exportFromServerAsync","getFilesToExportFromServerAsync","getHtmlFiles","getPathVariations","injectScriptTags","debug","require","html","scriptTags","scriptTagsHtml","map","tag","platform","src","join","replace","matchGroupName","name","match","projectRoot","manifest","serverManifest","renderAsync","exportServer","files","Map","subsetServerManifest","headers","redirects","set","contents","JSON","stringify","targetDomain","Promise","all","includeGroupVariations","route","filePath","pathname","type","data","routeId","e","logMetroErrorAsync","error","Error","modifyRouteNodeInRuntimeManifest","callback","iterateScreens","screens","Object","values","value","_route","makeRuntimeEntryPointsAbsolute","appDir","Array","isArray","entryPoints","entryPoint","shouldLinkExternally","startsWith","path","resolve","isAbsolute","resolveFrom","devServer","outputDir","baseUrl","includeSourceMaps","routerRoot","exp","Log","log","learnMore","isExporting","injectFaviconTag","getVirtualFaviconAssetsAsync","resources","executeLoaderAsync","getStaticResourcesAsync","getStaticRenderFunctionAsync","inspect","colors","depth","normalizedPathname","useServerLoaders","extra","router","unstable_useServerDataLoaders","renderOpts","loaderData","loaderPath","getLoaderModulePath","fileSystemPath","slice","loaderId","loader","template","serializeHtmlWithAssets","artifacts","hydrate","getFilesFromSerialAssets","isServerHosted","assets","persistMetroAssetsAsync","outputDirectory","apiRoutes","exportApiRoutesAsync","server","warnPossibleInvalidExportType","htmlFiles","Set","traverseScreens","key","entries","leaf","keys","length","endsWith","stripGroupSegmentsFromPath","addOptionalGroups","add","newPath","variations","variation","uniqueBy","from","parts","split","partsWithGroups","part","filePathLocation","array","seen","result","id","has","push","routePath","segments","generateVariations","current","head","rest","groups","group","trim","apiRoutesOnly","templateHtml","htmlManifest","getServerManifestAsync","isReactServerComponentsEnabled","props","exportExpoRouterApiRoutesAsync","prerenderManifest","htmlRoutes","notFoundRoutes","getApiRoutesForDirectory","warn","chalk","yellow","v","relative","middlewareFile","getMiddlewareForDirectory"],"mappings":"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"}
@@ -75,6 +75,7 @@ async function persistMetroFilesAsync(files, outputDir) {
75
75
  const middlewareEntries = [];
76
76
  const routeEntries = [];
77
77
  const rscEntries = [];
78
+ const loaderEntries = [];
78
79
  const remainingEntries = [];
79
80
  let hasServerOutput = false;
80
81
  for (const asset of files.entries()){
@@ -84,6 +85,7 @@ async function persistMetroFilesAsync(files, outputDir) {
84
85
  else if (asset[1].middlewareId != null) middlewareEntries.push(asset);
85
86
  else if (asset[1].apiRouteId != null) apiRouteEntries.push(asset);
86
87
  else if (asset[1].rscId != null) rscEntries.push(asset);
88
+ else if (asset[1].loaderId != null) loaderEntries.push(asset);
87
89
  else remainingEntries.push(asset);
88
90
  }
89
91
  const groups = groupBy(assetEntries, ([, { assetId }])=>assetId);
@@ -201,6 +203,14 @@ async function persistMetroFilesAsync(files, outputDir) {
201
203
  _log.Log.log(id, sizeStr(assets.contents), hasSourceMap ? _chalk().default.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : '');
202
204
  }
203
205
  }
206
+ if (loaderEntries.length) {
207
+ _log.Log.log('');
208
+ _log.Log.log(_chalk().default.bold`${BLT} Loader outputs (${loaderEntries.length}):`);
209
+ for (const [loaderFilename, assets] of loaderEntries.sort((a, b)=>a[0].length - b[0].length)){
210
+ const id = assets.loaderId;
211
+ _log.Log.log(id === '/' ? '/ ' + _chalk().default.gray('(index)') : id, sizeStr(assets.contents));
212
+ }
213
+ }
204
214
  // Decouple logging from writing for better performance.
205
215
  await Promise.all([
206
216
  ...files.entries()
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/export/saveAssets.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 type { AssetData } from '@expo/metro/metro';\nimport type { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport prettyBytes from 'pretty-bytes';\n\nimport { Log } from '../log';\nimport { env } from '../utils/env';\n\nconst BLT = '\\u203A';\n\nexport type BundleOptions = {\n entryPoint: string;\n platform: 'android' | 'ios' | 'web';\n dev?: boolean;\n minify?: boolean;\n bytecode: boolean;\n sourceMapUrl?: string;\n sourcemaps?: boolean;\n};\n\nexport type BundleAssetWithFileHashes = AssetData & {\n fileHashes: string[]; // added by the hashAssets asset plugin\n};\n\nexport type BundleOutput = {\n artifacts: SerialAsset[];\n assets: readonly BundleAssetWithFileHashes[];\n};\n\nexport type ManifestAsset = { fileHashes: string[]; files: string[]; hash: string };\n\nexport type Asset = ManifestAsset | BundleAssetWithFileHashes;\n\nexport type ExportAssetDescriptor = {\n contents: string | Buffer;\n originFilename?: string;\n /** An identifier for grouping together variations of the same asset. */\n assetId?: string;\n /** Expo Router route path for formatting the HTML output. */\n routeId?: string;\n /** Expo Router route path for formatting the middleware function output. */\n middlewareId?: string;\n /** Expo Router API route path for formatting the server function output. */\n apiRouteId?: string;\n /** Expo Router route path for formatting the RSC output. */\n rscId?: string;\n /** A key for grouping together output files by server- or client-side. */\n targetDomain?: 'server' | 'client';\n};\n\nexport type ExportAssetMap = Map<string, ExportAssetDescriptor>;\n\nexport async function persistMetroFilesAsync(files: ExportAssetMap, outputDir: string) {\n if (!files.size) {\n return;\n }\n await fs.promises.mkdir(path.join(outputDir), { recursive: true });\n\n // Test fixtures:\n // Log.log(\n // JSON.stringify(\n // Object.fromEntries([...files.entries()].map(([k, v]) => [k, { ...v, contents: '' }]))\n // )\n // );\n\n const assetEntries: [string, ExportAssetDescriptor][] = [];\n const apiRouteEntries: [string, ExportAssetDescriptor][] = [];\n const middlewareEntries: [string, ExportAssetDescriptor][] = [];\n const routeEntries: [string, ExportAssetDescriptor][] = [];\n const rscEntries: [string, ExportAssetDescriptor][] = [];\n const remainingEntries: [string, ExportAssetDescriptor][] = [];\n\n let hasServerOutput = false;\n for (const asset of files.entries()) {\n hasServerOutput = hasServerOutput || asset[1].targetDomain === 'server';\n if (asset[1].assetId) assetEntries.push(asset);\n else if (asset[1].routeId != null) routeEntries.push(asset);\n else if (asset[1].middlewareId != null) middlewareEntries.push(asset);\n else if (asset[1].apiRouteId != null) apiRouteEntries.push(asset);\n else if (asset[1].rscId != null) rscEntries.push(asset);\n else remainingEntries.push(asset);\n }\n\n const groups = groupBy(assetEntries, ([, { assetId }]) => assetId!);\n\n const contentSize = (contents: string | Buffer) => {\n const length =\n typeof contents === 'string' ? Buffer.byteLength(contents, 'utf8') : contents.length;\n return length;\n };\n\n const sizeStr = (contents: string | Buffer) => {\n const length = contentSize(contents);\n const size = chalk.gray`(${prettyBytes(length)})`;\n return size;\n };\n\n // TODO: If any Expo Router is used, then use a new style which is more simple:\n // `chalk.gray(/path/to/) + chalk.cyan('route')`\n // | index.html (1.2kb)\n // | /path\n // | other.html (1.2kb)\n\n const isExpoRouter = routeEntries.length;\n\n // Phase out printing all the assets as users can simply check the file system for more info.\n const showAdditionalInfo = !isExpoRouter || env.EXPO_DEBUG;\n\n const assetGroups = [...groups.entries()].sort((a, b) => a[0].localeCompare(b[0])) as [\n string,\n [string, ExportAssetDescriptor][],\n ][];\n\n if (showAdditionalInfo) {\n if (assetGroups.length) {\n const totalAssets = assetGroups.reduce((sum, [, assets]) => sum + assets.length, 0);\n\n Log.log('');\n Log.log(chalk.bold`${BLT} Assets (${totalAssets}):`);\n\n for (const [assetId, assets] of assetGroups) {\n const averageContentSize =\n assets.reduce((sum, [, { contents }]) => sum + contentSize(contents), 0) / assets.length;\n Log.log(\n assetId,\n chalk.gray(\n `(${[\n assets.length > 1 ? `${assets.length} variations` : '',\n `${prettyBytes(averageContentSize)}`,\n ]\n .filter(Boolean)\n .join(' | ')})`\n )\n );\n }\n }\n }\n\n const bundles: Map<string, [string, ExportAssetDescriptor][]> = new Map();\n const other: [string, ExportAssetDescriptor][] = [];\n\n remainingEntries.forEach(([filepath, asset]) => {\n if (!filepath.match(/_expo\\/static\\//)) {\n other.push([filepath, asset]);\n } else {\n const platform = filepath.match(/_expo\\/static\\/js\\/([^/]+)\\//)?.[1] ?? 'web';\n if (!bundles.has(platform)) bundles.set(platform, []);\n\n bundles.get(platform)!.push([filepath, asset]);\n }\n });\n\n [...bundles.entries()].forEach(([platform, assets]) => {\n Log.log('');\n Log.log(chalk.bold`${BLT} ${platform} bundles (${assets.length}):`);\n\n const allAssets = assets.sort((a, b) => a[0].localeCompare(b[0]));\n while (allAssets.length) {\n const [filePath, asset] = allAssets.shift()!;\n Log.log(filePath, sizeStr(asset.contents));\n if (filePath.match(/\\.(js|hbc)$/)) {\n // Get source map\n const sourceMapIndex = allAssets.findIndex(([fp]) => fp === filePath + '.map');\n if (sourceMapIndex !== -1) {\n const [sourceMapFilePath, sourceMapAsset] = allAssets.splice(sourceMapIndex, 1)[0];\n Log.log(chalk.gray(sourceMapFilePath), sizeStr(sourceMapAsset.contents));\n }\n }\n }\n });\n\n if (showAdditionalInfo && other.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Files (${other.length}):`);\n\n for (const [filePath, asset] of other.sort((a, b) => a[0].localeCompare(b[0]))) {\n Log.log(filePath, sizeStr(asset.contents));\n }\n }\n\n if (rscEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} React Server Components (${rscEntries.length}):`);\n\n for (const [filePath, assets] of rscEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.rscId!;\n Log.log(\n '/' + (id === '' ? chalk.gray(' (index)') : id),\n sizeStr(assets.contents),\n chalk.gray(filePath)\n );\n }\n }\n\n if (routeEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Static routes (${routeEntries.length}):`);\n\n for (const [, assets] of routeEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.routeId!;\n Log.log('/' + (id === '' ? chalk.gray(' (index)') : id), sizeStr(assets.contents));\n }\n }\n\n if (apiRouteEntries.length) {\n const apiRoutesWithoutSourcemaps = apiRouteEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} API routes (${apiRoutesWithoutSourcemaps.length}):`);\n\n for (const [apiRouteFilename, assets] of apiRoutesWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.apiRouteId!;\n const hasSourceMap = apiRouteEntries.find(\n ([filename, route]) =>\n filename !== apiRouteFilename &&\n route.apiRouteId === assets.apiRouteId &&\n filename.endsWith('.map')\n );\n Log.log(\n id === '' ? chalk.gray(' (index)') : id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n if (middlewareEntries.length) {\n const middlewareWithoutSourcemaps = middlewareEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} Middleware:`);\n\n for (const [middlewareFilename, assets] of middlewareWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.middlewareId!;\n const hasSourceMap = middlewareEntries.find(\n ([filename, route]) =>\n filename !== middlewareFilename &&\n route.middlewareId === assets.middlewareId &&\n filename.endsWith('.map')\n );\n Log.log(\n id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n // Decouple logging from writing for better performance.\n\n await Promise.all(\n [...files.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(async ([file, { contents, targetDomain }]) => {\n // NOTE: Only use `targetDomain` if we have at least one server asset\n const domain = (hasServerOutput && targetDomain) || '';\n const outputPath = path.join(outputDir, domain, file);\n await fs.promises.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.promises.writeFile(outputPath, contents);\n })\n );\n\n Log.log('');\n}\n\nfunction groupBy<T>(array: T[], key: (item: T) => string): Map<string, T[]> {\n const map = new Map<string, T[]>();\n array.forEach((item) => {\n const group = key(item);\n const list = map.get(group) ?? [];\n list.push(item);\n map.set(group, list);\n });\n return map;\n}\n\n// TODO: Move source map modification to the serializer\nexport function getFilesFromSerialAssets(\n resources: SerialAsset[],\n {\n includeSourceMaps,\n files = new Map(),\n platform,\n isServerHosted = platform === 'web',\n }: {\n includeSourceMaps: boolean;\n files?: ExportAssetMap;\n platform?: string;\n isServerHosted?: boolean;\n }\n) {\n resources.forEach((resource) => {\n if (resource.type === 'css-external') {\n return;\n }\n files.set(resource.filename, {\n contents: resource.source,\n originFilename: resource.originFilename,\n targetDomain: isServerHosted ? 'client' : undefined,\n });\n });\n\n return files;\n}\n"],"names":["getFilesFromSerialAssets","persistMetroFilesAsync","BLT","files","outputDir","size","fs","promises","mkdir","path","join","recursive","assetEntries","apiRouteEntries","middlewareEntries","routeEntries","rscEntries","remainingEntries","hasServerOutput","asset","entries","targetDomain","assetId","push","routeId","middlewareId","apiRouteId","rscId","groups","groupBy","contentSize","contents","length","Buffer","byteLength","sizeStr","chalk","gray","prettyBytes","isExpoRouter","showAdditionalInfo","env","EXPO_DEBUG","assetGroups","sort","a","b","localeCompare","totalAssets","reduce","sum","assets","Log","log","bold","averageContentSize","filter","Boolean","bundles","Map","other","forEach","filepath","match","platform","has","set","get","allAssets","filePath","shift","sourceMapIndex","findIndex","fp","sourceMapFilePath","sourceMapAsset","splice","id","apiRoutesWithoutSourcemaps","route","endsWith","apiRouteFilename","hasSourceMap","find","filename","middlewareWithoutSourcemaps","middlewareFilename","Promise","all","map","file","domain","outputPath","dirname","writeFile","array","key","item","group","list","resources","includeSourceMaps","isServerHosted","resource","type","source","originFilename","undefined"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/export/saveAssets.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 type { AssetData } from '@expo/metro/metro';\nimport type { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport prettyBytes from 'pretty-bytes';\n\nimport { Log } from '../log';\nimport { env } from '../utils/env';\n\nconst BLT = '\\u203A';\n\nexport type BundleOptions = {\n entryPoint: string;\n platform: 'android' | 'ios' | 'web';\n dev?: boolean;\n minify?: boolean;\n bytecode: boolean;\n sourceMapUrl?: string;\n sourcemaps?: boolean;\n};\n\nexport type BundleAssetWithFileHashes = AssetData & {\n fileHashes: string[]; // added by the hashAssets asset plugin\n};\n\nexport type BundleOutput = {\n artifacts: SerialAsset[];\n assets: readonly BundleAssetWithFileHashes[];\n};\n\nexport type ManifestAsset = { fileHashes: string[]; files: string[]; hash: string };\n\nexport type Asset = ManifestAsset | BundleAssetWithFileHashes;\n\nexport type ExportAssetDescriptor = {\n contents: string | Buffer;\n originFilename?: string;\n /** An identifier for grouping together variations of the same asset. */\n assetId?: string;\n /** Expo Router route path for formatting the HTML output. */\n routeId?: string;\n /** Expo Router route path for formatting the middleware function output. */\n middlewareId?: string;\n /** Expo Router API route path for formatting the server function output. */\n apiRouteId?: string;\n /** Expo Router route path for formatting the RSC output. */\n rscId?: string;\n /** Expo Router route path for formatting the loader module output. */\n loaderId?: string;\n /** A key for grouping together output files by server- or client-side. */\n targetDomain?: 'server' | 'client';\n};\n\nexport type ExportAssetMap = Map<string, ExportAssetDescriptor>;\n\nexport async function persistMetroFilesAsync(files: ExportAssetMap, outputDir: string) {\n if (!files.size) {\n return;\n }\n await fs.promises.mkdir(path.join(outputDir), { recursive: true });\n\n // Test fixtures:\n // Log.log(\n // JSON.stringify(\n // Object.fromEntries([...files.entries()].map(([k, v]) => [k, { ...v, contents: '' }]))\n // )\n // );\n\n const assetEntries: [string, ExportAssetDescriptor][] = [];\n const apiRouteEntries: [string, ExportAssetDescriptor][] = [];\n const middlewareEntries: [string, ExportAssetDescriptor][] = [];\n const routeEntries: [string, ExportAssetDescriptor][] = [];\n const rscEntries: [string, ExportAssetDescriptor][] = [];\n const loaderEntries: [string, ExportAssetDescriptor][] = [];\n const remainingEntries: [string, ExportAssetDescriptor][] = [];\n\n let hasServerOutput = false;\n for (const asset of files.entries()) {\n hasServerOutput = hasServerOutput || asset[1].targetDomain === 'server';\n if (asset[1].assetId) assetEntries.push(asset);\n else if (asset[1].routeId != null) routeEntries.push(asset);\n else if (asset[1].middlewareId != null) middlewareEntries.push(asset);\n else if (asset[1].apiRouteId != null) apiRouteEntries.push(asset);\n else if (asset[1].rscId != null) rscEntries.push(asset);\n else if (asset[1].loaderId != null) loaderEntries.push(asset);\n else remainingEntries.push(asset);\n }\n\n const groups = groupBy(assetEntries, ([, { assetId }]) => assetId!);\n\n const contentSize = (contents: string | Buffer) => {\n const length =\n typeof contents === 'string' ? Buffer.byteLength(contents, 'utf8') : contents.length;\n return length;\n };\n\n const sizeStr = (contents: string | Buffer) => {\n const length = contentSize(contents);\n const size = chalk.gray`(${prettyBytes(length)})`;\n return size;\n };\n\n // TODO: If any Expo Router is used, then use a new style which is more simple:\n // `chalk.gray(/path/to/) + chalk.cyan('route')`\n // | index.html (1.2kb)\n // | /path\n // | other.html (1.2kb)\n\n const isExpoRouter = routeEntries.length;\n\n // Phase out printing all the assets as users can simply check the file system for more info.\n const showAdditionalInfo = !isExpoRouter || env.EXPO_DEBUG;\n\n const assetGroups = [...groups.entries()].sort((a, b) => a[0].localeCompare(b[0])) as [\n string,\n [string, ExportAssetDescriptor][],\n ][];\n\n if (showAdditionalInfo) {\n if (assetGroups.length) {\n const totalAssets = assetGroups.reduce((sum, [, assets]) => sum + assets.length, 0);\n\n Log.log('');\n Log.log(chalk.bold`${BLT} Assets (${totalAssets}):`);\n\n for (const [assetId, assets] of assetGroups) {\n const averageContentSize =\n assets.reduce((sum, [, { contents }]) => sum + contentSize(contents), 0) / assets.length;\n Log.log(\n assetId,\n chalk.gray(\n `(${[\n assets.length > 1 ? `${assets.length} variations` : '',\n `${prettyBytes(averageContentSize)}`,\n ]\n .filter(Boolean)\n .join(' | ')})`\n )\n );\n }\n }\n }\n\n const bundles: Map<string, [string, ExportAssetDescriptor][]> = new Map();\n const other: [string, ExportAssetDescriptor][] = [];\n\n remainingEntries.forEach(([filepath, asset]) => {\n if (!filepath.match(/_expo\\/static\\//)) {\n other.push([filepath, asset]);\n } else {\n const platform = filepath.match(/_expo\\/static\\/js\\/([^/]+)\\//)?.[1] ?? 'web';\n if (!bundles.has(platform)) bundles.set(platform, []);\n\n bundles.get(platform)!.push([filepath, asset]);\n }\n });\n\n [...bundles.entries()].forEach(([platform, assets]) => {\n Log.log('');\n Log.log(chalk.bold`${BLT} ${platform} bundles (${assets.length}):`);\n\n const allAssets = assets.sort((a, b) => a[0].localeCompare(b[0]));\n while (allAssets.length) {\n const [filePath, asset] = allAssets.shift()!;\n Log.log(filePath, sizeStr(asset.contents));\n if (filePath.match(/\\.(js|hbc)$/)) {\n // Get source map\n const sourceMapIndex = allAssets.findIndex(([fp]) => fp === filePath + '.map');\n if (sourceMapIndex !== -1) {\n const [sourceMapFilePath, sourceMapAsset] = allAssets.splice(sourceMapIndex, 1)[0];\n Log.log(chalk.gray(sourceMapFilePath), sizeStr(sourceMapAsset.contents));\n }\n }\n }\n });\n\n if (showAdditionalInfo && other.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Files (${other.length}):`);\n\n for (const [filePath, asset] of other.sort((a, b) => a[0].localeCompare(b[0]))) {\n Log.log(filePath, sizeStr(asset.contents));\n }\n }\n\n if (rscEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} React Server Components (${rscEntries.length}):`);\n\n for (const [filePath, assets] of rscEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.rscId!;\n Log.log(\n '/' + (id === '' ? chalk.gray(' (index)') : id),\n sizeStr(assets.contents),\n chalk.gray(filePath)\n );\n }\n }\n\n if (routeEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Static routes (${routeEntries.length}):`);\n\n for (const [, assets] of routeEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.routeId!;\n Log.log('/' + (id === '' ? chalk.gray(' (index)') : id), sizeStr(assets.contents));\n }\n }\n\n if (apiRouteEntries.length) {\n const apiRoutesWithoutSourcemaps = apiRouteEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} API routes (${apiRoutesWithoutSourcemaps.length}):`);\n\n for (const [apiRouteFilename, assets] of apiRoutesWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.apiRouteId!;\n const hasSourceMap = apiRouteEntries.find(\n ([filename, route]) =>\n filename !== apiRouteFilename &&\n route.apiRouteId === assets.apiRouteId &&\n filename.endsWith('.map')\n );\n Log.log(\n id === '' ? chalk.gray(' (index)') : id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n if (middlewareEntries.length) {\n const middlewareWithoutSourcemaps = middlewareEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} Middleware:`);\n\n for (const [middlewareFilename, assets] of middlewareWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.middlewareId!;\n const hasSourceMap = middlewareEntries.find(\n ([filename, route]) =>\n filename !== middlewareFilename &&\n route.middlewareId === assets.middlewareId &&\n filename.endsWith('.map')\n );\n Log.log(\n id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n if (loaderEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Loader outputs (${loaderEntries.length}):`);\n\n for (const [loaderFilename, assets] of loaderEntries.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.loaderId!;\n Log.log(id === '/' ? '/ ' + chalk.gray('(index)') : id, sizeStr(assets.contents));\n }\n }\n\n // Decouple logging from writing for better performance.\n\n await Promise.all(\n [...files.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(async ([file, { contents, targetDomain }]) => {\n // NOTE: Only use `targetDomain` if we have at least one server asset\n const domain = (hasServerOutput && targetDomain) || '';\n const outputPath = path.join(outputDir, domain, file);\n await fs.promises.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.promises.writeFile(outputPath, contents);\n })\n );\n\n Log.log('');\n}\n\nfunction groupBy<T>(array: T[], key: (item: T) => string): Map<string, T[]> {\n const map = new Map<string, T[]>();\n array.forEach((item) => {\n const group = key(item);\n const list = map.get(group) ?? [];\n list.push(item);\n map.set(group, list);\n });\n return map;\n}\n\n// TODO: Move source map modification to the serializer\nexport function getFilesFromSerialAssets(\n resources: SerialAsset[],\n {\n includeSourceMaps,\n files = new Map(),\n platform,\n isServerHosted = platform === 'web',\n }: {\n includeSourceMaps: boolean;\n files?: ExportAssetMap;\n platform?: string;\n isServerHosted?: boolean;\n }\n) {\n resources.forEach((resource) => {\n if (resource.type === 'css-external') {\n return;\n }\n files.set(resource.filename, {\n contents: resource.source,\n originFilename: resource.originFilename,\n targetDomain: isServerHosted ? 'client' : undefined,\n });\n });\n\n return files;\n}\n"],"names":["getFilesFromSerialAssets","persistMetroFilesAsync","BLT","files","outputDir","size","fs","promises","mkdir","path","join","recursive","assetEntries","apiRouteEntries","middlewareEntries","routeEntries","rscEntries","loaderEntries","remainingEntries","hasServerOutput","asset","entries","targetDomain","assetId","push","routeId","middlewareId","apiRouteId","rscId","loaderId","groups","groupBy","contentSize","contents","length","Buffer","byteLength","sizeStr","chalk","gray","prettyBytes","isExpoRouter","showAdditionalInfo","env","EXPO_DEBUG","assetGroups","sort","a","b","localeCompare","totalAssets","reduce","sum","assets","Log","log","bold","averageContentSize","filter","Boolean","bundles","Map","other","forEach","filepath","match","platform","has","set","get","allAssets","filePath","shift","sourceMapIndex","findIndex","fp","sourceMapFilePath","sourceMapAsset","splice","id","apiRoutesWithoutSourcemaps","route","endsWith","apiRouteFilename","hasSourceMap","find","filename","middlewareWithoutSourcemaps","middlewareFilename","loaderFilename","Promise","all","map","file","domain","outputPath","dirname","writeFile","array","key","item","group","list","resources","includeSourceMaps","isServerHosted","resource","type","source","originFilename","undefined"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/interface/commandsTable.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport qrcode from 'qrcode-terminal';\nimport wrapAnsi from 'wrap-ansi';\n\nimport * as Log from '../../log';\n\nexport const BLT = '\\u203A';\n\nexport type StartOptions = {\n isWebSocketsEnabled?: boolean;\n devClient?: boolean;\n reset?: boolean;\n nonPersistent?: boolean;\n maxWorkers?: number;\n platforms?: ExpoConfig['platforms'];\n};\n\nexport const printHelp = (): void => {\n logCommandsTable([{ key: '?', msg: 'show all commands' }]);\n};\n\n/** Print the world famous 'Expo QR Code'. */\nexport function printQRCode(url: string) {\n qrcode.generate(url, { small: true }, (code) => Log.log(code));\n}\n\nexport const getTerminalColumns = () => process.stdout.columns || 80;\nexport const printItem = (text: string): string =>\n `${BLT} ` + wrapAnsi(text, getTerminalColumns()).trimStart();\n\nexport function printUsage(\n options: Pick<StartOptions, 'devClient' | 'isWebSocketsEnabled' | 'platforms'>,\n { verbose }: { verbose: boolean }\n) {\n const isMac = process.platform === 'darwin';\n\n const { platforms = ['ios', 'android', 'web'] } = options;\n\n const isAndroidDisabled = !platforms.includes('android');\n const isIosDisabled = !platforms.includes('ios');\n const isWebDisable = !platforms.includes('web');\n\n const switchMsg = `switch to ${options.devClient === false ? 'development build' : 'Expo Go'}`;\n const target = options.devClient === false ? `Expo Go` : 'development build';\n\n Log.log();\n Log.log(printItem(chalk`Using {cyan ${target}}`));\n\n if (verbose) {\n logCommandsTable([\n { key: 's', msg: switchMsg },\n {},\n { key: 'a', msg: 'open Android', disabled: isAndroidDisabled },\n { key: 'shift+a', msg: 'select an Android device or emulator', disabled: isAndroidDisabled },\n isMac && { key: 'i', msg: 'open iOS simulator', disabled: isIosDisabled },\n isMac && { key: 'shift+i', msg: 'select an iOS simulator', disabled: isIosDisabled },\n { key: 'w', msg: 'open web', disabled: isWebDisable },\n {},\n { key: 'r', msg: 'reload app' },\n !!options.isWebSocketsEnabled && { key: 'j', msg: 'open debugger' },\n !!options.isWebSocketsEnabled && { key: 'm', msg: 'toggle menu' },\n !!options.isWebSocketsEnabled && { key: 'shift+m', msg: 'more tools' },\n { key: 'o', msg: 'open project code in your editor' },\n { key: 'c', msg: 'show project QR' },\n {},\n ]);\n } else {\n logCommandsTable([\n { key: 's', msg: switchMsg },\n {},\n { key: 'a', msg: 'open Android', disabled: isAndroidDisabled },\n isMac && { key: 'i', msg: 'open iOS simulator', disabled: isIosDisabled },\n { key: 'w', msg: 'open web', disabled: isWebDisable },\n {},\n { key: 'j', msg: 'open debugger' },\n { key: 'r', msg: 'reload app' },\n !!options.isWebSocketsEnabled && { key: 'm', msg: 'toggle menu' },\n !!options.isWebSocketsEnabled && { key: 'shift+m', msg: 'more tools' },\n { key: 'o', msg: 'open project code in your editor' },\n {},\n ]);\n }\n}\n\nfunction logCommandsTable(\n ui: (false | { key?: string; msg?: string; status?: string; disabled?: boolean })[]\n) {\n Log.log(\n ui\n .filter(Boolean)\n // @ts-ignore: filter doesn't work\n .map(({ key, msg, status, disabled }) => {\n if (!key) return '';\n let view = `${BLT} `;\n if (key.length === 1) view += 'Press ';\n view += chalk`{bold ${key}} {dim │} `;\n view += msg;\n if (status) {\n view += ` ${chalk.dim(`(${chalk.italic(status)})`)}`;\n }\n if (disabled) {\n view = chalk.dim(view);\n }\n return view;\n })\n .join('\\n')\n );\n}\n"],"names":["BLT","getTerminalColumns","printHelp","printItem","printQRCode","printUsage","logCommandsTable","key","msg","url","qrcode","generate","small","code","Log","log","process","stdout","columns","text","wrapAnsi","trimStart","options","verbose","isMac","platform","platforms","isAndroidDisabled","includes","isIosDisabled","isWebDisable","switchMsg","devClient","target","chalk","disabled","isWebSocketsEnabled","ui","filter","Boolean","map","status","view","length","dim","italic","join"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/start/interface/commandsTable.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport qrcode from 'qrcode-terminal';\nimport wrapAnsi from 'wrap-ansi';\n\nimport * as Log from '../../log';\nimport type { McpServer } from '../server/MCP';\n\nexport const BLT = '\\u203A';\n\nexport type StartOptions = {\n isWebSocketsEnabled?: boolean;\n devClient?: boolean;\n reset?: boolean;\n nonPersistent?: boolean;\n maxWorkers?: number;\n platforms?: ExpoConfig['platforms'];\n mcpServer?: McpServer;\n};\n\nexport const printHelp = (): void => {\n logCommandsTable([{ key: '?', msg: 'show all commands' }]);\n};\n\n/** Print the world famous 'Expo QR Code'. */\nexport function printQRCode(url: string) {\n qrcode.generate(url, { small: true }, (code) => Log.log(code));\n}\n\nexport const getTerminalColumns = () => process.stdout.columns || 80;\nexport const printItem = (text: string): string =>\n `${BLT} ` + wrapAnsi(text, getTerminalColumns()).trimStart();\n\nexport function printUsage(\n options: Pick<StartOptions, 'devClient' | 'isWebSocketsEnabled' | 'platforms'>,\n { verbose }: { verbose: boolean }\n) {\n const isMac = process.platform === 'darwin';\n\n const { platforms = ['ios', 'android', 'web'] } = options;\n\n const isAndroidDisabled = !platforms.includes('android');\n const isIosDisabled = !platforms.includes('ios');\n const isWebDisable = !platforms.includes('web');\n\n const switchMsg = `switch to ${options.devClient === false ? 'development build' : 'Expo Go'}`;\n const target = options.devClient === false ? `Expo Go` : 'development build';\n\n Log.log();\n Log.log(printItem(chalk`Using {cyan ${target}}`));\n\n if (verbose) {\n logCommandsTable([\n { key: 's', msg: switchMsg },\n {},\n { key: 'a', msg: 'open Android', disabled: isAndroidDisabled },\n { key: 'shift+a', msg: 'select an Android device or emulator', disabled: isAndroidDisabled },\n isMac && { key: 'i', msg: 'open iOS simulator', disabled: isIosDisabled },\n isMac && { key: 'shift+i', msg: 'select an iOS simulator', disabled: isIosDisabled },\n { key: 'w', msg: 'open web', disabled: isWebDisable },\n {},\n { key: 'r', msg: 'reload app' },\n !!options.isWebSocketsEnabled && { key: 'j', msg: 'open debugger' },\n !!options.isWebSocketsEnabled && { key: 'm', msg: 'toggle menu' },\n !!options.isWebSocketsEnabled && { key: 'shift+m', msg: 'more tools' },\n { key: 'o', msg: 'open project code in your editor' },\n { key: 'c', msg: 'show project QR' },\n {},\n ]);\n } else {\n logCommandsTable([\n { key: 's', msg: switchMsg },\n {},\n { key: 'a', msg: 'open Android', disabled: isAndroidDisabled },\n isMac && { key: 'i', msg: 'open iOS simulator', disabled: isIosDisabled },\n { key: 'w', msg: 'open web', disabled: isWebDisable },\n {},\n { key: 'j', msg: 'open debugger' },\n { key: 'r', msg: 'reload app' },\n !!options.isWebSocketsEnabled && { key: 'm', msg: 'toggle menu' },\n !!options.isWebSocketsEnabled && { key: 'shift+m', msg: 'more tools' },\n { key: 'o', msg: 'open project code in your editor' },\n {},\n ]);\n }\n}\n\nfunction logCommandsTable(\n ui: (false | { key?: string; msg?: string; status?: string; disabled?: boolean })[]\n) {\n Log.log(\n ui\n .filter(Boolean)\n // @ts-ignore: filter doesn't work\n .map(({ key, msg, status, disabled }) => {\n if (!key) return '';\n let view = `${BLT} `;\n if (key.length === 1) view += 'Press ';\n view += chalk`{bold ${key}} {dim │} `;\n view += msg;\n if (status) {\n view += ` ${chalk.dim(`(${chalk.italic(status)})`)}`;\n }\n if (disabled) {\n view = chalk.dim(view);\n }\n return view;\n })\n .join('\\n')\n );\n}\n"],"names":["BLT","getTerminalColumns","printHelp","printItem","printQRCode","printUsage","logCommandsTable","key","msg","url","qrcode","generate","small","code","Log","log","process","stdout","columns","text","wrapAnsi","trimStart","options","verbose","isMac","platform","platforms","isAndroidDisabled","includes","isIosDisabled","isWebDisable","switchMsg","devClient","target","chalk","disabled","isWebSocketsEnabled","ui","filter","Boolean","map","status","view","length","dim","italic","join"],"mappings":"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"}
@@ -122,6 +122,9 @@ async function startInterfaceAsync(devServerManager, options) {
122
122
  }).start();
123
123
  try {
124
124
  await devServerManager.stopAsync();
125
+ if (options.mcpServer) {
126
+ await options.mcpServer.closeAsync();
127
+ }
125
128
  spinner.stopAndPersist({
126
129
  text: 'Stopped server',
127
130
  symbol: `\u203A`
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/interface/startInterface.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport { KeyPressHandler } from './KeyPressHandler';\nimport { BLT, printHelp, printUsage, StartOptions } from './commandsTable';\nimport { DevServerManagerActions } from './interactiveActions';\nimport * as Log from '../../log';\nimport { openInEditorAsync } from '../../utils/editor';\nimport { AbortCommandError } from '../../utils/errors';\nimport { getAllSpinners, ora } from '../../utils/ora';\nimport { getProgressBar, setProgressBar } from '../../utils/progress';\nimport { addInteractionListener, pauseInteractions } from '../../utils/prompts';\nimport { WebSupportProjectPrerequisite } from '../doctor/web/WebSupportProjectPrerequisite';\nimport { DevServerManager } from '../server/DevServerManager';\n\nconst debug = require('debug')('expo:start:interface:startInterface') as typeof console.log;\n\nconst CTRL_C = '\\u0003';\nconst CTRL_D = '\\u0004';\nconst CTRL_L = '\\u000C';\n\nconst PLATFORM_SETTINGS: Record<\n string,\n { name: string; key: 'android' | 'ios'; launchTarget: 'emulator' | 'simulator' }\n> = {\n android: {\n name: 'Android',\n key: 'android',\n launchTarget: 'emulator',\n },\n ios: {\n name: 'iOS',\n key: 'ios',\n launchTarget: 'simulator',\n },\n};\n\nexport async function startInterfaceAsync(\n devServerManager: DevServerManager,\n options: Pick<StartOptions, 'devClient' | 'platforms'>\n) {\n const actions = new DevServerManagerActions(devServerManager, options);\n\n const isWebSocketsEnabled = devServerManager.getDefaultDevServer()?.isTargetingNative();\n\n const usageOptions = {\n isWebSocketsEnabled,\n devClient: devServerManager.options.devClient,\n ...options,\n };\n\n actions.printDevServerInfo(usageOptions);\n\n const onPressAsync = async (key: string) => {\n // Auxillary commands all escape.\n switch (key) {\n case CTRL_C:\n case CTRL_D: {\n // Prevent terminal UI from accepting commands while the process is closing.\n // Without this, fast typers will close the server then start typing their\n // next command and have a bunch of unrelated things pop up.\n pauseInteractions();\n\n const spinners = getAllSpinners();\n spinners.forEach((spinner) => {\n spinner.fail();\n });\n\n const currentProgress = getProgressBar();\n if (currentProgress) {\n currentProgress.terminate();\n setProgressBar(null);\n }\n const spinner = ora({ text: 'Stopping server', color: 'white' }).start();\n try {\n await devServerManager.stopAsync();\n spinner.stopAndPersist({ text: 'Stopped server', symbol: `\\u203A` });\n // @ts-ignore: Argument of type '\"SIGINT\"' is not assignable to parameter of type '\"disconnect\"'.\n process.emit('SIGINT');\n\n // TODO: Is this the right place to do this?\n process.exit();\n } catch (error) {\n spinner.fail('Failed to stop server');\n throw error;\n }\n break;\n }\n case CTRL_L:\n return Log.clear();\n case '?':\n return printUsage(usageOptions, { verbose: true });\n }\n\n // Optionally enabled\n\n if (isWebSocketsEnabled) {\n switch (key) {\n case 'm':\n return actions.toggleDevMenu();\n case 'M':\n return actions.openMoreToolsAsync();\n }\n }\n\n const { platforms = ['ios', 'android', 'web'] } = options;\n\n if (['i', 'a'].includes(key.toLowerCase())) {\n const platform = key.toLowerCase() === 'i' ? 'ios' : 'android';\n\n const shouldPrompt = ['I', 'A'].includes(key);\n if (shouldPrompt) {\n Log.clear();\n }\n\n const server = devServerManager.getDefaultDevServer();\n const settings = PLATFORM_SETTINGS[platform];\n\n Log.log(`${BLT} Opening on ${settings.name}...`);\n\n if (server.isTargetingNative() && !platforms.includes(settings.key)) {\n Log.warn(\n chalk`${settings.name} is disabled, enable it by adding {bold ${settings.key}} to the platforms array in your app.json or app.config.js`\n );\n } else {\n try {\n await server.openPlatformAsync(settings.launchTarget, { shouldPrompt });\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n }\n // Break out early.\n return;\n }\n\n switch (key) {\n case 's': {\n Log.clear();\n if (await devServerManager.toggleRuntimeMode()) {\n usageOptions.devClient = devServerManager.options.devClient;\n return actions.printDevServerInfo(usageOptions);\n }\n break;\n }\n case 'w': {\n try {\n await devServerManager.ensureProjectPrerequisiteAsync(WebSupportProjectPrerequisite);\n if (!platforms.includes('web')) {\n platforms.push('web');\n options.platforms?.push('web');\n }\n } catch (e: any) {\n Log.warn(e.message);\n break;\n }\n\n const isDisabled = !platforms.includes('web');\n if (isDisabled) {\n debug('Web is disabled');\n // Use warnings from the web support setup.\n break;\n }\n\n // Ensure the Webpack dev server is running first\n if (!devServerManager.getWebDevServer()) {\n debug('Starting up webpack dev server');\n await devServerManager.ensureWebDevServerRunningAsync();\n // When this is the first time webpack is started, reprint the connection info.\n actions.printDevServerInfo(usageOptions);\n }\n\n Log.log(`${BLT} Open in the web browser...`);\n try {\n await devServerManager.getWebDevServer()?.openPlatformAsync('desktop');\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n break;\n }\n case 'c':\n Log.clear();\n return actions.printDevServerInfo(usageOptions);\n case 'j':\n return actions.openJsInspectorAsync();\n case 'r':\n return actions.reloadApp();\n case 'o':\n Log.log(`${BLT} Opening the editor...`);\n return openInEditorAsync(devServerManager.projectRoot);\n }\n };\n\n const keyPressHandler = new KeyPressHandler(onPressAsync);\n\n const listener = keyPressHandler.createInteractionListener();\n\n addInteractionListener(listener);\n\n // Start observing...\n keyPressHandler.startInterceptingKeyStrokes();\n}\n"],"names":["startInterfaceAsync","debug","require","CTRL_C","CTRL_D","CTRL_L","PLATFORM_SETTINGS","android","name","key","launchTarget","ios","devServerManager","options","actions","DevServerManagerActions","isWebSocketsEnabled","getDefaultDevServer","isTargetingNative","usageOptions","devClient","printDevServerInfo","onPressAsync","pauseInteractions","spinners","getAllSpinners","forEach","spinner","fail","currentProgress","getProgressBar","terminate","setProgressBar","ora","text","color","start","stopAsync","stopAndPersist","symbol","process","emit","exit","error","Log","clear","printUsage","verbose","toggleDevMenu","openMoreToolsAsync","platforms","includes","toLowerCase","platform","shouldPrompt","server","settings","log","BLT","warn","chalk","openPlatformAsync","printHelp","AbortCommandError","exception","toggleRuntimeMode","ensureProjectPrerequisiteAsync","WebSupportProjectPrerequisite","push","e","message","isDisabled","getWebDevServer","ensureWebDevServerRunningAsync","openJsInspectorAsync","reloadApp","openInEditorAsync","projectRoot","keyPressHandler","KeyPressHandler","listener","createInteractionListener","addInteractionListener","startInterceptingKeyStrokes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/start/interface/startInterface.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport { KeyPressHandler } from './KeyPressHandler';\nimport { BLT, printHelp, printUsage, StartOptions } from './commandsTable';\nimport { DevServerManagerActions } from './interactiveActions';\nimport * as Log from '../../log';\nimport { openInEditorAsync } from '../../utils/editor';\nimport { AbortCommandError } from '../../utils/errors';\nimport { getAllSpinners, ora } from '../../utils/ora';\nimport { getProgressBar, setProgressBar } from '../../utils/progress';\nimport { addInteractionListener, pauseInteractions } from '../../utils/prompts';\nimport { WebSupportProjectPrerequisite } from '../doctor/web/WebSupportProjectPrerequisite';\nimport { DevServerManager } from '../server/DevServerManager';\n\nconst debug = require('debug')('expo:start:interface:startInterface') as typeof console.log;\n\nconst CTRL_C = '\\u0003';\nconst CTRL_D = '\\u0004';\nconst CTRL_L = '\\u000C';\n\nconst PLATFORM_SETTINGS: Record<\n string,\n { name: string; key: 'android' | 'ios'; launchTarget: 'emulator' | 'simulator' }\n> = {\n android: {\n name: 'Android',\n key: 'android',\n launchTarget: 'emulator',\n },\n ios: {\n name: 'iOS',\n key: 'ios',\n launchTarget: 'simulator',\n },\n};\n\nexport async function startInterfaceAsync(\n devServerManager: DevServerManager,\n options: Pick<StartOptions, 'devClient' | 'platforms' | 'mcpServer'>\n) {\n const actions = new DevServerManagerActions(devServerManager, options);\n\n const isWebSocketsEnabled = devServerManager.getDefaultDevServer()?.isTargetingNative();\n\n const usageOptions = {\n isWebSocketsEnabled,\n devClient: devServerManager.options.devClient,\n ...options,\n };\n\n actions.printDevServerInfo(usageOptions);\n\n const onPressAsync = async (key: string) => {\n // Auxillary commands all escape.\n switch (key) {\n case CTRL_C:\n case CTRL_D: {\n // Prevent terminal UI from accepting commands while the process is closing.\n // Without this, fast typers will close the server then start typing their\n // next command and have a bunch of unrelated things pop up.\n pauseInteractions();\n\n const spinners = getAllSpinners();\n spinners.forEach((spinner) => {\n spinner.fail();\n });\n\n const currentProgress = getProgressBar();\n if (currentProgress) {\n currentProgress.terminate();\n setProgressBar(null);\n }\n const spinner = ora({ text: 'Stopping server', color: 'white' }).start();\n try {\n await devServerManager.stopAsync();\n if (options.mcpServer) {\n await options.mcpServer.closeAsync();\n }\n spinner.stopAndPersist({ text: 'Stopped server', symbol: `\\u203A` });\n // @ts-ignore: Argument of type '\"SIGINT\"' is not assignable to parameter of type '\"disconnect\"'.\n process.emit('SIGINT');\n\n // TODO: Is this the right place to do this?\n process.exit();\n } catch (error) {\n spinner.fail('Failed to stop server');\n throw error;\n }\n break;\n }\n case CTRL_L:\n return Log.clear();\n case '?':\n return printUsage(usageOptions, { verbose: true });\n }\n\n // Optionally enabled\n\n if (isWebSocketsEnabled) {\n switch (key) {\n case 'm':\n return actions.toggleDevMenu();\n case 'M':\n return actions.openMoreToolsAsync();\n }\n }\n\n const { platforms = ['ios', 'android', 'web'] } = options;\n\n if (['i', 'a'].includes(key.toLowerCase())) {\n const platform = key.toLowerCase() === 'i' ? 'ios' : 'android';\n\n const shouldPrompt = ['I', 'A'].includes(key);\n if (shouldPrompt) {\n Log.clear();\n }\n\n const server = devServerManager.getDefaultDevServer();\n const settings = PLATFORM_SETTINGS[platform];\n\n Log.log(`${BLT} Opening on ${settings.name}...`);\n\n if (server.isTargetingNative() && !platforms.includes(settings.key)) {\n Log.warn(\n chalk`${settings.name} is disabled, enable it by adding {bold ${settings.key}} to the platforms array in your app.json or app.config.js`\n );\n } else {\n try {\n await server.openPlatformAsync(settings.launchTarget, { shouldPrompt });\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n }\n // Break out early.\n return;\n }\n\n switch (key) {\n case 's': {\n Log.clear();\n if (await devServerManager.toggleRuntimeMode()) {\n usageOptions.devClient = devServerManager.options.devClient;\n return actions.printDevServerInfo(usageOptions);\n }\n break;\n }\n case 'w': {\n try {\n await devServerManager.ensureProjectPrerequisiteAsync(WebSupportProjectPrerequisite);\n if (!platforms.includes('web')) {\n platforms.push('web');\n options.platforms?.push('web');\n }\n } catch (e: any) {\n Log.warn(e.message);\n break;\n }\n\n const isDisabled = !platforms.includes('web');\n if (isDisabled) {\n debug('Web is disabled');\n // Use warnings from the web support setup.\n break;\n }\n\n // Ensure the Webpack dev server is running first\n if (!devServerManager.getWebDevServer()) {\n debug('Starting up webpack dev server');\n await devServerManager.ensureWebDevServerRunningAsync();\n // When this is the first time webpack is started, reprint the connection info.\n actions.printDevServerInfo(usageOptions);\n }\n\n Log.log(`${BLT} Open in the web browser...`);\n try {\n await devServerManager.getWebDevServer()?.openPlatformAsync('desktop');\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n break;\n }\n case 'c':\n Log.clear();\n return actions.printDevServerInfo(usageOptions);\n case 'j':\n return actions.openJsInspectorAsync();\n case 'r':\n return actions.reloadApp();\n case 'o':\n Log.log(`${BLT} Opening the editor...`);\n return openInEditorAsync(devServerManager.projectRoot);\n }\n };\n\n const keyPressHandler = new KeyPressHandler(onPressAsync);\n\n const listener = keyPressHandler.createInteractionListener();\n\n addInteractionListener(listener);\n\n // Start observing...\n keyPressHandler.startInterceptingKeyStrokes();\n}\n"],"names":["startInterfaceAsync","debug","require","CTRL_C","CTRL_D","CTRL_L","PLATFORM_SETTINGS","android","name","key","launchTarget","ios","devServerManager","options","actions","DevServerManagerActions","isWebSocketsEnabled","getDefaultDevServer","isTargetingNative","usageOptions","devClient","printDevServerInfo","onPressAsync","pauseInteractions","spinners","getAllSpinners","forEach","spinner","fail","currentProgress","getProgressBar","terminate","setProgressBar","ora","text","color","start","stopAsync","mcpServer","closeAsync","stopAndPersist","symbol","process","emit","exit","error","Log","clear","printUsage","verbose","toggleDevMenu","openMoreToolsAsync","platforms","includes","toLowerCase","platform","shouldPrompt","server","settings","log","BLT","warn","chalk","openPlatformAsync","printHelp","AbortCommandError","exception","toggleRuntimeMode","ensureProjectPrerequisiteAsync","WebSupportProjectPrerequisite","push","e","message","isDisabled","getWebDevServer","ensureWebDevServerRunningAsync","openJsInspectorAsync","reloadApp","openInEditorAsync","projectRoot","keyPressHandler","KeyPressHandler","listener","createInteractionListener","addInteractionListener","startInterceptingKeyStrokes"],"mappings":"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"}
@@ -188,15 +188,10 @@ class AndroidDeviceManager extends _DeviceManager.DeviceManager {
188
188
  }
189
189
  const parsed = new URL(url);
190
190
  if (parsed.protocol === 'exp:') {
191
- // NOTE(brentvatne): temporary workaround! launch Expo Go first, then
192
- // launch the project!
193
- // https://github.com/expo/expo/issues/7772
194
- // adb shell monkey -p host.exp.exponent -c android.intent.category.LAUNCHER 1
195
- // Note: this is not needed in Expo Development Client, it only applies to Expo Go
196
- await _adb.openAppIdAsync({
191
+ await _adb.launchActivityAsync({
197
192
  pid: this.device.pid
198
193
  }, {
199
- applicationId: EXPO_GO_APPLICATION_IDENTIFIER
194
+ launchActivity: `${EXPO_GO_APPLICATION_IDENTIFIER}/.experience.HomeActivity`
200
195
  });
201
196
  }
202
197
  await _adb.openUrlAsync({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/platforms/android/AndroidDeviceManager.ts"],"sourcesContent":["import assert from 'assert';\nimport chalk from 'chalk';\n\nimport { activateWindowAsync } from './activateWindow';\nimport * as AndroidDebugBridge from './adb';\nimport { startDeviceAsync } from './emulator';\nimport { getDevicesAsync } from './getDevices';\nimport { promptForDeviceAsync } from './promptAndroidDevice';\nimport * as Log from '../../../log';\nimport { AbortCommandError, CommandError } from '../../../utils/errors';\nimport { validateUrl } from '../../../utils/url';\nimport { DeviceManager } from '../DeviceManager';\nimport { ExpoGoInstaller } from '../ExpoGoInstaller';\nimport { BaseResolveDeviceProps } from '../PlatformManager';\n\nconst EXPO_GO_APPLICATION_IDENTIFIER = 'host.exp.exponent';\n\nexport class AndroidDeviceManager extends DeviceManager<AndroidDebugBridge.Device> {\n static async resolveFromNameAsync(name: string): Promise<AndroidDeviceManager> {\n const devices = await getDevicesAsync();\n const device = devices.find((device) => device.name === name);\n\n if (!device) {\n throw new CommandError('Could not find device with name: ' + name);\n }\n return AndroidDeviceManager.resolveAsync({ device, shouldPrompt: false });\n }\n\n static async resolveAsync({\n device,\n shouldPrompt,\n }: BaseResolveDeviceProps<AndroidDebugBridge.Device> = {}): Promise<AndroidDeviceManager> {\n if (device) {\n const manager = new AndroidDeviceManager(device);\n if (!(await manager.attemptToStartAsync())) {\n throw new AbortCommandError();\n }\n return manager;\n }\n\n const devices = await getDevicesAsync();\n const _device = shouldPrompt ? await promptForDeviceAsync(devices) : devices[0];\n return AndroidDeviceManager.resolveAsync({ device: _device, shouldPrompt: false });\n }\n\n get name() {\n // TODO: Maybe strip `_` from the device name?\n return this.device.name;\n }\n\n get identifier(): string {\n return this.device.pid ?? 'unknown';\n }\n\n async getAppVersionAsync(applicationId: string): Promise<string | null> {\n const info = await AndroidDebugBridge.getPackageInfoAsync(this.device, {\n appId: applicationId,\n });\n\n const regex = /versionName=([0-9.]+)/;\n return regex.exec(info)?.[1] ?? null;\n }\n\n protected async attemptToStartAsync(): Promise<AndroidDebugBridge.Device | null> {\n // TODO: Add a light-weight method for checking since a device could disconnect.\n if (!(await AndroidDebugBridge.isDeviceBootedAsync(this.device))) {\n this.device = await startDeviceAsync(this.device);\n }\n\n if (this.device.isAuthorized === false) {\n AndroidDebugBridge.logUnauthorized(this.device);\n return null;\n }\n\n return this.device;\n }\n\n async startAsync(): Promise<AndroidDebugBridge.Device> {\n const device = await this.attemptToStartAsync();\n assert(device, `Failed to boot emulator.`);\n return this.device;\n }\n\n async installAppAsync(binaryPath: string) {\n await AndroidDebugBridge.installAsync(this.device, {\n filePath: binaryPath,\n });\n }\n\n async uninstallAppAsync(appId: string) {\n // we need to check if the app is installed, else we might bump into \"Failure [DELETE_FAILED_INTERNAL_ERROR]\"\n const isInstalled = await this.isAppInstalledAndIfSoReturnContainerPathForIOSAsync(appId);\n if (!isInstalled) {\n return;\n }\n\n try {\n await AndroidDebugBridge.uninstallAsync(this.device, {\n appId,\n });\n } catch (e) {\n Log.error(\n `Could not uninstall app \"${appId}\" from your device, please uninstall it manually and try again.`\n );\n throw e;\n }\n }\n\n /**\n * @param launchActivity Activity to launch `[application identifier]/.[main activity name]`, ex: `com.bacon.app/.MainActivity`\n */\n async launchActivityAsync(launchActivity: string, url?: string): Promise<string> {\n try {\n return await AndroidDebugBridge.launchActivityAsync(this.device, {\n launchActivity,\n url,\n });\n } catch (error: any) {\n let errorMessage = `Couldn't open Android app with activity \"${launchActivity}\" on device \"${this.name}\".`;\n if (error instanceof CommandError && error.code === 'APP_NOT_INSTALLED') {\n errorMessage += `\\nThe app might not be installed, try installing it with: ${chalk.bold(\n `npx expo run:android -d ${this.name}`\n )}`;\n }\n errorMessage += chalk.gray(`\\n${error.message}`);\n error.message = errorMessage;\n throw error;\n }\n }\n\n async isAppInstalledAndIfSoReturnContainerPathForIOSAsync(applicationId: string) {\n return await AndroidDebugBridge.isPackageInstalledAsync(this.device, applicationId);\n }\n\n async openUrlAsync(url: string) {\n // Non-compliant URLs will be treated as application identifiers.\n if (!validateUrl(url, { requireProtocol: true })) {\n await this.launchActivityAsync(url);\n return;\n }\n\n const parsed = new URL(url);\n\n if (parsed.protocol === 'exp:') {\n // NOTE(brentvatne): temporary workaround! launch Expo Go first, then\n // launch the project!\n // https://github.com/expo/expo/issues/7772\n // adb shell monkey -p host.exp.exponent -c android.intent.category.LAUNCHER 1\n // Note: this is not needed in Expo Development Client, it only applies to Expo Go\n await AndroidDebugBridge.openAppIdAsync(\n { pid: this.device.pid },\n { applicationId: EXPO_GO_APPLICATION_IDENTIFIER }\n );\n }\n\n await AndroidDebugBridge.openUrlAsync({ pid: this.device.pid }, { url });\n }\n\n async activateWindowAsync() {\n // Bring the emulator window to the front on macos devices.\n await activateWindowAsync(this.device);\n }\n\n getExpoGoAppId(): string {\n return EXPO_GO_APPLICATION_IDENTIFIER;\n }\n\n async ensureExpoGoAsync(sdkVersion: string): Promise<boolean> {\n const installer = new ExpoGoInstaller('android', EXPO_GO_APPLICATION_IDENTIFIER, sdkVersion);\n return installer.ensureAsync(this);\n }\n}\n"],"names":["AndroidDeviceManager","EXPO_GO_APPLICATION_IDENTIFIER","DeviceManager","resolveFromNameAsync","name","devices","getDevicesAsync","device","find","CommandError","resolveAsync","shouldPrompt","manager","attemptToStartAsync","AbortCommandError","_device","promptForDeviceAsync","identifier","pid","getAppVersionAsync","applicationId","regex","info","AndroidDebugBridge","getPackageInfoAsync","appId","exec","isDeviceBootedAsync","startDeviceAsync","isAuthorized","logUnauthorized","startAsync","assert","installAppAsync","binaryPath","installAsync","filePath","uninstallAppAsync","isInstalled","isAppInstalledAndIfSoReturnContainerPathForIOSAsync","uninstallAsync","e","Log","error","launchActivityAsync","launchActivity","url","errorMessage","code","chalk","bold","gray","message","isPackageInstalledAsync","openUrlAsync","validateUrl","requireProtocol","parsed","URL","protocol","openAppIdAsync","activateWindowAsync","getExpoGoAppId","ensureExpoGoAsync","sdkVersion","installer","ExpoGoInstaller","ensureAsync"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/platforms/android/AndroidDeviceManager.ts"],"sourcesContent":["import assert from 'assert';\nimport chalk from 'chalk';\n\nimport { activateWindowAsync } from './activateWindow';\nimport * as AndroidDebugBridge from './adb';\nimport { startDeviceAsync } from './emulator';\nimport { getDevicesAsync } from './getDevices';\nimport { promptForDeviceAsync } from './promptAndroidDevice';\nimport * as Log from '../../../log';\nimport { AbortCommandError, CommandError } from '../../../utils/errors';\nimport { validateUrl } from '../../../utils/url';\nimport { DeviceManager } from '../DeviceManager';\nimport { ExpoGoInstaller } from '../ExpoGoInstaller';\nimport { BaseResolveDeviceProps } from '../PlatformManager';\n\nconst EXPO_GO_APPLICATION_IDENTIFIER = 'host.exp.exponent';\n\nexport class AndroidDeviceManager extends DeviceManager<AndroidDebugBridge.Device> {\n static async resolveFromNameAsync(name: string): Promise<AndroidDeviceManager> {\n const devices = await getDevicesAsync();\n const device = devices.find((device) => device.name === name);\n\n if (!device) {\n throw new CommandError('Could not find device with name: ' + name);\n }\n return AndroidDeviceManager.resolveAsync({ device, shouldPrompt: false });\n }\n\n static async resolveAsync({\n device,\n shouldPrompt,\n }: BaseResolveDeviceProps<AndroidDebugBridge.Device> = {}): Promise<AndroidDeviceManager> {\n if (device) {\n const manager = new AndroidDeviceManager(device);\n if (!(await manager.attemptToStartAsync())) {\n throw new AbortCommandError();\n }\n return manager;\n }\n\n const devices = await getDevicesAsync();\n const _device = shouldPrompt ? await promptForDeviceAsync(devices) : devices[0];\n return AndroidDeviceManager.resolveAsync({ device: _device, shouldPrompt: false });\n }\n\n get name() {\n // TODO: Maybe strip `_` from the device name?\n return this.device.name;\n }\n\n get identifier(): string {\n return this.device.pid ?? 'unknown';\n }\n\n async getAppVersionAsync(applicationId: string): Promise<string | null> {\n const info = await AndroidDebugBridge.getPackageInfoAsync(this.device, {\n appId: applicationId,\n });\n\n const regex = /versionName=([0-9.]+)/;\n return regex.exec(info)?.[1] ?? null;\n }\n\n protected async attemptToStartAsync(): Promise<AndroidDebugBridge.Device | null> {\n // TODO: Add a light-weight method for checking since a device could disconnect.\n if (!(await AndroidDebugBridge.isDeviceBootedAsync(this.device))) {\n this.device = await startDeviceAsync(this.device);\n }\n\n if (this.device.isAuthorized === false) {\n AndroidDebugBridge.logUnauthorized(this.device);\n return null;\n }\n\n return this.device;\n }\n\n async startAsync(): Promise<AndroidDebugBridge.Device> {\n const device = await this.attemptToStartAsync();\n assert(device, `Failed to boot emulator.`);\n return this.device;\n }\n\n async installAppAsync(binaryPath: string) {\n await AndroidDebugBridge.installAsync(this.device, {\n filePath: binaryPath,\n });\n }\n\n async uninstallAppAsync(appId: string) {\n // we need to check if the app is installed, else we might bump into \"Failure [DELETE_FAILED_INTERNAL_ERROR]\"\n const isInstalled = await this.isAppInstalledAndIfSoReturnContainerPathForIOSAsync(appId);\n if (!isInstalled) {\n return;\n }\n\n try {\n await AndroidDebugBridge.uninstallAsync(this.device, {\n appId,\n });\n } catch (e) {\n Log.error(\n `Could not uninstall app \"${appId}\" from your device, please uninstall it manually and try again.`\n );\n throw e;\n }\n }\n\n /**\n * @param launchActivity Activity to launch `[application identifier]/.[main activity name]`, ex: `com.bacon.app/.MainActivity`\n */\n async launchActivityAsync(launchActivity: string, url?: string): Promise<string> {\n try {\n return await AndroidDebugBridge.launchActivityAsync(this.device, {\n launchActivity,\n url,\n });\n } catch (error: any) {\n let errorMessage = `Couldn't open Android app with activity \"${launchActivity}\" on device \"${this.name}\".`;\n if (error instanceof CommandError && error.code === 'APP_NOT_INSTALLED') {\n errorMessage += `\\nThe app might not be installed, try installing it with: ${chalk.bold(\n `npx expo run:android -d ${this.name}`\n )}`;\n }\n errorMessage += chalk.gray(`\\n${error.message}`);\n error.message = errorMessage;\n throw error;\n }\n }\n\n async isAppInstalledAndIfSoReturnContainerPathForIOSAsync(applicationId: string) {\n return await AndroidDebugBridge.isPackageInstalledAsync(this.device, applicationId);\n }\n\n async openUrlAsync(url: string) {\n // Non-compliant URLs will be treated as application identifiers.\n if (!validateUrl(url, { requireProtocol: true })) {\n await this.launchActivityAsync(url);\n return;\n }\n\n const parsed = new URL(url);\n\n if (parsed.protocol === 'exp:') {\n await AndroidDebugBridge.launchActivityAsync(\n { pid: this.device.pid },\n {\n launchActivity: `${EXPO_GO_APPLICATION_IDENTIFIER}/.experience.HomeActivity`,\n }\n );\n }\n\n await AndroidDebugBridge.openUrlAsync({ pid: this.device.pid }, { url });\n }\n\n async activateWindowAsync() {\n // Bring the emulator window to the front on macos devices.\n await activateWindowAsync(this.device);\n }\n\n getExpoGoAppId(): string {\n return EXPO_GO_APPLICATION_IDENTIFIER;\n }\n\n async ensureExpoGoAsync(sdkVersion: string): Promise<boolean> {\n const installer = new ExpoGoInstaller('android', EXPO_GO_APPLICATION_IDENTIFIER, sdkVersion);\n return installer.ensureAsync(this);\n }\n}\n"],"names":["AndroidDeviceManager","EXPO_GO_APPLICATION_IDENTIFIER","DeviceManager","resolveFromNameAsync","name","devices","getDevicesAsync","device","find","CommandError","resolveAsync","shouldPrompt","manager","attemptToStartAsync","AbortCommandError","_device","promptForDeviceAsync","identifier","pid","getAppVersionAsync","applicationId","regex","info","AndroidDebugBridge","getPackageInfoAsync","appId","exec","isDeviceBootedAsync","startDeviceAsync","isAuthorized","logUnauthorized","startAsync","assert","installAppAsync","binaryPath","installAsync","filePath","uninstallAppAsync","isInstalled","isAppInstalledAndIfSoReturnContainerPathForIOSAsync","uninstallAsync","e","Log","error","launchActivityAsync","launchActivity","url","errorMessage","code","chalk","bold","gray","message","isPackageInstalledAsync","openUrlAsync","validateUrl","requireProtocol","parsed","URL","protocol","activateWindowAsync","getExpoGoAppId","ensureExpoGoAsync","sdkVersion","installer","ExpoGoInstaller","ensureAsync"],"mappings":"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"}