@expo/cli 55.0.29 → 55.0.31

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 (41) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/events/index.js +1 -1
  3. package/build/src/export/embed/exportEmbedAsync.js +1 -1
  4. package/build/src/export/embed/exportEmbedAsync.js.map +1 -1
  5. package/build/src/export/embed/exportServer.js +1 -1
  6. package/build/src/export/embed/exportServer.js.map +1 -1
  7. package/build/src/export/exportApp.js +1 -1
  8. package/build/src/export/exportApp.js.map +1 -1
  9. package/build/src/export/publicFolder.js +19 -1
  10. package/build/src/export/publicFolder.js.map +1 -1
  11. package/build/src/run/android/resolveLaunchProps.js +4 -1
  12. package/build/src/run/android/resolveLaunchProps.js.map +1 -1
  13. package/build/src/start/server/DevToolsPlugin.js +26 -1
  14. package/build/src/start/server/DevToolsPlugin.js.map +1 -1
  15. package/build/src/start/server/DevToolsPluginCliExtensionExecutor.js +57 -22
  16. package/build/src/start/server/DevToolsPluginCliExtensionExecutor.js.map +1 -1
  17. package/build/src/start/server/DevToolsPluginCliExtensionResults.js +29 -0
  18. package/build/src/start/server/DevToolsPluginCliExtensionResults.js.map +1 -1
  19. package/build/src/start/server/MCPDevToolsPluginCLIExtensions.js +15 -5
  20. package/build/src/start/server/MCPDevToolsPluginCLIExtensions.js.map +1 -1
  21. package/build/src/start/server/createMCPDevToolsExtensionSchema.js +13 -1
  22. package/build/src/start/server/createMCPDevToolsExtensionSchema.js.map +1 -1
  23. package/build/src/start/server/metro/createServerComponentsMiddleware.js +5 -12
  24. package/build/src/start/server/metro/createServerComponentsMiddleware.js.map +1 -1
  25. package/build/src/start/server/metro/dev-server/createMessageSocket.js +13 -2
  26. package/build/src/start/server/metro/dev-server/createMessageSocket.js.map +1 -1
  27. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js +2 -1
  28. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js.map +1 -1
  29. package/build/src/start/server/metro/instantiateMetro.js +5 -4
  30. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  31. package/build/src/start/server/metro/router.js +10 -1
  32. package/build/src/start/server/metro/router.js.map +1 -1
  33. package/build/src/start/server/middleware/ServeStaticMiddleware.js +2 -9
  34. package/build/src/start/server/middleware/ServeStaticMiddleware.js.map +1 -1
  35. package/build/src/start/server/webTemplate.js +3 -5
  36. package/build/src/start/server/webTemplate.js.map +1 -1
  37. package/build/src/utils/tar.js +2 -2
  38. package/build/src/utils/tar.js.map +1 -1
  39. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  40. package/build/src/utils/telemetry/utils/context.js +1 -1
  41. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/server/metro/router.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport type { MiddlewareMatcher } from 'expo-server';\nimport { sync as globSync } from 'glob';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { Log } from '../../../log';\nimport { directoryExistsSync } from '../../../utils/dir';\nimport { toPosixPath } from '../../../utils/filePath';\nimport { learnMore } from '../../../utils/link';\n\nconst debug = require('debug')('expo:start:server:metro:router') as typeof console.log;\n\n/**\n * Get the relative path for requiring the `/app` folder relative to the `expo-router/entry` file.\n * This mechanism does require the server to restart after the `expo-router` package is installed.\n */\nexport function getAppRouterRelativeEntryPath(\n projectRoot: string,\n routerDirectory: string = getRouterDirectory(projectRoot)\n): string | undefined {\n // Auto pick App entry\n const routerEntry =\n resolveFrom.silent(projectRoot, 'expo-router/entry') ?? getFallbackEntryRoot(projectRoot);\n if (!routerEntry) {\n return undefined;\n }\n // It doesn't matter if the app folder exists.\n const appFolder = path.join(projectRoot, routerDirectory);\n const appRoot = path.relative(path.dirname(routerEntry), appFolder);\n debug('expo-router entry', routerEntry, appFolder, appRoot);\n return appRoot;\n}\n\n/** If the `expo-router` package is not installed, then use the `expo` package to determine where the node modules are relative to the project. */\nfunction getFallbackEntryRoot(projectRoot: string): string {\n const expoRoot = resolveFrom.silent(projectRoot, 'expo/package.json');\n if (expoRoot) {\n return path.join(path.dirname(path.dirname(expoRoot)), 'expo-router/entry');\n }\n return path.join(projectRoot, 'node_modules/expo-router/entry');\n}\n\nexport function getRouterDirectoryModuleIdWithManifest(\n projectRoot: string,\n exp: ExpoConfig\n): string {\n return toPosixPath(exp.extra?.router?.root ?? getRouterDirectory(projectRoot));\n}\n\nlet hasWarnedAboutSrcDir = false;\nconst logSrcDir = () => {\n if (hasWarnedAboutSrcDir) return;\n hasWarnedAboutSrcDir = true;\n Log.log(chalk.gray('Using src/app as the root directory for Expo Router.'));\n};\n\nexport function getRouterDirectory(projectRoot: string): string {\n // more specific directories first\n if (directoryExistsSync(path.join(projectRoot, 'src', 'app'))) {\n logSrcDir();\n return path.join('src', 'app');\n }\n\n debug('Using app as the root directory for Expo Router.');\n return 'app';\n}\n\nexport function isApiRouteConvention(name: string): boolean {\n return /\\+api\\.[tj]sx?$/.test(name);\n}\n\nexport function getApiRoutesForDirectory(cwd: string) {\n return globSync('**/*+api.@(ts|tsx|js|jsx)', {\n cwd,\n absolute: true,\n dot: true,\n });\n}\n\n/**\n * Gets the +middleware file for a given directory. In\n * @param cwd\n */\nexport function getMiddlewareForDirectory(cwd: string): string | null {\n const files = globSync('+middleware.@(ts|tsx|js|jsx)', {\n cwd,\n absolute: true,\n dot: true,\n });\n\n if (files.length === 0) return null;\n\n if (files.length > 1) {\n // In development, throw an error if there are multiple root-level middleware files\n if (process.env.NODE_ENV !== 'production') {\n const relativePaths = files.map((f) => './' + path.relative(cwd, f)).sort();\n throw new Error(\n `Only one middleware file is allowed. Keep one of the conflicting files: ${relativePaths.map((p) => `\"${p}\"`).join(' or ')}`\n );\n }\n }\n\n return files[0];\n}\n\n// Used to emulate a context module, but way faster. TODO: May need to adjust the extensions to stay in sync with Metro.\nexport function getRoutePaths(cwd: string) {\n return globSync('**/*.@(ts|tsx|js|jsx)', {\n cwd,\n dot: true,\n }).map((p) => './' + normalizePaths(p));\n}\n\nfunction normalizePaths(p: string) {\n return p.replace(/\\\\/g, '/');\n}\n\nlet hasWarnedAboutApiRouteOutput = false;\nlet hasWarnedAboutMiddlewareOutput = false;\n\nexport function hasWarnedAboutApiRoutes() {\n return hasWarnedAboutApiRouteOutput;\n}\n\nexport function hasWarnedAboutMiddleware() {\n return hasWarnedAboutMiddlewareOutput;\n}\n\nexport function warnInvalidWebOutput() {\n if (!hasWarnedAboutApiRouteOutput) {\n Log.warn(\n chalk.yellow`Using API routes requires the {bold web.output} to be set to {bold \"server\"} in the project {bold app.json}. ${learnMore(\n 'https://docs.expo.dev/router/reference/api-routes/'\n )}`\n );\n }\n\n hasWarnedAboutApiRouteOutput = true;\n}\n\nexport function warnInvalidMiddlewareOutput() {\n if (!hasWarnedAboutMiddlewareOutput) {\n Log.warn(\n chalk.yellow`Using middleware requires the {bold web.output} to be set to {bold \"server\"} in the project {bold app.json}. ${learnMore(\n 'https://docs.expo.dev/router/reference/api-routes/'\n )}`\n );\n }\n\n hasWarnedAboutMiddlewareOutput = true;\n}\n\nexport function warnInvalidMiddlewareMatcherSettings(matcher: MiddlewareMatcher) {\n const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];\n\n // Ensure methods are valid HTTP methods\n if (matcher.methods) {\n if (!Array.isArray(matcher.methods)) {\n Log.error(\n chalk.red`Middleware matcher methods must be an array of valid HTTP methods. Supported methods are: ${validMethods.join(', ')}`\n );\n } else {\n for (const method of matcher.methods) {\n if (!validMethods.includes(method)) {\n Log.error(\n chalk.red`Invalid middleware HTTP method: ${method}. Supported methods are: ${validMethods.join(', ')}`\n );\n }\n }\n }\n }\n\n // Ensure patterns are either a string or RegExp\n if (matcher.patterns) {\n const patterns = Array.isArray(matcher.patterns) ? matcher.patterns : [matcher.patterns];\n for (const pattern of patterns) {\n if (typeof pattern !== 'string' && !(pattern instanceof RegExp)) {\n Log.error(\n chalk.red`Middleware matcher patterns must be strings or regular expressions. Received: ${String(\n pattern\n )}`\n );\n }\n\n if (typeof pattern === 'string' && !pattern.startsWith('/')) {\n Log.error(\n chalk.red`String patterns in middleware matcher must start with '/'. Received: ${pattern}`\n );\n }\n }\n }\n}\n"],"names":["getApiRoutesForDirectory","getAppRouterRelativeEntryPath","getMiddlewareForDirectory","getRoutePaths","getRouterDirectory","getRouterDirectoryModuleIdWithManifest","hasWarnedAboutApiRoutes","hasWarnedAboutMiddleware","isApiRouteConvention","warnInvalidMiddlewareMatcherSettings","warnInvalidMiddlewareOutput","warnInvalidWebOutput","debug","require","projectRoot","routerDirectory","routerEntry","resolveFrom","silent","getFallbackEntryRoot","undefined","appFolder","path","join","appRoot","relative","dirname","expoRoot","exp","toPosixPath","extra","router","root","hasWarnedAboutSrcDir","logSrcDir","Log","log","chalk","gray","directoryExistsSync","name","test","cwd","globSync","absolute","dot","files","length","process","env","NODE_ENV","relativePaths","map","f","sort","Error","p","normalizePaths","replace","hasWarnedAboutApiRouteOutput","hasWarnedAboutMiddlewareOutput","warn","yellow","learnMore","matcher","validMethods","methods","Array","isArray","error","red","method","includes","patterns","pattern","RegExp","String","startsWith"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/server/metro/router.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport type { MiddlewareMatcher } from 'expo-server';\nimport { sync as globSync } from 'glob';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { Log } from '../../../log';\nimport { directoryExistsSync, isPathInside } from '../../../utils/dir';\nimport { CommandError } from '../../../utils/errors';\nimport { toPosixPath } from '../../../utils/filePath';\nimport { learnMore } from '../../../utils/link';\n\nconst debug = require('debug')('expo:start:server:metro:router') as typeof console.log;\n\n/**\n * Get the relative path for requiring the `/app` folder relative to the `expo-router/entry` file.\n * This mechanism does require the server to restart after the `expo-router` package is installed.\n */\nexport function getAppRouterRelativeEntryPath(\n projectRoot: string,\n routerDirectory: string = getRouterDirectory(projectRoot)\n): string | undefined {\n // Auto pick App entry\n const routerEntry =\n resolveFrom.silent(projectRoot, 'expo-router/entry') ?? getFallbackEntryRoot(projectRoot);\n if (!routerEntry) {\n return undefined;\n }\n // It doesn't matter if the app folder exists.\n const appFolder = path.join(projectRoot, routerDirectory);\n const appRoot = path.relative(path.dirname(routerEntry), appFolder);\n debug('expo-router entry', routerEntry, appFolder, appRoot);\n return appRoot;\n}\n\n/** If the `expo-router` package is not installed, then use the `expo` package to determine where the node modules are relative to the project. */\nfunction getFallbackEntryRoot(projectRoot: string): string {\n const expoRoot = resolveFrom.silent(projectRoot, 'expo/package.json');\n if (expoRoot) {\n return path.join(path.dirname(path.dirname(expoRoot)), 'expo-router/entry');\n }\n return path.join(projectRoot, 'node_modules/expo-router/entry');\n}\n\nexport function getRouterDirectoryModuleIdWithManifest(\n projectRoot: string,\n exp: ExpoConfig\n): string {\n const configured = exp.extra?.router?.root;\n if (configured == null) {\n return toPosixPath(getRouterDirectory(projectRoot));\n }\n const absolute = path.isAbsolute(configured) ? configured : path.resolve(projectRoot, configured);\n if (!isPathInside(absolute, projectRoot)) {\n throw new CommandError(\n 'INVALID_ROUTER_ROOT',\n `The expo-router \\`root\\` (${configured}) resolves outside the project root. Set it to a path inside the project, or remove it to use the default.`\n );\n }\n return toPosixPath(configured);\n}\n\nlet hasWarnedAboutSrcDir = false;\nconst logSrcDir = () => {\n if (hasWarnedAboutSrcDir) return;\n hasWarnedAboutSrcDir = true;\n Log.log(chalk.gray('Using src/app as the root directory for Expo Router.'));\n};\n\nexport function getRouterDirectory(projectRoot: string): string {\n // more specific directories first\n if (directoryExistsSync(path.join(projectRoot, 'src', 'app'))) {\n logSrcDir();\n return path.join('src', 'app');\n }\n\n debug('Using app as the root directory for Expo Router.');\n return 'app';\n}\n\nexport function isApiRouteConvention(name: string): boolean {\n return /\\+api\\.[tj]sx?$/.test(name);\n}\n\nexport function getApiRoutesForDirectory(cwd: string) {\n return globSync('**/*+api.@(ts|tsx|js|jsx)', {\n cwd,\n absolute: true,\n dot: true,\n });\n}\n\n/**\n * Gets the +middleware file for a given directory. In\n * @param cwd\n */\nexport function getMiddlewareForDirectory(cwd: string): string | null {\n const files = globSync('+middleware.@(ts|tsx|js|jsx)', {\n cwd,\n absolute: true,\n dot: true,\n });\n\n if (files.length === 0) return null;\n\n if (files.length > 1) {\n // In development, throw an error if there are multiple root-level middleware files\n if (process.env.NODE_ENV !== 'production') {\n const relativePaths = files.map((f) => './' + path.relative(cwd, f)).sort();\n throw new Error(\n `Only one middleware file is allowed. Keep one of the conflicting files: ${relativePaths.map((p) => `\"${p}\"`).join(' or ')}`\n );\n }\n }\n\n return files[0];\n}\n\n// Used to emulate a context module, but way faster. TODO: May need to adjust the extensions to stay in sync with Metro.\nexport function getRoutePaths(cwd: string) {\n return globSync('**/*.@(ts|tsx|js|jsx)', {\n cwd,\n dot: true,\n }).map((p) => './' + normalizePaths(p));\n}\n\nfunction normalizePaths(p: string) {\n return p.replace(/\\\\/g, '/');\n}\n\nlet hasWarnedAboutApiRouteOutput = false;\nlet hasWarnedAboutMiddlewareOutput = false;\n\nexport function hasWarnedAboutApiRoutes() {\n return hasWarnedAboutApiRouteOutput;\n}\n\nexport function hasWarnedAboutMiddleware() {\n return hasWarnedAboutMiddlewareOutput;\n}\n\nexport function warnInvalidWebOutput() {\n if (!hasWarnedAboutApiRouteOutput) {\n Log.warn(\n chalk.yellow`Using API routes requires the {bold web.output} to be set to {bold \"server\"} in the project {bold app.json}. ${learnMore(\n 'https://docs.expo.dev/router/reference/api-routes/'\n )}`\n );\n }\n\n hasWarnedAboutApiRouteOutput = true;\n}\n\nexport function warnInvalidMiddlewareOutput() {\n if (!hasWarnedAboutMiddlewareOutput) {\n Log.warn(\n chalk.yellow`Using middleware requires the {bold web.output} to be set to {bold \"server\"} in the project {bold app.json}. ${learnMore(\n 'https://docs.expo.dev/router/reference/api-routes/'\n )}`\n );\n }\n\n hasWarnedAboutMiddlewareOutput = true;\n}\n\nexport function warnInvalidMiddlewareMatcherSettings(matcher: MiddlewareMatcher) {\n const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];\n\n // Ensure methods are valid HTTP methods\n if (matcher.methods) {\n if (!Array.isArray(matcher.methods)) {\n Log.error(\n chalk.red`Middleware matcher methods must be an array of valid HTTP methods. Supported methods are: ${validMethods.join(', ')}`\n );\n } else {\n for (const method of matcher.methods) {\n if (!validMethods.includes(method)) {\n Log.error(\n chalk.red`Invalid middleware HTTP method: ${method}. Supported methods are: ${validMethods.join(', ')}`\n );\n }\n }\n }\n }\n\n // Ensure patterns are either a string or RegExp\n if (matcher.patterns) {\n const patterns = Array.isArray(matcher.patterns) ? matcher.patterns : [matcher.patterns];\n for (const pattern of patterns) {\n if (typeof pattern !== 'string' && !(pattern instanceof RegExp)) {\n Log.error(\n chalk.red`Middleware matcher patterns must be strings or regular expressions. Received: ${String(\n pattern\n )}`\n );\n }\n\n if (typeof pattern === 'string' && !pattern.startsWith('/')) {\n Log.error(\n chalk.red`String patterns in middleware matcher must start with '/'. Received: ${pattern}`\n );\n }\n }\n }\n}\n"],"names":["getApiRoutesForDirectory","getAppRouterRelativeEntryPath","getMiddlewareForDirectory","getRoutePaths","getRouterDirectory","getRouterDirectoryModuleIdWithManifest","hasWarnedAboutApiRoutes","hasWarnedAboutMiddleware","isApiRouteConvention","warnInvalidMiddlewareMatcherSettings","warnInvalidMiddlewareOutput","warnInvalidWebOutput","debug","require","projectRoot","routerDirectory","routerEntry","resolveFrom","silent","getFallbackEntryRoot","undefined","appFolder","path","join","appRoot","relative","dirname","expoRoot","exp","configured","extra","router","root","toPosixPath","absolute","isAbsolute","resolve","isPathInside","CommandError","hasWarnedAboutSrcDir","logSrcDir","Log","log","chalk","gray","directoryExistsSync","name","test","cwd","globSync","dot","files","length","process","env","NODE_ENV","relativePaths","map","f","sort","Error","p","normalizePaths","replace","hasWarnedAboutApiRouteOutput","hasWarnedAboutMiddlewareOutput","warn","yellow","learnMore","matcher","validMethods","methods","Array","isArray","error","red","method","includes","patterns","pattern","RegExp","String","startsWith"],"mappings":"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"}
@@ -8,13 +8,6 @@ Object.defineProperty(exports, "ServeStaticMiddleware", {
8
8
  return ServeStaticMiddleware;
9
9
  }
10
10
  });
