@expo/cli 1.0.0-canary-20250404-3c3b5fd → 1.0.0-canary-20250701-6a945c5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -24
- package/build/bin/cli +1 -1
- package/build/metro-require/require.js +6 -4
- package/build/src/api/user/actions.js +25 -11
- package/build/src/api/user/actions.js.map +1 -1
- package/build/src/customize/templates.js +15 -1
- package/build/src/customize/templates.js.map +1 -1
- package/build/src/export/exportApp.js +26 -14
- package/build/src/export/exportApp.js.map +1 -1
- package/build/src/export/exportAsync.js +6 -0
- package/build/src/export/exportAsync.js.map +1 -1
- package/build/src/export/exportHermes.js +2 -2
- package/build/src/export/exportHermes.js.map +1 -1
- package/build/src/export/persistMetroAssets.js.map +1 -1
- package/build/src/install/checkPackages.js +22 -4
- package/build/src/install/checkPackages.js.map +1 -1
- package/build/src/install/index.js +3 -1
- package/build/src/install/index.js.map +1 -1
- package/build/src/install/resolveOptions.js +7 -2
- package/build/src/install/resolveOptions.js.map +1 -1
- package/build/src/install/utils/checkPackagesCompatibility.js +1 -1
- package/build/src/install/utils/checkPackagesCompatibility.js.map +1 -1
- package/build/src/lint/ESlintPrerequisite.js +32 -48
- package/build/src/lint/ESlintPrerequisite.js.map +1 -1
- package/build/src/lint/index.js +45 -47
- package/build/src/lint/index.js.map +1 -1
- package/build/src/lint/lintAsync.js +150 -4
- package/build/src/lint/lintAsync.js.map +1 -1
- package/build/src/lint/resolveOptions.js +115 -0
- package/build/src/lint/resolveOptions.js.map +1 -0
- package/build/src/prebuild/renameTemplateAppName.js +4 -1
- package/build/src/prebuild/renameTemplateAppName.js.map +1 -1
- package/build/src/prebuild/resolveTemplate.js +4 -4
- package/build/src/prebuild/resolveTemplate.js.map +1 -1
- package/build/src/prebuild/updatePackageJson.js +19 -9
- package/build/src/prebuild/updatePackageJson.js.map +1 -1
- package/build/src/run/android/resolveOptions.js +13 -1
- package/build/src/run/android/resolveOptions.js.map +1 -1
- package/build/src/run/android/runAndroidAsync.js +39 -17
- package/build/src/run/android/runAndroidAsync.js.map +1 -1
- package/build/src/run/ios/XcodeBuild.js +3 -3
- package/build/src/run/ios/XcodeBuild.js.map +1 -1
- package/build/src/run/ios/options/resolveOptions.js +13 -1
- package/build/src/run/ios/options/resolveOptions.js.map +1 -1
- package/build/src/run/ios/runIosAsync.js +38 -7
- package/build/src/run/ios/runIosAsync.js.map +1 -1
- package/build/src/start/doctor/SecurityBinPrerequisite.js +1 -1
- package/build/src/start/doctor/SecurityBinPrerequisite.js.map +1 -1
- package/build/src/start/doctor/apple/XcodePrerequisite.js +1 -1
- package/build/src/start/doctor/apple/XcodePrerequisite.js.map +1 -1
- package/build/src/start/doctor/dependencies/ensureDependenciesAsync.js +1 -1
- package/build/src/start/doctor/dependencies/ensureDependenciesAsync.js.map +1 -1
- package/build/src/start/doctor/dependencies/resolvePackages.js +1 -1
- package/build/src/start/doctor/dependencies/resolvePackages.js.map +1 -1
- package/build/src/start/doctor/ngrok/ExternalModule.js +1 -1
- package/build/src/start/doctor/ngrok/ExternalModule.js.map +1 -1
- package/build/src/start/index.js +1 -1
- package/build/src/start/index.js.map +1 -1
- package/build/src/start/platforms/PlatformManager.js +1 -1
- package/build/src/start/platforms/PlatformManager.js.map +1 -1
- package/build/src/start/platforms/android/AndroidPlatformManager.js +1 -1
- package/build/src/start/platforms/android/AndroidPlatformManager.js.map +1 -1
- package/build/src/start/platforms/android/getDevices.js +1 -1
- package/build/src/start/platforms/android/getDevices.js.map +1 -1
- package/build/src/start/platforms/ios/AppleDeviceManager.js +1 -1
- package/build/src/start/platforms/ios/AppleDeviceManager.js.map +1 -1
- package/build/src/start/platforms/ios/xcrun.js +1 -1
- package/build/src/start/platforms/ios/xcrun.js.map +1 -1
- package/build/src/start/project/dotExpo.js +5 -0
- package/build/src/start/project/dotExpo.js.map +1 -1
- package/build/src/start/resolveOptions.js +3 -0
- package/build/src/start/resolveOptions.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +38 -26
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/MetroTerminalReporter.js +29 -2
- package/build/src/start/server/metro/MetroTerminalReporter.js.map +1 -1
- package/build/src/start/server/metro/createExpoFallbackResolver.js +6 -4
- package/build/src/start/server/metro/createExpoFallbackResolver.js.map +1 -1
- package/build/src/start/server/metro/createJResolver.js +2 -2
- package/build/src/start/server/metro/createJResolver.js.map +1 -1
- package/build/src/start/server/metro/createServerComponentsMiddleware.js +16 -5
- package/build/src/start/server/metro/createServerComponentsMiddleware.js.map +1 -1
- package/build/src/start/server/metro/debugging/createDebugMiddleware.js +19 -19
- package/build/src/start/server/metro/debugging/createDebugMiddleware.js.map +1 -1
- package/build/src/start/server/metro/externals.js +1 -1
- package/build/src/start/server/metro/externals.js.map +1 -1
- package/build/src/start/server/metro/instantiateMetro.js +13 -8
- package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
- package/build/src/start/server/metro/log-box/LogBoxSymbolication.js +21 -2
- package/build/src/start/server/metro/log-box/LogBoxSymbolication.js.map +1 -1
- package/build/src/start/server/metro/log-box/formatProjectFilePath.js +15 -12
- package/build/src/start/server/metro/log-box/formatProjectFilePath.js.map +1 -1
- package/build/src/start/server/metro/metroErrorInterface.js +19 -8
- package/build/src/start/server/metro/metroErrorInterface.js.map +1 -1
- package/build/src/start/server/metro/runServer-fork.js +1 -1
- package/build/src/start/server/metro/runServer-fork.js.map +1 -1
- package/build/src/start/server/metro/withMetroMultiPlatform.js +7 -12
- package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
- package/build/src/start/server/middleware/CorsMiddleware.js +1 -1
- package/build/src/start/server/middleware/CorsMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/ManifestMiddleware.js +4 -8
- package/build/src/start/server/middleware/ManifestMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/inspector/JsInspector.js +2 -25
- package/build/src/start/server/middleware/inspector/JsInspector.js.map +1 -1
- package/build/src/start/server/middleware/metroOptions.js +2 -26
- package/build/src/start/server/middleware/metroOptions.js.map +1 -1
- package/build/src/utils/build-cache-providers/helpers.js +61 -0
- package/build/src/utils/build-cache-providers/helpers.js.map +1 -0
- package/build/src/utils/build-cache-providers/index.js +283 -0
- package/build/src/utils/build-cache-providers/index.js.map +1 -0
- package/build/src/utils/codesigning.js +14 -2
- package/build/src/utils/codesigning.js.map +1 -1
- package/build/src/utils/exit.js +0 -1
- package/build/src/utils/exit.js.map +1 -1
- package/build/src/utils/ip.js +7 -104
- package/build/src/utils/ip.js.map +1 -1
- package/build/src/utils/modifyConfigAsync.js +1 -1
- package/build/src/utils/modifyConfigAsync.js.map +1 -1
- package/build/src/utils/resolveArgs.js +8 -0
- package/build/src/utils/resolveArgs.js.map +1 -1
- package/build/src/utils/scheme.js +1 -1
- package/build/src/utils/scheme.js.map +1 -1
- package/build/src/utils/telemetry/clients/FetchClient.js +2 -2
- package/build/src/utils/telemetry/clients/FetchClient.js.map +1 -1
- package/build/src/utils/telemetry/utils/context.js +1 -1
- package/build/src/utils/tsconfig/evaluateTsConfig.js +7 -2
- package/build/src/utils/tsconfig/evaluateTsConfig.js.map +1 -1
- package/build/src/utils/variadic.js +63 -6
- package/build/src/utils/variadic.js.map +1 -1
- package/package.json +20 -20
- package/static/canary/react-is/cjs/react-is.development.js +118 -185
- package/static/canary/react-is/cjs/react-is.production.js +2 -2
- package/static/canary/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js +16582 -26565
- package/static/canary/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js +3495 -3357
- package/static/canary/react-native/Libraries/Renderer/implementations/ReactFabric-profiling.js +3929 -3801
- package/static/canary/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +16869 -27032
- package/static/canary/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +3535 -3428
- package/static/canary/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +4198 -4095
- package/static/canary/scheduler/cjs/scheduler-unstable_mock.development.js +387 -684
- package/static/canary/scheduler/cjs/scheduler-unstable_mock.production.js +0 -9
- package/static/canary/scheduler/cjs/scheduler-unstable_post_task.development.js +137 -195
- package/static/canary/scheduler/cjs/scheduler-unstable_post_task.production.js +0 -5
- package/static/canary/scheduler/cjs/scheduler.development.js +339 -600
- package/static/canary/scheduler/cjs/scheduler.native.development.js +324 -512
- package/static/canary/scheduler/cjs/scheduler.native.production.js +6 -5
- package/static/canary/scheduler/cjs/scheduler.production.js +16 -17
- package/static/canary-full/react/cjs/react-compiler-runtime.development.js +13 -68
- package/static/canary-full/react/cjs/react-jsx-dev-runtime.development.js +317 -1251
- package/static/canary-full/react/cjs/react-jsx-dev-runtime.react-server.development.js +353 -1286
- package/static/canary-full/react/cjs/react-jsx-runtime.development.js +326 -1279
- package/static/canary-full/react/cjs/react-jsx-runtime.react-server.development.js +353 -1286
- package/static/canary-full/react/cjs/react.development.js +1204 -2771
- package/static/canary-full/react/cjs/react.production.js +25 -20
- package/static/canary-full/react/cjs/react.react-server.development.js +783 -2162
- package/static/canary-full/react/cjs/react.react-server.production.js +13 -63
- package/static/canary-full/react/package.json +1 -1
- package/static/canary-full/react-dom/cjs/react-dom-client.development.js +24847 -37099
- package/static/canary-full/react-dom/cjs/react-dom-client.production.js +8261 -7475
- package/static/canary-full/react-dom/cjs/react-dom-profiling.development.js +25252 -37571
- package/static/canary-full/react-dom/cjs/react-dom-profiling.profiling.js +9442 -8662
- package/static/canary-full/react-dom/cjs/react-dom-server-legacy.browser.development.js +8944 -11568
- package/static/canary-full/react-dom/cjs/react-dom-server-legacy.browser.production.js +1378 -944
- package/static/canary-full/react-dom/cjs/react-dom-server-legacy.node.development.js +8944 -11568
- package/static/canary-full/react-dom/cjs/react-dom-server-legacy.node.production.js +1386 -954
- package/static/canary-full/react-dom/cjs/react-dom-server.browser.development.js +9344 -11600
- package/static/canary-full/react-dom/cjs/react-dom-server.browser.production.js +1545 -954
- package/static/canary-full/react-dom/cjs/react-dom-server.bun.development.js +8286 -11064
- package/static/canary-full/react-dom/cjs/react-dom-server.bun.production.js +1437 -976
- package/static/canary-full/react-dom/cjs/react-dom-server.edge.development.js +9356 -11609
- package/static/canary-full/react-dom/cjs/react-dom-server.edge.production.js +1542 -970
- package/static/canary-full/react-dom/cjs/react-dom-server.node.development.js +9227 -11571
- package/static/canary-full/react-dom/cjs/react-dom-server.node.production.js +1787 -1183
- package/static/canary-full/react-dom/cjs/react-dom-test-utils.development.js +13 -59
- package/static/canary-full/react-dom/cjs/react-dom.development.js +402 -604
- package/static/canary-full/react-dom/cjs/react-dom.production.js +4 -3
- package/static/canary-full/react-dom/cjs/react-dom.react-server.development.js +322 -382
- package/static/canary-full/react-dom/cjs/react-dom.react-server.production.js +6 -7
- package/static/canary-full/react-dom/package.json +5 -5
- package/static/canary-full/react-dom/static.browser.js +1 -0
- package/static/canary-full/react-dom/static.edge.js +1 -0
- package/static/canary-full/react-dom/static.node.js +1 -0
- package/static/template/eslint.config.js +10 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/export/exportHermes.ts"],"sourcesContent":["import { ExpoConfig, getConfigFilePaths, Platform } from '@expo/config';\nimport JsonFile from '@expo/json-file';\nimport fs from 'fs';\nimport path from 'path';\n\nexport async function assertEngineMismatchAsync(\n projectRoot: string,\n exp: Pick<ExpoConfig, 'ios' | 'android' | 'jsEngine'>,\n platform: Platform\n) {\n const isHermesManaged = isEnableHermesManaged(exp, platform);\n const paths = getConfigFilePaths(projectRoot);\n const configFilePath = paths.dynamicConfigPath ?? paths.staticConfigPath ?? 'app.json';\n await maybeThrowFromInconsistentEngineAsync(\n projectRoot,\n configFilePath,\n platform,\n isHermesManaged\n );\n}\n\nexport function isEnableHermesManaged(\n expoConfig: Partial<Pick<ExpoConfig, 'ios' | 'android' | 'jsEngine'>>,\n platform: string\n): boolean {\n switch (platform) {\n case 'android': {\n return (expoConfig.android?.jsEngine ?? expoConfig.jsEngine) !== 'jsc';\n }\n case 'ios': {\n return (expoConfig.ios?.jsEngine ?? expoConfig.jsEngine) !== 'jsc';\n }\n default:\n return false;\n }\n}\n\nexport function parseGradleProperties(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (let line of content.split('\\n')) {\n line = line.trim();\n if (!line || line.startsWith('#')) {\n continue;\n }\n\n const sepIndex = line.indexOf('=');\n const key = line.slice(0, sepIndex);\n const value = line.slice(sepIndex + 1);\n result[key] = value;\n }\n return result;\n}\n\nexport async function maybeThrowFromInconsistentEngineAsync(\n projectRoot: string,\n configFilePath: string,\n platform: string,\n isHermesManaged: boolean\n): Promise<void> {\n const configFileName = path.basename(configFilePath);\n if (\n platform === 'android' &&\n (await maybeInconsistentEngineAndroidAsync(projectRoot, isHermesManaged))\n ) {\n throw new Error(\n `JavaScript engine configuration is inconsistent between ${configFileName} and Android native project.\\n` +\n `In ${configFileName}: Hermes is ${isHermesManaged ? 'enabled' : 'not enabled'}\\n` +\n `In Android native project: Hermes is ${isHermesManaged ? 'not enabled' : 'enabled'}\\n` +\n `Please check the following files for inconsistencies:\\n` +\n ` - ${configFilePath}\\n` +\n ` - ${path.join(projectRoot, 'android', 'gradle.properties')}\\n` +\n ` - ${path.join(projectRoot, 'android', 'app', 'build.gradle')}\\n` +\n 'Learn more: https://expo.fyi/hermes-android-config'\n );\n }\n\n if (platform === 'ios' && (await maybeInconsistentEngineIosAsync(projectRoot, isHermesManaged))) {\n throw new Error(\n `JavaScript engine configuration is inconsistent between ${configFileName} and iOS native project.\\n` +\n `In ${configFileName}: Hermes is ${isHermesManaged ? 'enabled' : 'not enabled'}\\n` +\n `In iOS native project: Hermes is ${isHermesManaged ? 'not enabled' : 'enabled'}\\n` +\n `Please check the following files for inconsistencies:\\n` +\n ` - ${configFilePath}\\n` +\n ` - ${path.join(projectRoot, 'ios', 'Podfile')}\\n` +\n ` - ${path.join(projectRoot, 'ios', 'Podfile.properties.json')}\\n` +\n 'Learn more: https://expo.fyi/hermes-ios-config'\n );\n }\n}\n\nexport async function maybeInconsistentEngineAndroidAsync(\n projectRoot: string,\n isHermesManaged: boolean\n): Promise<boolean> {\n // Trying best to check android native project if by chance to be consistent between app config\n\n // Check gradle.properties from prebuild template\n const gradlePropertiesPath = path.join(projectRoot, 'android', 'gradle.properties');\n if (fs.existsSync(gradlePropertiesPath)) {\n const props = parseGradleProperties(await fs.promises.readFile(gradlePropertiesPath, 'utf8'));\n const isHermesBare = props['hermesEnabled'] === 'true';\n if (isHermesManaged !== isHermesBare) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function isHermesPossiblyEnabled(projectRoot: string): boolean | null {\n // Trying best to check ios native project if by chance to be consistent between app config\n\n // Check ios/Podfile for \":hermes_enabled => true\"\n const podfilePath = path.join(projectRoot, 'ios', 'Podfile');\n if (fs.existsSync(podfilePath)) {\n const content = fs.readFileSync(podfilePath, 'utf8');\n const isPropsReference =\n content.search(\n /^\\s*:hermes_enabled\\s*=>\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*nil\\s*\\|\\|\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*'hermes',?/m\n ) >= 0;\n const isHermesBare = content.search(/^\\s*:hermes_enabled\\s*=>\\s*true,?\\s+/m) >= 0;\n if (!isPropsReference && isHermesBare) {\n return true;\n }\n }\n\n // Check Podfile.properties.json from prebuild template\n const podfilePropertiesPath = path.join(projectRoot, 'ios', 'Podfile.properties.json');\n if (fs.existsSync(podfilePropertiesPath)) {\n try {\n const props = JsonFile.read(podfilePropertiesPath);\n return props['expo.jsEngine'] === 'hermes';\n } catch {\n // ignore\n }\n }\n\n return null;\n}\n\nexport async function maybeInconsistentEngineIosAsync(\n projectRoot: string,\n isHermesManaged: boolean\n): Promise<boolean> {\n // Trying best to check ios native project if by chance to be consistent between app config\n\n // Check ios/Podfile for \":hermes_enabled => true\"\n const podfilePath = path.join(projectRoot, 'ios', 'Podfile');\n if (fs.existsSync(podfilePath)) {\n const content = await fs.promises.readFile(podfilePath, 'utf8');\n const isPropsReference =\n content.search(\n /^\\s*:hermes_enabled\\s*=>\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*nil\\s*\\|\\|\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*'hermes',?/m\n ) >= 0;\n const isHermesBare = content.search(/^\\s*:hermes_enabled\\s*=>\\s*true,?\\s+/m) >= 0;\n if (!isPropsReference && isHermesManaged !== isHermesBare) {\n return true;\n }\n }\n\n // Check Podfile.properties.json from prebuild template\n const podfilePropertiesPath = path.join(projectRoot, 'ios', 'Podfile.properties.json');\n if (fs.existsSync(podfilePropertiesPath)) {\n const props = await parsePodfilePropertiesAsync(podfilePropertiesPath);\n const isHermesBare = props['expo.jsEngine'] === 'hermes';\n if (isHermesManaged !== isHermesBare) {\n return true;\n }\n }\n\n return false;\n}\n\n// https://github.com/facebook/hermes/blob/release-v0.5/include/hermes/BCGen/HBC/BytecodeFileFormat.h#L24-L25\nconst HERMES_MAGIC_HEADER = 'c61fbc03c103191f';\n\nexport async function isHermesBytecodeBundleAsync(file: string): Promise<boolean> {\n const header = await readHermesHeaderAsync(file);\n return header.subarray(0, 8).toString('hex') === HERMES_MAGIC_HEADER;\n}\n\nexport async function getHermesBytecodeBundleVersionAsync(file: string): Promise<number> {\n const header = await readHermesHeaderAsync(file);\n if (header.subarray(0, 8).toString('hex') !== HERMES_MAGIC_HEADER) {\n throw new Error('Invalid hermes bundle file');\n }\n return header.readUInt32LE(8);\n}\n\nasync function readHermesHeaderAsync(file: string): Promise<Buffer> {\n const fd = await fs.promises.open(file, 'r');\n const buffer = Buffer.alloc(12);\n await fd.read(buffer, 0, 12, null);\n await fd.close();\n return buffer;\n}\n\nasync function parsePodfilePropertiesAsync(\n podfilePropertiesPath: string\n): Promise<Record<string, string>> {\n try {\n return JSON.parse(await fs.promises.readFile(podfilePropertiesPath, 'utf8'));\n } catch {\n return {};\n }\n}\n\nexport function isAndroidUsingHermes(projectRoot: string) {\n // Check gradle.properties from prebuild template\n const gradlePropertiesPath = path.join(projectRoot, 'android', 'gradle.properties');\n if (fs.existsSync(gradlePropertiesPath)) {\n const props = parseGradleProperties(fs.readFileSync(gradlePropertiesPath, 'utf8'));\n return props['hermesEnabled'] === 'true';\n }\n\n // Assume Hermes is used by default.\n return true;\n}\n\nexport function isIosUsingHermes(projectRoot: string) {\n // If nullish, then assume Hermes is used.\n return isHermesPossiblyEnabled(projectRoot) !== false;\n}\n"],"names":["assertEngineMismatchAsync","getHermesBytecodeBundleVersionAsync","isAndroidUsingHermes","isEnableHermesManaged","isHermesBytecodeBundleAsync","isHermesPossiblyEnabled","isIosUsingHermes","maybeInconsistentEngineAndroidAsync","maybeInconsistentEngineIosAsync","maybeThrowFromInconsistentEngineAsync","parseGradleProperties","projectRoot","exp","platform","isHermesManaged","paths","getConfigFilePaths","configFilePath","dynamicConfigPath","staticConfigPath","expoConfig","android","jsEngine","ios","content","result","line","split","trim","startsWith","sepIndex","indexOf","key","slice","value","configFileName","path","basename","Error","join","gradlePropertiesPath","fs","existsSync","props","promises","readFile","isHermesBare","podfilePath","readFileSync","isPropsReference","search","podfilePropertiesPath","JsonFile","read","parsePodfilePropertiesAsync","HERMES_MAGIC_HEADER","file","header","readHermesHeaderAsync","subarray","toString","readUInt32LE","fd","open","buffer","Buffer","alloc","close","JSON","parse"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/export/exportHermes.ts"],"sourcesContent":["import { ExpoConfig, getConfigFilePaths, Platform } from '@expo/config';\nimport JsonFile from '@expo/json-file';\nimport fs from 'fs';\nimport path from 'path';\n\nexport async function assertEngineMismatchAsync(\n projectRoot: string,\n exp: Pick<ExpoConfig, 'ios' | 'android' | 'jsEngine'>,\n platform: Platform\n) {\n const isHermesManaged = isEnableHermesManaged(exp, platform);\n const paths = getConfigFilePaths(projectRoot);\n const configFilePath = paths.dynamicConfigPath ?? paths.staticConfigPath ?? 'app.json';\n await maybeThrowFromInconsistentEngineAsync(\n projectRoot,\n configFilePath,\n platform,\n isHermesManaged\n );\n}\n\nexport function isEnableHermesManaged(\n expoConfig: Partial<Pick<ExpoConfig, 'ios' | 'android' | 'jsEngine'>>,\n platform: string\n): boolean {\n switch (platform) {\n case 'android': {\n return (expoConfig.android?.jsEngine ?? expoConfig.jsEngine) !== 'jsc';\n }\n case 'ios': {\n return (expoConfig.ios?.jsEngine ?? expoConfig.jsEngine) !== 'jsc';\n }\n default:\n return false;\n }\n}\n\nexport function parseGradleProperties(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (let line of content.split('\\n')) {\n line = line.trim();\n if (!line || line.startsWith('#')) {\n continue;\n }\n\n const sepIndex = line.indexOf('=');\n const key = line.slice(0, sepIndex);\n const value = line.slice(sepIndex + 1);\n result[key] = value;\n }\n return result;\n}\n\nexport async function maybeThrowFromInconsistentEngineAsync(\n projectRoot: string,\n configFilePath: string,\n platform: string,\n isHermesManaged: boolean\n): Promise<void> {\n const configFileName = path.basename(configFilePath);\n if (\n platform === 'android' &&\n (await maybeInconsistentEngineAndroidAsync(projectRoot, isHermesManaged))\n ) {\n throw new Error(\n `JavaScript engine configuration is inconsistent between ${configFileName} and Android native project.\\n` +\n `In ${configFileName}: Hermes is ${isHermesManaged ? 'enabled' : 'not enabled'}\\n` +\n `In Android native project: Hermes is ${isHermesManaged ? 'not enabled' : 'enabled'}\\n` +\n `Check the following files for inconsistencies:\\n` +\n ` - ${configFilePath}\\n` +\n ` - ${path.join(projectRoot, 'android', 'gradle.properties')}\\n` +\n ` - ${path.join(projectRoot, 'android', 'app', 'build.gradle')}\\n` +\n 'Learn more: https://expo.fyi/hermes-android-config'\n );\n }\n\n if (platform === 'ios' && (await maybeInconsistentEngineIosAsync(projectRoot, isHermesManaged))) {\n throw new Error(\n `JavaScript engine configuration is inconsistent between ${configFileName} and iOS native project.\\n` +\n `In ${configFileName}: Hermes is ${isHermesManaged ? 'enabled' : 'not enabled'}\\n` +\n `In iOS native project: Hermes is ${isHermesManaged ? 'not enabled' : 'enabled'}\\n` +\n `Check the following files for inconsistencies:\\n` +\n ` - ${configFilePath}\\n` +\n ` - ${path.join(projectRoot, 'ios', 'Podfile')}\\n` +\n ` - ${path.join(projectRoot, 'ios', 'Podfile.properties.json')}\\n` +\n 'Learn more: https://expo.fyi/hermes-ios-config'\n );\n }\n}\n\nexport async function maybeInconsistentEngineAndroidAsync(\n projectRoot: string,\n isHermesManaged: boolean\n): Promise<boolean> {\n // Trying best to check android native project if by chance to be consistent between app config\n\n // Check gradle.properties from prebuild template\n const gradlePropertiesPath = path.join(projectRoot, 'android', 'gradle.properties');\n if (fs.existsSync(gradlePropertiesPath)) {\n const props = parseGradleProperties(await fs.promises.readFile(gradlePropertiesPath, 'utf8'));\n const isHermesBare = props['hermesEnabled'] === 'true';\n if (isHermesManaged !== isHermesBare) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function isHermesPossiblyEnabled(projectRoot: string): boolean | null {\n // Trying best to check ios native project if by chance to be consistent between app config\n\n // Check ios/Podfile for \":hermes_enabled => true\"\n const podfilePath = path.join(projectRoot, 'ios', 'Podfile');\n if (fs.existsSync(podfilePath)) {\n const content = fs.readFileSync(podfilePath, 'utf8');\n const isPropsReference =\n content.search(\n /^\\s*:hermes_enabled\\s*=>\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*nil\\s*\\|\\|\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*'hermes',?/m\n ) >= 0;\n const isHermesBare = content.search(/^\\s*:hermes_enabled\\s*=>\\s*true,?\\s+/m) >= 0;\n if (!isPropsReference && isHermesBare) {\n return true;\n }\n }\n\n // Check Podfile.properties.json from prebuild template\n const podfilePropertiesPath = path.join(projectRoot, 'ios', 'Podfile.properties.json');\n if (fs.existsSync(podfilePropertiesPath)) {\n try {\n const props = JsonFile.read(podfilePropertiesPath);\n return props['expo.jsEngine'] === 'hermes';\n } catch {\n // ignore\n }\n }\n\n return null;\n}\n\nexport async function maybeInconsistentEngineIosAsync(\n projectRoot: string,\n isHermesManaged: boolean\n): Promise<boolean> {\n // Trying best to check ios native project if by chance to be consistent between app config\n\n // Check ios/Podfile for \":hermes_enabled => true\"\n const podfilePath = path.join(projectRoot, 'ios', 'Podfile');\n if (fs.existsSync(podfilePath)) {\n const content = await fs.promises.readFile(podfilePath, 'utf8');\n const isPropsReference =\n content.search(\n /^\\s*:hermes_enabled\\s*=>\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*nil\\s*\\|\\|\\s*podfile_properties\\['expo.jsEngine'\\]\\s*==\\s*'hermes',?/m\n ) >= 0;\n const isHermesBare = content.search(/^\\s*:hermes_enabled\\s*=>\\s*true,?\\s+/m) >= 0;\n if (!isPropsReference && isHermesManaged !== isHermesBare) {\n return true;\n }\n }\n\n // Check Podfile.properties.json from prebuild template\n const podfilePropertiesPath = path.join(projectRoot, 'ios', 'Podfile.properties.json');\n if (fs.existsSync(podfilePropertiesPath)) {\n const props = await parsePodfilePropertiesAsync(podfilePropertiesPath);\n const isHermesBare = props['expo.jsEngine'] === 'hermes';\n if (isHermesManaged !== isHermesBare) {\n return true;\n }\n }\n\n return false;\n}\n\n// https://github.com/facebook/hermes/blob/release-v0.5/include/hermes/BCGen/HBC/BytecodeFileFormat.h#L24-L25\nconst HERMES_MAGIC_HEADER = 'c61fbc03c103191f';\n\nexport async function isHermesBytecodeBundleAsync(file: string): Promise<boolean> {\n const header = await readHermesHeaderAsync(file);\n return header.subarray(0, 8).toString('hex') === HERMES_MAGIC_HEADER;\n}\n\nexport async function getHermesBytecodeBundleVersionAsync(file: string): Promise<number> {\n const header = await readHermesHeaderAsync(file);\n if (header.subarray(0, 8).toString('hex') !== HERMES_MAGIC_HEADER) {\n throw new Error('Invalid hermes bundle file');\n }\n return header.readUInt32LE(8);\n}\n\nasync function readHermesHeaderAsync(file: string): Promise<Buffer> {\n const fd = await fs.promises.open(file, 'r');\n const buffer = Buffer.alloc(12);\n await fd.read(buffer, 0, 12, null);\n await fd.close();\n return buffer;\n}\n\nasync function parsePodfilePropertiesAsync(\n podfilePropertiesPath: string\n): Promise<Record<string, string>> {\n try {\n return JSON.parse(await fs.promises.readFile(podfilePropertiesPath, 'utf8'));\n } catch {\n return {};\n }\n}\n\nexport function isAndroidUsingHermes(projectRoot: string) {\n // Check gradle.properties from prebuild template\n const gradlePropertiesPath = path.join(projectRoot, 'android', 'gradle.properties');\n if (fs.existsSync(gradlePropertiesPath)) {\n const props = parseGradleProperties(fs.readFileSync(gradlePropertiesPath, 'utf8'));\n return props['hermesEnabled'] === 'true';\n }\n\n // Assume Hermes is used by default.\n return true;\n}\n\nexport function isIosUsingHermes(projectRoot: string) {\n // If nullish, then assume Hermes is used.\n return isHermesPossiblyEnabled(projectRoot) !== false;\n}\n"],"names":["assertEngineMismatchAsync","getHermesBytecodeBundleVersionAsync","isAndroidUsingHermes","isEnableHermesManaged","isHermesBytecodeBundleAsync","isHermesPossiblyEnabled","isIosUsingHermes","maybeInconsistentEngineAndroidAsync","maybeInconsistentEngineIosAsync","maybeThrowFromInconsistentEngineAsync","parseGradleProperties","projectRoot","exp","platform","isHermesManaged","paths","getConfigFilePaths","configFilePath","dynamicConfigPath","staticConfigPath","expoConfig","android","jsEngine","ios","content","result","line","split","trim","startsWith","sepIndex","indexOf","key","slice","value","configFileName","path","basename","Error","join","gradlePropertiesPath","fs","existsSync","props","promises","readFile","isHermesBare","podfilePath","readFileSync","isPropsReference","search","podfilePropertiesPath","JsonFile","read","parsePodfilePropertiesAsync","HERMES_MAGIC_HEADER","file","header","readHermesHeaderAsync","subarray","toString","readUInt32LE","fd","open","buffer","Buffer","alloc","close","JSON","parse"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/export/persistMetroAssets.ts"],"sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * Based on the community asset persisting for Metro but with base path and web support:\n * https://github.com/facebook/react-native/blob/d6e0bc714ad4d215ede4949d3c4f44af6dea5dd3/packages/community-cli-plugin/src/commands/bundle/saveAssets.js#L1\n */\nimport fs from 'fs';\nimport type { AssetData } from 'metro';\nimport path from 'path';\n\nimport { drawableFileTypes, getAssetLocalPath } from './metroAssetLocalPath';\nimport { ExportAssetMap } from './saveAssets';\nimport { Log } from '../log';\n\nfunction cleanAssetCatalog(catalogDir: string): void {\n const files = fs.readdirSync(catalogDir).filter((file) => file.endsWith('.imageset'));\n for (const file of files) {\n fs.rmSync(path.join(catalogDir, file));\n }\n}\n\nexport async function persistMetroAssetsAsync(\n projectRoot: string,\n assets: readonly AssetData[],\n {\n platform,\n outputDirectory,\n baseUrl,\n iosAssetCatalogDirectory,\n files,\n }: {\n platform: string;\n outputDirectory: string;\n baseUrl?: string;\n iosAssetCatalogDirectory?: string;\n files?: ExportAssetMap;\n }\n) {\n if (outputDirectory == null) {\n Log.warn('Assets destination folder is not set, skipping...');\n return;\n }\n\n // For iOS, we need to ensure that the outputDirectory exists.\n // The bundle code and images build phase script always tries to access this folder\n if (platform === 'ios' && !fs.existsSync(outputDirectory)) {\n fs.mkdirSync(outputDirectory, { recursive: true });\n }\n\n let assetsToCopy: AssetData[] = [];\n\n // TODO: Use `files` as below to defer writing files\n if (platform === 'ios' && iosAssetCatalogDirectory != null) {\n // Use iOS Asset Catalog for images. This will allow Apple app thinning to\n // remove unused scales from the optimized bundle.\n const catalogDir = path.join(iosAssetCatalogDirectory, 'RNAssets.xcassets');\n if (!fs.existsSync(catalogDir)) {\n Log.error(\n `Could not find asset catalog 'RNAssets.xcassets' in ${iosAssetCatalogDirectory}. Make sure to create it if it does not exist.`\n );\n return;\n }\n\n Log.log('Adding images to asset catalog', catalogDir);\n cleanAssetCatalog(catalogDir);\n for (const asset of assets) {\n if (isCatalogAsset(asset)) {\n const imageSet = getImageSet(\n catalogDir,\n asset,\n filterPlatformAssetScales(platform, asset.scales)\n );\n writeImageSet(imageSet);\n } else {\n assetsToCopy.push(asset);\n }\n }\n Log.log('Done adding images to asset catalog');\n } else {\n assetsToCopy = [...assets];\n }\n if (platform === 'android') {\n await createKeepFileAsync(assetsToCopy, outputDirectory);\n }\n\n const batches: Record<string, string> = {};\n\n for (const asset of assetsToCopy) {\n const validScales = new Set(filterPlatformAssetScales(platform, asset.scales));\n for (let idx = 0; idx < asset.scales.length; idx++) {\n const scale = asset.scales[idx];\n if (validScales.has(scale)) {\n const src = asset.files[idx];\n const dest = getAssetLocalPath(asset, { platform, scale, baseUrl });\n if (files) {\n const data = await fs.promises.readFile(src);\n files.set(dest, {\n contents: data,\n assetId: getAssetIdForLogGrouping(projectRoot, asset),\n targetDomain: platform === 'web' ? 'client' : undefined,\n });\n } else {\n batches[src] = path.join(outputDirectory, dest);\n }\n }\n }\n }\n\n if (!files) {\n await copyInBatchesAsync(batches);\n }\n}\n\nexport async function createKeepFileAsync(\n assets: AssetData[],\n outputDirectory: string\n): Promise<void> {\n if (!assets.length) {\n return;\n }\n const assetsList = [];\n for (const asset of assets) {\n const prefix = drawableFileTypes.has(asset.type) ? 'drawable' : 'raw';\n assetsList.push(`@${prefix}/${getResourceIdentifier(asset)}`);\n }\n const keepPath = path.join(outputDirectory, 'raw/keep.xml');\n const content = `<resources xmlns:tools=\"http://schemas.android.com/tools\" tools:keep=\"${assetsList.join(',')}\" />`;\n await fs.promises.mkdir(path.dirname(keepPath), { recursive: true });\n await fs.promises.writeFile(keepPath, content);\n}\n\nexport function getAssetIdForLogGrouping(\n projectRoot: string,\n asset: Partial<Pick<AssetData, 'fileSystemLocation' | 'name' | 'type'>>\n): string | undefined {\n return 'fileSystemLocation' in asset && asset.fileSystemLocation != null && asset.name != null\n ? path.relative(projectRoot, path.join(asset.fileSystemLocation, asset.name)) +\n (asset.type ? '.' + asset.type : '')\n : undefined;\n}\n\nfunction writeImageSet(imageSet: ImageSet): void {\n fs.mkdirSync(imageSet.baseUrl, { recursive: true });\n\n for (const file of imageSet.files) {\n const dest = path.join(imageSet.baseUrl, file.name);\n fs.copyFileSync(file.src, dest);\n }\n\n fs.writeFileSync(\n path.join(imageSet.baseUrl, 'Contents.json'),\n JSON.stringify({\n images: imageSet.files.map((file) => ({\n filename: file.name,\n idiom: 'universal',\n scale: `${file.scale}x`,\n })),\n info: {\n author: 'expo',\n version: 1,\n },\n })\n );\n}\n\nfunction isCatalogAsset(asset: Pick<AssetData, 'type'>): boolean {\n return asset.type === 'png' || asset.type === 'jpg' || asset.type === 'jpeg';\n}\n\ntype ImageSet = {\n baseUrl: string;\n files: { name: string; src: string; scale: number }[];\n};\n\nfunction getImageSet(\n catalogDir: string,\n asset: Pick<AssetData, 'httpServerLocation' | 'name' | 'type' | 'files'>,\n scales: number[]\n): ImageSet {\n const fileName = getResourceIdentifier(asset);\n return {\n baseUrl: path.join(catalogDir, `${fileName}.imageset`),\n files: scales.map((scale, idx) => {\n const suffix = scale === 1 ? '' : `@${scale}x`;\n return {\n name: `${fileName + suffix}.${asset.type}`,\n scale,\n src: asset.files[idx],\n };\n }),\n };\n}\n\nexport function copyInBatchesAsync(filesToCopy: Record<string, string>) {\n const queue = Object.keys(filesToCopy);\n if (queue.length === 0) {\n return;\n }\n\n Log.log(`Copying ${queue.length} asset files`);\n return new Promise<void>((resolve, reject) => {\n const copyNext = (error?: NodeJS.ErrnoException) => {\n if (error) {\n return reject(error);\n }\n if (queue.length) {\n // queue.length === 0 is checked in previous branch, so this is string\n const src = queue.shift() as string;\n const dest = filesToCopy[src];\n copy(src, dest, copyNext);\n } else {\n resolve();\n }\n };\n copyNext();\n });\n}\n\nfunction copy(src: string, dest: string, callback: (error: NodeJS.ErrnoException) => void): void {\n fs.mkdir(path.dirname(dest), { recursive: true }, (err?) => {\n if (err) {\n callback(err);\n return;\n }\n fs.createReadStream(src).pipe(fs.createWriteStream(dest)).on('finish', callback);\n });\n}\n\nconst ALLOWED_SCALES: { [key: string]: number[] } = {\n ios: [1, 2, 3],\n};\n\nexport function filterPlatformAssetScales(platform: string, scales: number[]): number[] {\n const whitelist: number[] = ALLOWED_SCALES[platform];\n if (!whitelist) {\n return scales;\n }\n const result = scales.filter((scale) => whitelist.includes(scale));\n if (!result.length && scales.length) {\n // No matching scale found, but there are some available. Ideally we don't\n // want to be in this situation and should throw, but for now as a fallback\n // let's just use the closest larger image\n const maxScale = whitelist[whitelist.length - 1];\n for (const scale of scales) {\n if (scale > maxScale) {\n result.push(scale);\n break;\n }\n }\n\n // There is no larger scales available, use the largest we have\n if (!result.length) {\n result.push(scales[scales.length - 1]);\n }\n }\n return result;\n}\n\nfunction getResourceIdentifier(asset: Pick<AssetData, 'httpServerLocation' | 'name'>): string {\n const folderPath = getBaseUrl(asset);\n return `${folderPath}/${asset.name}`\n .toLowerCase()\n .replace(/\\//g, '_') // Encode folder structure in file name\n .replace(/([^a-z0-9_])/g, '') // Remove illegal chars\n .replace(/^assets_/, ''); // Remove \"assets_\" prefix\n}\n\nfunction getBaseUrl(asset: Pick<AssetData, 'httpServerLocation'>): string {\n let baseUrl = asset.httpServerLocation;\n if (baseUrl[0] === '/') {\n baseUrl = baseUrl.substring(1);\n }\n return baseUrl;\n}\n"],"names":["copyInBatchesAsync","createKeepFileAsync","filterPlatformAssetScales","getAssetIdForLogGrouping","persistMetroAssetsAsync","cleanAssetCatalog","catalogDir","files","fs","readdirSync","filter","file","endsWith","rmSync","path","join","projectRoot","assets","platform","outputDirectory","baseUrl","iosAssetCatalogDirectory","Log","warn","existsSync","mkdirSync","recursive","assetsToCopy","error","log","asset","isCatalogAsset","imageSet","getImageSet","scales","writeImageSet","push","batches","validScales","Set","idx","length","scale","has","src","dest","getAssetLocalPath","data","promises","readFile","set","contents","assetId","targetDomain","undefined","assetsList","prefix","drawableFileTypes","type","getResourceIdentifier","keepPath","content","mkdir","dirname","writeFile","fileSystemLocation","name","relative","copyFileSync","writeFileSync","JSON","stringify","images","map","filename","idiom","info","author","version","fileName","suffix","filesToCopy","queue","Object","keys","Promise","resolve","reject","copyNext","shift","copy","callback","err","createReadStream","pipe","createWriteStream","on","ALLOWED_SCALES","ios","whitelist","result","includes","maxScale","folderPath","getBaseUrl","toLowerCase","replace","httpServerLocation","substring"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/export/persistMetroAssets.ts"],"sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * Based on the community asset persisting for Metro but with base path and web support:\n * https://github.com/facebook/react-native/blob/d6e0bc714ad4d215ede4949d3c4f44af6dea5dd3/packages/community-cli-plugin/src/commands/bundle/saveAssets.js#L1\n */\nimport fs from 'fs';\nimport type { AssetData } from 'metro';\nimport path from 'path';\n\nimport { drawableFileTypes, getAssetLocalPath } from './metroAssetLocalPath';\nimport { ExportAssetMap } from './saveAssets';\nimport { Log } from '../log';\n\nfunction cleanAssetCatalog(catalogDir: string): void {\n const files = fs.readdirSync(catalogDir).filter((file) => file.endsWith('.imageset'));\n for (const file of files) {\n fs.rmSync(path.join(catalogDir, file));\n }\n}\n\nexport async function persistMetroAssetsAsync(\n projectRoot: string,\n assets: readonly AssetData[],\n {\n platform,\n outputDirectory,\n baseUrl,\n iosAssetCatalogDirectory,\n files,\n }: {\n platform: string;\n outputDirectory: string;\n baseUrl?: string;\n iosAssetCatalogDirectory?: string;\n files?: ExportAssetMap;\n }\n) {\n if (outputDirectory == null) {\n Log.warn('Assets destination folder is not set, skipping...');\n return;\n }\n\n // For iOS, we need to ensure that the outputDirectory exists.\n // The bundle code and images build phase script always tries to access this folder\n if (platform === 'ios' && !fs.existsSync(outputDirectory)) {\n fs.mkdirSync(outputDirectory, { recursive: true });\n }\n\n let assetsToCopy: AssetData[] = [];\n\n // TODO: Use `files` as below to defer writing files\n if (platform === 'ios' && iosAssetCatalogDirectory != null) {\n // Use iOS Asset Catalog for images. This will allow Apple app thinning to\n // remove unused scales from the optimized bundle.\n const catalogDir = path.join(iosAssetCatalogDirectory, 'RNAssets.xcassets');\n if (!fs.existsSync(catalogDir)) {\n Log.error(\n `Could not find asset catalog 'RNAssets.xcassets' in ${iosAssetCatalogDirectory}. Make sure to create it if it does not exist.`\n );\n return;\n }\n\n Log.log('Adding images to asset catalog', catalogDir);\n cleanAssetCatalog(catalogDir);\n for (const asset of assets) {\n if (isCatalogAsset(asset)) {\n const imageSet = getImageSet(\n catalogDir,\n asset,\n filterPlatformAssetScales(platform, asset.scales)\n );\n writeImageSet(imageSet);\n } else {\n assetsToCopy.push(asset);\n }\n }\n Log.log('Done adding images to asset catalog');\n } else {\n assetsToCopy = [...assets];\n }\n if (platform === 'android') {\n await createKeepFileAsync(assetsToCopy, outputDirectory);\n }\n\n const batches: Record<string, string> = {};\n\n for (const asset of assetsToCopy) {\n const validScales = new Set(filterPlatformAssetScales(platform, asset.scales));\n for (let idx = 0; idx < asset.scales.length; idx++) {\n const scale = asset.scales[idx];\n if (validScales.has(scale)) {\n const src = asset.files[idx];\n const dest = getAssetLocalPath(asset, { platform, scale, baseUrl });\n if (files) {\n const data = await fs.promises.readFile(src);\n files.set(dest, {\n contents: data,\n assetId: getAssetIdForLogGrouping(projectRoot, asset),\n targetDomain: platform === 'web' ? 'client' : undefined,\n });\n } else {\n batches[src] = path.join(outputDirectory, dest);\n }\n }\n }\n }\n\n if (!files) {\n await copyInBatchesAsync(batches);\n }\n}\n\nexport async function createKeepFileAsync(\n assets: AssetData[],\n outputDirectory: string\n): Promise<void> {\n if (!assets.length) {\n return;\n }\n const assetsList = [];\n for (const asset of assets) {\n const prefix = drawableFileTypes.has(asset.type) ? 'drawable' : 'raw';\n assetsList.push(`@${prefix}/${getResourceIdentifier(asset)}`);\n }\n const keepPath = path.join(outputDirectory, 'raw/keep.xml');\n const content = `<resources xmlns:tools=\"http://schemas.android.com/tools\" tools:keep=\"${assetsList.join(',')}\" />`;\n await fs.promises.mkdir(path.dirname(keepPath), { recursive: true });\n await fs.promises.writeFile(keepPath, content);\n}\n\nexport function getAssetIdForLogGrouping(\n projectRoot: string,\n asset: Partial<Pick<AssetData, 'fileSystemLocation' | 'name' | 'type'>>\n): string | undefined {\n return 'fileSystemLocation' in asset && asset.fileSystemLocation != null && asset.name != null\n ? path.relative(projectRoot, path.join(asset.fileSystemLocation, asset.name)) +\n (asset.type ? '.' + asset.type : '')\n : undefined;\n}\n\nfunction writeImageSet(imageSet: ImageSet): void {\n fs.mkdirSync(imageSet.baseUrl, { recursive: true });\n\n for (const file of imageSet.files) {\n const dest = path.join(imageSet.baseUrl, file.name);\n fs.copyFileSync(file.src, dest);\n }\n\n fs.writeFileSync(\n path.join(imageSet.baseUrl, 'Contents.json'),\n JSON.stringify({\n images: imageSet.files.map((file) => ({\n filename: file.name,\n idiom: 'universal',\n scale: `${file.scale}x`,\n })),\n info: {\n author: 'expo',\n version: 1,\n },\n })\n );\n}\n\nfunction isCatalogAsset(asset: Pick<AssetData, 'type'>): boolean {\n return asset.type === 'png' || asset.type === 'jpg' || asset.type === 'jpeg';\n}\n\ntype ImageSet = {\n baseUrl: string;\n files: { name: string; src: string; scale: number }[];\n};\n\nfunction getImageSet(\n catalogDir: string,\n asset: Pick<AssetData, 'httpServerLocation' | 'name' | 'type' | 'files'>,\n scales: number[]\n): ImageSet {\n const fileName = getResourceIdentifier(asset);\n return {\n baseUrl: path.join(catalogDir, `${fileName}.imageset`),\n files: scales.map((scale, idx) => {\n const suffix = scale === 1 ? '' : `@${scale}x`;\n return {\n name: `${fileName + suffix}.${asset.type}`,\n scale,\n src: asset.files[idx],\n };\n }),\n };\n}\n\nexport function copyInBatchesAsync(filesToCopy: Record<string, string>) {\n const queue = Object.keys(filesToCopy);\n if (queue.length === 0) {\n return;\n }\n\n Log.log(`Copying ${queue.length} asset files`);\n return new Promise<void>((resolve, reject) => {\n const copyNext = (error?: NodeJS.ErrnoException) => {\n if (error) {\n return reject(error);\n }\n if (queue.length) {\n // queue.length === 0 is checked in previous branch, so this is string\n const src = queue.shift() as string;\n const dest = filesToCopy[src];\n copy(src, dest, copyNext);\n } else {\n resolve();\n }\n };\n copyNext();\n });\n}\n\nfunction copy(src: string, dest: string, callback: (error?: NodeJS.ErrnoException) => void): void {\n fs.mkdir(path.dirname(dest), { recursive: true }, (err?) => {\n if (err) {\n callback(err);\n return;\n }\n fs.createReadStream(src).pipe(fs.createWriteStream(dest)).on('finish', callback);\n });\n}\n\nconst ALLOWED_SCALES: { [key: string]: number[] } = {\n ios: [1, 2, 3],\n};\n\nexport function filterPlatformAssetScales(platform: string, scales: number[]): number[] {\n const whitelist: number[] = ALLOWED_SCALES[platform];\n if (!whitelist) {\n return scales;\n }\n const result = scales.filter((scale) => whitelist.includes(scale));\n if (!result.length && scales.length) {\n // No matching scale found, but there are some available. Ideally we don't\n // want to be in this situation and should throw, but for now as a fallback\n // let's just use the closest larger image\n const maxScale = whitelist[whitelist.length - 1];\n for (const scale of scales) {\n if (scale > maxScale) {\n result.push(scale);\n break;\n }\n }\n\n // There is no larger scales available, use the largest we have\n if (!result.length) {\n result.push(scales[scales.length - 1]);\n }\n }\n return result;\n}\n\nfunction getResourceIdentifier(asset: Pick<AssetData, 'httpServerLocation' | 'name'>): string {\n const folderPath = getBaseUrl(asset);\n return `${folderPath}/${asset.name}`\n .toLowerCase()\n .replace(/\\//g, '_') // Encode folder structure in file name\n .replace(/([^a-z0-9_])/g, '') // Remove illegal chars\n .replace(/^assets_/, ''); // Remove \"assets_\" prefix\n}\n\nfunction getBaseUrl(asset: Pick<AssetData, 'httpServerLocation'>): string {\n let baseUrl = asset.httpServerLocation;\n if (baseUrl[0] === '/') {\n baseUrl = baseUrl.substring(1);\n }\n return baseUrl;\n}\n"],"names":["copyInBatchesAsync","createKeepFileAsync","filterPlatformAssetScales","getAssetIdForLogGrouping","persistMetroAssetsAsync","cleanAssetCatalog","catalogDir","files","fs","readdirSync","filter","file","endsWith","rmSync","path","join","projectRoot","assets","platform","outputDirectory","baseUrl","iosAssetCatalogDirectory","Log","warn","existsSync","mkdirSync","recursive","assetsToCopy","error","log","asset","isCatalogAsset","imageSet","getImageSet","scales","writeImageSet","push","batches","validScales","Set","idx","length","scale","has","src","dest","getAssetLocalPath","data","promises","readFile","set","contents","assetId","targetDomain","undefined","assetsList","prefix","drawableFileTypes","type","getResourceIdentifier","keepPath","content","mkdir","dirname","writeFile","fileSystemLocation","name","relative","copyFileSync","writeFileSync","JSON","stringify","images","map","filename","idiom","info","author","version","fileName","suffix","filesToCopy","queue","Object","keys","Promise","resolve","reject","copyNext","shift","copy","callback","err","createReadStream","pipe","createWriteStream","on","ALLOWED_SCALES","ios","whitelist","result","includes","maxScale","folderPath","getBaseUrl","toLowerCase","replace","httpServerLocation","substring"],"mappings":"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"}
|
|
@@ -76,7 +76,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
76
76
|
return newObj;
|
|
77
77
|
}
|
|
78
78
|
const debug = require('debug')('expo:install:check');
|
|
79
|
-
async function checkPackagesAsync(projectRoot, { packages, packageManager, options: { fix }, packageManagerArguments }) {
|
|
79
|
+
async function checkPackagesAsync(projectRoot, { packages, packageManager, options: { fix, json }, packageManagerArguments }) {
|
|
80
80
|
var _pkg_expo_install_exclude, _pkg_expo_install, _pkg_expo, _pkg_dependencies;
|
|
81
81
|
// Read the project Expo config without plugins.
|
|
82
82
|
const { exp, pkg } = (0, _config().getConfig)(projectRoot, {
|
|
@@ -84,7 +84,7 @@ async function checkPackagesAsync(projectRoot, { packages, packageManager, optio
|
|
|
84
84
|
// this wouldn't work unless we dangerously disable plugin serialization.
|
|
85
85
|
skipPlugins: true
|
|
86
86
|
});
|
|
87
|
-
if ((_pkg_expo = pkg.expo) == null ? void 0 : (_pkg_expo_install = _pkg_expo.install) == null ? void 0 : (_pkg_expo_install_exclude = _pkg_expo_install.exclude) == null ? void 0 : _pkg_expo_install_exclude.length) {
|
|
87
|
+
if (((_pkg_expo = pkg.expo) == null ? void 0 : (_pkg_expo_install = _pkg_expo.install) == null ? void 0 : (_pkg_expo_install_exclude = _pkg_expo_install.exclude) == null ? void 0 : _pkg_expo_install_exclude.length) && !json) {
|
|
88
88
|
_log.log((0, _chalk().default)`Skipped ${fix ? 'fixing' : 'checking'} dependencies: ${(0, _strings.joinWithCommasAnd)(pkg.expo.install.exclude)}. These dependencies are listed in {bold expo.install.exclude} in package.json. ${(0, _link.learnMore)('https://docs.expo.dev/more/expo-cli/#configuring-dependency-validation')}`);
|
|
89
89
|
}
|
|
90
90
|
const dependencies = await (0, _validateDependenciesVersions.getVersionedDependenciesAsync)(projectRoot, exp, pkg, packages);
|
|
@@ -101,12 +101,30 @@ async function checkPackagesAsync(projectRoot, { packages, packageManager, optio
|
|
|
101
101
|
learnMore: _link.learnMore
|
|
102
102
|
}));
|
|
103
103
|
} catch (error) {
|
|
104
|
-
|
|
104
|
+
if (!json) {
|
|
105
|
+
_log.log(`Skipped checking expo-router dependencies: expo-router/doctor.js not found.`);
|
|
106
|
+
}
|
|
105
107
|
debug('expo-router/doctor error:', error);
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
if (!dependencies.length) {
|
|
109
|
-
|
|
111
|
+
if (json) {
|
|
112
|
+
console.log(JSON.stringify({
|
|
113
|
+
dependencies: [],
|
|
114
|
+
upToDate: true
|
|
115
|
+
}));
|
|
116
|
+
} else {
|
|
117
|
+
_log.exit(_chalk().default.greenBright('Dependencies are up to date'), 0);
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (json) {
|
|
122
|
+
console.log(JSON.stringify({
|
|
123
|
+
dependencies,
|
|
124
|
+
upToDate: false
|
|
125
|
+
}, null, 2));
|
|
126
|
+
// Exit with non-zero exit code to indicate outdated dependencies
|
|
127
|
+
process.exit(1);
|
|
110
128
|
}
|
|
111
129
|
(0, _validateDependenciesVersions.logIncorrectDependencies)(dependencies);
|
|
112
130
|
const value = // If `--fix` then always fix.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/install/checkPackages.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport * as PackageManager from '@expo/package-manager';\nimport chalk from 'chalk';\n\nimport { fixPackagesAsync } from './fixPackages';\nimport { Options } from './resolveOptions';\nimport * as Log from '../log';\nimport {\n getVersionedDependenciesAsync,\n logIncorrectDependencies,\n} from '../start/doctor/dependencies/validateDependenciesVersions';\nimport { isInteractive } from '../utils/interactive';\nimport { learnMore } from '../utils/link';\nimport { confirmAsync } from '../utils/prompts';\nimport { joinWithCommasAnd } from '../utils/strings';\n\nconst debug = require('debug')('expo:install:check') as typeof console.log;\n\n/**\n * Handles `expo install --fix|check'.\n * Checks installed dependencies against bundledNativeModules and versions endpoints to find any incompatibilities.\n * If `--fix` is passed, it will install the correct versions of the dependencies.\n * If `--check` is passed, it will prompt the user to install the correct versions of the dependencies (on interactive terminal).\n */\nexport async function checkPackagesAsync(\n projectRoot: string,\n {\n packages,\n packageManager,\n options: { fix },\n packageManagerArguments,\n }: {\n /**\n * List of packages to version\n * @example ['uuid', 'react-native-reanimated@latest']\n */\n packages: string[];\n /** Package manager to use when installing the versioned packages. */\n packageManager: PackageManager.NodePackageManager;\n\n /** How the check should resolve */\n options: Pick<Options, 'fix'>;\n /**\n * Extra parameters to pass to the `packageManager` when installing versioned packages.\n * @example ['--no-save']\n */\n packageManagerArguments: string[];\n }\n) {\n // Read the project Expo config without plugins.\n const { exp, pkg } = getConfig(projectRoot, {\n // Sometimes users will add a plugin to the config before installing the library,\n // this wouldn't work unless we dangerously disable plugin serialization.\n skipPlugins: true,\n });\n\n if (pkg.expo?.install?.exclude?.length) {\n Log.log(\n chalk`Skipped ${fix ? 'fixing' : 'checking'} dependencies: ${joinWithCommasAnd(\n pkg.expo.install.exclude\n )}. These dependencies are listed in {bold expo.install.exclude} in package.json. ${learnMore(\n 'https://docs.expo.dev/more/expo-cli/#configuring-dependency-validation'\n )}`\n );\n }\n\n const dependencies = await getVersionedDependenciesAsync(projectRoot, exp, pkg, packages);\n\n /*\n * Expo Router projects will do this additional check\n * Note: The e2e tests use nexpo which will always resolve 'expo-router/doctor.js'\n * For that reason, you cannot use nexpo to test for the sub-dependency check,\n * and you cannot replace this guard with a try/catch around the import('expo-router')\n */\n if (pkg.dependencies?.['expo-router']) {\n try {\n const { doctor: routerDoctor } = await import('expo-router/doctor.js');\n dependencies.push(\n ...routerDoctor(pkg, require.resolve('@react-navigation/native'), {\n bold: chalk.bold,\n learnMore,\n })\n );\n } catch (error) {\n Log.log(`Skipped checking expo-router dependencies: expo-router/doctor.js not found.`);\n debug('expo-router/doctor error:', error);\n }\n }\n\n if (!dependencies.length) {\n Log.exit(chalk.greenBright('Dependencies are up to date'), 0);\n }\n\n logIncorrectDependencies(dependencies);\n\n const value =\n // If `--fix` then always fix.\n fix ||\n // Otherwise prompt to fix when not running in CI.\n (isInteractive() && (await confirmAsync({ message: 'Fix dependencies?' }).catch(() => false)));\n\n if (value) {\n debug('Installing fixed dependencies:', dependencies);\n // Install the corrected dependencies.\n return fixPackagesAsync(projectRoot, {\n packageManager,\n packages: dependencies,\n packageManagerArguments,\n sdkVersion: exp.sdkVersion!,\n });\n }\n\n // Exit with non-zero exit code if any of the dependencies are out of date.\n Log.exit(chalk.red('Found outdated dependencies'), 1);\n}\n"],"names":["checkPackagesAsync","debug","require","projectRoot","packages","packageManager","options","fix","packageManagerArguments","pkg","exp","getConfig","skipPlugins","expo","install","exclude","length","Log","log","chalk","joinWithCommasAnd","learnMore","dependencies","getVersionedDependenciesAsync","doctor","routerDoctor","push","resolve","bold","error","exit","greenBright","logIncorrectDependencies","value","isInteractive","confirmAsync","message","catch","fixPackagesAsync","sdkVersion","red"],"mappings":";;;;+BAwBsBA;;;eAAAA;;;;yBAxBI;;;;;;;gEAER;;;;;;6BAEe;6DAEZ;8CAId;6BACuB;sBACJ;yBACG;yBACK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAElC,MAAMC,QAAQC,QAAQ,SAAS;AAQxB,eAAeF,mBACpBG,WAAmB,EACnB,EACEC,QAAQ,EACRC,cAAc,EACdC,SAAS,EAAEC,GAAG,EAAE,
|
|
1
|
+
{"version":3,"sources":["../../../src/install/checkPackages.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport * as PackageManager from '@expo/package-manager';\nimport chalk from 'chalk';\n\nimport { fixPackagesAsync } from './fixPackages';\nimport { Options } from './resolveOptions';\nimport * as Log from '../log';\nimport {\n getVersionedDependenciesAsync,\n logIncorrectDependencies,\n} from '../start/doctor/dependencies/validateDependenciesVersions';\nimport { isInteractive } from '../utils/interactive';\nimport { learnMore } from '../utils/link';\nimport { confirmAsync } from '../utils/prompts';\nimport { joinWithCommasAnd } from '../utils/strings';\n\nconst debug = require('debug')('expo:install:check') as typeof console.log;\n\n/**\n * Handles `expo install --fix|check'.\n * Checks installed dependencies against bundledNativeModules and versions endpoints to find any incompatibilities.\n * If `--fix` is passed, it will install the correct versions of the dependencies.\n * If `--check` is passed, it will prompt the user to install the correct versions of the dependencies (on interactive terminal).\n */\nexport async function checkPackagesAsync(\n projectRoot: string,\n {\n packages,\n packageManager,\n options: { fix, json },\n packageManagerArguments,\n }: {\n /**\n * List of packages to version\n * @example ['uuid', 'react-native-reanimated@latest']\n */\n packages: string[];\n /** Package manager to use when installing the versioned packages. */\n packageManager: PackageManager.NodePackageManager;\n\n /** How the check should resolve */\n options: Pick<Options, 'fix' | 'json'>;\n /**\n * Extra parameters to pass to the `packageManager` when installing versioned packages.\n * @example ['--no-save']\n */\n packageManagerArguments: string[];\n }\n) {\n // Read the project Expo config without plugins.\n const { exp, pkg } = getConfig(projectRoot, {\n // Sometimes users will add a plugin to the config before installing the library,\n // this wouldn't work unless we dangerously disable plugin serialization.\n skipPlugins: true,\n });\n\n if (pkg.expo?.install?.exclude?.length && !json) {\n Log.log(\n chalk`Skipped ${fix ? 'fixing' : 'checking'} dependencies: ${joinWithCommasAnd(\n pkg.expo.install.exclude\n )}. These dependencies are listed in {bold expo.install.exclude} in package.json. ${learnMore(\n 'https://docs.expo.dev/more/expo-cli/#configuring-dependency-validation'\n )}`\n );\n }\n\n const dependencies = await getVersionedDependenciesAsync(projectRoot, exp, pkg, packages);\n\n /*\n * Expo Router projects will do this additional check\n * Note: The e2e tests use nexpo which will always resolve 'expo-router/doctor.js'\n * For that reason, you cannot use nexpo to test for the sub-dependency check,\n * and you cannot replace this guard with a try/catch around the import('expo-router')\n */\n if (pkg.dependencies?.['expo-router']) {\n try {\n const { doctor: routerDoctor } = await import('expo-router/doctor.js');\n dependencies.push(\n ...routerDoctor(pkg, require.resolve('@react-navigation/native'), {\n bold: chalk.bold,\n learnMore,\n })\n );\n } catch (error) {\n if (!json) {\n Log.log(`Skipped checking expo-router dependencies: expo-router/doctor.js not found.`);\n }\n debug('expo-router/doctor error:', error);\n }\n }\n\n if (!dependencies.length) {\n if (json) {\n console.log(JSON.stringify({ dependencies: [], upToDate: true }));\n } else {\n Log.exit(chalk.greenBright('Dependencies are up to date'), 0);\n }\n return;\n }\n\n if (json) {\n console.log(JSON.stringify({ dependencies, upToDate: false }, null, 2));\n // Exit with non-zero exit code to indicate outdated dependencies\n process.exit(1);\n }\n\n logIncorrectDependencies(dependencies);\n\n const value =\n // If `--fix` then always fix.\n fix ||\n // Otherwise prompt to fix when not running in CI.\n (isInteractive() && (await confirmAsync({ message: 'Fix dependencies?' }).catch(() => false)));\n\n if (value) {\n debug('Installing fixed dependencies:', dependencies);\n // Install the corrected dependencies.\n return fixPackagesAsync(projectRoot, {\n packageManager,\n packages: dependencies,\n packageManagerArguments,\n sdkVersion: exp.sdkVersion!,\n });\n }\n\n // Exit with non-zero exit code if any of the dependencies are out of date.\n Log.exit(chalk.red('Found outdated dependencies'), 1);\n}\n"],"names":["checkPackagesAsync","debug","require","projectRoot","packages","packageManager","options","fix","json","packageManagerArguments","pkg","exp","getConfig","skipPlugins","expo","install","exclude","length","Log","log","chalk","joinWithCommasAnd","learnMore","dependencies","getVersionedDependenciesAsync","doctor","routerDoctor","push","resolve","bold","error","console","JSON","stringify","upToDate","exit","greenBright","process","logIncorrectDependencies","value","isInteractive","confirmAsync","message","catch","fixPackagesAsync","sdkVersion","red"],"mappings":";;;;+BAwBsBA;;;eAAAA;;;;yBAxBI;;;;;;;gEAER;;;;;;6BAEe;6DAEZ;8CAId;6BACuB;sBACJ;yBACG;yBACK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAElC,MAAMC,QAAQC,QAAQ,SAAS;AAQxB,eAAeF,mBACpBG,WAAmB,EACnB,EACEC,QAAQ,EACRC,cAAc,EACdC,SAAS,EAAEC,GAAG,EAAEC,IAAI,EAAE,EACtBC,uBAAuB,EAiBxB;QASGC,2BAAAA,mBAAAA,WAkBAA;IAzBJ,gDAAgD;IAChD,MAAM,EAAEC,GAAG,EAAED,GAAG,EAAE,GAAGE,IAAAA,mBAAS,EAACT,aAAa;QAC1C,iFAAiF;QACjF,yEAAyE;QACzEU,aAAa;IACf;IAEA,IAAIH,EAAAA,YAAAA,IAAII,IAAI,sBAARJ,oBAAAA,UAAUK,OAAO,sBAAjBL,4BAAAA,kBAAmBM,OAAO,qBAA1BN,0BAA4BO,MAAM,KAAI,CAACT,MAAM;QAC/CU,KAAIC,GAAG,CACLC,IAAAA,gBAAK,CAAA,CAAC,QAAQ,EAAEb,MAAM,WAAW,WAAW,eAAe,EAAEc,IAAAA,0BAAiB,EAC5EX,IAAII,IAAI,CAACC,OAAO,CAACC,OAAO,EACxB,gFAAgF,EAAEM,IAAAA,eAAS,EAC3F,0EACA,CAAC;IAEP;IAEA,MAAMC,eAAe,MAAMC,IAAAA,2DAA6B,EAACrB,aAAaQ,KAAKD,KAAKN;IAEhF;;;;;GAKC,GACD,KAAIM,oBAAAA,IAAIa,YAAY,qBAAhBb,iBAAkB,CAAC,cAAc,EAAE;QACrC,IAAI;YACF,MAAM,EAAEe,QAAQC,YAAY,EAAE,GAAG,MAAM,mEAAA,QAAO;YAC9CH,aAAaI,IAAI,IACZD,aAAahB,KAAKR,QAAQ0B,OAAO,CAAC,6BAA6B;gBAChEC,MAAMT,gBAAK,CAACS,IAAI;gBAChBP,WAAAA,eAAS;YACX;QAEJ,EAAE,OAAOQ,OAAO;YACd,IAAI,CAACtB,MAAM;gBACTU,KAAIC,GAAG,CAAC,CAAC,2EAA2E,CAAC;YACvF;YACAlB,MAAM,6BAA6B6B;QACrC;IACF;IAEA,IAAI,CAACP,aAAaN,MAAM,EAAE;QACxB,IAAIT,MAAM;YACRuB,QAAQZ,GAAG,CAACa,KAAKC,SAAS,CAAC;gBAAEV,cAAc,EAAE;gBAAEW,UAAU;YAAK;QAChE,OAAO;YACLhB,KAAIiB,IAAI,CAACf,gBAAK,CAACgB,WAAW,CAAC,gCAAgC;QAC7D;QACA;IACF;IAEA,IAAI5B,MAAM;QACRuB,QAAQZ,GAAG,CAACa,KAAKC,SAAS,CAAC;YAAEV;YAAcW,UAAU;QAAM,GAAG,MAAM;QACpE,iEAAiE;QACjEG,QAAQF,IAAI,CAAC;IACf;IAEAG,IAAAA,sDAAwB,EAACf;IAEzB,MAAMgB,QACJ,8BAA8B;IAC9BhC,OACA,kDAAkD;IACjDiC,IAAAA,0BAAa,OAAO,MAAMC,IAAAA,qBAAY,EAAC;QAAEC,SAAS;IAAoB,GAAGC,KAAK,CAAC,IAAM;IAExF,IAAIJ,OAAO;QACTtC,MAAM,kCAAkCsB;QACxC,sCAAsC;QACtC,OAAOqB,IAAAA,6BAAgB,EAACzC,aAAa;YACnCE;YACAD,UAAUmB;YACVd;YACAoC,YAAYlC,IAAIkC,UAAU;QAC5B;IACF;IAEA,2EAA2E;IAC3E3B,KAAIiB,IAAI,CAACf,gBAAK,CAAC0B,GAAG,CAAC,gCAAgC;AACrD"}
|
|
@@ -26,6 +26,7 @@ const expoInstall = async (argv)=>{
|
|
|
26
26
|
const args = (0, _args.assertWithOptionsArgs)({
|
|
27
27
|
// Other options are parsed manually.
|
|
28
28
|
'--help': Boolean,
|
|
29
|
+
'--json': Boolean,
|
|
29
30
|
// Aliases
|
|
30
31
|
'-h': '--help'
|
|
31
32
|
}, {
|
|
@@ -42,7 +43,8 @@ const expoInstall = async (argv)=>{
|
|
|
42
43
|
(0, _chalk().default)`--yarn Use Yarn to install dependencies. {dim Default when yarn.lock exists}`,
|
|
43
44
|
(0, _chalk().default)`--bun Use bun to install dependencies. {dim Default when bun.lock or bun.lockb exists}`,
|
|
44
45
|
(0, _chalk().default)`--pnpm Use pnpm to install dependencies. {dim Default when pnpm-lock.yaml exists}`,
|
|
45
|
-
`-h, --help Usage info
|
|
46
|
+
`-h, --help Usage info`,
|
|
47
|
+
`--json Output dependency information in JSON format with --check flag`
|
|
46
48
|
].join('\n'), [
|
|
47
49
|
'',
|
|
48
50
|
(0, _chalk().default)` Additional options can be passed to the underlying install command by using {bold --}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/install/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport chalk from 'chalk';\n\nimport { Command } from '../../bin/cli';\nimport { assertWithOptionsArgs, printHelp } from '../utils/args';\n\nexport const expoInstall: Command = async (argv) => {\n const args = assertWithOptionsArgs(\n {\n // Other options are parsed manually.\n '--help': Boolean,\n // Aliases\n '-h': '--help',\n },\n {\n argv,\n // Allow other options, we'll throw an error if unexpected values are passed.\n permissive: true,\n }\n );\n\n if (args['--help']) {\n printHelp(\n `Install a module or other package to a project`,\n `npx expo install`,\n [\n `--check Check which installed packages need to be updated`,\n '--dev Save the dependencies as devDependencies',\n `--fix Automatically update any invalid package versions`,\n chalk`--npm Use npm to install dependencies. {dim Default when package-lock.json exists}`,\n chalk`--yarn Use Yarn to install dependencies. {dim Default when yarn.lock exists}`,\n chalk`--bun Use bun to install dependencies. {dim Default when bun.lock or bun.lockb exists}`,\n chalk`--pnpm Use pnpm to install dependencies. {dim Default when pnpm-lock.yaml exists}`,\n `-h, --help Usage info`,\n ].join('\\n'),\n [\n '',\n chalk` Additional options can be passed to the underlying install command by using {bold --}`,\n chalk` {dim $} npx expo install react -- --verbose`,\n chalk` {dim >} yarn add react --verbose`,\n '',\n ].join('\\n')\n );\n }\n\n // Load modules after the help prompt so `npx expo install -h` shows as fast as possible.\n const { installAsync } = require('./installAsync') as typeof import('./installAsync');\n const { logCmdError } = require('../utils/errors') as typeof import('../utils/errors');\n const { resolveArgsAsync } = require('./resolveOptions') as typeof import('./resolveOptions');\n\n const { variadic, options, extras } = await resolveArgsAsync(process.argv.slice(3)).catch(\n logCmdError\n );\n return installAsync(variadic, options, extras).catch(logCmdError);\n};\n"],"names":["expoInstall","argv","args","assertWithOptionsArgs","Boolean","permissive","printHelp","chalk","join","installAsync","require","logCmdError","resolveArgsAsync","variadic","options","extras","process","slice","catch"],"mappings":";;;;;+BAMaA;;;eAAAA;;;;gEALK;;;;;;sBAG+B;;;;;;AAE1C,MAAMA,cAAuB,OAAOC;IACzC,MAAMC,OAAOC,IAAAA,2BAAqB,EAChC;QACE,qCAAqC;QACrC,UAAUC;QACV,UAAU;QACV,MAAM;IACR,GACA;QACEH;QACA,6EAA6E;QAC7EI,YAAY;IACd;IAGF,IAAIH,IAAI,CAAC,SAAS,EAAE;QAClBI,IAAAA,eAAS,EACP,CAAC,8CAA8C,CAAC,EAChD,CAAC,gBAAgB,CAAC,EAClB;YACE,CAAC,6DAA6D,CAAC;YAC/D;YACA,CAAC,6DAA6D,CAAC;YAC/DC,IAAAA,gBAAK,CAAA,CAAC,wFAAwF,CAAC;YAC/FA,IAAAA,gBAAK,CAAA,CAAC,iFAAiF,CAAC;YACxFA,IAAAA,gBAAK,CAAA,CAAC,4FAA4F,CAAC;YACnGA,IAAAA,gBAAK,CAAA,CAAC,sFAAsF,CAAC;YAC7F,CAAC,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"sources":["../../../src/install/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport chalk from 'chalk';\n\nimport { Command } from '../../bin/cli';\nimport { assertWithOptionsArgs, printHelp } from '../utils/args';\n\nexport const expoInstall: Command = async (argv) => {\n const args = assertWithOptionsArgs(\n {\n // Other options are parsed manually.\n '--help': Boolean,\n '--json': Boolean,\n // Aliases\n '-h': '--help',\n },\n {\n argv,\n // Allow other options, we'll throw an error if unexpected values are passed.\n permissive: true,\n }\n );\n\n if (args['--help']) {\n printHelp(\n `Install a module or other package to a project`,\n `npx expo install`,\n [\n `--check Check which installed packages need to be updated`,\n '--dev Save the dependencies as devDependencies',\n `--fix Automatically update any invalid package versions`,\n chalk`--npm Use npm to install dependencies. {dim Default when package-lock.json exists}`,\n chalk`--yarn Use Yarn to install dependencies. {dim Default when yarn.lock exists}`,\n chalk`--bun Use bun to install dependencies. {dim Default when bun.lock or bun.lockb exists}`,\n chalk`--pnpm Use pnpm to install dependencies. {dim Default when pnpm-lock.yaml exists}`,\n `-h, --help Usage info`,\n `--json Output dependency information in JSON format with --check flag`,\n ].join('\\n'),\n [\n '',\n chalk` Additional options can be passed to the underlying install command by using {bold --}`,\n chalk` {dim $} npx expo install react -- --verbose`,\n chalk` {dim >} yarn add react --verbose`,\n '',\n ].join('\\n')\n );\n }\n\n // Load modules after the help prompt so `npx expo install -h` shows as fast as possible.\n const { installAsync } = require('./installAsync') as typeof import('./installAsync');\n const { logCmdError } = require('../utils/errors') as typeof import('../utils/errors');\n const { resolveArgsAsync } = require('./resolveOptions') as typeof import('./resolveOptions');\n\n const { variadic, options, extras } = await resolveArgsAsync(process.argv.slice(3)).catch(\n logCmdError\n );\n return installAsync(variadic, options, extras).catch(logCmdError);\n};\n"],"names":["expoInstall","argv","args","assertWithOptionsArgs","Boolean","permissive","printHelp","chalk","join","installAsync","require","logCmdError","resolveArgsAsync","variadic","options","extras","process","slice","catch"],"mappings":";;;;;+BAMaA;;;eAAAA;;;;gEALK;;;;;;sBAG+B;;;;;;AAE1C,MAAMA,cAAuB,OAAOC;IACzC,MAAMC,OAAOC,IAAAA,2BAAqB,EAChC;QACE,qCAAqC;QACrC,UAAUC;QACV,UAAUA;QACV,UAAU;QACV,MAAM;IACR,GACA;QACEH;QACA,6EAA6E;QAC7EI,YAAY;IACd;IAGF,IAAIH,IAAI,CAAC,SAAS,EAAE;QAClBI,IAAAA,eAAS,EACP,CAAC,8CAA8C,CAAC,EAChD,CAAC,gBAAgB,CAAC,EAClB;YACE,CAAC,6DAA6D,CAAC;YAC/D;YACA,CAAC,6DAA6D,CAAC;YAC/DC,IAAAA,gBAAK,CAAA,CAAC,wFAAwF,CAAC;YAC/FA,IAAAA,gBAAK,CAAA,CAAC,iFAAiF,CAAC;YACxFA,IAAAA,gBAAK,CAAA,CAAC,4FAA4F,CAAC;YACnGA,IAAAA,gBAAK,CAAA,CAAC,sFAAsF,CAAC;YAC7F,CAAC,sBAAsB,CAAC;YACxB,CAAC,0EAA0E,CAAC;SAC7E,CAACC,IAAI,CAAC,OACP;YACE;YACAD,IAAAA,gBAAK,CAAA,CAAC,uFAAuF,CAAC;YAC9FA,IAAAA,gBAAK,CAAA,CAAC,+CAA+C,CAAC;YACtDA,IAAAA,gBAAK,CAAA,CAAC,oCAAoC,CAAC;YAC3C;SACD,CAACC,IAAI,CAAC;IAEX;IAEA,yFAAyF;IACzF,MAAM,EAAEC,YAAY,EAAE,GAAGC,QAAQ;IACjC,MAAM,EAAEC,WAAW,EAAE,GAAGD,QAAQ;IAChC,MAAM,EAAEE,gBAAgB,EAAE,GAAGF,QAAQ;IAErC,MAAM,EAAEG,QAAQ,EAAEC,OAAO,EAAEC,MAAM,EAAE,GAAG,MAAMH,iBAAiBI,QAAQf,IAAI,CAACgB,KAAK,CAAC,IAAIC,KAAK,CACvFP;IAEF,OAAOF,aAAaI,UAAUC,SAASC,QAAQG,KAAK,CAACP;AACvD"}
|
|
@@ -22,6 +22,9 @@ function resolveOptions(options) {
|
|
|
22
22
|
].filter(Boolean).length > 1) {
|
|
23
23
|
throw new _errors.CommandError('BAD_ARGS', 'Specify at most one of: --npm, --pnpm, --yarn, --bun');
|
|
24
24
|
}
|
|
25
|
+
if (options.json && !options.check) {
|
|
26
|
+
throw new _errors.CommandError('BAD_ARGS', 'The --json flag can only be used with --check');
|
|
27
|
+
}
|
|
25
28
|
return {
|
|
26
29
|
...options
|
|
27
30
|
};
|
|
@@ -35,7 +38,8 @@ async function resolveArgsAsync(argv) {
|
|
|
35
38
|
'--npm',
|
|
36
39
|
'--pnpm',
|
|
37
40
|
'--yarn',
|
|
38
|
-
'--bun'
|
|
41
|
+
'--bun',
|
|
42
|
+
'--json'
|
|
39
43
|
], {
|
|
40
44
|
variadic,
|
|
41
45
|
extras,
|
|
@@ -51,7 +55,8 @@ async function resolveArgsAsync(argv) {
|
|
|
51
55
|
yarn: !!flags['--yarn'],
|
|
52
56
|
npm: !!flags['--npm'],
|
|
53
57
|
pnpm: !!flags['--pnpm'],
|
|
54
|
-
bun: !!flags['--bun']
|
|
58
|
+
bun: !!flags['--bun'],
|
|
59
|
+
json: !!flags['--json']
|
|
55
60
|
}),
|
|
56
61
|
extras
|
|
57
62
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/install/resolveOptions.ts"],"sourcesContent":["import { NodePackageManagerForProject } from '@expo/package-manager';\n\nimport { CommandError } from '../utils/errors';\nimport { assertUnexpectedVariadicFlags, parseVariadicArguments } from '../utils/variadic';\n\nexport type Options = Pick<NodePackageManagerForProject, 'npm' | 'pnpm' | 'yarn' | 'bun'> & {\n /** Check which packages need to be updated, does not install any provided packages. */\n check?: boolean;\n /** Should the dependencies be fixed automatically. */\n fix?: boolean;\n /** Should disable install output, used for commands like `prebuild` that run install internally. */\n silent?: boolean;\n /** Should be installed as dev dependencies */\n dev?: boolean;\n};\n\nfunction resolveOptions(options: Options): Options {\n if (options.fix && options.check) {\n throw new CommandError('BAD_ARGS', 'Specify at most one of: --check, --fix');\n }\n if ([options.npm, options.pnpm, options.yarn, options.bun].filter(Boolean).length > 1) {\n throw new CommandError('BAD_ARGS', 'Specify at most one of: --npm, --pnpm, --yarn, --bun');\n }\n return {\n ...options,\n };\n}\n\nexport async function resolveArgsAsync(\n argv: string[]\n): Promise<{ variadic: string[]; options: Options; extras: string[] }> {\n const { variadic, extras, flags } = parseVariadicArguments(argv);\n\n assertUnexpectedVariadicFlags(\n ['--check', '--dev', '--fix', '--npm', '--pnpm', '--yarn', '--bun'],\n { variadic, extras, flags },\n 'npx expo install'\n );\n\n return {\n // Variadic arguments like `npx expo install react react-dom` -> ['react', 'react-dom']\n variadic,\n options: resolveOptions({\n fix: !!flags['--fix'],\n dev: !!flags['--dev'],\n check: !!flags['--check'],\n yarn: !!flags['--yarn'],\n npm: !!flags['--npm'],\n pnpm: !!flags['--pnpm'],\n bun: !!flags['--bun'],\n }),\n extras,\n };\n}\n"],"names":["resolveArgsAsync","resolveOptions","options","fix","check","CommandError","npm","pnpm","yarn","bun","filter","Boolean","length","argv","variadic","extras","flags","parseVariadicArguments","assertUnexpectedVariadicFlags","dev"],"mappings":";;;;+
|
|
1
|
+
{"version":3,"sources":["../../../src/install/resolveOptions.ts"],"sourcesContent":["import { NodePackageManagerForProject } from '@expo/package-manager';\n\nimport { CommandError } from '../utils/errors';\nimport { assertUnexpectedVariadicFlags, parseVariadicArguments } from '../utils/variadic';\n\nexport type Options = Pick<NodePackageManagerForProject, 'npm' | 'pnpm' | 'yarn' | 'bun'> & {\n /** Check which packages need to be updated, does not install any provided packages. */\n check?: boolean;\n /** Should the dependencies be fixed automatically. */\n fix?: boolean;\n /** Should disable install output, used for commands like `prebuild` that run install internally. */\n silent?: boolean;\n /** Should be installed as dev dependencies */\n dev?: boolean;\n /** Should output in JSON format (use with --check) */\n json?: boolean;\n};\n\nfunction resolveOptions(options: Options): Options {\n if (options.fix && options.check) {\n throw new CommandError('BAD_ARGS', 'Specify at most one of: --check, --fix');\n }\n if ([options.npm, options.pnpm, options.yarn, options.bun].filter(Boolean).length > 1) {\n throw new CommandError('BAD_ARGS', 'Specify at most one of: --npm, --pnpm, --yarn, --bun');\n }\n if (options.json && !options.check) {\n throw new CommandError('BAD_ARGS', 'The --json flag can only be used with --check');\n }\n return {\n ...options,\n };\n}\n\nexport async function resolveArgsAsync(\n argv: string[]\n): Promise<{ variadic: string[]; options: Options; extras: string[] }> {\n const { variadic, extras, flags } = parseVariadicArguments(argv);\n\n assertUnexpectedVariadicFlags(\n ['--check', '--dev', '--fix', '--npm', '--pnpm', '--yarn', '--bun', '--json'],\n { variadic, extras, flags },\n 'npx expo install'\n );\n\n return {\n // Variadic arguments like `npx expo install react react-dom` -> ['react', 'react-dom']\n variadic,\n options: resolveOptions({\n fix: !!flags['--fix'],\n dev: !!flags['--dev'],\n check: !!flags['--check'],\n yarn: !!flags['--yarn'],\n npm: !!flags['--npm'],\n pnpm: !!flags['--pnpm'],\n bun: !!flags['--bun'],\n json: !!flags['--json'],\n }),\n extras,\n };\n}\n"],"names":["resolveArgsAsync","resolveOptions","options","fix","check","CommandError","npm","pnpm","yarn","bun","filter","Boolean","length","json","argv","variadic","extras","flags","parseVariadicArguments","assertUnexpectedVariadicFlags","dev"],"mappings":";;;;+BAiCsBA;;;eAAAA;;;wBA/BO;0BACyC;AAetE,SAASC,eAAeC,OAAgB;IACtC,IAAIA,QAAQC,GAAG,IAAID,QAAQE,KAAK,EAAE;QAChC,MAAM,IAAIC,oBAAY,CAAC,YAAY;IACrC;IACA,IAAI;QAACH,QAAQI,GAAG;QAAEJ,QAAQK,IAAI;QAAEL,QAAQM,IAAI;QAAEN,QAAQO,GAAG;KAAC,CAACC,MAAM,CAACC,SAASC,MAAM,GAAG,GAAG;QACrF,MAAM,IAAIP,oBAAY,CAAC,YAAY;IACrC;IACA,IAAIH,QAAQW,IAAI,IAAI,CAACX,QAAQE,KAAK,EAAE;QAClC,MAAM,IAAIC,oBAAY,CAAC,YAAY;IACrC;IACA,OAAO;QACL,GAAGH,OAAO;IACZ;AACF;AAEO,eAAeF,iBACpBc,IAAc;IAEd,MAAM,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,KAAK,EAAE,GAAGC,IAAAA,gCAAsB,EAACJ;IAE3DK,IAAAA,uCAA6B,EAC3B;QAAC;QAAW;QAAS;QAAS;QAAS;QAAU;QAAU;QAAS;KAAS,EAC7E;QAAEJ;QAAUC;QAAQC;IAAM,GAC1B;IAGF,OAAO;QACL,uFAAuF;QACvFF;QACAb,SAASD,eAAe;YACtBE,KAAK,CAAC,CAACc,KAAK,CAAC,QAAQ;YACrBG,KAAK,CAAC,CAACH,KAAK,CAAC,QAAQ;YACrBb,OAAO,CAAC,CAACa,KAAK,CAAC,UAAU;YACzBT,MAAM,CAAC,CAACS,KAAK,CAAC,SAAS;YACvBX,KAAK,CAAC,CAACW,KAAK,CAAC,QAAQ;YACrBV,MAAM,CAAC,CAACU,KAAK,CAAC,SAAS;YACvBR,KAAK,CAAC,CAACQ,KAAK,CAAC,QAAQ;YACrBJ,MAAM,CAAC,CAACI,KAAK,CAAC,SAAS;QACzB;QACAD;IACF;AACF"}
|
|
@@ -27,7 +27,7 @@ function _interop_require_default(obj) {
|
|
|
27
27
|
const ERROR_MESSAGE = 'Unable to fetch compatibility data from React Native Directory. Skipping check.';
|
|
28
28
|
async function checkPackagesCompatibility(packages) {
|
|
29
29
|
try {
|
|
30
|
-
const packagesToCheck = packages.filter((packageName)=>!packageName.startsWith('@expo-google-fonts/'));
|
|
30
|
+
const packagesToCheck = packages.filter((packageName)=>!packageName.startsWith('@expo/') && !packageName.startsWith('@expo-google-fonts/'));
|
|
31
31
|
if (!packagesToCheck.length) {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/install/utils/checkPackagesCompatibility.ts"],"sourcesContent":["// note(Simek): https://github.com/react-native-community/directory/blob/main/pages/api/libraries/check.ts\nimport chalk from 'chalk';\n\nimport { Log } from '../../log';\nimport { fetch } from '../../utils/fetch';\nimport { learnMore } from '../../utils/link';\n\nexport type ReactNativeDirectoryCheckResult = {\n unmaintained: boolean;\n newArchitecture: 'supported' | 'unsupported' | 'untested';\n};\n\nconst ERROR_MESSAGE =\n 'Unable to fetch compatibility data from React Native Directory. Skipping check.';\n\nexport async function checkPackagesCompatibility(packages: string[]) {\n try {\n const packagesToCheck = packages.filter(\n (packageName)
|
|
1
|
+
{"version":3,"sources":["../../../../src/install/utils/checkPackagesCompatibility.ts"],"sourcesContent":["// note(Simek): https://github.com/react-native-community/directory/blob/main/pages/api/libraries/check.ts\nimport chalk from 'chalk';\n\nimport { Log } from '../../log';\nimport { fetch } from '../../utils/fetch';\nimport { learnMore } from '../../utils/link';\n\nexport type ReactNativeDirectoryCheckResult = {\n unmaintained: boolean;\n newArchitecture: 'supported' | 'unsupported' | 'untested';\n};\n\nconst ERROR_MESSAGE =\n 'Unable to fetch compatibility data from React Native Directory. Skipping check.';\n\nexport async function checkPackagesCompatibility(packages: string[]) {\n try {\n const packagesToCheck = packages.filter(\n (packageName) =>\n !packageName.startsWith('@expo/') && !packageName.startsWith('@expo-google-fonts/')\n );\n\n if (!packagesToCheck.length) {\n return;\n }\n\n const response = await fetch('https://reactnative.directory/api/libraries/check', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ packages: packagesToCheck }),\n });\n\n if (!response.ok) {\n Log.log(chalk.gray(ERROR_MESSAGE));\n }\n\n const packageMetadata = (await response.json()) as Record<\n string,\n ReactNativeDirectoryCheckResult\n >;\n\n const incompatiblePackages = packagesToCheck.filter(\n (packageName) => packageMetadata[packageName]?.newArchitecture === 'unsupported'\n );\n\n if (incompatiblePackages.length) {\n Log.warn(\n chalk.yellow(\n `${chalk.bold('Warning')}: ${formatPackageNames(incompatiblePackages)} do${incompatiblePackages.length > 1 ? '' : 'es'} not support the New Architecture. ${learnMore('https://docs.expo.dev/guides/new-architecture/')}`\n )\n );\n }\n } catch {\n Log.log(chalk.gray(ERROR_MESSAGE));\n }\n}\n\nfunction formatPackageNames(incompatiblePackages: string[]) {\n if (incompatiblePackages.length === 1) {\n return incompatiblePackages.join();\n }\n\n const lastPackage = incompatiblePackages.pop();\n return `${incompatiblePackages.join(', ')} and ${lastPackage}`;\n}\n"],"names":["checkPackagesCompatibility","ERROR_MESSAGE","packages","packagesToCheck","filter","packageName","startsWith","length","response","fetch","method","headers","body","JSON","stringify","ok","Log","log","chalk","gray","packageMetadata","json","incompatiblePackages","newArchitecture","warn","yellow","bold","formatPackageNames","learnMore","join","lastPackage","pop"],"mappings":"AAAA,0GAA0G;;;;;+BAepFA;;;eAAAA;;;;gEAdJ;;;;;;qBAEE;uBACE;sBACI;;;;;;AAO1B,MAAMC,gBACJ;AAEK,eAAeD,2BAA2BE,QAAkB;IACjE,IAAI;QACF,MAAMC,kBAAkBD,SAASE,MAAM,CACrC,CAACC,cACC,CAACA,YAAYC,UAAU,CAAC,aAAa,CAACD,YAAYC,UAAU,CAAC;QAGjE,IAAI,CAACH,gBAAgBI,MAAM,EAAE;YAC3B;QACF;QAEA,MAAMC,WAAW,MAAMC,IAAAA,YAAK,EAAC,qDAAqD;YAChFC,QAAQ;YACRC,SAAS;gBACP,gBAAgB;YAClB;YACAC,MAAMC,KAAKC,SAAS,CAAC;gBAAEZ,UAAUC;YAAgB;QACnD;QAEA,IAAI,CAACK,SAASO,EAAE,EAAE;YAChBC,QAAG,CAACC,GAAG,CAACC,gBAAK,CAACC,IAAI,CAAClB;QACrB;QAEA,MAAMmB,kBAAmB,MAAMZ,SAASa,IAAI;QAK5C,MAAMC,uBAAuBnB,gBAAgBC,MAAM,CACjD,CAACC;gBAAgBe;mBAAAA,EAAAA,+BAAAA,eAAe,CAACf,YAAY,qBAA5Be,6BAA8BG,eAAe,MAAK;;QAGrE,IAAID,qBAAqBf,MAAM,EAAE;YAC/BS,QAAG,CAACQ,IAAI,CACNN,gBAAK,CAACO,MAAM,CACV,GAAGP,gBAAK,CAACQ,IAAI,CAAC,WAAW,EAAE,EAAEC,mBAAmBL,sBAAsB,GAAG,EAAEA,qBAAqBf,MAAM,GAAG,IAAI,KAAK,KAAK,mCAAmC,EAAEqB,IAAAA,eAAS,EAAC,mDAAmD;QAG/N;IACF,EAAE,OAAM;QACNZ,QAAG,CAACC,GAAG,CAACC,gBAAK,CAACC,IAAI,CAAClB;IACrB;AACF;AAEA,SAAS0B,mBAAmBL,oBAA8B;IACxD,IAAIA,qBAAqBf,MAAM,KAAK,GAAG;QACrC,OAAOe,qBAAqBO,IAAI;IAClC;IAEA,MAAMC,cAAcR,qBAAqBS,GAAG;IAC5C,OAAO,GAAGT,qBAAqBO,IAAI,CAAC,MAAM,KAAK,EAAEC,aAAa;AAChE"}
|
|
@@ -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
|
|
46
|
+
const hasEslintConfig = await isEslintConfigured(this.projectRoot);
|
|
47
|
+
const hasLegacyConfig = await isLegacyEslintConfigured(this.projectRoot);
|
|
47
48
|
const hasLintScript = await lintScriptIsConfigured(this.projectRoot);
|
|
48
|
-
|
|
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
|
|
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,47 +65,26 @@ 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
|
-
|
|
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) {
|
|
93
76
|
const scripts = _jsonfile().default.read(_path().default.join(this.projectRoot, 'package.json')).scripts;
|
|
94
77
|
await _jsonfile().default.setAsync(_path().default.join(this.projectRoot, 'package.json'), 'scripts', typeof scripts === 'object' ? {
|
|
95
78
|
...scripts,
|
|
96
|
-
lint: '
|
|
79
|
+
lint: 'expo lint'
|
|
97
80
|
} : {
|
|
98
|
-
lint: '
|
|
81
|
+
lint: 'expo lint'
|
|
99
82
|
}, {
|
|
100
83
|
json5: false
|
|
101
84
|
});
|
|
102
85
|
}
|
|
103
86
|
_log.Log.log();
|
|
104
|
-
_log.Log.log('
|
|
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: '^
|
|
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
|
|
136
|
-
debug('
|
|
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
|
|
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
|
-
|
|
155
|
-
|
|
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
|
-
/**
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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: 'expo lint' } : { lint: 'expo lint' },\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":"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"}
|