@expo/cli 0.23.0 → 0.23.1

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 (76) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/customize/templates.js +15 -1
  3. package/build/src/customize/templates.js.map +1 -1
  4. package/build/src/lint/ESlintPrerequisite.js +30 -46
  5. package/build/src/lint/ESlintPrerequisite.js.map +1 -1
  6. package/build/src/start/doctor/apple/XcodePrerequisite.js +1 -1
  7. package/build/src/start/doctor/apple/XcodePrerequisite.js.map +1 -1
  8. package/build/src/start/server/metro/MetroTerminalReporter.js +28 -1
  9. package/build/src/start/server/metro/MetroTerminalReporter.js.map +1 -1
  10. package/build/src/start/server/metro/debugging/createDebugMiddleware.js +19 -19
  11. package/build/src/start/server/metro/debugging/createDebugMiddleware.js.map +1 -1
  12. package/build/src/start/server/metro/instantiateMetro.js +2 -2
  13. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  14. package/build/src/start/server/metro/log-box/LogBoxSymbolication.js +21 -2
  15. package/build/src/start/server/metro/log-box/LogBoxSymbolication.js.map +1 -1
  16. package/build/src/start/server/metro/metroErrorInterface.js +19 -8
  17. package/build/src/start/server/metro/metroErrorInterface.js.map +1 -1
  18. package/build/src/start/server/metro/withMetroMultiPlatform.js +0 -9
  19. package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
  20. package/build/src/start/server/middleware/inspector/JsInspector.js +2 -25
  21. package/build/src/start/server/middleware/inspector/JsInspector.js.map +1 -1
  22. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  23. package/build/src/utils/telemetry/utils/context.js +1 -1
  24. package/package.json +8 -8
  25. package/static/canary/react-is/cjs/react-is.development.js +118 -185
  26. package/static/canary/react-is/cjs/react-is.production.js +2 -2
  27. package/static/canary/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js +16582 -26565
  28. package/static/canary/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js +3495 -3357
  29. package/static/canary/react-native/Libraries/Renderer/implementations/ReactFabric-profiling.js +3929 -3801
  30. package/static/canary/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +16869 -27032
  31. package/static/canary/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +3535 -3428
  32. package/static/canary/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +4198 -4095
  33. package/static/canary/scheduler/cjs/scheduler-unstable_mock.development.js +387 -684
  34. package/static/canary/scheduler/cjs/scheduler-unstable_mock.production.js +0 -9
  35. package/static/canary/scheduler/cjs/scheduler-unstable_post_task.development.js +137 -195
  36. package/static/canary/scheduler/cjs/scheduler-unstable_post_task.production.js +0 -5
  37. package/static/canary/scheduler/cjs/scheduler.development.js +339 -600
  38. package/static/canary/scheduler/cjs/scheduler.native.development.js +324 -512
  39. package/static/canary/scheduler/cjs/scheduler.native.production.js +6 -5
  40. package/static/canary/scheduler/cjs/scheduler.production.js +16 -17
  41. package/static/canary-full/react/cjs/react-compiler-runtime.development.js +13 -68
  42. package/static/canary-full/react/cjs/react-jsx-dev-runtime.development.js +317 -1251
  43. package/static/canary-full/react/cjs/react-jsx-dev-runtime.react-server.development.js +353 -1286
  44. package/static/canary-full/react/cjs/react-jsx-runtime.development.js +326 -1279
  45. package/static/canary-full/react/cjs/react-jsx-runtime.react-server.development.js +353 -1286
  46. package/static/canary-full/react/cjs/react.development.js +1204 -2771
  47. package/static/canary-full/react/cjs/react.production.js +25 -20
  48. package/static/canary-full/react/cjs/react.react-server.development.js +783 -2162
  49. package/static/canary-full/react/cjs/react.react-server.production.js +13 -63
  50. package/static/canary-full/react/package.json +1 -1
  51. package/static/canary-full/react-dom/cjs/react-dom-client.development.js +24847 -37099
  52. package/static/canary-full/react-dom/cjs/react-dom-client.production.js +8261 -7475
  53. package/static/canary-full/react-dom/cjs/react-dom-profiling.development.js +25252 -37571
  54. package/static/canary-full/react-dom/cjs/react-dom-profiling.profiling.js +9442 -8662
  55. package/static/canary-full/react-dom/cjs/react-dom-server-legacy.browser.development.js +8944 -11568
  56. package/static/canary-full/react-dom/cjs/react-dom-server-legacy.browser.production.js +1378 -944
  57. package/static/canary-full/react-dom/cjs/react-dom-server-legacy.node.development.js +8944 -11568
  58. package/static/canary-full/react-dom/cjs/react-dom-server-legacy.node.production.js +1386 -954
  59. package/static/canary-full/react-dom/cjs/react-dom-server.browser.development.js +9344 -11600
  60. package/static/canary-full/react-dom/cjs/react-dom-server.browser.production.js +1545 -954
  61. package/static/canary-full/react-dom/cjs/react-dom-server.bun.development.js +8286 -11064
  62. package/static/canary-full/react-dom/cjs/react-dom-server.bun.production.js +1437 -976
  63. package/static/canary-full/react-dom/cjs/react-dom-server.edge.development.js +9356 -11609
  64. package/static/canary-full/react-dom/cjs/react-dom-server.edge.production.js +1542 -970
  65. package/static/canary-full/react-dom/cjs/react-dom-server.node.development.js +9227 -11571
  66. package/static/canary-full/react-dom/cjs/react-dom-server.node.production.js +1787 -1183
  67. package/static/canary-full/react-dom/cjs/react-dom-test-utils.development.js +13 -59
  68. package/static/canary-full/react-dom/cjs/react-dom.development.js +402 -604
  69. package/static/canary-full/react-dom/cjs/react-dom.production.js +4 -3
  70. package/static/canary-full/react-dom/cjs/react-dom.react-server.development.js +322 -382
  71. package/static/canary-full/react-dom/cjs/react-dom.react-server.production.js +6 -7
  72. package/static/canary-full/react-dom/package.json +5 -5
  73. package/static/canary-full/react-dom/static.browser.js +1 -0
  74. package/static/canary-full/react-dom/static.edge.js +1 -0
  75. package/static/canary-full/react-dom/static.node.js +1 -0
  76. package/static/template/eslint.config.js +10 -0
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("0.23.0");
126
+ console.log("0.23.1");
127
127
  process.exit(0);
128
128
  }