11
- function _path() {
12
- const data = /*#__PURE__*/ _interop_require_default(require("path"));
13
- _path = function() {
14
- return data;
15
- };
16
- return data;
17
- }
18
11
  function _send() {
19
12
  const data = /*#__PURE__*/ _interop_require_default(require("send"));
20
13
  _send = function() {
@@ -30,7 +23,7 @@ function _url() {
30
23
  return data;
31
24
  }
32
25
  const _resolvePlatform = require("./resolvePlatform");
33
- const _env = require("../../../utils/env");
26
+ const _publicFolder = require("../../../export/publicFolder");
34
27
  function _interop_require_default(obj) {
35
28
  return obj && obj.__esModule ? obj : {
36
29
  default: obj
@@ -42,7 +35,7 @@ class ServeStaticMiddleware {
42
35
  this.projectRoot = projectRoot;
43
36
  }
44
37
  getHandler() {
45
- const publicPath = _path().default.join(this.projectRoot, _env.env.EXPO_PUBLIC_FOLDER);
38
+ const publicPath = (0, _publicFolder.getPublicFolderPath)(this.projectRoot);
46
39
  debug(`Serving static files from:`, publicPath);
47
40
  const opts = {
48
41
  root: publicPath
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/server/middleware/ServeStaticMiddleware.ts"],"sourcesContent":["import path from 'path';\nimport send from 'send';\nimport { parse } from 'url';\n\nimport { parsePlatformHeader } from './resolvePlatform';\nimport { ServerRequest, ServerResponse } from './server.types';\nimport { env } from '../../../utils/env';\n\nconst debug = require('debug')('expo:start:server:middleware:serveStatic') as typeof console.log;\n\n/**\n * Adds support for serving the files in the static `public/` folder to web apps.\n */\nexport class ServeStaticMiddleware {\n constructor(private projectRoot: string) {}\n getHandler() {\n const publicPath = path.join(this.projectRoot, env.EXPO_PUBLIC_FOLDER);\n\n debug(`Serving static files from:`, publicPath);\n const opts = {\n root: publicPath,\n };\n return (req: ServerRequest, res: ServerResponse, next: any) => {\n if (!req?.url || (req.method !== 'GET' && req.method !== 'HEAD')) {\n return next();\n }\n\n const platform = parsePlatformHeader(req);\n // Currently this is web-only\n if (platform && platform !== 'web') {\n return next();\n }\n\n const pathname = parse(req.url).pathname;\n if (!pathname) {\n return next();\n }\n\n debug(`Maybe serve static:`, pathname);\n const stream = send(req, pathname, opts);\n\n // add file listener for fallthrough\n let forwardError = false;\n stream.on('file', function onFile() {\n // once file is determined, always forward error\n forwardError = true;\n });\n\n // forward errors\n stream.on('error', function error(err: any) {\n if (forwardError || !(err.statusCode < 500)) {\n next(err);\n return;\n }\n\n next();\n });\n\n // pipe\n stream.pipe(res);\n };\n }\n}\n"],"names":["ServeStaticMiddleware","debug","require","constructor","projectRoot","getHandler","publicPath","path","join","env","EXPO_PUBLIC_FOLDER","opts","root","req","res","next","url","method","platform","parsePlatformHeader","pathname","parse","stream","send","forwardError","on","onFile","error","err","statusCode","pipe"],"mappings":";;;;+BAaaA;;;eAAAA;;;;gEAbI;;;;;;;gEACA;;;;;;;yBACK;;;;;;iCAEc;qBAEhB;;;;;;AAEpB,MAAMC,QAAQC,QAAQ,SAAS;AAKxB,MAAMF;IACXG,YAAY,AAAQC,WAAmB,CAAE;aAArBA,cAAAA;IAAsB;IAC1CC,aAAa;QACX,MAAMC,aAAaC,eAAI,CAACC,IAAI,CAAC,IAAI,CAACJ,WAAW,EAAEK,QAAG,CAACC,kBAAkB;QAErET,MAAM,CAAC,0BAA0B,CAAC,EAAEK;QACpC,MAAMK,OAAO;YACXC,MAAMN;QACR;QACA,OAAO,CAACO,KAAoBC,KAAqBC;YAC/C,IAAI,EAACF,uBAAAA,IAAKG,GAAG,KAAKH,IAAII,MAAM,KAAK,SAASJ,IAAII,MAAM,KAAK,QAAS;gBAChE,OAAOF;YACT;YAEA,MAAMG,WAAWC,IAAAA,oCAAmB,EAACN;YACrC,6BAA6B;YAC7B,IAAIK,YAAYA,aAAa,OAAO;gBAClC,OAAOH;YACT;YAEA,MAAMK,WAAWC,IAAAA,YAAK,EAACR,IAAIG,GAAG,EAAEI,QAAQ;YACxC,IAAI,CAACA,UAAU;gBACb,OAAOL;YACT;YAEAd,MAAM,CAAC,mBAAmB,CAAC,EAAEmB;YAC7B,MAAME,SAASC,IAAAA,eAAI,EAACV,KAAKO,UAAUT;YAEnC,oCAAoC;YACpC,IAAIa,eAAe;YACnBF,OAAOG,EAAE,CAAC,QAAQ,SAASC;gBACzB,gDAAgD;gBAChDF,eAAe;YACjB;YAEA,iBAAiB;YACjBF,OAAOG,EAAE,CAAC,SAAS,SAASE,MAAMC,GAAQ;gBACxC,IAAIJ,gBAAgB,CAAEI,CAAAA,IAAIC,UAAU,GAAG,GAAE,GAAI;oBAC3Cd,KAAKa;oBACL;gBACF;gBAEAb;YACF;YAEA,OAAO;YACPO,OAAOQ,IAAI,CAAChB;QACd;IACF;AACF"}
1
+ {"version":3,"sources":["../../../../../src/start/server/middleware/ServeStaticMiddleware.ts"],"sourcesContent":["import send from 'send';\nimport { parse } from 'url';\n\nimport { parsePlatformHeader } from './resolvePlatform';\nimport type { ServerRequest, ServerResponse } from './server.types';\nimport { getPublicFolderPath } from '../../../export/publicFolder';\n\nconst debug = require('debug')('expo:start:server:middleware:serveStatic') as typeof console.log;\n\n/**\n * Adds support for serving the files in the static `public/` folder to web apps.\n */\nexport class ServeStaticMiddleware {\n constructor(private projectRoot: string) {}\n getHandler() {\n const publicPath = getPublicFolderPath(this.projectRoot);\n\n debug(`Serving static files from:`, publicPath);\n const opts = {\n root: publicPath,\n };\n return (req: ServerRequest, res: ServerResponse, next: any) => {\n if (!req?.url || (req.method !== 'GET' && req.method !== 'HEAD')) {\n return next();\n }\n\n const platform = parsePlatformHeader(req);\n // Currently this is web-only\n if (platform && platform !== 'web') {\n return next();\n }\n\n const pathname = parse(req.url).pathname;\n if (!pathname) {\n return next();\n }\n\n debug(`Maybe serve static:`, pathname);\n const stream = send(req, pathname, opts);\n\n // add file listener for fallthrough\n let forwardError = false;\n stream.on('file', function onFile() {\n // once file is determined, always forward error\n forwardError = true;\n });\n\n // forward errors\n stream.on('error', function error(err: any) {\n if (forwardError || !(err.statusCode < 500)) {\n next(err);\n return;\n }\n\n next();\n });\n\n // pipe\n stream.pipe(res);\n };\n }\n}\n"],"names":["ServeStaticMiddleware","debug","require","constructor","projectRoot","getHandler","publicPath","getPublicFolderPath","opts","root","req","res","next","url","method","platform","parsePlatformHeader","pathname","parse","stream","send","forwardError","on","onFile","error","err","statusCode","pipe"],"mappings":";;;;+BAYaA;;;eAAAA;;;;gEAZI;;;;;;;yBACK;;;;;;iCAEc;8BAEA;;;;;;AAEpC,MAAMC,QAAQC,QAAQ,SAAS;AAKxB,MAAMF;IACXG,YAAY,AAAQC,WAAmB,CAAE;aAArBA,cAAAA;IAAsB;IAC1CC,aAAa;QACX,MAAMC,aAAaC,IAAAA,iCAAmB,EAAC,IAAI,CAACH,WAAW;QAEvDH,MAAM,CAAC,0BAA0B,CAAC,EAAEK;QACpC,MAAME,OAAO;YACXC,MAAMH;QACR;QACA,OAAO,CAACI,KAAoBC,KAAqBC;YAC/C,IAAI,EAACF,uBAAAA,IAAKG,GAAG,KAAKH,IAAII,MAAM,KAAK,SAASJ,IAAII,MAAM,KAAK,QAAS;gBAChE,OAAOF;YACT;YAEA,MAAMG,WAAWC,IAAAA,oCAAmB,EAACN;YACrC,6BAA6B;YAC7B,IAAIK,YAAYA,aAAa,OAAO;gBAClC,OAAOH;YACT;YAEA,MAAMK,WAAWC,IAAAA,YAAK,EAACR,IAAIG,GAAG,EAAEI,QAAQ;YACxC,IAAI,CAACA,UAAU;gBACb,OAAOL;YACT;YAEAX,MAAM,CAAC,mBAAmB,CAAC,EAAEgB;YAC7B,MAAME,SAASC,IAAAA,eAAI,EAACV,KAAKO,UAAUT;YAEnC,oCAAoC;YACpC,IAAIa,eAAe;YACnBF,OAAOG,EAAE,CAAC,QAAQ,SAASC;gBACzB,gDAAgD;gBAChDF,eAAe;YACjB;YAEA,iBAAiB;YACjBF,OAAOG,EAAE,CAAC,SAAS,SAASE,MAAMC,GAAQ;gBACxC,IAAIJ,gBAAgB,CAAEI,CAAAA,IAAIC,UAAU,GAAG,GAAE,GAAI;oBAC3Cd,KAAKa;oBACL;gBACF;gBAEAb;YACF;YAEA,OAAO;YACPO,OAAOQ,IAAI,CAAChB;QACd;IACF;AACF"}
@@ -39,7 +39,7 @@ function _path() {
39
39
  }
40
40
  const _templates = require("../../customize/templates");
41
41
  const _html = require("../../export/html");
42
- const _env = require("../../utils/env");
42
+ const _publicFolder = require("../../export/publicFolder");
43
43
  function _interop_require_default(obj) {
44
44
  return obj && obj.__esModule ? obj : {
45
45
  default: obj
@@ -58,8 +58,8 @@ async function createTemplateHtmlFromExpoConfigAsync(projectRoot, { scripts, css
58
58
  themeColor: (_exp_web2 = exp.web) == null ? void 0 : _exp_web2.themeColor
59
59
  });
60
60
  }
61
- function getFileFromLocalPublicFolder(projectRoot, { publicFolder, filePath }) {
62
- const localFilePath = _path().default.resolve(projectRoot, publicFolder, filePath);
61
+ function getFileFromLocalPublicFolder(projectRoot, { filePath }) {
62
+ const localFilePath = _path().default.resolve((0, _publicFolder.getPublicFolderPath)(projectRoot), filePath);
63
63
  if (!_fs().default.existsSync(localFilePath)) {
64
64
  return null;
65
65
  }
@@ -67,8 +67,6 @@ function getFileFromLocalPublicFolder(projectRoot, { publicFolder, filePath }) {
67
67
  }
68
68
  /** Attempt to read the `index.html` from the local project before falling back on the template `index.html`. */ async function getTemplateIndexHtmlAsync(projectRoot) {
69
69
  let filePath = getFileFromLocalPublicFolder(projectRoot, {
70
- // TODO: Maybe use the app.json override.
71
- publicFolder: _env.env.EXPO_PUBLIC_FOLDER,
72
70
  filePath: 'index.html'
73
71
  });
74
72
  if (!filePath) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/server/webTemplate.ts"],"sourcesContent":["import { ExpoConfig, getConfig, getNameFromConfig } from '@expo/config';\nimport fs from 'fs';\nimport path from 'path';\n\nimport { TEMPLATES } from '../../customize/templates';\nimport { appendLinkToHtml, appendScriptsToHtml } from '../../export/html';\nimport { env } from '../../utils/env';\n\n/**\n * Create a static HTML for SPA styled websites.\n * This method attempts to reuse the same patterns as `@expo/webpack-config`.\n */\nexport async function createTemplateHtmlFromExpoConfigAsync(\n projectRoot: string,\n {\n scripts,\n cssLinks,\n exp = getConfig(projectRoot, { skipSDKVersionRequirement: true }).exp,\n }: {\n scripts: string[];\n cssLinks?: string[];\n exp?: ExpoConfig;\n }\n) {\n return createTemplateHtmlAsync(projectRoot, {\n langIsoCode: exp.web?.lang ?? 'en',\n scripts,\n cssLinks,\n title: getNameFromConfig(exp).webName ?? 'Expo App',\n description: exp.web?.description,\n themeColor: exp.web?.themeColor,\n });\n}\n\nfunction getFileFromLocalPublicFolder(\n projectRoot: string,\n { publicFolder, filePath }: { publicFolder: string; filePath: string }\n): string | null {\n const localFilePath = path.resolve(projectRoot, publicFolder, filePath);\n if (!fs.existsSync(localFilePath)) {\n return null;\n }\n return localFilePath;\n}\n\n/** Attempt to read the `index.html` from the local project before falling back on the template `index.html`. */\nasync function getTemplateIndexHtmlAsync(projectRoot: string): Promise<string> {\n let filePath = getFileFromLocalPublicFolder(projectRoot, {\n // TODO: Maybe use the app.json override.\n publicFolder: env.EXPO_PUBLIC_FOLDER,\n filePath: 'index.html',\n });\n if (!filePath) {\n filePath = TEMPLATES.find((value) => value.id === 'index.html')!.file(projectRoot);\n }\n return fs.promises.readFile(filePath, 'utf8');\n}\n\n/** Return an `index.html` string with template values added. */\nexport async function createTemplateHtmlAsync(\n projectRoot: string,\n {\n scripts,\n cssLinks,\n description,\n langIsoCode,\n title,\n themeColor,\n }: {\n scripts: string[];\n cssLinks?: string[];\n description?: string;\n langIsoCode: string;\n title: string;\n themeColor?: string;\n }\n): Promise<string> {\n // Resolve the best possible index.html template file.\n let contents = await getTemplateIndexHtmlAsync(projectRoot);\n\n contents = contents.replace('%LANG_ISO_CODE%', langIsoCode);\n contents = contents.replace('%WEB_TITLE%', title);\n\n contents = appendScriptsToHtml(contents, scripts);\n\n if (cssLinks) {\n contents = appendLinkToHtml(\n contents,\n cssLinks\n .map((href) => [\n // NOTE: We probably don't have to preload the CSS files for SPA-styled websites.\n {\n as: 'style',\n rel: 'preload',\n href,\n },\n {\n rel: 'stylesheet',\n href,\n },\n ])\n .flat()\n );\n }\n\n if (themeColor) {\n contents = addMeta(contents, `name=\"theme-color\" content=\"${themeColor}\"`);\n }\n\n if (description) {\n contents = addMeta(contents, `name=\"description\" content=\"${description}\"`);\n }\n\n return contents;\n}\n\n/** Add a `<meta />` tag to the `<head />` element. */\nfunction addMeta(contents: string, meta: string): string {\n return contents.replace('</head>', `<meta ${meta}>\\n</head>`);\n}\n"],"names":["createTemplateHtmlAsync","createTemplateHtmlFromExpoConfigAsync","projectRoot","scripts","cssLinks","exp","getConfig","skipSDKVersionRequirement","langIsoCode","web","lang","title","getNameFromConfig","webName","description","themeColor","getFileFromLocalPublicFolder","publicFolder","filePath","localFilePath","path","resolve","fs","existsSync","getTemplateIndexHtmlAsync","env","EXPO_PUBLIC_FOLDER","TEMPLATES","find","value","id","file","promises","readFile","contents","replace","appendScriptsToHtml","appendLinkToHtml","map","href","as","rel","flat","addMeta","meta"],"mappings":";;;;;;;;;;;IA2DsBA,uBAAuB;eAAvBA;;IA/CAC,qCAAqC;eAArCA;;;;yBAZmC;;;;;;;gEAC1C;;;;;;;gEACE;;;;;;2BAES;sBAC4B;qBAClC;;;;;;AAMb,eAAeA,sCACpBC,WAAmB,EACnB,EACEC,OAAO,EACPC,QAAQ,EACRC,MAAMC,IAAAA,mBAAS,EAACJ,aAAa;IAAEK,2BAA2B;AAAK,GAAGF,GAAG,EAKtE;QAGcA,UAIAA,WACDA;IANd,OAAOL,wBAAwBE,aAAa;QAC1CM,aAAaH,EAAAA,WAAAA,IAAII,GAAG,qBAAPJ,SAASK,IAAI,KAAI;QAC9BP;QACAC;QACAO,OAAOC,IAAAA,2BAAiB,EAACP,KAAKQ,OAAO,IAAI;QACzCC,WAAW,GAAET,YAAAA,IAAII,GAAG,qBAAPJ,UAASS,WAAW;QACjCC,UAAU,GAAEV,YAAAA,IAAII,GAAG,qBAAPJ,UAASU,UAAU;IACjC;AACF;AAEA,SAASC,6BACPd,WAAmB,EACnB,EAAEe,YAAY,EAAEC,QAAQ,EAA8C;IAEtE,MAAMC,gBAAgBC,eAAI,CAACC,OAAO,CAACnB,aAAae,cAAcC;IAC9D,IAAI,CAACI,aAAE,CAACC,UAAU,CAACJ,gBAAgB;QACjC,OAAO;IACT;IACA,OAAOA;AACT;AAEA,8GAA8G,GAC9G,eAAeK,0BAA0BtB,WAAmB;IAC1D,IAAIgB,WAAWF,6BAA6Bd,aAAa;QACvD,yCAAyC;QACzCe,cAAcQ,QAAG,CAACC,kBAAkB;QACpCR,UAAU;IACZ;IACA,IAAI,CAACA,UAAU;QACbA,WAAWS,oBAAS,CAACC,IAAI,CAAC,CAACC,QAAUA,MAAMC,EAAE,KAAK,cAAeC,IAAI,CAAC7B;IACxE;IACA,OAAOoB,aAAE,CAACU,QAAQ,CAACC,QAAQ,CAACf,UAAU;AACxC;AAGO,eAAelB,wBACpBE,WAAmB,EACnB,EACEC,OAAO,EACPC,QAAQ,EACRU,WAAW,EACXN,WAAW,EACXG,KAAK,EACLI,UAAU,EAQX;IAED,sDAAsD;IACtD,IAAImB,WAAW,MAAMV,0BAA0BtB;IAE/CgC,WAAWA,SAASC,OAAO,CAAC,mBAAmB3B;IAC/C0B,WAAWA,SAASC,OAAO,CAAC,eAAexB;IAE3CuB,WAAWE,IAAAA,yBAAmB,EAACF,UAAU/B;IAEzC,IAAIC,UAAU;QACZ8B,WAAWG,IAAAA,sBAAgB,EACzBH,UACA9B,SACGkC,GAAG,CAAC,CAACC,OAAS;gBACb,iFAAiF;gBACjF;oBACEC,IAAI;oBACJC,KAAK;oBACLF;gBACF;gBACA;oBACEE,KAAK;oBACLF;gBACF;aACD,EACAG,IAAI;IAEX;IAEA,IAAI3B,YAAY;QACdmB,WAAWS,QAAQT,UAAU,CAAC,4BAA4B,EAAEnB,WAAW,CAAC,CAAC;IAC3E;IAEA,IAAID,aAAa;QACfoB,WAAWS,QAAQT,UAAU,CAAC,4BAA4B,EAAEpB,YAAY,CAAC,CAAC;IAC5E;IAEA,OAAOoB;AACT;AAEA,oDAAoD,GACpD,SAASS,QAAQT,QAAgB,EAAEU,IAAY;IAC7C,OAAOV,SAASC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAES,KAAK,UAAU,CAAC;AAC9D"}
1
+ {"version":3,"sources":["../../../../src/start/server/webTemplate.ts"],"sourcesContent":["import { ExpoConfig, getConfig, getNameFromConfig } from '@expo/config';\nimport fs from 'fs';\nimport path from 'path';\n\nimport { TEMPLATES } from '../../customize/templates';\nimport { appendLinkToHtml, appendScriptsToHtml } from '../../export/html';\nimport { getPublicFolderPath } from '../../export/publicFolder';\n\n/**\n * Create a static HTML for SPA styled websites.\n * This method attempts to reuse the same patterns as `@expo/webpack-config`.\n */\nexport async function createTemplateHtmlFromExpoConfigAsync(\n projectRoot: string,\n {\n scripts,\n cssLinks,\n exp = getConfig(projectRoot, { skipSDKVersionRequirement: true }).exp,\n }: {\n scripts: string[];\n cssLinks?: string[];\n exp?: ExpoConfig;\n }\n) {\n return createTemplateHtmlAsync(projectRoot, {\n langIsoCode: exp.web?.lang ?? 'en',\n scripts,\n cssLinks,\n title: getNameFromConfig(exp).webName ?? 'Expo App',\n description: exp.web?.description,\n themeColor: exp.web?.themeColor,\n });\n}\n\nfunction getFileFromLocalPublicFolder(\n projectRoot: string,\n { filePath }: { filePath: string }\n): string | null {\n const localFilePath = path.resolve(getPublicFolderPath(projectRoot), filePath);\n if (!fs.existsSync(localFilePath)) {\n return null;\n }\n return localFilePath;\n}\n\n/** Attempt to read the `index.html` from the local project before falling back on the template `index.html`. */\nasync function getTemplateIndexHtmlAsync(projectRoot: string): Promise<string> {\n let filePath = getFileFromLocalPublicFolder(projectRoot, {\n filePath: 'index.html',\n });\n if (!filePath) {\n filePath = TEMPLATES.find((value) => value.id === 'index.html')!.file(projectRoot);\n }\n return fs.promises.readFile(filePath, 'utf8');\n}\n\n/** Return an `index.html` string with template values added. */\nexport async function createTemplateHtmlAsync(\n projectRoot: string,\n {\n scripts,\n cssLinks,\n description,\n langIsoCode,\n title,\n themeColor,\n }: {\n scripts: string[];\n cssLinks?: string[];\n description?: string;\n langIsoCode: string;\n title: string;\n themeColor?: string;\n }\n): Promise<string> {\n // Resolve the best possible index.html template file.\n let contents = await getTemplateIndexHtmlAsync(projectRoot);\n\n contents = contents.replace('%LANG_ISO_CODE%', langIsoCode);\n contents = contents.replace('%WEB_TITLE%', title);\n\n contents = appendScriptsToHtml(contents, scripts);\n\n if (cssLinks) {\n contents = appendLinkToHtml(\n contents,\n cssLinks\n .map((href) => [\n // NOTE: We probably don't have to preload the CSS files for SPA-styled websites.\n {\n as: 'style',\n rel: 'preload',\n href,\n },\n {\n rel: 'stylesheet',\n href,\n },\n ])\n .flat()\n );\n }\n\n if (themeColor) {\n contents = addMeta(contents, `name=\"theme-color\" content=\"${themeColor}\"`);\n }\n\n if (description) {\n contents = addMeta(contents, `name=\"description\" content=\"${description}\"`);\n }\n\n return contents;\n}\n\n/** Add a `<meta />` tag to the `<head />` element. */\nfunction addMeta(contents: string, meta: string): string {\n return contents.replace('</head>', `<meta ${meta}>\\n</head>`);\n}\n"],"names":["createTemplateHtmlAsync","createTemplateHtmlFromExpoConfigAsync","projectRoot","scripts","cssLinks","exp","getConfig","skipSDKVersionRequirement","langIsoCode","web","lang","title","getNameFromConfig","webName","description","themeColor","getFileFromLocalPublicFolder","filePath","localFilePath","path","resolve","getPublicFolderPath","fs","existsSync","getTemplateIndexHtmlAsync","TEMPLATES","find","value","id","file","promises","readFile","contents","replace","appendScriptsToHtml","appendLinkToHtml","map","href","as","rel","flat","addMeta","meta"],"mappings":";;;;;;;;;;;IAyDsBA,uBAAuB;eAAvBA;;IA7CAC,qCAAqC;eAArCA;;;;yBAZmC;;;;;;;gEAC1C;;;;;;;gEACE;;;;;;2BAES;sBAC4B;8BAClB;;;;;;AAM7B,eAAeA,sCACpBC,WAAmB,EACnB,EACEC,OAAO,EACPC,QAAQ,EACRC,MAAMC,IAAAA,mBAAS,EAACJ,aAAa;IAAEK,2BAA2B;AAAK,GAAGF,GAAG,EAKtE;QAGcA,UAIAA,WACDA;IANd,OAAOL,wBAAwBE,aAAa;QAC1CM,aAAaH,EAAAA,WAAAA,IAAII,GAAG,qBAAPJ,SAASK,IAAI,KAAI;QAC9BP;QACAC;QACAO,OAAOC,IAAAA,2BAAiB,EAACP,KAAKQ,OAAO,IAAI;QACzCC,WAAW,GAAET,YAAAA,IAAII,GAAG,qBAAPJ,UAASS,WAAW;QACjCC,UAAU,GAAEV,YAAAA,IAAII,GAAG,qBAAPJ,UAASU,UAAU;IACjC;AACF;AAEA,SAASC,6BACPd,WAAmB,EACnB,EAAEe,QAAQ,EAAwB;IAElC,MAAMC,gBAAgBC,eAAI,CAACC,OAAO,CAACC,IAAAA,iCAAmB,EAACnB,cAAce;IACrE,IAAI,CAACK,aAAE,CAACC,UAAU,CAACL,gBAAgB;QACjC,OAAO;IACT;IACA,OAAOA;AACT;AAEA,8GAA8G,GAC9G,eAAeM,0BAA0BtB,WAAmB;IAC1D,IAAIe,WAAWD,6BAA6Bd,aAAa;QACvDe,UAAU;IACZ;IACA,IAAI,CAACA,UAAU;QACbA,WAAWQ,oBAAS,CAACC,IAAI,CAAC,CAACC,QAAUA,MAAMC,EAAE,KAAK,cAAeC,IAAI,CAAC3B;IACxE;IACA,OAAOoB,aAAE,CAACQ,QAAQ,CAACC,QAAQ,CAACd,UAAU;AACxC;AAGO,eAAejB,wBACpBE,WAAmB,EACnB,EACEC,OAAO,EACPC,QAAQ,EACRU,WAAW,EACXN,WAAW,EACXG,KAAK,EACLI,UAAU,EAQX;IAED,sDAAsD;IACtD,IAAIiB,WAAW,MAAMR,0BAA0BtB;IAE/C8B,WAAWA,SAASC,OAAO,CAAC,mBAAmBzB;IAC/CwB,WAAWA,SAASC,OAAO,CAAC,eAAetB;IAE3CqB,WAAWE,IAAAA,yBAAmB,EAACF,UAAU7B;IAEzC,IAAIC,UAAU;QACZ4B,WAAWG,IAAAA,sBAAgB,EACzBH,UACA5B,SACGgC,GAAG,CAAC,CAACC,OAAS;gBACb,iFAAiF;gBACjF;oBACEC,IAAI;oBACJC,KAAK;oBACLF;gBACF;gBACA;oBACEE,KAAK;oBACLF;gBACF;aACD,EACAG,IAAI;IAEX;IAEA,IAAIzB,YAAY;QACdiB,WAAWS,QAAQT,UAAU,CAAC,4BAA4B,EAAEjB,WAAW,CAAC,CAAC;IAC3E;IAEA,IAAID,aAAa;QACfkB,WAAWS,QAAQT,UAAU,CAAC,4BAA4B,EAAElB,YAAY,CAAC,CAAC;IAC5E;IAEA,OAAOkB;AACT;AAEA,oDAAoD,GACpD,SAASS,QAAQT,QAAgB,EAAEU,IAAY;IAC7C,OAAOV,SAASC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAES,KAAK,UAAU,CAAC;AAC9D"}
@@ -71,8 +71,8 @@ class ChecksumStream extends TransformStream {
71
71
  return this.hash.digest(encoding);
72
72
  }
73
73
  }
74
- async function extractStream(input, output, options = {}) {
75
- output = _nodepath().default.resolve(output);
74
+ async function extractStream(input, targetOutput, options = {}) {
75
+ const output = _nodepath().default.resolve(targetOutput) + _nodepath().default.sep;
76
76
  await _nodefs().default.promises.mkdir(output, {
77
77
  recursive: true
78
78
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/tar.ts"],"sourcesContent":["import { streamToAsyncIterable, TarTypeFlag, untar } from 'multitars';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\n\nconst debug = require('debug')('expo:utils:tar') as typeof console.log;\n\nclass ChecksumStream extends TransformStream {\n hash: crypto.Hash;\n constructor(algorithm: string) {\n super({\n transform: (chunk, controller) => {\n this.hash.update(chunk);\n controller.enqueue(chunk);\n },\n });\n this.hash = crypto.createHash(algorithm);\n }\n\n digest(): Buffer;\n digest(encoding: crypto.BinaryToTextEncoding): string;\n digest(encoding?: crypto.BinaryToTextEncoding): string | Buffer {\n return this.hash.digest(encoding!);\n }\n}\n\nexport interface ExtractOptions {\n strip?: number;\n filter?(name: string, type: TarTypeFlag): boolean | null | undefined;\n rename?(name: string, type: TarTypeFlag): string | null | undefined;\n checksumAlgorithm?: string;\n}\n\nexport async function extractStream(\n input: ReadableStream,\n output: string,\n options: ExtractOptions = {}\n): Promise<string> {\n output = path.resolve(output);\n await fs.promises.mkdir(output, { recursive: true });\n\n const { checksumAlgorithm, strip = 0, rename, filter } = options;\n\n const checksumStream = new ChecksumStream(checksumAlgorithm || 'md5');\n const decompressionStream = new DecompressionStream('gzip');\n\n const body = input.pipeThrough(checksumStream).pipeThrough(decompressionStream);\n\n for await (const file of untar(body)) {\n let name = path.normalize(file.name);\n if (filter && !filter(name, file.typeflag)) {\n debug(`filtered: ${path.resolve(output, name)}`);\n continue;\n } else if (rename) {\n name = rename(name, file.typeflag) ?? name;\n }\n\n for (let idx = 0; idx < strip; idx++) {\n const sepIdx = name.indexOf(path.sep);\n if (sepIdx > -1) {\n name = name.slice(sepIdx + 1);\n } else {\n break;\n }\n }\n\n const resolved = path.resolve(output, name);\n if (!resolved.startsWith(output)) {\n debug(`skip: ${resolved}`);\n continue;\n }\n\n const parent = path.dirname(resolved);\n if (parent !== output) {\n let exists = false;\n try {\n const stat = await fs.promises.lstat(parent);\n if (stat.isSymbolicLink() || (!stat.isDirectory() && !stat.isFile())) {\n debug(`skip: ${resolved}`);\n continue;\n } else if (stat.isDirectory()) {\n exists = true;\n }\n } catch {}\n\n if (!exists) {\n debug(`mkdir(p): ${parent}`);\n await fs.promises.mkdir(parent, { recursive: true });\n }\n }\n\n switch (file.typeflag) {\n case TarTypeFlag.FILE:\n debug(`write(${file.mode.toString(8)}): ${resolved}`);\n await fs.promises.writeFile(resolved, streamToAsyncIterable(file.stream()), {\n mode: file.mode,\n });\n break;\n case TarTypeFlag.DIRECTORY:\n debug(`mkdir(${file.mode.toString(8)}): ${resolved}`);\n try {\n await fs.promises.mkdir(resolved, { mode: file.mode });\n } catch (error: any) {\n if (error.code !== 'EEXIST') {\n throw error;\n }\n }\n break;\n case TarTypeFlag.SYMLINK:\n case TarTypeFlag.LINK: {\n const target = path.resolve(parent, file.linkname ?? '');\n if (!target.startsWith(output) || target === parent) {\n debug(`skip: ${resolved} -> ${target}`);\n continue;\n }\n\n if (file.typeflag === TarTypeFlag.LINK) {\n debug(`link: ${resolved} -> ${target}`);\n await fs.promises.link(target, resolved);\n } else {\n const stat = await fs.promises.lstat(target).catch(() => null);\n const type = stat?.isDirectory() ? 'dir' : 'file';\n debug(`symlink(${type}): ${resolved} -> ${target}`);\n await fs.promises.symlink(target, resolved, type);\n }\n break;\n }\n }\n }\n\n return checksumStream.digest('hex');\n}\n\n/** Extract a tar using built-in tools if available and falling back on Node.js. */\nexport async function extractAsync(\n input: string,\n output: string,\n options?: ExtractOptions\n): Promise<void> {\n await extractStream(\n Readable.toWeb(fs.createReadStream(input)) as ReadableStream,\n output,\n options\n );\n}\n"],"names":["extractAsync","extractStream","debug","require","ChecksumStream","TransformStream","constructor","algorithm","transform","chunk","controller","hash","update","enqueue","crypto","createHash","digest","encoding","input","output","options","path","resolve","fs","promises","mkdir","recursive","checksumAlgorithm","strip","rename","filter","checksumStream","decompressionStream","DecompressionStream","body","pipeThrough","file","untar","name","normalize","typeflag","idx","sepIdx","indexOf","sep","slice","resolved","startsWith","parent","dirname","exists","stat","lstat","isSymbolicLink","isDirectory","isFile","TarTypeFlag","FILE","mode","toString","writeFile","streamToAsyncIterable","stream","DIRECTORY","error","code","SYMLINK","LINK","target","linkname","link","catch","type","symlink","Readable","toWeb","createReadStream"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/utils/tar.ts"],"sourcesContent":["import { streamToAsyncIterable, TarTypeFlag, untar } from 'multitars';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\n\nconst debug = require('debug')('expo:utils:tar') as typeof console.log;\n\nclass ChecksumStream extends TransformStream {\n hash: crypto.Hash;\n constructor(algorithm: string) {\n super({\n transform: (chunk, controller) => {\n this.hash.update(chunk);\n controller.enqueue(chunk);\n },\n });\n this.hash = crypto.createHash(algorithm);\n }\n\n digest(): Buffer;\n digest(encoding: crypto.BinaryToTextEncoding): string;\n digest(encoding?: crypto.BinaryToTextEncoding): string | Buffer {\n return this.hash.digest(encoding!);\n }\n}\n\nexport interface ExtractOptions {\n strip?: number;\n filter?(name: string, type: TarTypeFlag): boolean | null | undefined;\n rename?(name: string, type: TarTypeFlag): string | null | undefined;\n checksumAlgorithm?: string;\n}\n\nexport async function extractStream(\n input: ReadableStream,\n targetOutput: string,\n options: ExtractOptions = {}\n): Promise<string> {\n const output = path.resolve(targetOutput) + path.sep;\n await fs.promises.mkdir(output, { recursive: true });\n\n const { checksumAlgorithm, strip = 0, rename, filter } = options;\n\n const checksumStream = new ChecksumStream(checksumAlgorithm || 'md5');\n const decompressionStream = new DecompressionStream('gzip');\n\n const body = input.pipeThrough(checksumStream).pipeThrough(decompressionStream);\n\n for await (const file of untar(body)) {\n let name = path.normalize(file.name);\n if (filter && !filter(name, file.typeflag)) {\n debug(`filtered: ${path.resolve(output, name)}`);\n continue;\n } else if (rename) {\n name = rename(name, file.typeflag) ?? name;\n }\n\n for (let idx = 0; idx < strip; idx++) {\n const sepIdx = name.indexOf(path.sep);\n if (sepIdx > -1) {\n name = name.slice(sepIdx + 1);\n } else {\n break;\n }\n }\n\n const resolved = path.resolve(output, name);\n if (!resolved.startsWith(output)) {\n debug(`skip: ${resolved}`);\n continue;\n }\n\n const parent = path.dirname(resolved);\n if (parent !== output) {\n let exists = false;\n try {\n const stat = await fs.promises.lstat(parent);\n if (stat.isSymbolicLink() || (!stat.isDirectory() && !stat.isFile())) {\n debug(`skip: ${resolved}`);\n continue;\n } else if (stat.isDirectory()) {\n exists = true;\n }\n } catch {}\n\n if (!exists) {\n debug(`mkdir(p): ${parent}`);\n await fs.promises.mkdir(parent, { recursive: true });\n }\n }\n\n switch (file.typeflag) {\n case TarTypeFlag.FILE:\n debug(`write(${file.mode.toString(8)}): ${resolved}`);\n await fs.promises.writeFile(resolved, streamToAsyncIterable(file.stream()), {\n mode: file.mode,\n });\n break;\n case TarTypeFlag.DIRECTORY:\n debug(`mkdir(${file.mode.toString(8)}): ${resolved}`);\n try {\n await fs.promises.mkdir(resolved, { mode: file.mode });\n } catch (error: any) {\n if (error.code !== 'EEXIST') {\n throw error;\n }\n }\n break;\n case TarTypeFlag.SYMLINK:\n case TarTypeFlag.LINK: {\n const target = path.resolve(parent, file.linkname ?? '');\n if (!target.startsWith(output) || target === parent) {\n debug(`skip: ${resolved} -> ${target}`);\n continue;\n }\n\n if (file.typeflag === TarTypeFlag.LINK) {\n debug(`link: ${resolved} -> ${target}`);\n await fs.promises.link(target, resolved);\n } else {\n const stat = await fs.promises.lstat(target).catch(() => null);\n const type = stat?.isDirectory() ? 'dir' : 'file';\n debug(`symlink(${type}): ${resolved} -> ${target}`);\n await fs.promises.symlink(target, resolved, type);\n }\n break;\n }\n }\n }\n\n return checksumStream.digest('hex');\n}\n\n/** Extract a tar using built-in tools if available and falling back on Node.js. */\nexport async function extractAsync(\n input: string,\n output: string,\n options?: ExtractOptions\n): Promise<void> {\n await extractStream(\n Readable.toWeb(fs.createReadStream(input)) as ReadableStream,\n output,\n options\n );\n}\n"],"names":["extractAsync","extractStream","debug","require","ChecksumStream","TransformStream","constructor","algorithm","transform","chunk","controller","hash","update","enqueue","crypto","createHash","digest","encoding","input","targetOutput","options","output","path","resolve","sep","fs","promises","mkdir","recursive","checksumAlgorithm","strip","rename","filter","checksumStream","decompressionStream","DecompressionStream","body","pipeThrough","file","untar","name","normalize","typeflag","idx","sepIdx","indexOf","slice","resolved","startsWith","parent","dirname","exists","stat","lstat","isSymbolicLink","isDirectory","isFile","TarTypeFlag","FILE","mode","toString","writeFile","streamToAsyncIterable","stream","DIRECTORY","error","code","SYMLINK","LINK","target","linkname","link","catch","type","symlink","Readable","toWeb","createReadStream"],"mappings":";;;;;;;;;;;IAuIsBA,YAAY;eAAZA;;IArGAC,aAAa;eAAbA;;;;yBAlCoC;;;;;;;gEACvC;;;;;;;gEACJ;;;;;;;gEACE;;;;;;;yBACQ;;;;;;;;;;;AAEzB,MAAMC,QAAQC,QAAQ,SAAS;AAE/B,MAAMC,uBAAuBC;IAE3BC,YAAYC,SAAiB,CAAE;QAC7B,KAAK,CAAC;YACJC,WAAW,CAACC,OAAOC;gBACjB,IAAI,CAACC,IAAI,CAACC,MAAM,CAACH;gBACjBC,WAAWG,OAAO,CAACJ;YACrB;QACF;QACA,IAAI,CAACE,IAAI,GAAGG,qBAAM,CAACC,UAAU,CAACR;IAChC;IAIAS,OAAOC,QAAsC,EAAmB;QAC9D,OAAO,IAAI,CAACN,IAAI,CAACK,MAAM,CAACC;IAC1B;AACF;AASO,eAAehB,cACpBiB,KAAqB,EACrBC,YAAoB,EACpBC,UAA0B,CAAC,CAAC;IAE5B,MAAMC,SAASC,mBAAI,CAACC,OAAO,CAACJ,gBAAgBG,mBAAI,CAACE,GAAG;IACpD,MAAMC,iBAAE,CAACC,QAAQ,CAACC,KAAK,CAACN,QAAQ;QAAEO,WAAW;IAAK;IAElD,MAAM,EAAEC,iBAAiB,EAAEC,QAAQ,CAAC,EAAEC,MAAM,EAAEC,MAAM,EAAE,GAAGZ;IAEzD,MAAMa,iBAAiB,IAAI7B,eAAeyB,qBAAqB;IAC/D,MAAMK,sBAAsB,IAAIC,oBAAoB;IAEpD,MAAMC,OAAOlB,MAAMmB,WAAW,CAACJ,gBAAgBI,WAAW,CAACH;IAE3D,WAAW,MAAMI,QAAQC,IAAAA,kBAAK,EAACH,MAAO;QACpC,IAAII,OAAOlB,mBAAI,CAACmB,SAAS,CAACH,KAAKE,IAAI;QACnC,IAAIR,UAAU,CAACA,OAAOQ,MAAMF,KAAKI,QAAQ,GAAG;YAC1CxC,MAAM,CAAC,UAAU,EAAEoB,mBAAI,CAACC,OAAO,CAACF,QAAQmB,OAAO;YAC/C;QACF,OAAO,IAAIT,QAAQ;YACjBS,OAAOT,OAAOS,MAAMF,KAAKI,QAAQ,KAAKF;QACxC;QAEA,IAAK,IAAIG,MAAM,GAAGA,MAAMb,OAAOa,MAAO;YACpC,MAAMC,SAASJ,KAAKK,OAAO,CAACvB,mBAAI,CAACE,GAAG;YACpC,IAAIoB,SAAS,CAAC,GAAG;gBACfJ,OAAOA,KAAKM,KAAK,CAACF,SAAS;YAC7B,OAAO;gBACL;YACF;QACF;QAEA,MAAMG,WAAWzB,mBAAI,CAACC,OAAO,CAACF,QAAQmB;QACtC,IAAI,CAACO,SAASC,UAAU,CAAC3B,SAAS;YAChCnB,MAAM,CAAC,MAAM,EAAE6C,UAAU;YACzB;QACF;QAEA,MAAME,SAAS3B,mBAAI,CAAC4B,OAAO,CAACH;QAC5B,IAAIE,WAAW5B,QAAQ;YACrB,IAAI8B,SAAS;YACb,IAAI;gBACF,MAAMC,OAAO,MAAM3B,iBAAE,CAACC,QAAQ,CAAC2B,KAAK,CAACJ;gBACrC,IAAIG,KAAKE,cAAc,MAAO,CAACF,KAAKG,WAAW,MAAM,CAACH,KAAKI,MAAM,IAAK;oBACpEtD,MAAM,CAAC,MAAM,EAAE6C,UAAU;oBACzB;gBACF,OAAO,IAAIK,KAAKG,WAAW,IAAI;oBAC7BJ,SAAS;gBACX;YACF,EAAE,OAAM,CAAC;YAET,IAAI,CAACA,QAAQ;gBACXjD,MAAM,CAAC,UAAU,EAAE+C,QAAQ;gBAC3B,MAAMxB,iBAAE,CAACC,QAAQ,CAACC,KAAK,CAACsB,QAAQ;oBAAErB,WAAW;gBAAK;YACpD;QACF;QAEA,OAAQU,KAAKI,QAAQ;YACnB,KAAKe,wBAAW,CAACC,IAAI;gBACnBxD,MAAM,CAAC,MAAM,EAAEoC,KAAKqB,IAAI,CAACC,QAAQ,CAAC,GAAG,GAAG,EAAEb,UAAU;gBACpD,MAAMtB,iBAAE,CAACC,QAAQ,CAACmC,SAAS,CAACd,UAAUe,IAAAA,kCAAqB,EAACxB,KAAKyB,MAAM,KAAK;oBAC1EJ,MAAMrB,KAAKqB,IAAI;gBACjB;gBACA;YACF,KAAKF,wBAAW,CAACO,SAAS;gBACxB9D,MAAM,CAAC,MAAM,EAAEoC,KAAKqB,IAAI,CAACC,QAAQ,CAAC,GAAG,GAAG,EAAEb,UAAU;gBACpD,IAAI;oBACF,MAAMtB,iBAAE,CAACC,QAAQ,CAACC,KAAK,CAACoB,UAAU;wBAAEY,MAAMrB,KAAKqB,IAAI;oBAAC;gBACtD,EAAE,OAAOM,OAAY;oBACnB,IAAIA,MAAMC,IAAI,KAAK,UAAU;wBAC3B,MAAMD;oBACR;gBACF;gBACA;YACF,KAAKR,wBAAW,CAACU,OAAO;YACxB,KAAKV,wBAAW,CAACW,IAAI;gBAAE;oBACrB,MAAMC,SAAS/C,mBAAI,CAACC,OAAO,CAAC0B,QAAQX,KAAKgC,QAAQ,IAAI;oBACrD,IAAI,CAACD,OAAOrB,UAAU,CAAC3B,WAAWgD,WAAWpB,QAAQ;wBACnD/C,MAAM,CAAC,MAAM,EAAE6C,SAAS,IAAI,EAAEsB,QAAQ;wBACtC;oBACF;oBAEA,IAAI/B,KAAKI,QAAQ,KAAKe,wBAAW,CAACW,IAAI,EAAE;wBACtClE,MAAM,CAAC,MAAM,EAAE6C,SAAS,IAAI,EAAEsB,QAAQ;wBACtC,MAAM5C,iBAAE,CAACC,QAAQ,CAAC6C,IAAI,CAACF,QAAQtB;oBACjC,OAAO;wBACL,MAAMK,OAAO,MAAM3B,iBAAE,CAACC,QAAQ,CAAC2B,KAAK,CAACgB,QAAQG,KAAK,CAAC,IAAM;wBACzD,MAAMC,OAAOrB,CAAAA,wBAAAA,KAAMG,WAAW,MAAK,QAAQ;wBAC3CrD,MAAM,CAAC,QAAQ,EAAEuE,KAAK,GAAG,EAAE1B,SAAS,IAAI,EAAEsB,QAAQ;wBAClD,MAAM5C,iBAAE,CAACC,QAAQ,CAACgD,OAAO,CAACL,QAAQtB,UAAU0B;oBAC9C;oBACA;gBACF;QACF;IACF;IAEA,OAAOxC,eAAejB,MAAM,CAAC;AAC/B;AAGO,eAAehB,aACpBkB,KAAa,EACbG,MAAc,EACdD,OAAwB;IAExB,MAAMnB,cACJ0E,sBAAQ,CAACC,KAAK,CAACnD,iBAAE,CAACoD,gBAAgB,CAAC3D,SACnCG,QACAD;AAEJ"}
@@ -26,7 +26,7 @@ class FetchClient {
26
26
  this.headers = {
27
27
  accept: 'application/json',
28
28
  'content-type': 'application/json',
29
- 'user-agent': `expo-cli/${"55.0.29"}`,
29
+ 'user-agent': `expo-cli/${"55.0.31"}`,
30
30
  authorization: 'Basic ' + _nodebuffer().Buffer.from(`${target}:`).toString('base64')
31
31
  };
32
32
  }
@@ -83,7 +83,7 @@ function createContext() {
83
83
  cpu: summarizeCpuInfo(),
84
84
  app: {
85
85
  name: 'expo/cli',
86
- version: "55.0.29"
86
+ version: "55.0.31"
87
87
  },
88
88
  ci: _ciinfo().isCI ? {
89
89
  name: _ciinfo().name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/cli",
3
- "version": "55.0.29",
3
+ "version": "55.0.31",
4
4
  "description": "The Expo CLI",
5
5
  "main": "build/bin/cli",
6
6
  "bin": {
@@ -41,21 +41,21 @@
41
41
  "homepage": "https://github.com/expo/expo/tree/main/packages/@expo/cli",
42
42
  "dependencies": {
43
43
  "@expo/code-signing-certificates": "^0.0.6",
44
- "@expo/config": "~55.0.16",
45
- "@expo/config-plugins": "~55.0.8",
44
+ "@expo/config": "~55.0.17",
45
+ "@expo/config-plugins": "~55.0.9",
46
46
  "@expo/devcert": "^1.2.1",
47
47
  "@expo/env": "~2.1.2",
48
48
  "@expo/image-utils": "^0.8.14",
49
49
  "@expo/json-file": "^10.0.14",
50
50
  "@expo/log-box": "55.0.12",
51
51
  "@expo/metro": "~55.1.1",
52
- "@expo/metro-config": "~55.0.20",
52
+ "@expo/metro-config": "~55.0.22",
53
53
  "@expo/osascript": "^2.4.3",
54
54
  "@expo/package-manager": "^1.10.5",
55
55
  "@expo/plist": "^0.5.3",
56
- "@expo/prebuild-config": "^55.0.17",
56
+ "@expo/prebuild-config": "^55.0.18",
57
57
  "@expo/require-utils": "^55.0.5",
58
- "@expo/router-server": "^55.0.16",
58
+ "@expo/router-server": "^55.0.17",
59
59
  "@expo/schema-utils": "^55.0.4",
60
60
  "@expo/spawn-async": "^1.7.2",
61
61
  "@expo/ws-tunnel": "^1.0.1",
@@ -72,7 +72,7 @@
72
72
  "connect": "^3.7.0",
73
73
  "debug": "^4.3.4",
74
74
  "dnssd-advertise": "^1.1.4",
75
- "expo-server": "^55.0.9",
75
+ "expo-server": "^55.0.10",
76
76
  "fetch-nodeshim": "^0.4.10",
77
77
  "getenv": "^2.0.0",
78
78
  "glob": "^13.0.0",
@@ -158,5 +158,5 @@
158
158
  "tree-kill": "^1.2.2",
159
159
  "tsd": "^0.28.1"
160
160
  },
161
- "gitHead": "7c081282cf88968f81732feb67a71840e769a40f"
161
+ "gitHead": "fcb091766242d53248cd3c5949965961dbc5ec1d"
162
162
  }