129
129
  if (args['--non-interactive']) {
@@ -106,7 +106,7 @@ const TEMPLATES = [
106
106
  {
107
107
  id: '.eslintrc.js',
108
108
  dependencies: [],
109
- destination: ()=>'.eslintrc.js',
109
+ destination: ()=>'.eslintrc.js (deprecated)',
110
110
  file: (projectRoot)=>importFromVendor(projectRoot, '.eslintrc.js'),
111
111
  configureAsync: async (projectRoot)=>{
112
112
  const { ESLintProjectPrerequisite } = require('../lint/ESlintPrerequisite');
@@ -117,6 +117,20 @@ const TEMPLATES = [
117
117
  return false;
118
118
  }
119
119
  },
120
+ {
121
+ id: 'eslint.config.js',
122
+ dependencies: [],
123
+ destination: ()=>'eslint.config.js',
124
+ file: (projectRoot)=>importFromVendor(projectRoot, 'eslint.config.js'),
125
+ configureAsync: async (projectRoot)=>{
126
+ const { ESLintProjectPrerequisite } = require('../lint/ESlintPrerequisite');
127
+ const prerequisite = new ESLintProjectPrerequisite(projectRoot);
128
+ if (!await prerequisite.assertAsync()) {
129
+ await prerequisite.bootstrapAsync();
130
+ }
131
+ return false;
132
+ }
133
+ },
120
134
  {
121
135
  id: 'index.html',
122
136
  file: (projectRoot)=>importFromExpoWebpackConfig(projectRoot, 'web-default', 'index.html'),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/customize/templates.ts"],"sourcesContent":["import chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport prompt, { ExpoChoice } from '../utils/prompts';\n\nconst debug = require('debug')('expo:customize:templates');\n\nexport type DestinationResolutionProps = {\n /** Web 'public' folder path (defaults to `/web`). This technically can be changed but shouldn't be. */\n webStaticPath: string;\n /** The Expo Router app directory. */\n appDirPath: string;\n};\n\nfunction importFromExpoWebpackConfig(projectRoot: string, folder: string, moduleId: string) {\n try {\n const filePath = resolveFrom(projectRoot, `@expo/webpack-config/${folder}/${moduleId}`);\n debug(`Using @expo/webpack-config template for \"${moduleId}\": ${filePath}`);\n return filePath;\n } catch {\n debug(`@expo/webpack-config template for \"${moduleId}\" not found, falling back on @expo/cli`);\n }\n return importFromVendor(projectRoot, moduleId);\n}\n\nfunction importFromVendor(projectRoot: string, moduleId: string) {\n try {\n const filePath = resolveFrom(projectRoot, '@expo/cli/static/template/' + moduleId);\n debug(`Using @expo/cli template for \"${moduleId}\": ${filePath}`);\n return filePath;\n } catch {\n // For dev mode, testing and other cases where @expo/cli is not installed\n const filePath = require.resolve(`@expo/cli/static/template/${moduleId}`);\n debug(\n `Local @expo/cli template for \"${moduleId}\" not found, falling back on template relative to @expo/cli: ${filePath}`\n );\n\n return filePath;\n }\n}\n\nexport const TEMPLATES: {\n /** Unique ID for easily indexing. */\n id: string;\n /** Template file path to copy into the project. */\n file: (projectRoot: string) => string;\n /** Output location for the file in the user project. */\n destination: (props: DestinationResolutionProps) => string;\n /** List of dependencies to install in the project. These are used inside of the template file. */\n dependencies: string[];\n\n /** Custom step for configuring the file. Return true to exit early. */\n configureAsync?: (projectRoot: string) => Promise<boolean>;\n}[] = [\n {\n id: 'babel.config.js',\n file: (projectRoot) => importFromVendor(projectRoot, 'babel.config.js'),\n destination: () => 'babel.config.js',\n dependencies: [\n // Even though this is installed in `expo`, we should add it for now.\n 'babel-preset-expo',\n ],\n },\n {\n id: 'metro.config.js',\n dependencies: ['@expo/metro-config'],\n destination: () => 'metro.config.js',\n file: (projectRoot) => importFromVendor(projectRoot, 'metro.config.js'),\n },\n {\n // `tsconfig.json` is special-cased and doesn't follow the template.\n id: 'tsconfig.json',\n dependencies: [],\n destination: () => 'tsconfig.json',\n file: () => '',\n configureAsync: async (projectRoot) => {\n const { typescript } = require('./typescript') as typeof import('./typescript');\n await typescript(projectRoot);\n return true;\n },\n },\n {\n id: '.eslintrc.js',\n dependencies: [],\n destination: () => '.eslintrc.js',\n file: (projectRoot) => importFromVendor(projectRoot, '.eslintrc.js'),\n configureAsync: async (projectRoot) => {\n const { ESLintProjectPrerequisite } =\n require('../lint/ESlintPrerequisite') as typeof import('../lint/ESlintPrerequisite.js');\n const prerequisite = new ESLintProjectPrerequisite(projectRoot);\n if (!(await prerequisite.assertAsync())) {\n await prerequisite.bootstrapAsync();\n }\n return false;\n },\n },\n {\n id: 'index.html',\n file: (projectRoot) => importFromExpoWebpackConfig(projectRoot, 'web-default', 'index.html'),\n // web/index.html\n destination: ({ webStaticPath }) => webStaticPath + '/index.html',\n dependencies: [],\n },\n {\n id: 'webpack.config.js',\n file: (projectRoot) =>\n importFromExpoWebpackConfig(projectRoot, 'template', 'webpack.config.js'),\n destination: () => 'webpack.config.js',\n dependencies: ['@expo/webpack-config'],\n },\n {\n id: '+html.tsx',\n file: (projectRoot) => importFromVendor(projectRoot, '+html.tsx'),\n destination: ({ appDirPath }) => path.join(appDirPath, '+html.tsx'),\n dependencies: [],\n },\n {\n id: '+native-intent.ts',\n file: (projectRoot) => importFromVendor(projectRoot, '+native-intent.ts'),\n destination: ({ appDirPath }) => path.join(appDirPath, '+native-intent.ts'),\n dependencies: [],\n },\n];\n\n/** Generate the prompt choices. */\nfunction createChoices(\n projectRoot: string,\n props: DestinationResolutionProps\n): ExpoChoice<number>[] {\n return TEMPLATES.map((template, index) => {\n const destination = template.destination(props);\n const localProjectFile = path.resolve(projectRoot, destination);\n const exists = fs.existsSync(localProjectFile);\n\n return {\n title: destination,\n value: index,\n description: exists ? chalk.red('This will overwrite the existing file') : undefined,\n };\n });\n}\n\n/** Prompt to select templates to add. */\nexport async function selectTemplatesAsync(projectRoot: string, props: DestinationResolutionProps) {\n const options = createChoices(projectRoot, props);\n\n const { answer } = await prompt({\n type: 'multiselect',\n name: 'answer',\n message: 'Which files would you like to generate?',\n hint: '- Space to select. Return to submit',\n warn: 'File already exists.',\n limit: options.length,\n instructions: '',\n choices: options,\n });\n return answer;\n}\n"],"names":["TEMPLATES","selectTemplatesAsync","debug","require","importFromExpoWebpackConfig","projectRoot","folder","moduleId","filePath","resolveFrom","importFromVendor","resolve","id","file","destination","dependencies","configureAsync","typescript","ESLintProjectPrerequisite","prerequisite","assertAsync","bootstrapAsync","webStaticPath","appDirPath","path","join","createChoices","props","map","template","index","localProjectFile","exists","fs","existsSync","title","value","description","chalk","red","undefined","options","answer","prompt","type","name","message","hint","warn","limit","length","instructions","choices"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/customize/templates.ts"],"sourcesContent":["import chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport prompt, { ExpoChoice } from '../utils/prompts';\n\nconst debug = require('debug')('expo:customize:templates');\n\nexport type DestinationResolutionProps = {\n /** Web 'public' folder path (defaults to `/web`). This technically can be changed but shouldn't be. */\n webStaticPath: string;\n /** The Expo Router app directory. */\n appDirPath: string;\n};\n\nfunction importFromExpoWebpackConfig(projectRoot: string, folder: string, moduleId: string) {\n try {\n const filePath = resolveFrom(projectRoot, `@expo/webpack-config/${folder}/${moduleId}`);\n debug(`Using @expo/webpack-config template for \"${moduleId}\": ${filePath}`);\n return filePath;\n } catch {\n debug(`@expo/webpack-config template for \"${moduleId}\" not found, falling back on @expo/cli`);\n }\n return importFromVendor(projectRoot, moduleId);\n}\n\nfunction importFromVendor(projectRoot: string, moduleId: string) {\n try {\n const filePath = resolveFrom(projectRoot, '@expo/cli/static/template/' + moduleId);\n debug(`Using @expo/cli template for \"${moduleId}\": ${filePath}`);\n return filePath;\n } catch {\n // For dev mode, testing and other cases where @expo/cli is not installed\n const filePath = require.resolve(`@expo/cli/static/template/${moduleId}`);\n debug(\n `Local @expo/cli template for \"${moduleId}\" not found, falling back on template relative to @expo/cli: ${filePath}`\n );\n\n return filePath;\n }\n}\n\nexport const TEMPLATES: {\n /** Unique ID for easily indexing. */\n id: string;\n /** Template file path to copy into the project. */\n file: (projectRoot: string) => string;\n /** Output location for the file in the user project. */\n destination: (props: DestinationResolutionProps) => string;\n /** List of dependencies to install in the project. These are used inside of the template file. */\n dependencies: string[];\n\n /** Custom step for configuring the file. Return true to exit early. */\n configureAsync?: (projectRoot: string) => Promise<boolean>;\n}[] = [\n {\n id: 'babel.config.js',\n file: (projectRoot) => importFromVendor(projectRoot, 'babel.config.js'),\n destination: () => 'babel.config.js',\n dependencies: [\n // Even though this is installed in `expo`, we should add it for now.\n 'babel-preset-expo',\n ],\n },\n {\n id: 'metro.config.js',\n dependencies: ['@expo/metro-config'],\n destination: () => 'metro.config.js',\n file: (projectRoot) => importFromVendor(projectRoot, 'metro.config.js'),\n },\n {\n // `tsconfig.json` is special-cased and doesn't follow the template.\n id: 'tsconfig.json',\n dependencies: [],\n destination: () => 'tsconfig.json',\n file: () => '',\n configureAsync: async (projectRoot) => {\n const { typescript } = require('./typescript') as typeof import('./typescript');\n await typescript(projectRoot);\n return true;\n },\n },\n {\n id: '.eslintrc.js',\n dependencies: [],\n destination: () => '.eslintrc.js (deprecated)',\n file: (projectRoot) => importFromVendor(projectRoot, '.eslintrc.js'),\n configureAsync: async (projectRoot) => {\n const { ESLintProjectPrerequisite } =\n require('../lint/ESlintPrerequisite') as typeof import('../lint/ESlintPrerequisite.js');\n const prerequisite = new ESLintProjectPrerequisite(projectRoot);\n if (!(await prerequisite.assertAsync())) {\n await prerequisite.bootstrapAsync();\n }\n return false;\n },\n },\n {\n id: 'eslint.config.js',\n dependencies: [],\n destination: () => 'eslint.config.js',\n file: (projectRoot) => importFromVendor(projectRoot, 'eslint.config.js'),\n configureAsync: async (projectRoot) => {\n const { ESLintProjectPrerequisite } =\n require('../lint/ESlintPrerequisite') as typeof import('../lint/ESlintPrerequisite.js');\n const prerequisite = new ESLintProjectPrerequisite(projectRoot);\n if (!(await prerequisite.assertAsync())) {\n await prerequisite.bootstrapAsync();\n }\n return false;\n },\n },\n {\n id: 'index.html',\n file: (projectRoot) => importFromExpoWebpackConfig(projectRoot, 'web-default', 'index.html'),\n // web/index.html\n destination: ({ webStaticPath }) => webStaticPath + '/index.html',\n dependencies: [],\n },\n {\n id: 'webpack.config.js',\n file: (projectRoot) =>\n importFromExpoWebpackConfig(projectRoot, 'template', 'webpack.config.js'),\n destination: () => 'webpack.config.js',\n dependencies: ['@expo/webpack-config'],\n },\n {\n id: '+html.tsx',\n file: (projectRoot) => importFromVendor(projectRoot, '+html.tsx'),\n destination: ({ appDirPath }) => path.join(appDirPath, '+html.tsx'),\n dependencies: [],\n },\n {\n id: '+native-intent.ts',\n file: (projectRoot) => importFromVendor(projectRoot, '+native-intent.ts'),\n destination: ({ appDirPath }) => path.join(appDirPath, '+native-intent.ts'),\n dependencies: [],\n },\n];\n\n/** Generate the prompt choices. */\nfunction createChoices(\n projectRoot: string,\n props: DestinationResolutionProps\n): ExpoChoice<number>[] {\n return TEMPLATES.map((template, index) => {\n const destination = template.destination(props);\n const localProjectFile = path.resolve(projectRoot, destination);\n const exists = fs.existsSync(localProjectFile);\n\n return {\n title: destination,\n value: index,\n description: exists ? chalk.red('This will overwrite the existing file') : undefined,\n };\n });\n}\n\n/** Prompt to select templates to add. */\nexport async function selectTemplatesAsync(projectRoot: string, props: DestinationResolutionProps) {\n const options = createChoices(projectRoot, props);\n\n const { answer } = await prompt({\n type: 'multiselect',\n name: 'answer',\n message: 'Which files would you like to generate?',\n hint: '- Space to select. Return to submit',\n warn: 'File already exists.',\n limit: options.length,\n instructions: '',\n choices: options,\n });\n return answer;\n}\n"],"names":["TEMPLATES","selectTemplatesAsync","debug","require","importFromExpoWebpackConfig","projectRoot","folder","moduleId","filePath","resolveFrom","importFromVendor","resolve","id","file","destination","dependencies","configureAsync","typescript","ESLintProjectPrerequisite","prerequisite","assertAsync","bootstrapAsync","webStaticPath","appDirPath","path","join","createChoices","props","map","template","index","localProjectFile","exists","fs","existsSync","title","value","description","chalk","red","undefined","options","answer","prompt","type","name","message","hint","warn","limit","length","instructions","choices"],"mappings":"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"}
@@ -43,13 +43,17 @@ function _interop_require_default(obj) {
43
43
  const debug = require('debug')('expo:lint');
44
44
  class ESLintProjectPrerequisite extends _Prerequisite.ProjectPrerequisite {
45
45
  async assertImplementation() {
46
- const hasEslintConfig = await eslintIsConfigured(this.projectRoot);
46
+ const hasEslintConfig = await isEslintConfigured(this.projectRoot);
47
+ const hasLegacyConfig = await isLegacyEslintConfigured(this.projectRoot);
47
48
  const hasLintScript = await lintScriptIsConfigured(this.projectRoot);
48
- return hasEslintConfig && hasLintScript;
49
+ if (hasLegacyConfig) {
50
+ _log.Log.warn(`Using legacy ESLint config. Consider upgrading to flat config.`);
51
+ }
52
+ return (hasEslintConfig || hasLegacyConfig) && hasLintScript;
49
53
  }
50
54
  async bootstrapAsync() {
51
55
  debug('Setting up ESLint');
52
- const hasEslintConfig = await eslintIsConfigured(this.projectRoot);
56
+ const hasEslintConfig = await isEslintConfigured(this.projectRoot);
53
57
  if (!hasEslintConfig) {
54
58
  if (!(0, _interactive.isInteractive)()) {
55
59
  _log.Log.warn(`No ESLint config found. Configuring automatically.`);
@@ -61,32 +65,11 @@ class ESLintProjectPrerequisite extends _Prerequisite.ProjectPrerequisite {
61
65
  throw new _Prerequisite.PrerequisiteCommandError('ESLint is not configured for this project.');
62
66
  }
63
67
  }
64
- // TODO(cedric): if we want to add prettier, also configure proper prettier rules
65
- // const shouldIncludePrettier = await confirmAsync({
66
- // message: 'Include Prettier?',
67
- // });
68
- // if (shouldIncludePrettier) {
69
- // packages.push({ file: 'prettier/package.json', pkg: 'prettier', dev: true });
70
- // packages.push({
71
- // file: 'eslint-config-prettier/package.json',
72
- // pkg: 'eslint-config-prettier',
73
- // dev: true,
74
- // });
75
- // packages.push({
76
- // file: 'eslint-plugin-prettier/package.json',
77
- // pkg: 'eslint-plugin-prettier',
78
- // dev: true,
79
- // });
80
- // }
81
68
  await this._ensureDependenciesInstalledAsync({
82
69
  skipPrompt: true,
83
70
  isProjectMutable: true
84
71
  });
85
- // TODO(cedric): if we want to add prettier, also configure proper prettier rules
86
- // if (shouldIncludePrettier) {
87
- // await fs.writeFile(path.join(this.projectRoot, '.prettierrc'), '{}', 'utf8');
88
- // }
89
- await _promises().default.writeFile(_path().default.join(this.projectRoot, '.eslintrc.js'), await _promises().default.readFile(require.resolve(`@expo/cli/static/template/.eslintrc.js`), 'utf8'), 'utf8');
72
+ await _promises().default.writeFile(_path().default.join(this.projectRoot, 'eslint.config.js'), await _promises().default.readFile(require.resolve(`@expo/cli/static/template/eslint.config.js`), 'utf8'), 'utf8');
90
73
  }
91
74
  const hasLintScript = await lintScriptIsConfigured(this.projectRoot);
92
75
  if (!hasLintScript) {
@@ -101,7 +84,7 @@ class ESLintProjectPrerequisite extends _Prerequisite.ProjectPrerequisite {
101
84
  });
102
85
  }
103
86
  _log.Log.log();
104
- _log.Log.log('ESlint has been configured 🎉');
87
+ _log.Log.log('ESLint has been configured 🎉');
105
88
  _log.Log.log();
106
89
  return true;
107
90
  }
@@ -114,7 +97,7 @@ class ESLintProjectPrerequisite extends _Prerequisite.ProjectPrerequisite {
114
97
  warningMessage: 'ESLint not installed, unable to set up linting for your project.',
115
98
  requiredPackages: [
116
99
  {
117
- version: '^8.57.0',
100
+ version: '^9.0.0',
118
101
  pkg: 'eslint',
119
102
  file: 'eslint/package.json',
120
103
  dev: true
@@ -132,17 +115,14 @@ class ESLintProjectPrerequisite extends _Prerequisite.ProjectPrerequisite {
132
115
  }
133
116
  }
134
117
  }
135
- async function eslintIsConfigured(projectRoot) {
136
- debug('Ensuring ESlint is configured in', projectRoot);
137
- // TODO(cedric): drop `package.json` check once we swap to flat config
118
+ async function isLegacyEslintConfigured(projectRoot) {
119
+ debug('Checking for legacy ESLint configuration', projectRoot);
138
120
  const packageFile = await _jsonfile().default.readAsync(_path().default.join(projectRoot, 'package.json'));
139
121
  if (typeof packageFile.eslintConfig === 'object' && Object.keys(packageFile.eslintConfig).length > 0) {
140
- debug('Found ESlint config in package.json');
122
+ debug('Found legacy ESLint config in package.json');
141
123
  return true;
142
124
  }
143
125
  const eslintConfigFiles = [
144
- // TODO(cedric): drop these files once we swap to flat config
145
- // See: https://eslint.org/docs/latest/use/configure/configuration-files-deprecated
146
126
  '.eslintrc.js',
147
127
  '.eslintrc.cjs',
148
128
  '.eslintrc.yaml',
@@ -151,24 +131,28 @@ async function eslintIsConfigured(projectRoot) {
151
131
  ];
152
132
  for (const configFile of eslintConfigFiles){
153
133
  const configPath = (0, _findUp.findFileInParents)(projectRoot, configFile);
154
- const configIsEmpty = configPath ? await eslintConfigIsEmpty(configPath) : null;
155
- if (configPath && !configIsEmpty) {
156
- debug('Found ESlint config file:', configPath);
134
+ if (configPath) {
135
+ debug('Found ESLint config file:', configPath);
157
136
  return true;
158
- } else if (configPath && configIsEmpty) {
159
- debug('Skipping empty ESlint config file:', configPath);
160
137
  }
161
138
  }
162
139
  return false;
163
140
  }
164
- /** Determine if the eslint config file is empty. */ async function eslintConfigIsEmpty(filePath) {
165
- const content = await _promises().default.readFile(filePath, 'utf8').then((text)=>text.trim().replaceAll(/\s|\r\n|\n|\r/g, ''), ()=>null);
166
- return !content || content === '{}' || // .eslintrc.json
167
- content === '---' || // .eslintrc.yaml / .eslintrc.yml
168
- content.startsWith('module.exports={}') || // .eslintrc.js / .eslintrc.cjs / eslint.config.js / eslint.config.cjs
169
- content.startsWith('exportdefault{}') || // .eslint.config.mjs
170
- content.startsWith('exportdefault[]') // .eslint.config.mjs
171
- ;
141
+ /** Check for flat config. */ async function isEslintConfigured(projectRoot) {
142
+ debug('Ensuring ESLint is configured in', projectRoot);
143
+ const eslintConfigFiles = [
144
+ 'eslint.config.js',
145
+ 'eslint.config.mjs',
146
+ 'eslint.config.cjs'
147
+ ];
148
+ for (const configFile of eslintConfigFiles){
149
+ const configPath = (0, _findUp.findFileInParents)(projectRoot, configFile);
150
+ if (configPath) {
151
+ debug('Found ESLint config file:', configPath);
152
+ return true;
153
+ }
154
+ }
155
+ return false;
172
156
  }
173
157
  async function lintScriptIsConfigured(projectRoot) {
174
158
  var _packageFile_scripts;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lint/ESlintPrerequisite.ts"],"sourcesContent":["import JsonFile, { JSONObject } from '@expo/json-file';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nimport { Log } from '../log';\nimport { PrerequisiteCommandError, ProjectPrerequisite } from '../start/doctor/Prerequisite';\nimport { ensureDependenciesAsync } from '../start/doctor/dependencies/ensureDependenciesAsync';\nimport { findFileInParents } from '../utils/findUp';\nimport { isInteractive } from '../utils/interactive';\nimport { confirmAsync } from '../utils/prompts';\n\nconst debug = require('debug')('expo:lint') as typeof console.log;\n\n// TODO(cedric): if we want to add prettier, also configure proper prettier rules\n// const ESLINT_TEMPLATE_PRETTIER = `// https://docs.expo.dev/guides/using-eslint/\n// module.exports = {\n// extends: ['expo', 'prettier'],\n// plugins: ['prettier'],\n// rules: {\n// 'prettier/prettier': ['warn'],\n// },\n// };\n// `;\n\n/** Ensure the project has the required ESlint config. */\nexport class ESLintProjectPrerequisite extends ProjectPrerequisite<boolean> {\n async assertImplementation(): Promise<boolean> {\n const hasEslintConfig = await eslintIsConfigured(this.projectRoot);\n const hasLintScript = await lintScriptIsConfigured(this.projectRoot);\n\n return hasEslintConfig && hasLintScript;\n }\n\n async bootstrapAsync(): Promise<boolean> {\n debug('Setting up ESLint');\n\n const hasEslintConfig = await eslintIsConfigured(this.projectRoot);\n if (!hasEslintConfig) {\n if (!isInteractive()) {\n Log.warn(`No ESLint config found. Configuring automatically.`);\n } else {\n const shouldSetupLint = await confirmAsync({\n message: 'No ESLint config found. Install and configure ESLint in this project?',\n });\n if (!shouldSetupLint) {\n throw new PrerequisiteCommandError('ESLint is not configured for this project.');\n }\n }\n\n // TODO(cedric): if we want to add prettier, also configure proper prettier rules\n // const shouldIncludePrettier = await confirmAsync({\n // message: 'Include Prettier?',\n // });\n\n // if (shouldIncludePrettier) {\n // packages.push({ file: 'prettier/package.json', pkg: 'prettier', dev: true });\n // packages.push({\n // file: 'eslint-config-prettier/package.json',\n // pkg: 'eslint-config-prettier',\n // dev: true,\n // });\n // packages.push({\n // file: 'eslint-plugin-prettier/package.json',\n // pkg: 'eslint-plugin-prettier',\n // dev: true,\n // });\n // }\n\n await this._ensureDependenciesInstalledAsync({ skipPrompt: true, isProjectMutable: true });\n\n // TODO(cedric): if we want to add prettier, also configure proper prettier rules\n // if (shouldIncludePrettier) {\n // await fs.writeFile(path.join(this.projectRoot, '.prettierrc'), '{}', 'utf8');\n // }\n\n await fs.writeFile(\n path.join(this.projectRoot, '.eslintrc.js'),\n await fs.readFile(require.resolve(`@expo/cli/static/template/.eslintrc.js`), 'utf8'),\n 'utf8'\n );\n }\n\n const hasLintScript = await lintScriptIsConfigured(this.projectRoot);\n if (!hasLintScript) {\n const scripts = JsonFile.read(path.join(this.projectRoot, 'package.json')).scripts;\n await JsonFile.setAsync(\n path.join(this.projectRoot, 'package.json'),\n 'scripts',\n typeof scripts === 'object' ? { ...scripts, lint: 'eslint .' } : { lint: 'eslint .' },\n { json5: false }\n );\n }\n\n Log.log();\n Log.log('ESlint has been configured 🎉');\n Log.log();\n\n return true;\n }\n\n async _ensureDependenciesInstalledAsync({\n skipPrompt,\n isProjectMutable,\n }: {\n skipPrompt?: boolean;\n isProjectMutable?: boolean;\n }): Promise<boolean> {\n try {\n return await ensureDependenciesAsync(this.projectRoot, {\n skipPrompt,\n isProjectMutable,\n installMessage: 'ESLint is required to lint your project.',\n warningMessage: 'ESLint not installed, unable to set up linting for your project.',\n requiredPackages: [\n { version: '^8.57.0', pkg: 'eslint', file: 'eslint/package.json', dev: true },\n {\n pkg: 'eslint-config-expo',\n file: 'eslint-config-expo/package.json',\n dev: true,\n },\n ],\n });\n } catch (error) {\n this.resetAssertion();\n throw error;\n }\n }\n}\n\nasync function eslintIsConfigured(projectRoot: string) {\n debug('Ensuring ESlint is configured in', projectRoot);\n\n // TODO(cedric): drop `package.json` check once we swap to flat config\n const packageFile = await JsonFile.readAsync(path.join(projectRoot, 'package.json'));\n if (\n typeof packageFile.eslintConfig === 'object' &&\n Object.keys(packageFile.eslintConfig as JSONObject).length > 0\n ) {\n debug('Found ESlint config in package.json');\n return true;\n }\n\n const eslintConfigFiles = [\n // TODO(cedric): drop these files once we swap to flat config\n // See: https://eslint.org/docs/latest/use/configure/configuration-files-deprecated\n '.eslintrc.js',\n '.eslintrc.cjs',\n '.eslintrc.yaml',\n '.eslintrc.yml',\n '.eslintrc.json',\n // TODO(cedric): use these files once we swap to flat config\n // See: https://eslint.org/docs/latest/use/configure/configuration-files\n // 'eslint.config.js',\n // 'eslint.config.mjs',\n // 'eslint.config.cjs',\n ];\n for (const configFile of eslintConfigFiles) {\n const configPath = findFileInParents(projectRoot, configFile);\n const configIsEmpty = configPath ? await eslintConfigIsEmpty(configPath) : null;\n\n if (configPath && !configIsEmpty) {\n debug('Found ESlint config file:', configPath);\n return true;\n } else if (configPath && configIsEmpty) {\n debug('Skipping empty ESlint config file:', configPath);\n }\n }\n\n return false;\n}\n\n/** Determine if the eslint config file is empty. */\nasync function eslintConfigIsEmpty(filePath: string) {\n const content = await fs.readFile(filePath, 'utf8').then(\n (text) => text.trim().replaceAll(/\\s|\\r\\n|\\n|\\r/g, ''),\n () => null\n );\n\n return (\n !content ||\n content === '{}' || // .eslintrc.json\n content === '---' || // .eslintrc.yaml / .eslintrc.yml\n content.startsWith('module.exports={}') || // .eslintrc.js / .eslintrc.cjs / eslint.config.js / eslint.config.cjs\n content.startsWith('exportdefault{}') || // .eslint.config.mjs\n content.startsWith('exportdefault[]') // .eslint.config.mjs\n );\n}\n\nasync function lintScriptIsConfigured(projectRoot: string) {\n const packageFile = await JsonFile.readAsync(path.join(projectRoot, 'package.json'));\n return typeof (packageFile.scripts as JSONObject | undefined)?.lint === 'string';\n}\n"],"names":["ESLintProjectPrerequisite","debug","require","ProjectPrerequisite","assertImplementation","hasEslintConfig","eslintIsConfigured","projectRoot","hasLintScript","lintScriptIsConfigured","bootstrapAsync","isInteractive","Log","warn","shouldSetupLint","confirmAsync","message","PrerequisiteCommandError","_ensureDependenciesInstalledAsync","skipPrompt","isProjectMutable","fs","writeFile","path","join","readFile","resolve","scripts","JsonFile","read","setAsync","lint","json5","log","ensureDependenciesAsync","installMessage","warningMessage","requiredPackages","version","pkg","file","dev","error","resetAssertion","packageFile","readAsync","eslintConfig","Object","keys","length","eslintConfigFiles","configFile","configPath","findFileInParents","configIsEmpty","eslintConfigIsEmpty","filePath","content","then","text","trim","replaceAll","startsWith"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/lint/ESlintPrerequisite.ts"],"sourcesContent":["import JsonFile, { JSONObject } from '@expo/json-file';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nimport { Log } from '../log';\nimport { PrerequisiteCommandError, ProjectPrerequisite } from '../start/doctor/Prerequisite';\nimport { ensureDependenciesAsync } from '../start/doctor/dependencies/ensureDependenciesAsync';\nimport { findFileInParents } from '../utils/findUp';\nimport { isInteractive } from '../utils/interactive';\nimport { confirmAsync } from '../utils/prompts';\n\nconst debug = require('debug')('expo:lint') as typeof console.log;\n\n/** Ensure the project has the required ESLint config. */\nexport class ESLintProjectPrerequisite extends ProjectPrerequisite<boolean> {\n async assertImplementation(): Promise<boolean> {\n const hasEslintConfig = await isEslintConfigured(this.projectRoot);\n const hasLegacyConfig = await isLegacyEslintConfigured(this.projectRoot);\n const hasLintScript = await lintScriptIsConfigured(this.projectRoot);\n\n if (hasLegacyConfig) {\n Log.warn(`Using legacy ESLint config. Consider upgrading to flat config.`);\n }\n\n return (hasEslintConfig || hasLegacyConfig) && hasLintScript;\n }\n\n async bootstrapAsync(): Promise<boolean> {\n debug('Setting up ESLint');\n\n const hasEslintConfig = await isEslintConfigured(this.projectRoot);\n if (!hasEslintConfig) {\n if (!isInteractive()) {\n Log.warn(`No ESLint config found. Configuring automatically.`);\n } else {\n const shouldSetupLint = await confirmAsync({\n message: 'No ESLint config found. Install and configure ESLint in this project?',\n });\n if (!shouldSetupLint) {\n throw new PrerequisiteCommandError('ESLint is not configured for this project.');\n }\n }\n\n await this._ensureDependenciesInstalledAsync({ skipPrompt: true, isProjectMutable: true });\n\n await fs.writeFile(\n path.join(this.projectRoot, 'eslint.config.js'),\n await fs.readFile(require.resolve(`@expo/cli/static/template/eslint.config.js`), 'utf8'),\n 'utf8'\n );\n }\n\n const hasLintScript = await lintScriptIsConfigured(this.projectRoot);\n if (!hasLintScript) {\n const scripts = JsonFile.read(path.join(this.projectRoot, 'package.json')).scripts;\n await JsonFile.setAsync(\n path.join(this.projectRoot, 'package.json'),\n 'scripts',\n typeof scripts === 'object' ? { ...scripts, lint: 'eslint .' } : { lint: 'eslint .' },\n { json5: false }\n );\n }\n\n Log.log();\n Log.log('ESLint has been configured 🎉');\n Log.log();\n\n return true;\n }\n\n async _ensureDependenciesInstalledAsync({\n skipPrompt,\n isProjectMutable,\n }: {\n skipPrompt?: boolean;\n isProjectMutable?: boolean;\n }): Promise<boolean> {\n try {\n return await ensureDependenciesAsync(this.projectRoot, {\n skipPrompt,\n isProjectMutable,\n installMessage: 'ESLint is required to lint your project.',\n warningMessage: 'ESLint not installed, unable to set up linting for your project.',\n requiredPackages: [\n { version: '^9.0.0', pkg: 'eslint', file: 'eslint/package.json', dev: true },\n {\n pkg: 'eslint-config-expo',\n file: 'eslint-config-expo/package.json',\n dev: true,\n },\n ],\n });\n } catch (error) {\n this.resetAssertion();\n throw error;\n }\n }\n}\n\nasync function isLegacyEslintConfigured(projectRoot: string) {\n debug('Checking for legacy ESLint configuration', projectRoot);\n\n const packageFile = await JsonFile.readAsync(path.join(projectRoot, 'package.json'));\n if (\n typeof packageFile.eslintConfig === 'object' &&\n Object.keys(packageFile.eslintConfig as JSONObject).length > 0\n ) {\n debug('Found legacy ESLint config in package.json');\n return true;\n }\n\n const eslintConfigFiles = [\n '.eslintrc.js',\n '.eslintrc.cjs',\n '.eslintrc.yaml',\n '.eslintrc.yml',\n '.eslintrc.json',\n ];\n for (const configFile of eslintConfigFiles) {\n const configPath = findFileInParents(projectRoot, configFile);\n\n if (configPath) {\n debug('Found ESLint config file:', configPath);\n return true;\n }\n }\n\n return false;\n}\n\n/** Check for flat config. */\nasync function isEslintConfigured(projectRoot: string) {\n debug('Ensuring ESLint is configured in', projectRoot);\n\n const eslintConfigFiles = ['eslint.config.js', 'eslint.config.mjs', 'eslint.config.cjs'];\n for (const configFile of eslintConfigFiles) {\n const configPath = findFileInParents(projectRoot, configFile);\n\n if (configPath) {\n debug('Found ESLint config file:', configPath);\n return true;\n }\n }\n\n return false;\n}\n\nasync function lintScriptIsConfigured(projectRoot: string) {\n const packageFile = await JsonFile.readAsync(path.join(projectRoot, 'package.json'));\n return typeof (packageFile.scripts as JSONObject | undefined)?.lint === 'string';\n}\n"],"names":["ESLintProjectPrerequisite","debug","require","ProjectPrerequisite","assertImplementation","hasEslintConfig","isEslintConfigured","projectRoot","hasLegacyConfig","isLegacyEslintConfigured","hasLintScript","lintScriptIsConfigured","Log","warn","bootstrapAsync","isInteractive","shouldSetupLint","confirmAsync","message","PrerequisiteCommandError","_ensureDependenciesInstalledAsync","skipPrompt","isProjectMutable","fs","writeFile","path","join","readFile","resolve","scripts","JsonFile","read","setAsync","lint","json5","log","ensureDependenciesAsync","installMessage","warningMessage","requiredPackages","version","pkg","file","dev","error","resetAssertion","packageFile","readAsync","eslintConfig","Object","keys","length","eslintConfigFiles","configFile","configPath","findFileInParents"],"mappings":";;;;+BAcaA;;;eAAAA;;;;gEAdwB;;;;;;;gEACtB;;;;;;;gEACE;;;;;;qBAEG;8BAC0C;yCACtB;wBACN;6BACJ;yBACD;;;;;;AAE7B,MAAMC,QAAQC,QAAQ,SAAS;AAGxB,MAAMF,kCAAkCG,iCAAmB;IAChE,MAAMC,uBAAyC;QAC7C,MAAMC,kBAAkB,MAAMC,mBAAmB,IAAI,CAACC,WAAW;QACjE,MAAMC,kBAAkB,MAAMC,yBAAyB,IAAI,CAACF,WAAW;QACvE,MAAMG,gBAAgB,MAAMC,uBAAuB,IAAI,CAACJ,WAAW;QAEnE,IAAIC,iBAAiB;YACnBI,QAAG,CAACC,IAAI,CAAC,CAAC,8DAA8D,CAAC;QAC3E;QAEA,OAAO,AAACR,CAAAA,mBAAmBG,eAAc,KAAME;IACjD;IAEA,MAAMI,iBAAmC;QACvCb,MAAM;QAEN,MAAMI,kBAAkB,MAAMC,mBAAmB,IAAI,CAACC,WAAW;QACjE,IAAI,CAACF,iBAAiB;YACpB,IAAI,CAACU,IAAAA,0BAAa,KAAI;gBACpBH,QAAG,CAACC,IAAI,CAAC,CAAC,kDAAkD,CAAC;YAC/D,OAAO;gBACL,MAAMG,kBAAkB,MAAMC,IAAAA,qBAAY,EAAC;oBACzCC,SAAS;gBACX;gBACA,IAAI,CAACF,iBAAiB;oBACpB,MAAM,IAAIG,sCAAwB,CAAC;gBACrC;YACF;YAEA,MAAM,IAAI,CAACC,iCAAiC,CAAC;gBAAEC,YAAY;gBAAMC,kBAAkB;YAAK;YAExF,MAAMC,mBAAE,CAACC,SAAS,CAChBC,eAAI,CAACC,IAAI,CAAC,IAAI,CAACnB,WAAW,EAAE,qBAC5B,MAAMgB,mBAAE,CAACI,QAAQ,CAACzB,QAAQ0B,OAAO,CAAC,CAAC,0CAA0C,CAAC,GAAG,SACjF;QAEJ;QAEA,MAAMlB,gBAAgB,MAAMC,uBAAuB,IAAI,CAACJ,WAAW;QACnE,IAAI,CAACG,eAAe;YAClB,MAAMmB,UAAUC,mBAAQ,CAACC,IAAI,CAACN,eAAI,CAACC,IAAI,CAAC,IAAI,CAACnB,WAAW,EAAE,iBAAiBsB,OAAO;YAClF,MAAMC,mBAAQ,CAACE,QAAQ,CACrBP,eAAI,CAACC,IAAI,CAAC,IAAI,CAACnB,WAAW,EAAE,iBAC5B,WACA,OAAOsB,YAAY,WAAW;gBAAE,GAAGA,OAAO;gBAAEI,MAAM;YAAW,IAAI;gBAAEA,MAAM;YAAW,GACpF;gBAAEC,OAAO;YAAM;QAEnB;QAEAtB,QAAG,CAACuB,GAAG;QACPvB,QAAG,CAACuB,GAAG,CAAC;QACRvB,QAAG,CAACuB,GAAG;QAEP,OAAO;IACT;IAEA,MAAMf,kCAAkC,EACtCC,UAAU,EACVC,gBAAgB,EAIjB,EAAoB;QACnB,IAAI;YACF,OAAO,MAAMc,IAAAA,gDAAuB,EAAC,IAAI,CAAC7B,WAAW,EAAE;gBACrDc;gBACAC;gBACAe,gBAAgB;gBAChBC,gBAAgB;gBAChBC,kBAAkB;oBAChB;wBAAEC,SAAS;wBAAUC,KAAK;wBAAUC,MAAM;wBAAuBC,KAAK;oBAAK;oBAC3E;wBACEF,KAAK;wBACLC,MAAM;wBACNC,KAAK;oBACP;iBACD;YACH;QACF,EAAE,OAAOC,OAAO;YACd,IAAI,CAACC,cAAc;YACnB,MAAMD;QACR;IACF;AACF;AAEA,eAAenC,yBAAyBF,WAAmB;IACzDN,MAAM,4CAA4CM;IAElD,MAAMuC,cAAc,MAAMhB,mBAAQ,CAACiB,SAAS,CAACtB,eAAI,CAACC,IAAI,CAACnB,aAAa;IACpE,IACE,OAAOuC,YAAYE,YAAY,KAAK,YACpCC,OAAOC,IAAI,CAACJ,YAAYE,YAAY,EAAgBG,MAAM,GAAG,GAC7D;QACAlD,MAAM;QACN,OAAO;IACT;IAEA,MAAMmD,oBAAoB;QACxB;QACA;QACA;QACA;QACA;KACD;IACD,KAAK,MAAMC,cAAcD,kBAAmB;QAC1C,MAAME,aAAaC,IAAAA,yBAAiB,EAAChD,aAAa8C;QAElD,IAAIC,YAAY;YACdrD,MAAM,6BAA6BqD;YACnC,OAAO;QACT;IACF;IAEA,OAAO;AACT;AAEA,2BAA2B,GAC3B,eAAehD,mBAAmBC,WAAmB;IACnDN,MAAM,oCAAoCM;IAE1C,MAAM6C,oBAAoB;QAAC;QAAoB;QAAqB;KAAoB;IACxF,KAAK,MAAMC,cAAcD,kBAAmB;QAC1C,MAAME,aAAaC,IAAAA,yBAAiB,EAAChD,aAAa8C;QAElD,IAAIC,YAAY;YACdrD,MAAM,6BAA6BqD;YACnC,OAAO;QACT;IACF;IAEA,OAAO;AACT;AAEA,eAAe3C,uBAAuBJ,WAAmB;QAExCuC;IADf,MAAMA,cAAc,MAAMhB,mBAAQ,CAACiB,SAAS,CAACtB,eAAI,CAACC,IAAI,CAACnB,aAAa;IACpE,OAAO,SAAQuC,uBAAAA,YAAYjB,OAAO,qBAApB,AAACiB,qBAAgDb,IAAI,MAAK;AAC1E"}
@@ -225,7 +225,7 @@ class XcodePrerequisite extends _Prerequisite.Prerequisite {
225
225
  }
226
226
  }
227
227
  // Almost certainly Xcode isn't installed.
228
- await promptToOpenAppStoreAsync(`Xcode must be fully installed before you can continue. Continue to the App Store?`);
228
+ await promptToOpenAppStoreAsync(`Xcode must be fully installed before you can continue. If this message is still occurring after installing Xcode, you may need to finish the installation of the developer tools by running: \`sudo xcode-select -s /Applications/Xcode.app/Contents/Developer\`. Continue to the App Store?`);
229
229
  throw new _errors.AbortCommandError();
230
230
  }
231
231
  if (_semver().default.lt(version, SUGGESTED_XCODE_VERSION)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/doctor/apple/XcodePrerequisite.ts"],"sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport semver from 'semver';\n\nimport * as Log from '../../../log';\nimport { AbortCommandError } from '../../../utils/errors';\nimport { profile } from '../../../utils/profile';\nimport { confirmAsync } from '../../../utils/prompts';\nimport { Prerequisite } from '../Prerequisite';\n\nconst debug = require('debug')('expo:doctor:apple:xcode') as typeof console.log;\n\n// Based on the Apple announcement (last updated: Aug 2023).\n// https://developer.apple.com/news/upcoming-requirements/?id=04252023a\nconst MIN_XCODE_VERSION = '14.1';\nconst APP_STORE_ID = '497799835';\n\nconst SUGGESTED_XCODE_VERSION = `${MIN_XCODE_VERSION}.0`;\n\nconst promptToOpenAppStoreAsync = async (message: string) => {\n // This prompt serves no purpose accept informing the user what to do next, we could just open the App Store but it could be confusing if they don't know what's going on.\n const confirm = await confirmAsync({ initial: true, message });\n if (confirm) {\n Log.log(`Going to the App Store, re-run Expo CLI when Xcode has finished installing.`);\n openAppStore(APP_STORE_ID);\n }\n};\n\nlet _xcodeVersionPromise: Promise<{ value: string | null | false; error?: string }> | null = null;\n\nexport const getXcodeVersionAsync = async ({\n silent,\n force,\n}: { silent?: boolean; force?: boolean } = {}): Promise<string | null | false> => {\n const logError = silent ? debug : Log.warn;\n const getVersion = async (): Promise<{ value: string | null | false; error?: string }> => {\n try {\n const { stdout } = await spawnAsync('xcodebuild', ['-version']);\n const last = stdout.match(/^Xcode (\\d+\\.\\d+)/)?.[1];\n // Convert to a semver string\n if (last) {\n const version = `${last}.0`;\n\n if (!semver.valid(version)) {\n // Not sure why this would happen, if it does we should add a more confident error message.\n return { error: `Xcode version is in an unknown format: ${version}`, value: false };\n }\n return { value: version };\n }\n\n // not sure what's going on\n return {\n error:\n 'Unable to check Xcode version. Command ran successfully but no version number was found.',\n value: null,\n };\n } catch {\n // not installed\n }\n return { value: null };\n };\n\n if (force) {\n _xcodeVersionPromise = null;\n }\n\n _xcodeVersionPromise = _xcodeVersionPromise ?? getVersion();\n\n const result = await _xcodeVersionPromise;\n\n if (result.error) {\n logError(result.error);\n }\n\n return result.value;\n};\n\n/**\n * Open a link to the App Store. Just link in mobile apps, **never** redirect without prompting first.\n *\n * @param appId\n */\nfunction openAppStore(appId: string) {\n const link = getAppStoreLink(appId);\n execSync(`open ${link}`, { stdio: 'ignore' });\n}\n\nfunction getAppStoreLink(appId: string): string {\n if (process.platform === 'darwin') {\n // TODO: Is there ever a case where the macappstore isn't available on mac?\n return `macappstore://itunes.apple.com/app/id${appId}`;\n }\n return `https://apps.apple.com/us/app/id${appId}`;\n}\n\nfunction spawnForString(cmd: string): string | null {\n try {\n return execSync(cmd, { stdio: 'pipe' }).toString().trim();\n } catch {}\n return null;\n}\n\n/** @returns a string like `/Applications/Xcode.app/Contents/Developer` when Xcode has a correctly selected path. */\nfunction getXcodeSelectPathAsync() {\n return spawnForString('/usr/bin/xcode-select --print-path');\n}\nfunction getXcodeInstalled() {\n return spawnForString('ls /Applications/Xcode.app/Contents/Developer');\n}\n\nexport class XcodePrerequisite extends Prerequisite {\n static instance = new XcodePrerequisite();\n\n /**\n * Ensure Xcode is installed and recent enough to be used with Expo.\n */\n async assertImplementation(): Promise<void> {\n const version = await profile(getXcodeVersionAsync)({ force: process.env.NODE_ENV === 'test' });\n debug(`Xcode version: ${version}`);\n if (!version) {\n // A couple different issues could have occurred, let's check them after we're past the point of no return\n // since we no longer need to be fast about validation.\n\n // Ensure Xcode.app can be found before we prompt to sudo select it.\n if (getXcodeInstalled()) {\n const selectPath = profile(getXcodeSelectPathAsync)();\n debug(`Xcode select path: ${selectPath}`);\n if (!selectPath) {\n Log.error(\n [\n '',\n chalk.bold('Xcode has not been fully setup for Apple development yet.'),\n 'Download at: https://developer.apple.com/xcode/',\n 'or in the App Store.',\n '',\n 'After downloading Xcode, run the following two commands in your terminal:',\n chalk.cyan(' sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer'),\n chalk.cyan(' sudo xcodebuild -runFirstLaunch'),\n '',\n 'Then you can re-run Expo CLI. Alternatively, you can build apps in the cloud with EAS CLI, or preview using the Expo Go app on a physical device.',\n '',\n ].join('\\n')\n );\n throw new AbortCommandError();\n } else {\n debug(`Unexpected Xcode setup (version: ${version}, select: ${selectPath})`);\n }\n }\n\n // Almost certainly Xcode isn't installed.\n await promptToOpenAppStoreAsync(\n `Xcode must be fully installed before you can continue. Continue to the App Store?`\n );\n throw new AbortCommandError();\n }\n\n if (semver.lt(version, SUGGESTED_XCODE_VERSION)) {\n // Xcode version is too old.\n await promptToOpenAppStoreAsync(\n `Xcode (${version}) needs to be updated to at least version ${MIN_XCODE_VERSION}. Continue to the App Store?`\n );\n throw new AbortCommandError();\n }\n }\n}\n"],"names":["XcodePrerequisite","getXcodeVersionAsync","debug","require","MIN_XCODE_VERSION","APP_STORE_ID","SUGGESTED_XCODE_VERSION","promptToOpenAppStoreAsync","message","confirm","confirmAsync","initial","Log","log","openAppStore","_xcodeVersionPromise","silent","force","logError","warn","getVersion","stdout","spawnAsync","last","match","version","semver","valid","error","value","result","appId","link","getAppStoreLink","execSync","stdio","process","platform","spawnForString","cmd","toString","trim","getXcodeSelectPathAsync","getXcodeInstalled","Prerequisite","instance","assertImplementation","profile","env","NODE_ENV","selectPath","chalk","bold","cyan","join","AbortCommandError","lt"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/doctor/apple/XcodePrerequisite.ts"],"sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport semver from 'semver';\n\nimport * as Log from '../../../log';\nimport { AbortCommandError } from '../../../utils/errors';\nimport { profile } from '../../../utils/profile';\nimport { confirmAsync } from '../../../utils/prompts';\nimport { Prerequisite } from '../Prerequisite';\n\nconst debug = require('debug')('expo:doctor:apple:xcode') as typeof console.log;\n\n// Based on the Apple announcement (last updated: Aug 2023).\n// https://developer.apple.com/news/upcoming-requirements/?id=04252023a\nconst MIN_XCODE_VERSION = '14.1';\nconst APP_STORE_ID = '497799835';\n\nconst SUGGESTED_XCODE_VERSION = `${MIN_XCODE_VERSION}.0`;\n\nconst promptToOpenAppStoreAsync = async (message: string) => {\n // This prompt serves no purpose accept informing the user what to do next, we could just open the App Store but it could be confusing if they don't know what's going on.\n const confirm = await confirmAsync({ initial: true, message });\n if (confirm) {\n Log.log(`Going to the App Store, re-run Expo CLI when Xcode has finished installing.`);\n openAppStore(APP_STORE_ID);\n }\n};\n\nlet _xcodeVersionPromise: Promise<{ value: string | null | false; error?: string }> | null = null;\n\nexport const getXcodeVersionAsync = async ({\n silent,\n force,\n}: { silent?: boolean; force?: boolean } = {}): Promise<string | null | false> => {\n const logError = silent ? debug : Log.warn;\n const getVersion = async (): Promise<{ value: string | null | false; error?: string }> => {\n try {\n const { stdout } = await spawnAsync('xcodebuild', ['-version']);\n const last = stdout.match(/^Xcode (\\d+\\.\\d+)/)?.[1];\n // Convert to a semver string\n if (last) {\n const version = `${last}.0`;\n\n if (!semver.valid(version)) {\n // Not sure why this would happen, if it does we should add a more confident error message.\n return { error: `Xcode version is in an unknown format: ${version}`, value: false };\n }\n return { value: version };\n }\n\n // not sure what's going on\n return {\n error:\n 'Unable to check Xcode version. Command ran successfully but no version number was found.',\n value: null,\n };\n } catch {\n // not installed\n }\n return { value: null };\n };\n\n if (force) {\n _xcodeVersionPromise = null;\n }\n\n _xcodeVersionPromise = _xcodeVersionPromise ?? getVersion();\n\n const result = await _xcodeVersionPromise;\n\n if (result.error) {\n logError(result.error);\n }\n\n return result.value;\n};\n\n/**\n * Open a link to the App Store. Just link in mobile apps, **never** redirect without prompting first.\n *\n * @param appId\n */\nfunction openAppStore(appId: string) {\n const link = getAppStoreLink(appId);\n execSync(`open ${link}`, { stdio: 'ignore' });\n}\n\nfunction getAppStoreLink(appId: string): string {\n if (process.platform === 'darwin') {\n // TODO: Is there ever a case where the macappstore isn't available on mac?\n return `macappstore://itunes.apple.com/app/id${appId}`;\n }\n return `https://apps.apple.com/us/app/id${appId}`;\n}\n\nfunction spawnForString(cmd: string): string | null {\n try {\n return execSync(cmd, { stdio: 'pipe' }).toString().trim();\n } catch {}\n return null;\n}\n\n/** @returns a string like `/Applications/Xcode.app/Contents/Developer` when Xcode has a correctly selected path. */\nfunction getXcodeSelectPathAsync() {\n return spawnForString('/usr/bin/xcode-select --print-path');\n}\nfunction getXcodeInstalled() {\n return spawnForString('ls /Applications/Xcode.app/Contents/Developer');\n}\n\nexport class XcodePrerequisite extends Prerequisite {\n static instance = new XcodePrerequisite();\n\n /**\n * Ensure Xcode is installed and recent enough to be used with Expo.\n */\n async assertImplementation(): Promise<void> {\n const version = await profile(getXcodeVersionAsync)({ force: process.env.NODE_ENV === 'test' });\n debug(`Xcode version: ${version}`);\n if (!version) {\n // A couple different issues could have occurred, let's check them after we're past the point of no return\n // since we no longer need to be fast about validation.\n\n // Ensure Xcode.app can be found before we prompt to sudo select it.\n if (getXcodeInstalled()) {\n const selectPath = profile(getXcodeSelectPathAsync)();\n debug(`Xcode select path: ${selectPath}`);\n if (!selectPath) {\n Log.error(\n [\n '',\n chalk.bold('Xcode has not been fully setup for Apple development yet.'),\n 'Download at: https://developer.apple.com/xcode/',\n 'or in the App Store.',\n '',\n 'After downloading Xcode, run the following two commands in your terminal:',\n chalk.cyan(' sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer'),\n chalk.cyan(' sudo xcodebuild -runFirstLaunch'),\n '',\n 'Then you can re-run Expo CLI. Alternatively, you can build apps in the cloud with EAS CLI, or preview using the Expo Go app on a physical device.',\n '',\n ].join('\\n')\n );\n throw new AbortCommandError();\n } else {\n debug(`Unexpected Xcode setup (version: ${version}, select: ${selectPath})`);\n }\n }\n\n // Almost certainly Xcode isn't installed.\n await promptToOpenAppStoreAsync(\n `Xcode must be fully installed before you can continue. If this message is still occurring after installing Xcode, you may need to finish the installation of the developer tools by running: \\`sudo xcode-select -s /Applications/Xcode.app/Contents/Developer\\`. Continue to the App Store?`\n );\n throw new AbortCommandError();\n }\n\n if (semver.lt(version, SUGGESTED_XCODE_VERSION)) {\n // Xcode version is too old.\n await promptToOpenAppStoreAsync(\n `Xcode (${version}) needs to be updated to at least version ${MIN_XCODE_VERSION}. Continue to the App Store?`\n );\n throw new AbortCommandError();\n }\n }\n}\n"],"names":["XcodePrerequisite","getXcodeVersionAsync","debug","require","MIN_XCODE_VERSION","APP_STORE_ID","SUGGESTED_XCODE_VERSION","promptToOpenAppStoreAsync","message","confirm","confirmAsync","initial","Log","log","openAppStore","_xcodeVersionPromise","silent","force","logError","warn","getVersion","stdout","spawnAsync","last","match","version","semver","valid","error","value","result","appId","link","getAppStoreLink","execSync","stdio","process","platform","spawnForString","cmd","toString","trim","getXcodeSelectPathAsync","getXcodeInstalled","Prerequisite","instance","assertImplementation","profile","env","NODE_ENV","selectPath","chalk","bold","cyan","join","AbortCommandError","lt"],"mappings":"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"}
@@ -38,6 +38,7 @@ function _path() {
38
38
  }
39
39
  const _TerminalReporter = require("./TerminalReporter");
40
40
  const _externals = require("./externals");
41
+ const _env = require("../../../utils/env");
41
42
  const _link = require("../../../utils/link");
42
43
  const _serverLogLikeMetro = require("../serverLogLikeMetro");
43
44
  function _interop_require_default(obj) {
@@ -55,6 +56,32 @@ class MetroTerminalReporter extends _TerminalReporter.TerminalReporter {
55
56
  }
56
57
  _log(event) {
57
58
  switch(event.type){
59
+ case 'unstable_server_log':
60
+ var _event_data;
61
+ if (typeof ((_event_data = event.data) == null ? void 0 : _event_data[0]) === 'string') {
62
+ const message = event.data[0];
63
+ if (message.match(/JavaScript logs have moved/)) {
64
+ // Hide this very loud message from upstream React Native in favor of the note in the terminal UI:
65
+ // The "› Press j │ open debugger"
66
+ // logger?.info(
67
+ // '\u001B[1m\u001B[7m💡 JavaScript logs have moved!\u001B[22m They can now be ' +
68
+ // 'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' +
69
+ // 'the terminal to open (requires Google Chrome or Microsoft Edge).' +
70
+ // '\u001B[27m',
71
+ // );
72
+ return;
73
+ }
74
+ if (!_env.env.EXPO_DEBUG) {
75
+ // In the context of developing an iOS app or website, the MetroInspectorProxy "connection" logs are very confusing.
76
+ // Here we'll hide them behind EXPO_DEBUG or DEBUG=expo:*. In the future we can reformat them to clearly indicate that the "Connection" is regarding the debugger.
77
+ // These logs are also confusing because they can say "connection established" even when the debugger is not in a usable state. Really they belong in a UI or behind some sort of debug logging.
78
+ if (message.match(/Connection (closed|established|failed|terminated)/i)) {
79
+ // Skip logging.
80
+ return;
81
+ }
82
+ }
83
+ }
84
+ break;
58
85
  case 'client_log':
59
86
  {
60
87
  if (this.shouldFilterClientLog(event)) {
@@ -64,7 +91,7 @@ class MetroTerminalReporter extends _TerminalReporter.TerminalReporter {
64
91
  if (!level) {
65
92
  break;
66
93
  }
67
- const mode = event.mode === 'NOBRIDGE' ? '' : event.mode ?? '';
94
+ const mode = event.mode === 'NOBRIDGE' || event.mode === 'BRIDGE' ? '' : event.mode ?? '';
68
95
  // @ts-expect-error
69
96
  if (level === 'warn' || level === 'error') {
70
97
  // Quick check to see if an unsymbolicated stack is being logged.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/server/metro/MetroTerminalReporter.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { Terminal } from 'metro-core';\nimport path from 'path';\n\nimport { logWarning, TerminalReporter } from './TerminalReporter';\nimport {\n BuildPhase,\n BundleDetails,\n BundleProgress,\n SnippetError,\n TerminalReportableEvent,\n} from './TerminalReporter.types';\nimport { NODE_STDLIB_MODULES } from './externals';\nimport { learnMore } from '../../../utils/link';\nimport {\n logLikeMetro,\n maybeSymbolicateAndFormatReactErrorLogAsync,\n parseErrorStringToObject,\n} from '../serverLogLikeMetro';\n\nconst debug = require('debug')('expo:metro:logger') as typeof console.log;\n\nconst MAX_PROGRESS_BAR_CHAR_WIDTH = 16;\nconst DARK_BLOCK_CHAR = '\\u2593';\nconst LIGHT_BLOCK_CHAR = '\\u2591';\n/**\n * Extends the default Metro logger and adds some additional features.\n * Also removes the giant Metro logo from the output.\n */\nexport class MetroTerminalReporter extends TerminalReporter {\n constructor(\n public projectRoot: string,\n terminal: Terminal\n ) {\n super(terminal);\n }\n\n _log(event: TerminalReportableEvent): void {\n switch (event.type) {\n case 'client_log': {\n if (this.shouldFilterClientLog(event)) {\n return;\n }\n const { level } = event;\n\n if (!level) {\n break;\n }\n\n const mode = event.mode === 'NOBRIDGE' ? '' : (event.mode ?? '');\n // @ts-expect-error\n if (level === 'warn' || level === 'error') {\n // Quick check to see if an unsymbolicated stack is being logged.\n const msg = event.data.join('\\n');\n if (msg.includes('.bundle//&platform=')) {\n const parsed = parseErrorStringToObject(msg);\n if (parsed) {\n maybeSymbolicateAndFormatReactErrorLogAsync(this.projectRoot, level, parsed)\n .then((res) => {\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, mode, res);\n })\n .catch((e) => {\n // Fallback on the original error message if we can't symbolicate the stack.\n debug('Error formatting stack', e);\n\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, mode, ...event.data);\n });\n\n return;\n }\n }\n }\n\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, mode, ...event.data);\n return;\n }\n }\n return super._log(event);\n }\n\n // Used for testing\n _getElapsedTime(startTime: bigint): bigint {\n return process.hrtime.bigint() - startTime;\n }\n /**\n * Extends the bundle progress to include the current platform that we're bundling.\n *\n * @returns `iOS path/to/bundle.js ▓▓▓▓▓░░░░░░░░░░░ 36.6% (4790/7922)`\n */\n _getBundleStatusMessage(progress: BundleProgress, phase: BuildPhase): string {\n const env = getEnvironmentForBuildDetails(progress.bundleDetails);\n const platform = env || getPlatformTagForBuildDetails(progress.bundleDetails);\n const inProgress = phase === 'in_progress';\n\n let localPath: string;\n\n if (\n typeof progress.bundleDetails?.customTransformOptions?.dom === 'string' &&\n progress.bundleDetails.customTransformOptions.dom.includes(path.sep)\n ) {\n // Because we use a generated entry file for DOM components, we need to adjust the logging path so it\n // shows a unique path for each component.\n // Here, we take the relative import path and remove all the starting slashes.\n localPath = progress.bundleDetails.customTransformOptions.dom.replace(/^(\\.?\\.[\\\\/])+/, '');\n } else {\n const inputFile = progress.bundleDetails.entryFile;\n\n localPath = path.isAbsolute(inputFile)\n ? path.relative(this.projectRoot, inputFile)\n : inputFile;\n }\n\n if (!inProgress) {\n const status = phase === 'done' ? `Bundled ` : `Bundling failed `;\n const color = phase === 'done' ? chalk.green : chalk.red;\n\n const startTime = this._bundleTimers.get(progress.bundleDetails.buildID!);\n\n let time: string = '';\n\n if (startTime != null) {\n const elapsed: bigint = this._getElapsedTime(startTime);\n const micro = Number(elapsed) / 1000;\n const converted = Number(elapsed) / 1e6;\n // If the milliseconds are < 0.5 then it will display as 0, so we display in microseconds.\n if (converted <= 0.5) {\n const tenthFractionOfMicro = ((micro * 10) / 1000).toFixed(0);\n // Format as microseconds to nearest tenth\n time = chalk.cyan.bold(`0.${tenthFractionOfMicro}ms`);\n } else {\n time = chalk.dim(converted.toFixed(0) + 'ms');\n }\n }\n\n // iOS Bundled 150ms\n const plural = progress.totalFileCount === 1 ? '' : 's';\n return (\n color(platform + status) +\n time +\n chalk.reset.dim(` ${localPath} (${progress.totalFileCount} module${plural})`)\n );\n }\n\n const filledBar = Math.floor(progress.ratio * MAX_PROGRESS_BAR_CHAR_WIDTH);\n\n const _progress = inProgress\n ? chalk.green.bgGreen(DARK_BLOCK_CHAR.repeat(filledBar)) +\n chalk.bgWhite.white(LIGHT_BLOCK_CHAR.repeat(MAX_PROGRESS_BAR_CHAR_WIDTH - filledBar)) +\n chalk.bold(` ${(100 * progress.ratio).toFixed(1).padStart(4)}% `) +\n chalk.dim(\n `(${progress.transformedFileCount\n .toString()\n .padStart(progress.totalFileCount.toString().length)}/${progress.totalFileCount})`\n )\n : '';\n\n return (\n platform +\n chalk.reset.dim(`${path.dirname(localPath)}${path.sep}`) +\n chalk.bold(path.basename(localPath)) +\n ' ' +\n _progress\n );\n }\n\n _logInitializing(port: number, hasReducedPerformance: boolean): void {\n // Don't print a giant logo...\n this.terminal.log(chalk.dim('Starting Metro Bundler'));\n }\n\n shouldFilterClientLog(event: { type: 'client_log'; data: unknown[] }): boolean {\n return isAppRegistryStartupMessage(event.data);\n }\n\n shouldFilterBundleEvent(event: TerminalReportableEvent): boolean {\n return 'bundleDetails' in event && event.bundleDetails?.bundleType === 'map';\n }\n\n /** Print the cache clear message. */\n transformCacheReset(): void {\n logWarning(\n this.terminal,\n chalk`Bundler cache is empty, rebuilding {dim (this may take a minute)}`\n );\n }\n\n /** One of the first logs that will be printed */\n dependencyGraphLoading(hasReducedPerformance: boolean): void {\n // this.terminal.log('Dependency graph is loading...');\n if (hasReducedPerformance) {\n // Extends https://github.com/facebook/metro/blob/347b1d7ed87995d7951aaa9fd597c04b06013dac/packages/metro/src/lib/TerminalReporter.js#L283-L290\n this.terminal.log(\n chalk.red(\n [\n 'Metro is operating with reduced performance.',\n 'Please fix the problem above and restart Metro.',\n ].join('\\n')\n )\n );\n }\n }\n\n _logBundlingError(error: SnippetError): void {\n const moduleResolutionError = formatUsingNodeStandardLibraryError(this.projectRoot, error);\n const cause = error.cause as undefined | { _expoImportStack?: string };\n if (moduleResolutionError) {\n let message = maybeAppendCodeFrame(moduleResolutionError, error.message);\n if (cause?._expoImportStack) {\n message += `\\n\\n${cause?._expoImportStack}`;\n }\n return this.terminal.log(message);\n }\n if (cause?._expoImportStack) {\n error.message += `\\n\\n${cause._expoImportStack}`;\n }\n return super._logBundlingError(error);\n }\n}\n\n/**\n * Formats an error where the user is attempting to import a module from the Node.js standard library.\n * Exposed for testing.\n *\n * @param error\n * @returns error message or null if not a module resolution error\n */\nexport function formatUsingNodeStandardLibraryError(\n projectRoot: string,\n error: SnippetError\n): string | null {\n if (!error.message) {\n return null;\n }\n const { targetModuleName, originModulePath } = error;\n if (!targetModuleName || !originModulePath) {\n return null;\n }\n const relativePath = path.relative(projectRoot, originModulePath);\n\n const DOCS_PAGE_URL =\n 'https://docs.expo.dev/workflow/using-libraries/#using-third-party-libraries';\n\n if (isNodeStdLibraryModule(targetModuleName)) {\n if (originModulePath.includes('node_modules')) {\n return [\n `The package at \"${chalk.bold(\n relativePath\n )}\" attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n } else {\n return [\n `You attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\" from \"${chalk.bold(relativePath)}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n }\n }\n return `Unable to resolve \"${targetModuleName}\" from \"${relativePath}\"`;\n}\n\nexport function isNodeStdLibraryModule(moduleName: string): boolean {\n return /^node:/.test(moduleName) || NODE_STDLIB_MODULES.includes(moduleName);\n}\n\n/** If the code frame can be found then append it to the existing message. */\nfunction maybeAppendCodeFrame(message: string, rawMessage: string): string {\n const codeFrame = stripMetroInfo(rawMessage);\n if (codeFrame) {\n message += '\\n' + codeFrame;\n }\n return message;\n}\n\n/**\n * Remove the Metro cache clearing steps if they exist.\n * In future versions we won't need this.\n * Returns the remaining code frame logs.\n */\nexport function stripMetroInfo(errorMessage: string): string | null {\n // Newer versions of Metro don't include the list.\n if (!errorMessage.includes('4. Remove the cache')) {\n return null;\n }\n const lines = errorMessage.split('\\n');\n const index = lines.findIndex((line) => line.includes('4. Remove the cache'));\n if (index === -1) {\n return null;\n }\n return lines.slice(index + 1).join('\\n');\n}\n\n/** @returns if the message matches the initial startup log */\nfunction isAppRegistryStartupMessage(body: any[]): boolean {\n return (\n body.length === 1 &&\n (/^Running application \"main\" with appParams:/.test(body[0]) ||\n /^Running \"main\" with \\{/.test(body[0]))\n );\n}\n\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getPlatformTagForBuildDetails(bundleDetails?: BundleDetails | null): string {\n const platform = bundleDetails?.platform ?? null;\n if (platform) {\n const formatted = { ios: 'iOS', android: 'Android', web: 'Web' }[platform] || platform;\n return `${chalk.bold(formatted)} `;\n }\n\n return '';\n}\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getEnvironmentForBuildDetails(bundleDetails?: BundleDetails | null): string {\n // Expo CLI will pass `customTransformOptions.environment = 'node'` when bundling for the server.\n const env = bundleDetails?.customTransformOptions?.environment ?? null;\n if (env === 'node') {\n return chalk.bold('λ') + ' ';\n } else if (env === 'react-server') {\n return chalk.bold(`RSC(${getPlatformTagForBuildDetails(bundleDetails).trim()})`) + ' ';\n }\n\n if (\n bundleDetails?.customTransformOptions?.dom &&\n typeof bundleDetails?.customTransformOptions?.dom === 'string'\n ) {\n return chalk.bold(`DOM`) + ' ';\n }\n\n return '';\n}\n"],"names":["MetroTerminalReporter","formatUsingNodeStandardLibraryError","isNodeStdLibraryModule","stripMetroInfo","debug","require","MAX_PROGRESS_BAR_CHAR_WIDTH","DARK_BLOCK_CHAR","LIGHT_BLOCK_CHAR","TerminalReporter","constructor","projectRoot","terminal","_log","event","type","shouldFilterClientLog","level","mode","msg","data","join","includes","parsed","parseErrorStringToObject","maybeSymbolicateAndFormatReactErrorLogAsync","then","res","logLikeMetro","log","bind","catch","e","_getElapsedTime","startTime","process","hrtime","bigint","_getBundleStatusMessage","progress","phase","env","getEnvironmentForBuildDetails","bundleDetails","platform","getPlatformTagForBuildDetails","inProgress","localPath","customTransformOptions","dom","path","sep","replace","inputFile","entryFile","isAbsolute","relative","status","color","chalk","green","red","_bundleTimers","get","buildID","time","elapsed","micro","Number","converted","tenthFractionOfMicro","toFixed","cyan","bold","dim","plural","totalFileCount","reset","filledBar","Math","floor","ratio","_progress","bgGreen","repeat","bgWhite","white","padStart","transformedFileCount","toString","length","dirname","basename","_logInitializing","port","hasReducedPerformance","isAppRegistryStartupMessage","shouldFilterBundleEvent","bundleType","transformCacheReset","logWarning","dependencyGraphLoading","_logBundlingError","error","moduleResolutionError","cause","message","maybeAppendCodeFrame","_expoImportStack","targetModuleName","originModulePath","relativePath","DOCS_PAGE_URL","learnMore","moduleName","test","NODE_STDLIB_MODULES","rawMessage","codeFrame","errorMessage","lines","split","index","findIndex","line","slice","body","formatted","ios","android","web","environment","trim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/server/metro/MetroTerminalReporter.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { Terminal } from 'metro-core';\nimport path from 'path';\n\nimport { logWarning, TerminalReporter } from './TerminalReporter';\nimport {\n BuildPhase,\n BundleDetails,\n BundleProgress,\n SnippetError,\n TerminalReportableEvent,\n} from './TerminalReporter.types';\nimport { NODE_STDLIB_MODULES } from './externals';\nimport { env } from '../../../utils/env';\nimport { learnMore } from '../../../utils/link';\nimport {\n logLikeMetro,\n maybeSymbolicateAndFormatReactErrorLogAsync,\n parseErrorStringToObject,\n} from '../serverLogLikeMetro';\n\nconst debug = require('debug')('expo:metro:logger') as typeof console.log;\n\nconst MAX_PROGRESS_BAR_CHAR_WIDTH = 16;\nconst DARK_BLOCK_CHAR = '\\u2593';\nconst LIGHT_BLOCK_CHAR = '\\u2591';\n/**\n * Extends the default Metro logger and adds some additional features.\n * Also removes the giant Metro logo from the output.\n */\nexport class MetroTerminalReporter extends TerminalReporter {\n constructor(\n public projectRoot: string,\n terminal: Terminal\n ) {\n super(terminal);\n }\n\n _log(event: TerminalReportableEvent): void {\n switch (event.type) {\n case 'unstable_server_log':\n if (typeof event.data?.[0] === 'string') {\n const message = event.data[0];\n if (message.match(/JavaScript logs have moved/)) {\n // Hide this very loud message from upstream React Native in favor of the note in the terminal UI:\n // The \"› Press j │ open debugger\"\n\n // logger?.info(\n // '\\u001B[1m\\u001B[7m💡 JavaScript logs have moved!\\u001B[22m They can now be ' +\n // 'viewed in React Native DevTools. Tip: Type \\u001B[1mj\\u001B[22m in ' +\n // 'the terminal to open (requires Google Chrome or Microsoft Edge).' +\n // '\\u001B[27m',\n // );\n return;\n }\n\n if (!env.EXPO_DEBUG) {\n // In the context of developing an iOS app or website, the MetroInspectorProxy \"connection\" logs are very confusing.\n // Here we'll hide them behind EXPO_DEBUG or DEBUG=expo:*. In the future we can reformat them to clearly indicate that the \"Connection\" is regarding the debugger.\n // These logs are also confusing because they can say \"connection established\" even when the debugger is not in a usable state. Really they belong in a UI or behind some sort of debug logging.\n if (message.match(/Connection (closed|established|failed|terminated)/i)) {\n // Skip logging.\n return;\n }\n }\n }\n break;\n case 'client_log': {\n if (this.shouldFilterClientLog(event)) {\n return;\n }\n const { level } = event;\n\n if (!level) {\n break;\n }\n\n const mode = event.mode === 'NOBRIDGE' || event.mode === 'BRIDGE' ? '' : (event.mode ?? '');\n // @ts-expect-error\n if (level === 'warn' || level === 'error') {\n // Quick check to see if an unsymbolicated stack is being logged.\n const msg = event.data.join('\\n');\n if (msg.includes('.bundle//&platform=')) {\n const parsed = parseErrorStringToObject(msg);\n\n if (parsed) {\n maybeSymbolicateAndFormatReactErrorLogAsync(this.projectRoot, level, parsed)\n .then((res) => {\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, mode, res);\n })\n .catch((e) => {\n // Fallback on the original error message if we can't symbolicate the stack.\n debug('Error formatting stack', e);\n\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, mode, ...event.data);\n });\n\n return;\n }\n }\n }\n\n // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.\n logLikeMetro(this.terminal.log.bind(this.terminal), level, mode, ...event.data);\n return;\n }\n }\n return super._log(event);\n }\n\n // Used for testing\n _getElapsedTime(startTime: bigint): bigint {\n return process.hrtime.bigint() - startTime;\n }\n /**\n * Extends the bundle progress to include the current platform that we're bundling.\n *\n * @returns `iOS path/to/bundle.js ▓▓▓▓▓░░░░░░░░░░░ 36.6% (4790/7922)`\n */\n _getBundleStatusMessage(progress: BundleProgress, phase: BuildPhase): string {\n const env = getEnvironmentForBuildDetails(progress.bundleDetails);\n const platform = env || getPlatformTagForBuildDetails(progress.bundleDetails);\n const inProgress = phase === 'in_progress';\n\n let localPath: string;\n\n if (\n typeof progress.bundleDetails?.customTransformOptions?.dom === 'string' &&\n progress.bundleDetails.customTransformOptions.dom.includes(path.sep)\n ) {\n // Because we use a generated entry file for DOM components, we need to adjust the logging path so it\n // shows a unique path for each component.\n // Here, we take the relative import path and remove all the starting slashes.\n localPath = progress.bundleDetails.customTransformOptions.dom.replace(/^(\\.?\\.[\\\\/])+/, '');\n } else {\n const inputFile = progress.bundleDetails.entryFile;\n\n localPath = path.isAbsolute(inputFile)\n ? path.relative(this.projectRoot, inputFile)\n : inputFile;\n }\n\n if (!inProgress) {\n const status = phase === 'done' ? `Bundled ` : `Bundling failed `;\n const color = phase === 'done' ? chalk.green : chalk.red;\n\n const startTime = this._bundleTimers.get(progress.bundleDetails.buildID!);\n\n let time: string = '';\n\n if (startTime != null) {\n const elapsed: bigint = this._getElapsedTime(startTime);\n const micro = Number(elapsed) / 1000;\n const converted = Number(elapsed) / 1e6;\n // If the milliseconds are < 0.5 then it will display as 0, so we display in microseconds.\n if (converted <= 0.5) {\n const tenthFractionOfMicro = ((micro * 10) / 1000).toFixed(0);\n // Format as microseconds to nearest tenth\n time = chalk.cyan.bold(`0.${tenthFractionOfMicro}ms`);\n } else {\n time = chalk.dim(converted.toFixed(0) + 'ms');\n }\n }\n\n // iOS Bundled 150ms\n const plural = progress.totalFileCount === 1 ? '' : 's';\n return (\n color(platform + status) +\n time +\n chalk.reset.dim(` ${localPath} (${progress.totalFileCount} module${plural})`)\n );\n }\n\n const filledBar = Math.floor(progress.ratio * MAX_PROGRESS_BAR_CHAR_WIDTH);\n\n const _progress = inProgress\n ? chalk.green.bgGreen(DARK_BLOCK_CHAR.repeat(filledBar)) +\n chalk.bgWhite.white(LIGHT_BLOCK_CHAR.repeat(MAX_PROGRESS_BAR_CHAR_WIDTH - filledBar)) +\n chalk.bold(` ${(100 * progress.ratio).toFixed(1).padStart(4)}% `) +\n chalk.dim(\n `(${progress.transformedFileCount\n .toString()\n .padStart(progress.totalFileCount.toString().length)}/${progress.totalFileCount})`\n )\n : '';\n\n return (\n platform +\n chalk.reset.dim(`${path.dirname(localPath)}${path.sep}`) +\n chalk.bold(path.basename(localPath)) +\n ' ' +\n _progress\n );\n }\n\n _logInitializing(port: number, hasReducedPerformance: boolean): void {\n // Don't print a giant logo...\n this.terminal.log(chalk.dim('Starting Metro Bundler'));\n }\n\n shouldFilterClientLog(event: { type: 'client_log'; data: unknown[] }): boolean {\n return isAppRegistryStartupMessage(event.data);\n }\n\n shouldFilterBundleEvent(event: TerminalReportableEvent): boolean {\n return 'bundleDetails' in event && event.bundleDetails?.bundleType === 'map';\n }\n\n /** Print the cache clear message. */\n transformCacheReset(): void {\n logWarning(\n this.terminal,\n chalk`Bundler cache is empty, rebuilding {dim (this may take a minute)}`\n );\n }\n\n /** One of the first logs that will be printed */\n dependencyGraphLoading(hasReducedPerformance: boolean): void {\n // this.terminal.log('Dependency graph is loading...');\n if (hasReducedPerformance) {\n // Extends https://github.com/facebook/metro/blob/347b1d7ed87995d7951aaa9fd597c04b06013dac/packages/metro/src/lib/TerminalReporter.js#L283-L290\n this.terminal.log(\n chalk.red(\n [\n 'Metro is operating with reduced performance.',\n 'Please fix the problem above and restart Metro.',\n ].join('\\n')\n )\n );\n }\n }\n\n _logBundlingError(error: SnippetError): void {\n const moduleResolutionError = formatUsingNodeStandardLibraryError(this.projectRoot, error);\n const cause = error.cause as undefined | { _expoImportStack?: string };\n if (moduleResolutionError) {\n let message = maybeAppendCodeFrame(moduleResolutionError, error.message);\n if (cause?._expoImportStack) {\n message += `\\n\\n${cause?._expoImportStack}`;\n }\n return this.terminal.log(message);\n }\n if (cause?._expoImportStack) {\n error.message += `\\n\\n${cause._expoImportStack}`;\n }\n return super._logBundlingError(error);\n }\n}\n\n/**\n * Formats an error where the user is attempting to import a module from the Node.js standard library.\n * Exposed for testing.\n *\n * @param error\n * @returns error message or null if not a module resolution error\n */\nexport function formatUsingNodeStandardLibraryError(\n projectRoot: string,\n error: SnippetError\n): string | null {\n if (!error.message) {\n return null;\n }\n const { targetModuleName, originModulePath } = error;\n if (!targetModuleName || !originModulePath) {\n return null;\n }\n const relativePath = path.relative(projectRoot, originModulePath);\n\n const DOCS_PAGE_URL =\n 'https://docs.expo.dev/workflow/using-libraries/#using-third-party-libraries';\n\n if (isNodeStdLibraryModule(targetModuleName)) {\n if (originModulePath.includes('node_modules')) {\n return [\n `The package at \"${chalk.bold(\n relativePath\n )}\" attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n } else {\n return [\n `You attempted to import the Node standard library module \"${chalk.bold(\n targetModuleName\n )}\" from \"${chalk.bold(relativePath)}\".`,\n `It failed because the native React runtime does not include the Node standard library.`,\n learnMore(DOCS_PAGE_URL),\n ].join('\\n');\n }\n }\n return `Unable to resolve \"${targetModuleName}\" from \"${relativePath}\"`;\n}\n\nexport function isNodeStdLibraryModule(moduleName: string): boolean {\n return /^node:/.test(moduleName) || NODE_STDLIB_MODULES.includes(moduleName);\n}\n\n/** If the code frame can be found then append it to the existing message. */\nfunction maybeAppendCodeFrame(message: string, rawMessage: string): string {\n const codeFrame = stripMetroInfo(rawMessage);\n if (codeFrame) {\n message += '\\n' + codeFrame;\n }\n return message;\n}\n\n/**\n * Remove the Metro cache clearing steps if they exist.\n * In future versions we won't need this.\n * Returns the remaining code frame logs.\n */\nexport function stripMetroInfo(errorMessage: string): string | null {\n // Newer versions of Metro don't include the list.\n if (!errorMessage.includes('4. Remove the cache')) {\n return null;\n }\n const lines = errorMessage.split('\\n');\n const index = lines.findIndex((line) => line.includes('4. Remove the cache'));\n if (index === -1) {\n return null;\n }\n return lines.slice(index + 1).join('\\n');\n}\n\n/** @returns if the message matches the initial startup log */\nfunction isAppRegistryStartupMessage(body: any[]): boolean {\n return (\n body.length === 1 &&\n (/^Running application \"main\" with appParams:/.test(body[0]) ||\n /^Running \"main\" with \\{/.test(body[0]))\n );\n}\n\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getPlatformTagForBuildDetails(bundleDetails?: BundleDetails | null): string {\n const platform = bundleDetails?.platform ?? null;\n if (platform) {\n const formatted = { ios: 'iOS', android: 'Android', web: 'Web' }[platform] || platform;\n return `${chalk.bold(formatted)} `;\n }\n\n return '';\n}\n/** @returns platform specific tag for a `BundleDetails` object */\nfunction getEnvironmentForBuildDetails(bundleDetails?: BundleDetails | null): string {\n // Expo CLI will pass `customTransformOptions.environment = 'node'` when bundling for the server.\n const env = bundleDetails?.customTransformOptions?.environment ?? null;\n if (env === 'node') {\n return chalk.bold('λ') + ' ';\n } else if (env === 'react-server') {\n return chalk.bold(`RSC(${getPlatformTagForBuildDetails(bundleDetails).trim()})`) + ' ';\n }\n\n if (\n bundleDetails?.customTransformOptions?.dom &&\n typeof bundleDetails?.customTransformOptions?.dom === 'string'\n ) {\n return chalk.bold(`DOM`) + ' ';\n }\n\n return '';\n}\n"],"names":["MetroTerminalReporter","formatUsingNodeStandardLibraryError","isNodeStdLibraryModule","stripMetroInfo","debug","require","MAX_PROGRESS_BAR_CHAR_WIDTH","DARK_BLOCK_CHAR","LIGHT_BLOCK_CHAR","TerminalReporter","constructor","projectRoot","terminal","_log","event","type","data","message","match","env","EXPO_DEBUG","shouldFilterClientLog","level","mode","msg","join","includes","parsed","parseErrorStringToObject","maybeSymbolicateAndFormatReactErrorLogAsync","then","res","logLikeMetro","log","bind","catch","e","_getElapsedTime","startTime","process","hrtime","bigint","_getBundleStatusMessage","progress","phase","getEnvironmentForBuildDetails","bundleDetails","platform","getPlatformTagForBuildDetails","inProgress","localPath","customTransformOptions","dom","path","sep","replace","inputFile","entryFile","isAbsolute","relative","status","color","chalk","green","red","_bundleTimers","get","buildID","time","elapsed","micro","Number","converted","tenthFractionOfMicro","toFixed","cyan","bold","dim","plural","totalFileCount","reset","filledBar","Math","floor","ratio","_progress","bgGreen","repeat","bgWhite","white","padStart","transformedFileCount","toString","length","dirname","basename","_logInitializing","port","hasReducedPerformance","isAppRegistryStartupMessage","shouldFilterBundleEvent","bundleType","transformCacheReset","logWarning","dependencyGraphLoading","_logBundlingError","error","moduleResolutionError","cause","maybeAppendCodeFrame","_expoImportStack","targetModuleName","originModulePath","relativePath","DOCS_PAGE_URL","learnMore","moduleName","test","NODE_STDLIB_MODULES","rawMessage","codeFrame","errorMessage","lines","split","index","findIndex","line","slice","body","formatted","ios","android","web","environment","trim"],"mappings":"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"}
@@ -8,13 +8,6 @@ Object.defineProperty(exports, "createDebugMiddleware", {
8
8
  return createDebugMiddleware;
9
9
  }
10
10
  });
11
- function _chalk() {
12
- const data = /*#__PURE__*/ _interop_require_default(require("chalk"));
13
- _chalk = function() {
14
- return data;
15
- };
16
- return data;
17
- }
18
11
  function _ws() {
19
12
  const data = require("ws");
20
13
  _ws = function() {
@@ -23,16 +16,10 @@ function _ws() {
23
16
  return data;
24
17
  }
25
18
  const _createHandlersFactory = require("./createHandlersFactory");
26
- const _log = require("../../../../log");
27
19
  const _env = require("../../../../utils/env");
28
20
  const _NetworkResponse = require("./messageHandlers/NetworkResponse");
29
- function _interop_require_default(obj) {
30
- return obj && obj.__esModule ? obj : {
31
- default: obj
32
- };
33
- }
34
21
  const debug = require('debug')('expo:metro:debugging:middleware');
35
- function createDebugMiddleware(metroBundler) {
22
+ function createDebugMiddleware(metroBundler, reporter) {
36
23
  // Load the React Native debugging tools from project
37
24
  // TODO: check if this works with isolated modules
38
25
  const { createDevMiddleware } = require('@react-native/dev-middleware');
@@ -42,8 +29,14 @@ function createDebugMiddleware(metroBundler) {
42
29
  scheme: 'http',
43
30
  hostType: 'localhost'
44
31
  }),
45
- logger: createLogger(_chalk().default.bold('Debug:')),
32
+ logger: createLogger(reporter),
46
33
  unstable_customInspectorMessageHandler: (0, _createHandlersFactory.createHandlersFactory)(),
34
+ // TODO: Forward all events to the shared Metro log reporter. Do this when we have opinions on how all logs should be presented.
35
+ // unstable_eventReporter: {
36
+ // logEvent(event) {
37
+ // reporter.update(event);
38
+ // },
39
+ // },
47
40
  unstable_experiments: {
48
41
  // Enable the Network tab in React Native DevTools
49
42
  enableNetworkInspector: true,
@@ -59,13 +52,20 @@ function createDebugMiddleware(metroBundler) {
59
52
  debugWebsocketEndpoints: websocketEndpoints
60
53
  };
61
54
  }
62
- function createLogger(logPrefix) {
55
+ function createLogger(reporter) {
63
56
  return {
64
- info: (...args)=>_log.Log.log(logPrefix, ...args),
65
- warn: (...args)=>_log.Log.warn(logPrefix, ...args),
66
- error: (...args)=>_log.Log.error(logPrefix, ...args)
57
+ info: makeLogger(reporter, 'info'),
58
+ warn: makeLogger(reporter, 'warn'),
59
+ error: makeLogger(reporter, 'error')
67
60
  };
68
61
  }
62
+ function makeLogger(reporter, level) {
63
+ return (...data)=>reporter.update({
64
+ type: 'unstable_server_log',
65
+ level,
66
+ data
67
+ });
68
+ }
69
69
  /**
70
70
  * This adds a dedicated websocket connection that handles Network-related CDP events.
71
71
  * It's a temporary solution until Fusebox either implements the Network CDP domain,